Gemini Nano'dan gelen yanıtları daha sonra işlemek üzere JSON gibi belirli biçimlere ayrıştırmanız gerekiyorsa doğrudan model erişimiyle Structured Output API'yi kullanın.
Structured Output API ile hedef çıkış yapısını Kotlin sınıflarını ve ek açıklamalarını kullanarak tanımlarsınız. Doğrudan model erişimi, Kotlin nesneniz biçiminde bir yanıt döndürür.
Yapılandırılmış çıkış oluşturmak, özellikle aşağıdaki gibi görevler için kullanışlıdır:
- Varlık ayıklama: Yapılandırılmamış metinden yapılandırılmış alanları (ör. etkinlik adı, tarih, konum) ayıklama.
- Sınıflandırma: Giriş metnini önceden tanımlanmış kategorilere ayırma.
- Veri serileştirme: Yapılandırılmamış kullanıcı girişini veritabanı depolama alanı veya API çağrıları için uygun bir biçime dönüştürme.
Ön koşullar
Structured Output API'nin cihazda kullanılabilir olduğunu doğrulamak için isStructuredOutputFeatureAvailable() API'sini kullanın. Cihazda Structured Output API varsa API true değerini, yoksa false değerini döndürür.
suspend fun isStructuredOutputFeatureAvailable(): Boolean
Structured Output API'nin aşağıdaki şartları da vardır:
- Android API düzeyi 26 veya daha yüksek (
minSdk26) - KSP eklentisi 2.3.6 veya sonraki bir sürüm
Sınırlamalar
Structured Output API'nin aşağıdaki sınırlamaları vardır:
- Yalnızca Kotlin'de çalışır.
- ProGuard, ek açıklamalı sınıfınızın ayrıştırılmasını engelleyebilir. Ayrıştırma sırasında hata alırsanız ek açıklamalı sınıfınızı saklama kurallarınıza ekleyerek ProGuard'dan hariç tutun. Örneğin:
# Keep classes used by structured output for deserialization for release builds.
-keep class com.google.mlkit.genai.demo.kotlin.Plant { *; }
Projeyi yapılandırma
Structured Output API'yi kullanmaya başlamak için aşağıdaki adımları uygulayın:
Henüz yapmadıysanız uygulama düzeyindeki
build.gradle.kts(veyabuild.gradle) dosyanızacom.google.mlkit:genai-promptbağımlılığını ekleyin.KSP eklentisini proje düzeyindeki
build.gradle.ktsdosyanıza ekleyin. Kotlin sürümünüzle uyumlu bir KSP eklentisi sürümü kullanın. KSP 2.3.6 veya sonraki bir sürümü kullanmanızı öneririz.dependencies { ... classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.3.6" }Uygulama düzeyindeki
build.gradle.ktsdosyanıza yapılandırılmış derleyici bağımlılıklarını ekleyin:dependencies { ... ksp("com.google.mlkit:genai-schema-compiler:1.0.0-alpha1") }
Çıkış yapısını tanımlama
Kotlin veri sınıflarını kullanarak modelin döndürmesini istediğiniz verilerin yapısını tanımlayın. Çıkış yapısını tanımlamak için iki ana ek açıklama vardır:
- Sınıfı yapılandırılmış çıkış için hedef olarak tanımlamak üzere
@Generableek açıklamasını kullanın. - Modelin çıkışını yönlendiren açıklamalar ve kısıtlamalar sağlamak için sınıf özelliklerindeki
@Guideek açıklamalarını kullanın.
Aşağıdaki örnekte, bitki bilgilerini ayıklamak için bir yapı tanımlanmaktadır:
import com.google.mlkit.genai.schema.annotations.Generable
import com.google.mlkit.genai.schema.annotations.Guide
@Generable
data class PlantList(
@Guide(description = "The list of plants found", minItems = 1, maxItems = 5)
val plants: List<Plant>
)
@Generable("Information about a plant species")
data class Plant(
@Guide(description = "The common name of the plant")
val commonName: String,
@Guide(description = "The full latin scientific name of the plant")
val scientificName: String,
@Guide(
description = "The maximum height of the plant in centimeters.",
minimum = 1.0,
maximum = 10000.0
)
val maxHeightCm: Int,
@Guide(description = "Whether the plant is poisonous or not")
val isPoisonous: Boolean?,
@Guide(
description = "The primary continent where this plant is native to",
enumValues = ["Africa", "Antarctica", "Asia", "Australia", "Europe", "North America", "South America"]
)
val nativeContinent: String
)
Desteklenen türler ve kısıtlamalar
@Generable ek açıklamalı bir sınıfta, ilgili @Guide kısıtlamalarıyla birlikte aşağıdaki türler desteklenir:
| Tür | Açıklama | Desteklenen @Guide kısıtlamaları |
|---|---|---|
String |
Metin için. | description, enumValues |
Double/Float |
Kayan noktalı sayılar için. | description, minimum ve maximum |
Int/Long |
Tam sayılar için. | description, minimum ve maximum |
Boolean |
Doğru/yanlış değerleri için. | description |
List<T> |
Desteklenen türlerin veya iç içe yerleştirilmiş @Generable sınıflarının listeleri için.
|
description, minItems ve maxItems |
List<String> |
String değer listeleri için. |
description, enumValues, minItems,
maxItems |
@Generable sınıfı |
İç içe yerleştirilmiş yapılandırılmış nesneler için. | description |
Yapılandırılmış içerik oluşturma
Yapılandırılmış çıkış istemek için generateTypedContentRequest yardımcı işlevini kullanarak standart isteminizi sarmalayın ve hedef çıkış sınıfını belirtin.
// 1. Initialize your GenerativeModel as usual
val generativeModel = Generation.getClient()
// 2. Prepare the prompt text
val promptText = "List some common plants found in California."
val baseRequest = GenerateContentRequest.Builder(TextPart(promptText)).build()
// 3. Create the typed request, specifying the target class (e.g., PlantList)
val typedRequest = generateTypedContentRequest(
generateContentRequest = baseRequest,
outputClass = PlantList::class
)
// 4. Run the inference
try {
val typedResponse = generativeModel.generateContent(typedRequest)
// 5. Access the parsed object
// The response candidates contain the parsed object of type T (PlantList in this case)
val plantList: PlantList? = typedResponse.candidates.firstOrNull()?.response
if (plantList != null) {
// Process the structured data
for (plant in plantList.plants) {
Log.d("StructuredOutput", "Found plant: ${plant.commonName} (${plant.scientificName})")
}
} else {
Log.e("StructuredOutput", "Failed to parse response into the desired structure.")
// Inspect finish reason for details
val finishReason = typedResponse.candidates.firstOrNull()?.finishReason
Log.d("StructuredOutput", "Finish reason: $finishReason")
}
} catch (e: GenAiException) {
// Handle API errors
when (e.errorCode) {
GenAiException.STRUCTURED_OUTPUT_INVALID_CLASS -> {
Log.e("StructuredOutput", "The class structure is not supported.")
}
GenAiException.STRUCTURED_OUTPUT_INVALID_VALUE -> {
Log.e("StructuredOutput", "The model generated values that violate the schema constraints.")
}
else -> {
Log.e("StructuredOutput", "API error: ${e.message}")
}
}
}
Sonlanma nedenlerini ve hataları işleme
Structured Output API'yi kullanırken API tarafından oluşturulan olası istisnaları işlemeniz ve ayrıştırılmış yanıt boşsa yanıt adaylarındaki finishReason özelliğini incelemeniz gerekir.
finishReason değerleri
finishReason özelliği aşağıdaki değerlerden birini alabilir:
TypedFinishReason.STOP: Model, oluşturma işlemini başarıyla tamamladı ve çıkış, şemayla eşleşiyor.TypedFinishReason.MAX_TOKENS: Model, jeton sınırına ulaştığı için durdu. Çıktı eksik olabilir.TypedFinishReason.PARSE_CLASS_ERROR: Model, oluşturma işlemini tamamladı ancak elde edilen JSON, hedef Kotlin sınıfına ayrıştırılamadı.TypedFinishReason.STRUCTURE_NOT_ANNOTATED: Hedef sınıfta veya iç içe yerleştirilmiş sınıflarında gerekli@Generableek açıklaması eksik.TypedFinishReason.STRUCTURE_VALUES_INVALID: Oluşturulan değerler,@Guideek açıklamalarında tanımlanan kısıtlamaları ihlal etti (ör. aralık dışı değer, sınır dışı liste boyutu).TypedFinishReason.OTHER: Oluşturma işlemi başka nedenlerden dolayı durduruldu.
İstisnalar
Structured Output API, aşağıdaki hata kodlarıyla GenAiException hatası verebilir:
GenAiException.STRUCTURED_OUTPUT_INVALID_CLASS(-104): Ek açıklamalı sınıfın yapısı geçersiz veya desteklenmeyen türler içeriyor. Bu genellikle geliştirme aşamasındaki bir yapılandırma hatasıdır. Tüm özellik türlerinin desteklendiğinden ve döngüsel bağımlılık olmadığından emin olmak için@Generableveri sınıfı tanımınızı inceleyin.GenAiException.STRUCTURED_OUTPUT_INVALID_VALUE(-105): Model tarafından oluşturulan değerler geçersiz veya kısıtlama doğrulamasından geçemiyor. Bu bir çalışma zamanı hatasıdır. Bu hatayla sık sık karşılaşıyorsanız aşağıdaki çözümleri deneyin:- Modeli daha sıkı bir şekilde yönlendirmek için istem talimatlarınızı hassaslaştırma.
@Guideek açıklamalarınızdaki kısıtlamalar (ör. minimum, maksimum veya liste boyutu sınırları) modelin kapasitesi için çok kısıtlayıcıysa bunları esnetme.- Uygulamanızda, isteği yeniden deneme veya varsayılan bir durum gösterme gibi bir yedek strateji uygulama
Parça sayma
Yapılandırılmış isteminizin giriş jetonu sınırını aşmadığından emin olmak için countTokens() yöntemini kullanarak jeton sayısını hesaplayın.
Yapılandırılmış çıkış isteklerinin, modele şema yapısı hakkında talimat vermesi gerektiğinden, yalnızca ham istem metnindeki (GenerateContentRequest örneği kullanarak) parçaları saymak doğru değildir. Doğru bir jeton sayısı elde etmek için hedef sınıfınızı ve şema yapılandırmalarınızı içeren GenerateTypedContentRequest örneğinin tamamını countTokens() yöntemine iletmeniz gerekir:
suspend fun <T : Any> countTokens(request: GenerateTypedContentRequest<T>): CountTokensResponse