在 Android 应用中为混合体验生成结构化输出


Gemini 模型默认以非结构化文本的形式返回回答。 不过,某些使用情形需要结构化文本(例如 JSON 或枚举)。例如,您可能正在将响应用于需要已建立数据架构的其他下游任务。

为确保模型生成的输出始终遵循特定架构,您可以定义架构,该架构类似于模型响应的蓝图。这样一来,您就可以直接从模型的输出中提取数据,而无需进行太多后期处理。

以下是一些示例用例:

  • 确保模型的回答生成有效的 JSON 并符合您提供的架构。
    例如,该模型可以为食谱生成结构化条目,这些条目始终包含食谱名称、配料列表和步骤。这样一来,您就可以更轻松地在应用的界面中解析和显示此信息。

  • 限制模型在分类任务期间的回答方式。
    例如,您可以让模型使用一组特定的标签(例如一组特定的枚举,如 positivenegative)来注释文本,而不是使用模型生成的标签(这些标签可能具有一定程度的可变性,如 goodpositivenegativebad)。

本页介绍了如何在 Android 应用的混合体验中生成结构化输出(例如 JSON 和枚举)。

跳转到 JSON 输出 跳转到枚举输出

结构化输出的配置

无论是设备端推理还是云端托管推理,都支持生成结构化输出(例如 JSON 和枚举)。

如需生成结构化输出,请将架构直接传递给 generateObject()。架构要求取决于您配置的推理模式:

  • 对于设备端和混合推理(ONLY_ON_DEVICEPREFER_ON_DEVICEPREFER_IN_CLOUD

    • 需要使用 KSP 处理器在 Kotlin data class 上使用 @Generable 注解;不支持手动架构和直接 enum class 注解。
    • 当推理在设备上运行时,SDK 会使用机器学习套件 Prompt API 自动将架构转换为设备端模型的限制条件。
    • 如果混合请求回退到云端推理,SDK 会自动将 responseMimeType 设置为 application/json,并将架构传递给云端托管的 Gemini 模型。
  • 对于仅限云端的推理 (ONLY_IN_CLOUD)

    • 支持 @Generable 注释(推荐)和手动架构(使用 JsonSchema 辅助方法构建)。
    • SDK 会自动将 responseMimeType 设置为 application/json,并将架构传递给云端托管的 Gemini 模型。

准备工作

点击您的 Gemini API 提供商,以查看此页面上特定于提供商的内容和代码。

在生成结构化输出之前,请确保您已完成以下设置:

  1. 完成打造混合体验的入门指南,其中介绍了如何设置 Firebase 项目、下载设备端模型和配置 App Check

  2. 配置 Kotlin Symbol Processing (KSP) 插件,并将 Firebase AI KSP 依赖项添加到您的应用中。

    在您的模块(应用级)Gradle 文件(例如 <project>/<app-module>/build.gradle.kts)中,添加 KSP 插件、Kotlin 序列化插件和必需的依赖项:

    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")
    }


跳转到 JSON 输出 跳转到枚举输出

JSON 输出

以下示例调整了常规 JSON 输出示例,以适应混合推理(例如 PREFER_ON_DEVICE)。

在这些示例的场景中,模型会生成一个奇幻故事的角色资料列表,其中包含名称、年龄、种族和可选配件等结构化属性。

您可以使用以下任一方法定义回答架构

  • KSP 注释(@Generable@Guide

    • 支持所有推理模式,并且是设备端推理和混合推理(具体而言,是 ONLY_ON_DEVICEPREFER_ON_DEVICEPREFER_IN_CLOUD)的必需项。
    • 定义 Kotlin 数据类,以便在编译时自动生成架构,并使用 getObject() 将响应直接反序列化为强类型对象。
  • 手动 JsonSchema 辅助方法

    • 支持基于云端的推理(具体而言,是 ONLY_IN_CLOUD)。
    • 在代码中手动构建 JsonSchema,而不使用 KSP 处理器,并从 response.response.text 读取原始 JSON 字符串。

示例 1:将 @Generable@Guide 注释与 KSP 搭配使用

定义一个带有 @Serializable@Generable 注释的 Kotlin data class。 在属性上使用 @Guide 注释可为模型提供说明、值界限或商品限制。

此方法适用于所有推理模式,并且是设备端和混合体验(具体而言,是 ONLY_ON_DEVICEPREFER_ON_DEVICEPREFER_IN_CLOUD)的必需方法。

在试用此示例之前,请完成本指南的准备工作部分,以设置您的项目和应用。
在该部分中,您还需要点击所选Gemini API提供商对应的按钮,以便在此页面上看到特定于提供商的内容

对于 Kotlin,此 SDK 中的方法是挂起函数,需要从协程范围调用。
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"}")
}

示例 2:使用手动 JsonSchema 辅助方法

如果您的应用使用基于云的推理(具体来说是 ONLY_IN_CLOUD),那么您可以使用 Firebase AI Logic SDK 提供的辅助方法手动构建 JsonSchema

在试用此示例之前,请完成本指南的准备工作部分,以设置您的项目和应用。
在该部分中,您还需要点击所选Gemini API提供商对应的按钮,以便在此页面上看到特定于提供商的内容

对于 Kotlin,此 SDK 中的方法是挂起函数,需要从协程范围调用。
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)

枚举输出

以下示例调整了常规枚举输出示例,以适应混合推理(例如 PREFER_ON_DEVICE)。

在这些示例的场景中,模型通过从预定义的允许选项列表(dramacomedydocumentary)中选择单个类型来对电影说明进行分类。

您可以使用以下任一方法定义回答架构

  • KSP 注释 (@Generable)

    • 支持所有推理模式,并且是设备端推理和混合推理(具体而言,是 ONLY_ON_DEVICEPREFER_ON_DEVICEPREFER_IN_CLOUD)的必需项。
    • 定义一个封装在 Kotlin data class 中的枚举,以自动生成架构并使用 getObject() 将响应直接反序列化为强类型对象。
  • 手动 JsonSchema 辅助方法

    • 支持基于云端的推理(具体而言,是 ONLY_IN_CLOUD)。
    • 使用 JsonSchema.enumeration() 手动构建枚举 JsonSchema(不使用 KSP 处理器),并从 response.response.text 中读取所选字符串。

示例 1:将 @Generable 注释与 KSP 搭配使用

定义一个表示允许值的 enum class,并将其作为属性封装在带有 @Serializable@Generable 注解的 Kotlin data class 中。

此方法适用于所有推理模式,并且是设备端和混合体验(具体而言,是 ONLY_ON_DEVICEPREFER_ON_DEVICEPREFER_IN_CLOUD)的必需方法。

在试用此示例之前,请完成本指南的准备工作部分,以设置您的项目和应用。
在该部分中,您还需要点击所选Gemini API提供商对应的按钮,以便在此页面上看到特定于提供商的内容

对于 Kotlin,此 SDK 中的方法是挂起函数,需要从协程范围调用。
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")

示例 2:使用手动 JsonSchema 辅助方法

如果您的应用使用基于云的推理(具体而言,是 ONLY_IN_CLOUD),则可以使用 Firebase AI Logic SDK 提供的辅助方法手动构建枚举 JsonSchema

在试用此示例之前,请完成本指南的准备工作部分,以设置您的项目和应用。
在该部分中,您还需要点击所选Gemini API提供商对应的按钮,以便在此页面上看到特定于提供商的内容

对于 Kotlin,此 SDK 中的方法是挂起函数,需要从协程范围调用。
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)


就您使用 Firebase AI Logic 的体验提供反馈