Jika Anda perlu mengurai respons dari Gemini Nano ke dalam format tertentu, seperti JSON, untuk pemrosesan lebih lanjut, gunakan Structured Output API dengan akses model langsung.
Dengan Structured Output API, Anda menentukan struktur output target menggunakan class dan anotasi Kotlin. Akses model langsung kemudian menampilkan respons dalam bentuk objek Kotlin Anda.
Membuat output terstruktur sangat berguna untuk tugas-tugas seperti berikut:
- Ekstraksi entity: Mengekstrak kolom terstruktur (misalnya, nama, tanggal, lokasi acara) dari teks tidak terstruktur.
- Klasifikasi: Mengategorikan teks input ke dalam kategori yang telah ditentukan.
- Serialisasi data: Mengonversi input pengguna yang tidak terstruktur menjadi format yang sesuai untuk penyimpanan database atau panggilan API.
Prasyarat
Untuk memverifikasi bahwa Structured Output API tersedia di perangkat, gunakan
API isStructuredOutputFeatureAvailable(). API akan 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 yang dianotasi. Tambahkan class yang dianotasi ke aturan keep untuk mengecualikannya dari ProGuard jika Anda mendapatkan error saat mengurai, 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 dependensi
com.google.mlkit:genai-promptdi filebuild.gradle.kts(ataubuild.gradle) level aplikasi, jika Anda belum melakukannya.Tambahkan plugin KSP ke file
build.gradle.ktslevel project. Gunakan versi plugin KSP 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.ktslevel aplikasi:dependencies { ... ksp("com.google.mlkit:genai-schema-compiler:1.0.0-alpha1") }
Menentukan struktur output
Tentukan struktur data yang Anda inginkan untuk ditampilkan oleh model menggunakan class data Kotlin. Ada dua anotasi utama untuk menentukan struktur output:
- Gunakan anotasi
@Generableuntuk menentukan class sebagai target untuk 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 yang dianotasi @Generable,
bersama dengan 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 |
Membuat konten terstruktur
Untuk meminta output terstruktur, gunakan fungsi bantuan generateTypedContentRequest
untuk menggabungkan perintah standar 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
)
// 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 penghentian 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 diurai bernilai null.
Nilai finishReason
Properti finishReason dapat menggunakan salah satu nilai berikut:
TypedFinishReason.STOP: Model berhasil menyelesaikan pembuatan dan output-nya cocok dengan skema.TypedFinishReason.MAX_TOKENS: Model berhenti karena telah mencapai batas token. Output mungkin tidak lengkap.TypedFinishReason.PARSE_CLASS_ERROR: Model menyelesaikan pembuatan, tetapi JSON yang dihasilkan tidak dapat diurai 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 dihentikan karena alasan lain.
Pengecualian
Structured Output API mungkin menampilkan GenAiException dengan kode error berikut:
GenAiException.STRUCTURED_OUTPUT_INVALID_CLASS(-104): Struktur class yang dianotasi tidak valid atau berisi jenis yang tidak didukung. Hal ini biasanya merupakan error konfigurasi waktu pengembangan. Tinjau definisi class data@GenerableAnda untuk memeriksa apakah semua jenis properti didukung dan tidak ada dependensi sirkular.GenAiException.STRUCTURED_OUTPUT_INVALID_VALUE(-105): Nilai yang dihasilkan oleh model tidak valid atau gagal dalam verifikasi batasan. Ini adalah error runtime. Jika Anda sering mengalami error ini, pertimbangkan solusi berikut:- Menyempurnakan petunjuk perintah untuk memandu model dengan lebih ketat.
- Melonggarkan batasan (seperti batas minimum, maksimum, atau ukuran daftar) dalam
anotasi
@GuideAnda jika terlalu membatasi kemampuan model. - Menerapkan strategi penggantian di aplikasi Anda, seperti mencoba ulang permintaan atau menampilkan status default.
Menghitung token
Untuk memeriksa apakah perintah terstruktur Anda berada dalam batas token input, hitung
jumlah token menggunakan metode countTokens().
Karena permintaan output terstruktur perlu menginstruksikan model tentang struktur
skema, penghitungan token hanya pada teks perintah mentah (menggunakan
instance GenerateContentRequest) tidak akan akurat. Untuk mendapatkan jumlah token yang akurat, Anda harus meneruskan instance GenerateTypedContentRequest lengkap, yang mencakup konfigurasi class dan skema target, ke metode countTokens():
suspend fun <T : Any> countTokens(request: GenerateTypedContentRequest<T>): CountTokensResponse