Gerar saída estruturada para experiências híbridas em apps Android


Por padrão, os modelos Gemini retornam respostas como texto não estruturado. No entanto, alguns casos de uso exigem texto estruturado, como JSON ou enums. Por exemplo, você pode estar usando a resposta para outras tarefas downstream que exigem um esquema de dados estabelecido.

Para garantir que a saída gerada do modelo sempre siga um esquema específico, defina um esquema, que funciona como um modelo para as respostas. Assim, é possível extrair dados diretamente da saída do modelo com menos pós-processamento.

Veja alguns exemplos de casos de uso:

  • Garantir que a resposta de um modelo gere um JSON válido e esteja em conformidade com o esquema fornecido.
    Por exemplo, o modelo pode gerar entradas estruturadas para receitas que sempre incluem o nome da receita, a lista de ingredientes e as etapas. Assim, é mais fácil analisar e mostrar essas informações na interface do app.

  • Restringir a forma como um modelo pode responder durante tarefas de classificação.
    Por exemplo, você pode fazer com que o modelo anote o texto com um conjunto específico de rótulos (por exemplo, um conjunto específico de enums como positive e negative), em vez de rótulos que o modelo produz (que podem ter um grau de variabilidade como good, positive, negative ou bad).

Esta página descreve como gerar saída estruturada (como JSON e enums) nas suas experiências híbridas para apps Android.

Ir para a saída JSON Ir para a saída de enumeração

Configuração para saída estruturada

A geração de saída estruturada (como JSON e enums) é compatível com a inferência no dispositivo e hospedada na nuvem.

Para gerar uma saída estruturada, transmita seu esquema diretamente para generateObject(). Os requisitos de esquema dependem do modo de inferência configurado:

  • Para inferência híbrida e no dispositivo (ONLY_ON_DEVICE, PREFER_ON_DEVICE e PREFER_IN_CLOUD):

    • Exige o uso da anotação @Generable em um data class do Kotlin com o processador KSP. Schemas manuais e anotações enum class diretas não são compatíveis.
    • Quando a inferência é executada no dispositivo, o SDK traduz automaticamente o esquema em restrições para o modelo no dispositivo (usando a API Prompt do Kit de ML).
    • Se uma solicitação híbrida voltar para a inferência na nuvem, o SDK vai definir automaticamente o responseMimeType como application/json e transmitir o esquema para o modelo Gemini hospedado na nuvem.
  • Para inferência somente na nuvem (ONLY_IN_CLOUD):

    • Aceita anotações @Generable (recomendado) e esquemas manuais (criados usando métodos auxiliares JsonSchema).
    • O SDK define automaticamente o responseMimeType como application/json e transmite o esquema para o modelo Gemini hospedado na nuvem.

Antes de começar

Clique no seu provedor de Gemini API para conferir o conteúdo e o código específicos do provedor nesta página.

Antes de gerar uma saída estruturada, verifique se você concluiu a configuração a seguir:

  1. Conclua o guia de início rápido para criar experiências híbridas, que aborda a configuração do projeto do Firebase, o download do modelo no dispositivo e a configuração do App Check.

  2. Configure o plug-in Kotlin Symbol Processing (KSP) e adicione a dependência Firebase AI KSP ao app.

    No arquivo Gradle do módulo (nível do app) (como <project>/<app-module>/build.gradle.kts), adicione o plug-in KSP, o plug-in Kotlin Serialization e as dependências necessárias:

    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 para a saída JSON Ir para a saída de enumeração

Saída JSON

Os exemplos a seguir adaptam o exemplo de saída JSON geral para acomodar a inferência híbrida (por exemplo, PREFER_ON_DEVICE).

No cenário desses exemplos, o modelo gera uma lista de perfis de personagens para uma história de fantasia, com atributos estruturados como nome, idade, espécie e acessórios opcionais.

É possível definir seus esquemas de resposta usando uma das seguintes abordagens:

  • Anotações do KSP (@Generable e @Guide)

    • Compatível com todos os modos de inferência e obrigatório para inferência híbrida e no dispositivo (especificamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE e PREFER_IN_CLOUD).
    • Defina classes de dados Kotlin para gerar automaticamente esquemas no tempo de compilação e desserializar respostas diretamente em objetos fortemente tipados usando getObject().
  • Métodos auxiliares manuais do JsonSchema

    • Compatível apenas com inferência baseada na nuvem (especificamente, ONLY_IN_CLOUD).
    • Construa manualmente um JsonSchema no código sem usar o processador KSP e leia a string JSON bruta de response.response.text.

Exemplo 1: usar anotações @Generable e @Guide com KSP

Defina uma data class do Kotlin com anotações @Serializable e @Generable. Use anotações @Guide em propriedades para fornecer ao modelo descrições, limites de valor ou restrições de itens.

Essa abordagem é compatível com todos os modos de inferência e é obrigatória para experiências híbridas e no dispositivo (especificamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE e PREFER_IN_CLOUD).

Antes de testar esta amostra, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, clique também em um botão para o provedor de Gemini API escolhido para ver o conteúdo específico do provedor nesta página.

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de um escopo de corrotina.
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"}")
}

Exemplo 2: usar métodos auxiliares manuais de JsonSchema

Se o app estiver usando apenas a inferência baseada na nuvem (especificamente, ONLY_IN_CLOUD), crie manualmente um JsonSchema usando métodos auxiliares fornecidos pelo SDK do Firebase AI Logic.

Antes de testar esta amostra, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, clique também em um botão para o provedor de Gemini API escolhido para ver o conteúdo específico do provedor nesta página.

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de um escopo de corrotina.
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)

Saída de enumeração

Os exemplos a seguir adaptam o exemplo de saída de enumeração geral para acomodar a inferência híbrida (por exemplo, PREFER_ON_DEVICE).

No cenário desses exemplos, o modelo classifica uma descrição de filme selecionando um único gênero de uma lista predefinida de opções permitidas (drama, comedy ou documentary).

É possível definir seus esquemas de resposta usando uma das seguintes abordagens:

  • Anotações do KSP (@Generable)

    • Compatível com todos os modos de inferência e obrigatório para inferência híbrida e no dispositivo (especificamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE e PREFER_IN_CLOUD).
    • Defina uma enumeração encapsulada em um data class do Kotlin para gerar automaticamente o esquema e desserializar respostas diretamente em objetos fortemente tipados usando getObject().
  • Métodos auxiliares manuais do JsonSchema

    • Compatível apenas com inferência baseada na nuvem (especificamente, ONLY_IN_CLOUD).
    • Crie manualmente uma enumeração JsonSchema usando JsonSchema.enumeration() sem usar o processador KSP e leia a string selecionada de response.response.text.

Exemplo 1: usar anotações @Generable com KSP

Defina um enum class que represente os valores permitidos e encapsule-o como uma propriedade em um data class do Kotlin com anotações @Serializable e @Generable.

Essa abordagem é compatível com todos os modos de inferência e é obrigatória para experiências híbridas e no dispositivo (especificamente, ONLY_ON_DEVICE, PREFER_ON_DEVICE e PREFER_IN_CLOUD).

Antes de testar esta amostra, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, clique também em um botão para o provedor de Gemini API escolhido para ver o conteúdo específico do provedor nesta página.

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de um escopo de corrotina.
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")

Exemplo 2: usar métodos auxiliares manuais de JsonSchema

Se o app estiver usando apenas a inferência baseada na nuvem (especificamente, ONLY_IN_CLOUD), crie manualmente uma enumeração JsonSchema usando métodos auxiliares fornecidos pelo SDK do Firebase AI Logic.

Antes de testar esta amostra, conclua a seção Antes de começar deste guia para configurar seu projeto e app.
Nessa seção, clique também em um botão para o provedor de Gemini API escolhido para ver o conteúdo específico do provedor nesta página.

Para Kotlin, os métodos neste SDK são funções de suspensão e precisam ser chamados de um escopo de corrotina.
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)


Envie feedback sobre sua experiência com Firebase AI Logic