Jika Anda perlu mengurai respons dari Prompt API ke dalam format tertentu, seperti JSON, untuk diproses lebih lanjut, gunakan Structured Output API.
Dengan Structured Output API, Anda menentukan struktur output target menggunakan class dan anotasi Kotlin. Prompt API kemudian menampilkan respons dalam bentuk objek Kotlin Anda.
Membuat output terstruktur sangat berguna untuk tugas seperti berikut:
- Ekstraksi entity: Mengekstrak kolom terstruktur (misalnya, nama acara, tanggal, lokasi) dari teks tidak terstruktur.
- Klasifikasi: Mengategorikan teks input ke dalam kategori yang telah ditentukan.
- Serialisasi data: Mengonversi input pengguna yang tidak terstruktur ke dalam format yang sesuai untuk penyimpanan database atau panggilan API.
Prasyarat
Untuk memverifikasi bahwa Structured Output API tersedia di perangkat, gunakan isStructuredOutputFeatureAvailable() API. API menampilkan true jika Structured Output API tersedia di perangkat, dan false jika tidak.
suspend fun isStructuredOutputFeatureAvailable(): Boolean
Structured Output API juga memiliki persyaratan berikut:
- Android API level 26 atau yang lebih tinggi (
minSdk26) - Plugin KSP versi 2.3.6 atau yang lebih tinggi
Batasan
Structured Output API memiliki batasan berikut:
- Hanya berfungsi di Kotlin.
- ProGuard mungkin mengganggu penguraian class beranotasi Anda. Tambahkan class beranotasi ke aturan keep untuk mengecualikannya dari ProGuard jika Anda mengalami error penguraian, misalnya:
# Keep classes used by structured output for deserialization for release builds.
-keep class com.google.mlkit.genai.demo.kotlin.Plant { *; }
Konfigurasikan project
Untuk mulai menggunakan Structured Output API, ikuti langkah-langkah berikut:
Tambahkan ML Kit Prompt API sebagai dependensi di file
build.gradle.kts(ataubuild.gradle) tingkat aplikasi Anda, jika belum.Tambahkan plugin KSP ke file
build.gradle.ktstingkat project Anda. Gunakan plugin KSP versi yang kompatibel dengan versi Kotlin Anda; sebaiknya gunakan KSP versi 2.3.6 atau yang lebih tinggi.dependencies { ... classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.3.6" }Tambahkan dependensi compiler terstruktur ke file
build.gradle.ktstingkat aplikasi Anda:dependencies { ... ksp("com.google.mlkit:genai-schema-compiler:1.0.0-alpha1") }
Tentukan struktur output
Tentukan struktur data yang ingin Anda tampilkan oleh model menggunakan class data Kotlin. Ada dua anotasi utama untuk menentukan struktur output:
- Gunakan anotasi
@Generableuntuk menentukan class sebagai target output terstruktur. - Gunakan anotasi
@Guidepada properti class untuk memberikan deskripsi dan batasan yang memandu output model.
Contoh berikut menentukan struktur untuk mengekstrak informasi tanaman:
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
)
Jenis dan batasan yang didukung
Jenis berikut didukung dalam class beranotasi @Generable, beserta batasan @Guide masing-masing:
| Jenis | Deskripsi | Batasan @Guide yang didukung |
|---|---|---|
String |
Untuk teks. | description, enumValues |
Double / Float |
Untuk angka floating point. | description, minimum, maximum |
Int / Long |
Untuk bilangan bulat. | description, minimum, maximum |
Boolean |
Untuk nilai benar/salah. | description |
List<T> |
Untuk daftar jenis yang didukung atau class @Generable bertingkat.
|
description, minItems, maxItems |
List<String> |
Untuk daftar nilai String. |
description, enumValues, minItems,
maxItems |
Class @Generable |
Untuk objek terstruktur bertingkat. | description |
Buat konten terstruktur
Untuk meminta output terstruktur, gunakan fungsi helper generateTypedContentRequest untuk menggabungkan perintah standar Anda dan menentukan class output target.
// 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,
// Instructs ML Kit to include the generated schema structure in the prompt
// sent to AICore. This should always be set to `true` unless the model
// already knows what output format to use.
includeSchemaInPrompt = true
)
// 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}")
}
}
}
Menangani alasan penyelesaian dan error
Saat menggunakan Structured Output API, Anda harus menangani potensi pengecualian yang ditampilkan oleh API dan memeriksa properti finishReason dalam kandidat respons jika respons yang diuraikan adalah null.
Nilai finishReason
Properti finishReason dapat mengambil salah satu nilai berikut:
TypedFinishReason.STOP: Model berhasil menyelesaikan pembuatan dan output cocok dengan skema.TypedFinishReason.MAX_TOKENS: Model berhenti karena mencapai batas token. Output mungkin tidak lengkap.TypedFinishReason.PARSE_CLASS_ERROR: Model menyelesaikan pembuatan, tetapi JSON yang dihasilkan tidak dapat diuraikan ke dalam class Kotlin target.TypedFinishReason.STRUCTURE_NOT_ANNOTATED: Class target atau class bertingkatnya tidak memiliki anotasi@Generableyang diperlukan.TypedFinishReason.STRUCTURE_VALUES_INVALID: Nilai yang dihasilkan melanggar batasan yang ditentukan dalam anotasi@Guide(misalnya, nilai di luar rentang, ukuran daftar di luar batas).TypedFinishReason.OTHER: Pembuatan berhenti karena alasan lain.
Pengecualian
Structured Output API mungkin menampilkan GenAiException dengan kode error berikut:
GenAiException.STRUCTURED_OUTPUT_INVALID_CLASS(-104): Struktur class beranotasi tidak valid atau berisi jenis yang tidak didukung. Error ini biasanya merupakan error konfigurasi waktu pengembangan. Tinjau definisi class data@GenerableAnda untuk memeriksa apakah semua jenis properti didukung dan tidak ada dependensi melingkar.GenAiException.STRUCTURED_OUTPUT_INVALID_VALUE(-105): Nilai yang dihasilkan oleh model tidak valid atau gagal dalam verifikasi batasan. Error ini adalah error runtime. Jika Anda sering mengalami error ini, pertimbangkan solusi berikut:- Memperbaiki petunjuk perintah Anda untuk memandu model dengan lebih ketat.
- Melonggarkan batasan (seperti batas ukuran minimum, maksimum, atau daftar) dalam anotasi
@Guidejika terlalu ketat untuk kemampuan model. - Menerapkan strategi penggantian di aplikasi Anda, seperti mencoba kembali permintaan atau menampilkan status default.
Menghitung token
Untuk memeriksa apakah perintah terstruktur Anda berada dalam batas token input, hitung
jumlah token menggunakan countTokens() metode.
Karena permintaan output terstruktur perlu menginstruksikan model tentang struktur skema, menghitung token hanya pada teks perintah mentah (menggunakan instance GenerateContentRequest) tidak akurat. Untuk mendapatkan jumlah token yang akurat, Anda harus meneruskan instance GenerateTypedContentRequest lengkap, yang mencakup konfigurasi skema dan class target, ke metode countTokens():
suspend fun <T : Any> countTokens(request: GenerateTypedContentRequest<T>): CountTokensResponse