Wenn Sie Antworten von Gemini Nano zur weiteren Verarbeitung in bestimmte Formate wie JSON parsen müssen, verwenden Sie die Structured Output API mit direktem Modellzugriff.
Mit der Structured Output API definieren Sie die Zielausgabestruktur mithilfe von Kotlin-Klassen und ‑Anmerkungen. Der direkte Modellzugriff gibt dann eine Antwort in Form Ihres Kotlin-Objekts zurück.
Das Generieren strukturierter Ausgaben ist besonders für die folgenden Aufgaben nützlich:
- Entitätsextraktion: Strukturierte Felder (z. B. Ereignisname, Datum, Ort) aus unstrukturiertem Text extrahieren.
- Klassifizierung: Eingabetext in vordefinierte Kategorien einteilen.
- Datenserialisierung: Unstrukturierte Nutzereingaben werden in ein Format umgewandelt, das für die Speicherung in einer Datenbank oder für API-Aufrufe geeignet ist.
Vorbereitung
Mit der isStructuredOutputFeatureAvailable() API können Sie prüfen, ob die Structured Output API auf dem Gerät verfügbar ist. Die API gibt true zurück, wenn die Structured Output API auf dem Gerät verfügbar ist, andernfalls false.
suspend fun isStructuredOutputFeatureAvailable(): Boolean
Für die Structured Output API gelten außerdem die folgenden Anforderungen:
- Android API-Level 26 oder höher (
minSdk26) - KSP-Plug-in-Version 2.3.6 oder höher
Beschränkungen
Für die Structured Output API gelten die folgenden Einschränkungen:
- Funktioniert nur in Kotlin.
- ProGuard kann das Parsen Ihrer annotierten Klasse beeinträchtigen. Fügen Sie die annotierte Klasse zu den Beibehaltungsregeln hinzu, um sie von ProGuard auszuschließen, wenn beim Parsen Fehler auftreten, z. B.:
# Keep classes used by structured output for deserialization for release builds.
-keep class com.google.mlkit.genai.demo.kotlin.Plant { *; }
Projekt konfigurieren
So verwenden Sie die Structured Output API:
Fügen Sie die Abhängigkeit
com.google.mlkit:genai-promptin die Dateibuild.gradle.kts(oderbuild.gradle) auf App-Ebene ein, falls noch nicht geschehen.Fügen Sie das KSP-Plug-in der
build.gradle.kts-Datei auf Projektebene hinzu. Verwenden Sie eine KSP-Plug-in-Version, die mit Ihrer Kotlin-Version kompatibel ist. Wir empfehlen KSP-Version 2.3.6 oder höher.dependencies { ... classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.3.6" }Fügen Sie der Datei
build.gradle.ktsauf App-Ebene die Abhängigkeiten für den strukturierten Compiler hinzu:dependencies { ... ksp("com.google.mlkit:genai-schema-compiler:1.0.0-alpha1") }
Ausgabestruktur definieren
Definieren Sie die Struktur der Daten, die das Modell zurückgeben soll, mithilfe von Kotlin-Datenklassen. Es gibt zwei Hauptannotationen zum Definieren der Ausgabestruktur:
- Verwenden Sie die Annotation
@Generable, um die Klasse als Ziel für die strukturierte Ausgabe zu definieren. - Verwenden Sie die
@Guide-Annotationen für die Klasseneigenschaften, um Beschreibungen und Einschränkungen anzugeben, die die Ausgabe des Modells steuern.
Im folgenden Beispiel wird eine Struktur zum Extrahieren von Pflanzeninformationen definiert:
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
)
Unterstützte Typen und Einschränkungen
Die folgenden Typen werden in einer mit @Generable annotierten Klasse unterstützt, zusammen mit den entsprechenden @Guide-Einschränkungen:
| Typ | Beschreibung | Unterstützte @Guide-Einschränkungen |
|---|---|---|
String |
Für Text. | description, enumValues |
Double/Float |
Für Gleitkommazahlen. | description, minimum, maximum |
Int/Long |
Für ganze Zahlen. | description, minimum, maximum |
Boolean |
Für Wahr/Falsch-Werte. | description |
List<T> |
Für Listen mit unterstützten Typen oder verschachtelten @Generable-Klassen.
|
description, minItems, maxItems |
List<String> |
Für Listen mit String-Werten. |
description, enumValues, minItems,
maxItems |
Klasse @Generable |
Für verschachtelte strukturierte Objekte. | description |
Strukturierte Inhalte generieren
Wenn Sie eine strukturierte Ausgabe anfordern möchten, verwenden Sie die Hilfsfunktion generateTypedContentRequest, um Ihren Standard-Prompt zu umschließen und die Zielausgabeklasse anzugeben.
// 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}")
}
}
}
Gründe für das Beenden und Fehler verarbeiten
Wenn Sie die Structured Output API verwenden, sollten Sie potenzielle Ausnahmen behandeln, die von der API ausgelöst werden, und das Attribut finishReason in den Antwortkandidaten prüfen, wenn die geparste Antwort null ist.
finishReason-Werte
Die Property finishReason kann einen der folgenden Werte haben:
TypedFinishReason.STOP: Das Modell hat die Generierung erfolgreich abgeschlossen und die Ausgabe entspricht dem Schema.TypedFinishReason.MAX_TOKENS: Das Modell wurde beendet, weil das Tokenlimit erreicht wurde. Die Ausgabe ist möglicherweise unvollständig.TypedFinishReason.PARSE_CLASS_ERROR: Das Modell hat die Generierung abgeschlossen, aber das resultierende JSON konnte nicht in die Kotlin-Zielklasse geparst werden.TypedFinishReason.STRUCTURE_NOT_ANNOTATED: In der Zielklasse oder ihren verschachtelten Klassen fehlt die erforderliche@Generable-Annotation.TypedFinishReason.STRUCTURE_VALUES_INVALID: Die generierten Werte haben gegen die in den@Guide-Annotationen definierten Einschränkungen verstoßen (z. B. Wert außerhalb des Bereichs, Listengröße außerhalb der Grenzen).TypedFinishReason.OTHER: Die Generierung wurde aus anderen Gründen beendet.
Ausnahmen
Die Structured Output API kann GenAiException mit den folgenden Fehlercodes ausgeben:
GenAiException.STRUCTURED_OUTPUT_INVALID_CLASS(-104): Die Struktur der annotierten Klasse ist ungültig oder enthält nicht unterstützte Typen. Dies ist in der Regel ein Konfigurationsfehler während der Entwicklung. Prüfen Sie die Definition der Datenklasse@Generable, um sicherzustellen, dass alle Property-Typen unterstützt werden und keine Zirkelbezüge vorhanden sind.GenAiException.STRUCTURED_OUTPUT_INVALID_VALUE(-105): Die vom Modell generierten Werte sind ungültig oder bestehen die Einschränkungsprüfung nicht. Dies ist ein Laufzeitfehler. Wenn dieser Fehler häufig auftritt, können Sie Folgendes versuchen:- Prompt-Anweisungen verfeinern, um das Modell genauer zu steuern.
- Lockerung der Einschränkungen (z. B. Mindest-, Höchst- oder Listengrößenlimits) in Ihren
@Guide-Anmerkungen, wenn sie für die Funktionen des Modells zu restriktiv sind. - Implementieren Sie eine Fallback-Strategie in Ihrer App, z. B. die Anfrage wiederholen oder einen Standardstatus anzeigen.
Tokens zählen
Wenn Sie prüfen möchten, ob Ihr strukturierter Prompt innerhalb des Limits für Eingabe-Tokens liegt, berechnen Sie die Tokenanzahl mit der Methode countTokens().
Da bei Anfragen für strukturierte Ausgaben das Modell über die Schemastruktur informiert werden muss, ist das Zählen von Tokens nur für den Rohtext des Prompts (mit einer GenerateContentRequest-Instanz) nicht genau. Wenn Sie eine genaue Tokenanzahl erhalten möchten, müssen Sie die vollständige GenerateTypedContentRequest-Instanz, die Ihre Zielklasse und Schemakonfigurationen enthält, an die countTokens()-Methode übergeben:
suspend fun <T : Any> countTokens(request: GenerateTypedContentRequest<T>): CountTokensResponse