TensorFlow Lite ve Firebase - Android Codelab ile uygulamanıza Öneriler ekleme

1. Genel Bakış

TensorFlow Lite ve Firebase ile Öneriler adlı codelab'e hoş geldiniz. Bu codelab'de, uygulamanıza bir öneri modeli dağıtmak için TensorFlow Lite ve Firebase'i nasıl kullanacağınızı öğreneceksiniz. Bu codelab, TensorFlow Lite örneğini temel alır.

Öneriler, uygulamaların her kullanıcı için en alakalı içeriği akıllıca sunmak üzere makine öğreniminden yararlanmasına olanak tanır. Çok sayıda kullanıcının toplu davranışları üzerinde eğitilmiş bir model kullanarak, kullanıcının gelecekte etkileşimde bulunmak isteyebileceği uygulama içeriklerini önermek için geçmiş kullanıcı davranışlarını dikkate alırlar.

Bu eğiticide, Firebase Analytics ile uygulamanızın kullanıcılarından nasıl veri elde edeceğiniz, bu verilerden öneriler için bir makine öğrenimi modeli oluşturacağınız ve ardından çıkarım çalıştırmak ve öneri almak için bu modeli bir Android uygulamasında nasıl kullanacağınız gösterilmektedir. Özellikle, önerilerimiz kullanıcının daha önce beğendiği filmler listesine göre hangi filmleri izleme olasılığının en yüksek olduğunu gösterir.

Neler öğreneceksiniz?

  • Kullanıcı davranışı verilerini toplamak için Firebase Analytics'i bir Android uygulamasına entegre etme
  • Bu verileri Google BigQuery'ye aktarın.
  • Verileri önceden işleme ve TF Lite öneri modeli eğitme
  • TF Lite modelini Firebase ML'ye dağıtma ve uygulamanızdan erişme
  • Kullanıcılara öneriler sunmak için modeli kullanarak cihaz üzerinde çıkarım çalıştırma

Gerekenler

  • En son Android Studio sürümü.
  • Örnek kod.
  • Android 7 veya sonraki sürümlerin yüklü olduğu ve Google Play Hizmetleri 9.8 ya da sonraki sürümlerin bulunduğu bir test cihazı veya Google Play Hizmetleri 9.8 ya da sonraki sürümlerin bulunduğu bir emülatör
  • Cihaz kullanıyorsanız bağlantı kablosu.

Bu eğitimi nasıl kullanacaksınız?

Sadece okuyun Okuyun ve alıştırmaları tamamlayın

Android uygulamaları oluşturma deneyiminizi nasıl değerlendirirsiniz?

Başlangıç Orta İleri

2. Örnek kodu alın

GitHub deposunu komut satırından klonlayın.

$ git clone https://github.com/FirebaseExtended/codelab-contentrecommendation-android.git

3. Başlangıç uygulamasını içe aktarma

Android Studio'da örnek kod indirme işleminden ( Dosya > > .../codelab-recommendations-android/start) codelab-recommendations-android dizinini (android_studio_folder.png) seçin.

Başlangıç projesi artık Android Studio'da açık olmalıdır.

4. Firebase konsolu projesi oluşturma

Yeni proje oluşturma

  1. Firebase konsoluna gidin.
  2. Proje ekle'yi (veya ilk proje ise Proje oluştur'u) seçin.
  3. Bir proje adı seçin veya girin ve Devam'ı tıklayın.
  4. "Bu proje için Google Analytics'i etkinleştir" seçeneğinin etkinleştirildiğinden emin olun.
  5. Firebase konsolunda kalan kurulum adımlarını uygulayın, ardından Proje oluştur'u (veya mevcut bir Google projesi kullanıyorsanız Firebase ekle'yi) tıklayın.

5. Firebase Ekle

  1. Yeni projenizin genel bakış ekranında, kurulum iş akışını başlatmak için Android simgesini tıklayın.
  2. Codelab'in paket adını girin: com.google.firebase.codelabs.recommendations
  3. Uygulamayı kaydet'i seçin.

Uygulamanıza google-services.json dosyasını ekleme

Paket adını ekleyip Kaydet'i seçtikten sonra Firebase Android yapılandırma dosyanızı almak için google-services.json dosyasını indir'i tıklayın, ardından google-services.json dosyasını projenizdeki app dizinine kopyalayın. Dosya indirildikten sonra konsolda gösterilen sonraki adımları atlayabilirsiniz (bu adımlar, build-android-start projesinde sizin için zaten yapılmıştır).

Uygulamanıza google-services eklentisini ekleme

google-services eklentisi, uygulamanızı Firebase'i kullanacak şekilde yapılandırmak için google-services.json dosyasını kullanır. Aşağıdaki satırların projede build.gradle.kts dosyalarına eklenmiş olması gerekir (onaylamak için kontrol edin):

app/build.grade.kts

plugins {
    id("com.google.gms.google-services")
}

build.grade.kts

plugins {
    id("com.google.gms.google-services") version "4.3.15" apply false
}

Projenizi Gradle dosyalarıyla senkronize etme

Tüm bağımlılıkların uygulamanızda kullanılabilir olduğundan emin olmak için bu noktada projenizi Gradle dosyalarıyla senkronize etmeniz gerekir. Android Studio araç çubuğundan File > Sync Project with Gradle Files (Dosya > Projeyi Gradle Dosyalarıyla Senkronize Et) seçeneğini belirleyin.

6. Başlangıç uygulamasını çalıştırma

Projeyi Android Studio'ya aktarıp google-services eklentisini JSON dosyanızla yapılandırdığınıza göre artık uygulamayı ilk kez çalıştırmaya hazırsınız. Android cihazınızı bağlayın ve Android Studio araç çubuğunda Run'ı ( execute.png) tıklayın.

Uygulama, cihazınızda başlatılmalıdır. Bu noktada, filmlerin listesini içeren bir sekme, Beğenilen filmler sekmesi ve Öneriler sekmesi gösteren çalışan bir uygulama görebilirsiniz. Beğenilenler listenize eklemek istediğiniz filmi listeden tıklayabilirsiniz. Codelab'in kalan adımlarını tamamladıktan sonra Öneriler sekmesinde film önerileri oluşturabileceğiz.

7. Uygulamaya Firebase Analytics'i ekleme

Bu adımda, kullanıcı davranış verilerini (bu örnekte, kullanıcının beğendiği filmler) kaydetmek için uygulamaya Firebase Analytics'i ekleyeceksiniz. Bu veriler, öneri modelini eğitmek için gelecekteki adımlarda toplu olarak kullanılır.

Firebase Malzeme Listesi'ni ve Analytics bağımlılığını ekleme

Firebase Analytics'i uygulamanıza eklemek için aşağıdaki bağımlılıklar gereklidir. Bu bağımlılıklar, app/build.gradle.kts dosyasına zaten eklenmiş olmalıdır (doğrulayın).

app/build.grade.kts

implementation(platform("com.google.firebase:firebase-bom:32.0.0"))
implementation("com.google.firebase:firebase-analytics-ktx")

Uygulamada Firebase Analytics'i ayarlama

LikedMoviesViewModel, kullanıcının beğendiği filmleri depolamaya yönelik işlevler içerir. Kullanıcı her yeni filmi beğendiğinde, bu beğeniyi kaydetmek için bir Analytics günlük etkinliği de göndermek istiyoruz.

Kullanıcı bir filmde beğen düğmesini tıkladığında bir analiz etkinliği kaydetmek için aşağıdaki kodla birlikte onMovieLiked işlevini ekleyin.

LikedMoviesViewModel.kt

import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase


class LikedMoviesViewModel internal constructor (application: Application) : AndroidViewModel(application) {

    ...

    fun onMovieLiked(movie: Movie) {
        movies.setLike(movie, true)
        logAnalyticsEvent(movie.id.toString())
    }
       
}

Kullanıcının Beğenilenler listesine bir film eklendiğinde Analytics etkinliği kaydetmek için aşağıdaki alanı ve işlevi ekleyin.

LikedMoviesViewModel.kt

import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase


class LikedMoviesViewModel internal constructor (application: Application) : AndroidViewModel(application) {
    ...
    private val firebaseAnalytics = Firebase.analytics

    ...

    /**
     * Logs an event in Firebase Analytics that is used in aggregate to train the recommendations
     * model.
     */
    private fun logAnalyticsEvent(id: String) {
        firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_ITEM) {
            param(FirebaseAnalytics.Param.ITEM_ID, id)
        }
    }

8. Analytics entegrasyonunuzu test etme

Bu adımda, uygulamada Analytics etkinlikleri oluşturacak ve bunların Firebase konsoluna gönderildiğini doğrulayacağız.

Analytics hata ayıklama günlük kaydını etkinleştirme

Firebase Analytics, kullanıcıların pil ömrünü en üst düzeye çıkarmak için tasarlanmıştır. Etkinlikleri cihazda toplu olarak işler ve yalnızca ara sıra Firebase'e gönderir. Hata ayıklama amacıyla, kabukta aşağıdaki komutu çalıştırarak etkinlikleri gerçek zamanlı olarak günlüğe kaydedildikleri şekilde görmek için bu davranışı devre dışı bırakabiliriz.

Terminal

adb shell setprop debug.firebase.analytics.app com.google.firebase.codelabs.recommendations

Analytics etkinliklerinin oluşturulduğunu doğrulama

  1. Android Studio'da, uygulamanızdaki günlükleri incelemek için Logcat penceresini açın.
  2. Logcat filtresini "Logging event" dizesine ayarlayın.
  3. Uygulamada bir filmi her beğendiğinizde "select_item" Analytics etkinliklerinin yayınlandığını doğrulayın.

Bu noktada, Firebase Analytics'i uygulamanıza başarıyla entegre ettiniz. Kullanıcılar uygulamanızı kullandıkça ve filmleri beğendikçe beğenileri toplu olarak kaydedilir. Öneri modelimizi eğitmek için bu toplu verileri bu codelab'in geri kalanında kullanacağız. Aşağıdaki adım, Logcat'te gördüğünüz Analytics etkinliklerinin Firebase konsoluna da aktarıldığını görmek için isteğe bağlı olarak uygulanabilir. İsterseniz sonraki sayfaya geçebilirsiniz.

İsteğe bağlı: Firebase konsolunda Analytics etkinliklerini onaylayın

  1. Firebase konsoluna gidin.
  2. Analytics bölümünde DebugView'u seçin.
  3. Android Studio'da Çalıştır'ı seçerek uygulamayı başlatın ve Beğenilenler listenize bazı filmler ekleyin.
  4. Firebase konsolunun DebugView bölümünde, uygulamaya film eklerken bu etkinliklerin kaydedildiğini doğrulayın.

9. Analytics verilerini BigQuery'ye aktarma

BigQuery, büyük miktarda veriyi incelemenize ve işlemenize olanak tanıyan bir Google Cloud ürünüdür. Bu adımda, uygulamanız tarafından oluşturulan Analytics verilerinin otomatik olarak BigQuery'ye aktarılması için Firebase Console projenizi BigQuery'ye bağlayacaksınız.

BigQuery Export'u etkinleştirme

  1. Firebase konsoluna gidin.
  2. Proje Genel Bakışı'nın yanındaki Ayarlar dişli simgesini ve ardından Proje ayarları'nı seçin.
  3. Entegrasyonlar sekmesini seçin.
  4. BigQuery bloğunda Bağla'yı (veya Yönet'i) seçin.
  5. Firebase'i BigQuery'ye Bağlama Hakkında adımında Sonraki'yi seçin.
  6. Entegrasyonu yapılandırın bölümünde, Google Analytics verilerinin gönderilmesini etkinleştirmek için anahtarı tıklayın ve BigQuery'ye bağla'yı seçin.

Artık Firebase konsolu projenizi, Firebase Analytics etkinlik verilerini otomatik olarak BigQuery'ye gönderecek şekilde etkinleştirdiniz. Bu işlem, başka bir etkileşim olmadan otomatik olarak gerçekleşir. Ancak BigQuery'de analiz veri kümesini oluşturan ilk dışa aktarma işlemi 24 saat sürebilir. Veri kümesi oluşturulduktan sonra Firebase, yeni Analytics etkinliklerini gün içinde doldurulan tabloya sürekli olarak BigQuery'ye aktarır ve geçmiş günlerdeki etkinlikleri events tablosunda gruplandırır.

Öneri modelini eğitmek için çok fazla veri gerekir. Şu anda büyük miktarda veri üreten bir uygulamamız olmadığı için bu eğitimin geri kalanında kullanmak üzere bir örnek veri kümesini BigQuery'ye aktaracağız.

10. Model eğitimi verilerini elde etmek için BigQuery'yi kullanma

Firebase konsolumuzu BigQuery'ye aktaracak şekilde bağladığımıza göre, uygulama analizleri etkinlik verilerimiz bir süre sonra BigQuery konsolunda otomatik olarak gösterilecek. Bu eğitimin amaçları doğrultusunda başlangıç verileri elde etmek için bu adımda, öneri modelimizi eğitmek üzere kullanacağımız mevcut bir örnek veri kümesini BigQuery konsolunuza aktaracağız.

Örnek veri kümesini BigQuery'ye aktarma

  1. Google Cloud Console'da BigQuery kontrol paneline gidin.
  2. Menüde proje adınızı seçin.
  3. Ayrıntıları görmek için BigQuery'nin sol gezinme bölümünün alt kısmında proje adınızı seçin.
  4. Veri kümesi oluşturma panelini açmak için Veri kümesi oluştur'u seçin.
  5. Veri kümesi kimliği için "firebase_recommendations_dataset" girin ve Veri kümesi oluştur'u seçin.
  6. Yeni veri kümesi, sol menüde proje adının altında gösterilir. Bu simgeyi tıklayın.
  7. Tablo oluşturma panelini açmak için Tablo oluştur'u seçin.
  8. Şu kaynaktan tablo oluşturun için "Google Cloud Storage"ı seçin.
  9. GCS paketinden dosya seçin alanına "gs://firebase-recommendations/recommendations-test/formatted_data_filtered.txt" girin.
  10. Dosya biçimi açılır listesinde "JSONL"yi seçin.
  11. Tablo adı için "recommendations_table" girin.
  12. Şema > Otomatik algılama > Şema ve giriş parametreleri bölümündeki kutuyu işaretleyin.
  13. Tablo oluştur'u seçin.

Örnek veri kümesini keşfetme

Bu aşamada, isteğe bağlı olarak şemayı keşfedebilir ve bu veri kümesini önizleyebilirsiniz.

  1. İçerdiği tabloları genişletmek için sol menüden firebase-recommendations-dataset'i seçin.
  2. Tablo şemasını görüntülemek için recommendations-table tablosunu seçin.
  3. Bu tablonun içerdiği gerçek Analytics etkinlik verilerini görmek için Önizleme'yi seçin.

Hizmet hesabı kimlik bilgileri oluşturma

Şimdi, Google Cloud Console projemizde hizmet hesabı kimlik bilgileri oluşturacağız. Bu kimlik bilgilerini, BigQuery verilerimize erişmek ve bunları yüklemek için Colab ortamında kullanacağız.

  1. Google Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun.
  2. BigQuery ve BigQuery Storage API'lerini etkinleştirin. < burayı tıklayın>
  3. Hizmet Hesabı Anahtarı Oluşturma sayfasına gidin.
  4. Hizmet hesabı listesinden Yeni hizmet hesabı'nı seçin.
  5. Hizmet hesabı adı alanına bir ad girin.
  6. Rol listesinden Proje > Sahip'i seçin.
  7. Oluştur'u tıklayın. Anahtarınızı içeren bir JSON dosyası bilgisayarınıza indirilir.

Bir sonraki adımda, bu verileri önceden işlemek ve öneri modelimizi eğitmek için Google Colab'i kullanacağız.

11. Verileri önceden işleme ve öneri modelini eğitme

Bu adımda, aşağıdaki adımları uygulamak için bir Colab not defteri kullanacağız:

  1. BigQuery verilerini Colab not defterine aktarma
  2. verileri model eğitimine hazırlamak için önceden işleme
  3. öneri modelini analiz verileri üzerinde eğitme
  4. Modeli TF Lite modeli olarak dışa aktarma
  5. modeli Firebase konsoluna dağıtarak uygulamamızda kullanabilme

Colab eğitim not defterini kullanıma sunmadan önce, eğitilen modeli Firebase konsolumuza dağıtabilmesi için Firebase Model Management API'yi etkinleştireceğiz.

Firebase Model Management API'yi etkinleştirme

ML modellerinizi depolamak için paket oluşturma

Firebase konsolunuzda Storage'a gidip Başlayın'ı tıklayın. fbbea78f0eb3dc9f.png

Bucket'ınızı ayarlamak için diyalogdaki adımları uygulayın.

19517c0d6d2aa14d.png

Firebase ML API'yi etkinleştirme

Google Cloud Console'da Firebase ML API sayfasına gidin ve Etkinleştir'i tıklayın.

Modeli eğitmek ve dağıtmak için Colab not defterini kullanma

Aşağıdaki bağlantıyı kullanarak Colab not defterini açın ve içindeki adımları tamamlayın. Colab not defterindeki adımları tamamladıktan sonra, Firebase konsoluna dağıtılmış bir TF Lite model dosyanız olur. Bu dosyayı uygulamamızla senkronize edebiliriz.

Colab'de aç

12. Modeli uygulamanıza indirme

Bu adımda, uygulamamızı Firebase Machine Learning'den yeni eğittiğimiz modeli indirecek şekilde değiştireceğiz.

Firebase ML bağımlılığını ekleme

Uygulamanızda Firebase makine öğrenimi modellerini kullanmak için aşağıdaki bağımlılık gereklidir. Bu bağımlılık zaten eklenmiş olmalıdır (doğrulayın).

app/build.grade.kts

implementation("com.google.firebase:firebase-ml-modeldownloader:24.1.2")

Firebase Model Manager API ile modeli indirme

Modelin indirileceği koşulları ayarlamak ve uzak modeli uygulamamızla senkronize etmek için bir indirme görevi oluşturmak üzere aşağıdaki kodu RecommendationClient.kt dosyasına kopyalayın.

RecommendationClient.kt

    private fun downloadModel(modelName: String) {
        val conditions = CustomModelDownloadConditions.Builder()
            .requireWifi()
            .build()
        FirebaseModelDownloader.getInstance()
            .getModel(modelName, DownloadType.LOCAL_MODEL, conditions)
            .addOnCompleteListener {
                if (!it.isSuccessful) {
                    showToast(context, "Failed to get model file.")
                } else {
                    showToast(context, "Downloaded remote model: $modelName")
                    GlobalScope.launch { initializeInterpreter(it.result) }
                }
            }
            .addOnFailureListener {
                showToast(context, "Model download failed for recommendations, please check your connection.")
            }
    }

13. Tensorflow Lite öneri modelini uygulamanıza entegre etme

TensorFlow Lite çalışma zamanı, öneri oluşturmak için modelinizi uygulamada kullanmanıza olanak tanır. Önceki adımda, indirdiğimiz model dosyasıyla bir TFlite yorumlayıcısı başlatmıştık. Bu adımda, önce çıkarım adımında modelimize eşlik edecek bir sözlük ve etiketler yükleyeceğiz. Ardından, modelimize giriş oluşturmak için ön işleme ve çıkarımımızdan sonuçları çıkaracağımız son işleme ekleyeceğiz.

Load Dictionary and Labels (Sözlük ve Etiketleri Yükle)

Öneri modeli tarafından öneri adayları oluşturmak için kullanılan etiketler, res/assets klasöründeki sorted_movie_vocab.json dosyasında listelenir. Bu adayları yüklemek için aşağıdaki kodu kopyalayın.

RecommendationClient.kt

    /** Load recommendation candidate list.  */
    private suspend fun loadCandidateList() {
        return withContext(Dispatchers.IO) {
            val collection = MovieRepository.getInstance(context).getContent()
            for (item in collection) {
                candidates[item.id] = item
            }
            Log.v(TAG, "Candidate list loaded.")
        }
    }

Ön işlemeyi uygulama

Ön işleme adımında, giriş verilerinin biçimini modelimizin beklediği biçime göre değiştiririz. Burada, henüz çok fazla kullanıcı beğenisi oluşturmadıysak giriş uzunluğunu bir yer tutucu değerle doldururuz. Aşağıdaki kodu kopyalayın:

RecommendationClient.kt

    /** Given a list of selected items, preprocess to get tflite input.  */
    @Synchronized
    private suspend fun preprocess(selectedMovies: List<Movie>): IntArray {
        return withContext(Dispatchers.Default) {
            val inputContext = IntArray(config.inputLength)
            for (i in 0 until config.inputLength) {
                if (i < selectedMovies.size) {
                    val (id) = selectedMovies[i]
                    inputContext[i] = id
                } else {
                    // Padding input.
                    inputContext[i] = config.pad
                }
            }
            inputContext
        }
    }


Öneriler oluşturmak için yorumlayıcıyı çalıştırma

Burada, önceden işlenmiş girişimizde çıkarım çalıştırmak için önceki adımda indirdiğimiz modeli kullanıyoruz. Modelimizin giriş ve çıkış türünü belirleyip film önerilerimizi oluşturmak için çıkarım gerçekleştiririz. Aşağıdaki kodu uygulamanıza kopyalayın.

RecommendationClient.kt

    /** Given a list of selected items, and returns the recommendation results.  */
    @Synchronized
    suspend fun recommend(selectedMovies: List<Movie>): List<Result> {
        return withContext(Dispatchers.Default) {
            val inputs = arrayOf<Any>(preprocess(selectedMovies))

            // Run inference.
            val outputIds = IntArray(config.outputLength)
            val confidences = FloatArray(config.outputLength)
            val outputs: MutableMap<Int, Any> = HashMap()
            outputs[config.outputIdsIndex] = outputIds
            outputs[config.outputScoresIndex] = confidences
            tflite?.let {
                it.runForMultipleInputsOutputs(inputs, outputs)
                postprocess(outputIds, confidences, selectedMovies)
            } ?: run {
                Log.e(TAG, "No tflite interpreter loaded")
                emptyList()
            }
        }
    }



Son İşlemeyi Uygulama

Son olarak, bu adımda modelimizin çıktısını işleriz. En yüksek güvene sahip sonuçları seçer ve içerilen değerleri (kullanıcının daha önce beğendiği filmler) kaldırırız. Aşağıdaki kodu uygulamanıza kopyalayın.

RecommendationClient.kt

    /** Postprocess to gets results from tflite inference.  */
    @Synchronized
    private suspend fun postprocess(
        outputIds: IntArray, confidences: FloatArray, selectedMovies: List<Movie>
    ): List<Result> {
        return withContext(Dispatchers.Default) {
            val results = ArrayList<Result>()

            // Add recommendation results. Filter null or contained items.
            for (i in outputIds.indices) {
                if (results.size >= config.topK) {
                    Log.v(TAG, String.format("Selected top K: %d. Ignore the rest.", config.topK))
                    break
                }
                val id = outputIds[i]
                val item = candidates[id]
                if (item == null) {
                    Log.v(TAG, String.format("Inference output[%d]. Id: %s is null", i, id))
                    continue
                }
                if (selectedMovies.contains(item)) {
                    Log.v(TAG, String.format("Inference output[%d]. Id: %s is contained", i, id))
                    continue
                }
                val result = Result(
                    id, item,
                    confidences[i]
                )
                results.add(result)
                Log.v(TAG, String.format("Inference output[%d]. Result: %s", i, result))
            }
            results
        }
    }


Uygulamanızı test edin.

Uygulamanızı yeniden çalıştırın. Birkaç film seçtiğinizde yeni model otomatik olarak indirilir ve öneriler oluşturulmaya başlanır.

14. Tebrikler!

TensorFlow Lite ve Firebase kullanarak uygulamanıza öneri özelliği eklediniz. Bu Codelab'de gösterilen tekniklerin ve işlem hattının genelleştirilebileceğini ve diğer öneri türlerini sunmak için de kullanılabileceğini unutmayın.

İşlediğimiz konular

  • Firebase ML
  • Firebase Analytics
  • Analytics etkinliklerini BigQuery'ye aktarma
  • Analiz etkinliklerini ön işleme
  • Öneri TensorFlow modelini eğitme
  • Modeli dışa aktarma ve Firebase Konsolu'na dağıtma
  • Uygulamada film önerileri sunma

Sonraki adımlar

  • Uygulamanızda Firebase ML önerilerini uygulayın.

Daha Fazla Bilgi

Sorunuz mu var?

Sorunları Bildirme