Genera resultados estructurados para experiencias híbridas en apps para Android


De forma predeterminada, los modelos de Gemini devuelven respuestas como texto no estructurado. Sin embargo, algunos casos de uso requieren texto estructurado (como JSON o enumeraciones). Por ejemplo, es posible que uses la respuesta para otras tareas posteriores que requieran un esquema de datos establecido.

Para garantizar que el resultado generado por el modelo siempre cumpla con un esquema específico, puedes definir un esquema, que funciona como un modelo para las respuestas del modelo. Luego, puedes extraer datos directamente del resultado del modelo con menos procesamiento posterior.

Estos son algunos ejemplos de casos de uso:

  • Garantizar que la respuesta de un modelo genere un JSON válido y cumpla con el esquema que proporcionaste
    Por ejemplo, el modelo puede generar entradas estructuradas para recetas que siempre incluyen el nombre de la receta, la lista de ingredientes y los pasos. Luego, puedes analizar y mostrar esta información con mayor facilidad en la IU de tu app.

  • Restringe la forma en que un modelo puede responder durante las tareas de clasificación.
    Por ejemplo, puedes hacer que el modelo anote texto con un conjunto específico de etiquetas (por ejemplo, un conjunto específico de enumeraciones como positive y negative), en lugar de etiquetas que produce el modelo (que podrían tener un grado de variabilidad como good, positive, negative o bad).

En esta página, se describe cómo generar resultados estructurados (como JSON y enumeraciones) en tus experiencias híbridas para apps para Android.

Ir a la salida de JSON Ir a la salida de enumeración

Configuración de los resultados estructurados

La generación de resultados estructurados (como JSON y enumeraciones) se admite tanto para la inferencia integrado en el dispositivo como para la inferencia alojada en la nube.

Para generar una salida estructurada, pasa tu esquema directamente a generateObject(). Los requisitos del esquema dependen del modo de inferencia configurado:

  • Para la inferencia integrada en el dispositivo e híbrida (ONLY_ON_DEVICE, PREFER_ON_DEVICE y PREFER_IN_CLOUD):

    • Requiere el uso de la anotación @Generable en un data class de Kotlin con el procesador de KSP. No se admiten esquemas manuales ni anotaciones enum class directas.
    • Cuando la inferencia se ejecuta integrado en el dispositivo, el SDK traduce automáticamente el esquema en restricciones para el modelo integrado en el dispositivo (con la API de ML Kit Prompt).
    • Si una solicitud híbrida recurre a la inferencia en la nube, el SDK establece automáticamente responseMimeType en application/json y pasa el esquema al modelo Gemini alojado en la nube.
  • Para la inferencia solo en la nube (ONLY_IN_CLOUD):

    • Admite anotaciones @Generable (recomendado) y esquemas manuales (creados con métodos de ayuda JsonSchema).
    • El SDK establece automáticamente responseMimeType en application/json y pasa el esquema al modelo Gemini alojado en la nube.

Antes de comenzar

Haz clic en tu proveedor de Gemini API para ver el contenido y el código específicos del proveedor en esta página.

Antes de generar el resultado estructurado, asegúrate de haber completado la siguiente configuración:

  1. Completa la guía de introducción para crear experiencias híbridas, en la que se explica cómo configurar tu proyecto de Firebase, descargar el modelo integrado en el dispositivo y configurar App Check.

  2. Configura el complemento Kotlin Symbol Processing (KSP) y agrega la dependencia Firebase AI KSP a tu app.

    En el archivo Gradle del módulo (nivel de la app) (como <project>/<app-module>/build.gradle.kts), agrega el complemento de KSP, el complemento de serialización de Kotlin y las dependencias requeridas:

    plugins {
       // ... other plugins
       id("com.google.gms.google-services")
       id("com.google.devtools.ksp") version "LATEST_VERSION"
       id("org.jetbrains.kotlin.plugin.serialization") version "LATEST_VERSION"
    }
    
    dependencies {
       // ... other androidx dependencies
    
       // Add the dependencies for the Firebase AI Logic and App Check libraries.
       implementation("com.google.firebase:firebase-ai:17.17.0")
       implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta05")
       implementation("com.google.firebase:firebase-appcheck-debug:19.4.1")
    
       // Add the Firebase AI KSP processor for schema generation.
       ksp("com.google.firebase:firebase-ai-ksp-processor:16.0.2")
    
       // (Optional) Add kotlinx.serialization JSON library for object decoding.
       implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:LATEST_VERSION")
    }


Ir a la salida de JSON Ir a la salida de enumeración

Salida de JSON

En los siguientes ejemplos, se adapta el ejemplo general de salida en formato JSON para admitir la inferencia híbrida (por ejemplo, PREFER_ON_DEVICE).

En la situación de estos ejemplos, el modelo genera una lista de perfiles de personajes para un cuento de fantasía, con atributos estructurados como nombre, edad, especie y accesorios opcionales.

Puedes definir tus esquemas de respuesta con cualquiera de los siguientes enfoques:

  • Anotaciones de KSP (@Generable y @Guide)

    • Se admite en todos los modos de inferencia y es obligatorio para la inferencia híbrida e integrado en el dispositivo (específicamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE y PREFER_IN_CLOUD).
    • Define clases de datos de Kotlin para generar automáticamente esquemas en el tiempo de compilación y deserializar respuestas directamente en objetos con escritura segura con getObject().
  • Métodos auxiliares de JsonSchema manuales

    • Solo se admite para la inferencia basada en la nube (específicamente, ONLY_IN_CLOUD).
    • Construye manualmente un JsonSchema en el código sin usar el procesador de KSP y lee la cadena JSON sin procesar de response.response.text.

Ejemplo 1: Uso de anotaciones @Generable y @Guide con KSP

Define un data class de Kotlin anotado con @Serializable y @Generable. Usa anotaciones @Guide en las propiedades para proporcionar al modelo descripciones, límites de valores o restricciones de elementos.

Este enfoque se admite para todos los modos de inferencia y es obligatorio para las experiencias integradas en el dispositivo e híbridas (específicamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE y PREFER_IN_CLOUD).

Antes de probar este ejemplo, completa la sección Antes de comenzar de esta guía para configurar tu proyecto y tu app.
En esa sección, también harás clic en un botón para el proveedor de Gemini API que elijas, de modo que veas contenido específico del proveedor en esta página.

En Kotlin, los métodos de este SDK son funciones de suspensión y deben llamarse desde un alcance de corrutina.
import com.google.firebase.Firebase
import com.google.firebase.ai.type.GenerativeBackend
import com.google.firebase.ai.InferenceMode
import com.google.firebase.ai.OnDeviceConfig
import com.google.firebase.ai.annotations.Generable
import com.google.firebase.ai.annotations.Guide
import com.google.firebase.ai.ai
import kotlinx.serialization.Serializable

// Define data classes representing the schema, annotated with @Serializable and @Generable.
// You can provide descriptions on @Generable and @Guide to guide the model's output.
@Serializable
@Generable(description = "A character profile for a fantasy story")
data class Character(
    val name: String,
    val age: Int,
    val species: String,
    // Use @Guide to add property descriptions, value bounds (minimum/maximum), or formats.
    // Properties with default values or nullable types are treated as optional in the schema.
    @Guide(description = "An accessory the character wears or carries")
    val accessory: String? = null
) {
    // An empty companion object is required for KSP to generate the firebaseAISchema() extension.
    companion object
}

@Serializable
@Generable(description = "A list of character profiles")
data class CharacterList(
    // Use minItems or maxItems to specify collection size bounds for the model.
    @Guide(description = "List of characters", minItems = 1)
    val characters: List<Character>
) {
    // An empty companion object is required for KSP to generate the firebaseAISchema() extension.
    companion object
}

// Initialize the Gemini Developer API backend service.
// Create a GenerativeModel instance configured for hybrid inference (like PREFER_ON_DEVICE).
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "CLOUD_MODEL_NAME",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.INFERENCE_MODE)
    )

// Obtain the schema generated by KSP via the firebaseAISchema() extension.
val schema = CharacterList.firebaseAISchema()
val prompt = "Create profiles for some characters for a fantasy story."

// Generate the structured object (the SDK applies the schema to on-device or cloud models).
val response = model.generateObject(schema, prompt)

// Access the strongly-typed deserialized object directly via getObject().
val characterList: CharacterList? = response.getObject()
characterList?.characters?.forEach { character ->
    println("Name: ${character.name}, Species: ${character.species}, Age: ${character.age}")
    println("Accessory: ${character.accessory ?: "None"}")
}

Ejemplo 2: Uso de métodos auxiliares JsonSchema manuales

Si tu app solo usa la inferencia basada en la nube (específicamente, ONLY_IN_CLOUD), puedes compilar manualmente un JsonSchema con los métodos auxiliares que proporciona el SDK de Firebase AI Logic.

Antes de probar este ejemplo, completa la sección Antes de comenzar de esta guía para configurar tu proyecto y tu app.
En esa sección, también harás clic en un botón para el proveedor de Gemini API que elijas, de modo que veas contenido específico del proveedor en esta página.

En Kotlin, los métodos de este SDK son funciones de suspensión y deben llamarse desde un alcance de corrutina.
import com.google.firebase.Firebase
import com.google.firebase.ai.type.GenerativeBackend
import com.google.firebase.ai.InferenceMode
import com.google.firebase.ai.OnDeviceConfig
import com.google.firebase.ai.ai
import com.google.firebase.ai.type.JsonSchema

// Define the schema manually using JsonSchema helper methods.
// Properties are required by default unless specified in optionalProperties.
val jsonSchema = JsonSchema.obj(
    properties = mapOf(
        "characters" to JsonSchema.array(
            items = JsonSchema.obj(
                properties = mapOf(
                    "name" to JsonSchema.string(),
                    "accessory" to JsonSchema.string(),
                    "age" to JsonSchema.integer(),
                    "species" to JsonSchema.string()
                ),
                optionalProperties = listOf("accessory")
            )
        )
    )
)

// Initialize the Gemini Developer API backend service.
// Manual schemas are only supported for cloud-based inference (specifically, ONLY_IN_CLOUD).
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "CLOUD_MODEL_NAME",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.ONLY_IN_CLOUD)
    )

// Call generateObject() with the manual schema and prompt.
val response = model.generateObject(
    jsonSchema,
    "Create profiles for some characters for a fantasy story."
)

// Access the generated JSON string conforming to the schema from response.response.text.
println(response.response.text)

Salida de enumeración

En los siguientes ejemplos, se adapta el ejemplo general de resultado de enum para admitir la inferencia híbrida (por ejemplo, PREFER_ON_DEVICE).

En la situación de estos ejemplos, el modelo clasifica la descripción de una película seleccionando un solo género de una lista predefinida de opciones permitidas (drama, comedy o documentary).

Puedes definir tus esquemas de respuesta con cualquiera de los siguientes enfoques:

  • Anotaciones de KSP (@Generable)

    • Se admite en todos los modos de inferencia y es obligatorio para la inferencia híbrida e integrado en el dispositivo (específicamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE y PREFER_IN_CLOUD).
    • Define un enum encapsulado en un data class de Kotlin para generar automáticamente el esquema y deserializar las respuestas directamente en objetos con escritura segura usando getObject().
  • Métodos auxiliares de JsonSchema manuales

    • Solo se admite para la inferencia basada en la nube (específicamente, ONLY_IN_CLOUD).
    • Compila manualmente un enum JsonSchema con JsonSchema.enumeration() sin usar el procesador de KSP y lee la cadena seleccionada de response.response.text.

Ejemplo 1: Cómo usar anotaciones @Generable con KSP

Define un enum class que represente los valores permitidos y envuélvelo como una propiedad dentro de un data class de Kotlin anotado con @Serializable y @Generable.

Este enfoque se admite para todos los modos de inferencia y es obligatorio para las experiencias integradas en el dispositivo e híbridas (específicamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE y PREFER_IN_CLOUD).

Antes de probar esta muestra, completa la sección Antes de comenzar de esta guía para configurar tu proyecto y tu app.
En esa sección, también harás clic en un botón para el proveedor de Gemini API que elijas, de modo que veas contenido específico del proveedor en esta página.

En Kotlin, los métodos de este SDK son funciones de suspensión y deben llamarse desde un alcance de corrutina.
import com.google.firebase.Firebase
import com.google.firebase.ai.type.GenerativeBackend
import com.google.firebase.ai.InferenceMode
import com.google.firebase.ai.OnDeviceConfig
import com.google.firebase.ai.annotations.Generable
import com.google.firebase.ai.annotations.Guide
import com.google.firebase.ai.ai
import kotlinx.serialization.Serializable

// Define an enum class representing the allowed options.
@Serializable
enum class FilmGenre {
    DRAMA,
    COMEDY,
    DOCUMENTARY
}

// Wrap the enum in a data class annotated with @Serializable and @Generable.
// On-device inference requires an @Generable data class.
// Direct enum annotations are not supported on-device.
@Serializable
@Generable(description = "The classification result for the film")
data class FilmClassification(
    @Guide(description = "The genre of the film")
    val genre: FilmGenre
) {
    // An empty companion object is required for KSP to generate the firebaseAISchema() extension.
    companion object
}

// Initialize the Gemini Developer API backend service.
// Create a GenerativeModel instance configured for hybrid inference (like PREFER_ON_DEVICE).
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "CLOUD_MODEL_NAME",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.INFERENCE_MODE)
    )

// Obtain the schema generated by KSP via the firebaseAISchema() extension.
val schema = FilmClassification.firebaseAISchema()
val prompt = """
    The film aims to educate and inform viewers about real-life subjects, events, or people.
    It offers a factual record of a particular topic by combining interviews, historical footage,
    and narration. The primary purpose of a film is to present information and provide insights
    into various aspects of reality.
    """

// Generate the structured object (the SDK applies the schema to on-device or cloud models).
val response = model.generateObject(schema, prompt)

// Access the strongly-typed deserialized object and enum value directly via getObject().
val classification: FilmClassification? = response.getObject()
val genre: FilmGenre? = classification?.genre
println("Selected genre: $genre")

Ejemplo 2: Uso de métodos auxiliares JsonSchema manuales

Si tu app solo usa la inferencia basada en la nube (específicamente, ONLY_IN_CLOUD), puedes compilar manualmente un enum JsonSchema con los métodos auxiliares que proporciona el SDK de Firebase AI Logic.

Antes de probar esta muestra, completa la sección Antes de comenzar de esta guía para configurar tu proyecto y tu app.
En esa sección, también harás clic en un botón para el proveedor de Gemini API que elijas, de modo que veas contenido específico del proveedor en esta página.

En Kotlin, los métodos de este SDK son funciones de suspensión y deben llamarse desde un alcance de corrutina.
import com.google.firebase.Firebase
import com.google.firebase.ai.type.GenerativeBackend
import com.google.firebase.ai.InferenceMode
import com.google.firebase.ai.OnDeviceConfig
import com.google.firebase.ai.ai
import com.google.firebase.ai.type.JsonSchema

// Define an enum schema with allowed string values and a description.
val enumSchema = JsonSchema.enumeration(
    values = listOf("drama", "comedy", "documentary"),
    description = "The genre of the film"
)

// Initialize the Gemini Developer API backend service.
// Manual schemas are only supported for cloud-based inference (specifically, ONLY_IN_CLOUD).
val model = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "CLOUD_MODEL_NAME",
        onDeviceConfig = OnDeviceConfig(mode = InferenceMode.ONLY_IN_CLOUD)
    )

val prompt = """
    The film aims to educate and inform viewers about real-life subjects, events, or people.
    It offers a factual record of a particular topic by combining interviews, historical footage,
    and narration. The primary purpose of a film is to present information and provide insights
    into various aspects of reality.
    """

// Call generateObject() with the enum schema and prompt.
val response = model.generateObject(enumSchema, prompt)

// Access the selected enum value string from response.response.text.
println(response.response.text)


Envía comentarios sobre tu experiencia con Firebase AI Logic