Generowanie danych strukturalnych na potrzeby funkcji hybrydowych w aplikacjach na Androida


Modele Gemini domyślnie zwracają odpowiedzi w postaci nieuporządkowanego tekstu. Niektóre przypadki użycia wymagają jednak tekstu uporządkowanego (np. JSON lub typów wyliczeniowych). Możesz na przykład używać odpowiedzi do innych zadań podrzędnych, które wymagają ustalonego schematu danych.

Aby mieć pewność, że dane wyjściowe wygenerowane przez model zawsze są zgodne z określonym schematem, możesz zdefiniować schemat, który działa jak plan odpowiedzi modelu. Możesz wtedy bezpośrednio wyodrębnić dane z danych wyjściowych modelu przy mniejszym przetwarzaniu końcowym.

Oto kilka przykładowych przypadków użycia:

  • Upewnij się, że odpowiedź modelu generuje prawidłowy kod JSON i jest zgodna z podanym schematem.
    Model może na przykład generować uporządkowane wpisy dotyczące przepisów, które zawsze zawierają nazwę przepisu, listę składników i kroki. Dzięki temu możesz łatwiej analizować i wyświetlać te informacje w interfejsie aplikacji.

  • Ograniczanie sposobu, w jaki model może odpowiadać podczas zadań klasyfikacji.
    Możesz na przykład poprosić model o dodanie do tekstu adnotacji z określonym zestawem etykiet (np. określonym zestawem typów wyliczeniowych, takich jak positive i negative), a nie etykiet, które model generuje (które mogą mieć pewien stopień zmienności, np. good, positive, negative lub bad).

Na tej stronie opisujemy, jak generować ustrukturyzowane dane wyjściowe (takie jak JSON i typy wyliczeniowe) w hybrydowych środowiskach aplikacji na Androida.

Przejdź do danych wyjściowych JSON Przejdź do danych wyjściowych typu wyliczeniowego

Konfiguracja uporządkowanych danych wyjściowych

Generowanie uporządkowanych danych wyjściowych (takich jak JSON i typy wyliczeniowe) jest obsługiwane zarówno w przypadku wnioskowania na urządzeniu, jak i w chmurze.

Aby wygenerować ustrukturyzowane dane wyjściowe, przekaż schemat bezpośrednio do generateObject(). Wymagania dotyczące schematu zależą od skonfigurowanego trybu wnioskowania:

  • W przypadku wnioskowania na urządzeniu i wnioskowania hybrydowego (ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD):

    • Wymaga użycia adnotacji @Generable w klasie data class w języku Kotlin z procesorem KSP. Schematy ręczne i bezpośrednie adnotacje enum class nie są obsługiwane.
    • Gdy wnioskowanie jest wykonywane na urządzeniu, pakiet SDK automatycznie tłumaczy schemat na ograniczenia dla modelu na urządzeniu (za pomocą interfejsu ML Kit Prompt API).
    • Jeśli żądanie hybrydowe zostanie przekierowane do wnioskowania w chmurze, pakiet SDK automatycznie ustawi responseMimeType na application/json i przekaże schemat do modelu Gemini hostowanego w chmurze.
  • Wnioskowanie tylko w chmurze (ONLY_IN_CLOUD):

    • Obsługuje zarówno adnotacje @Generable (zalecane), jak i schematy ręczne (tworzone za pomocą metod pomocniczych JsonSchema).
    • Pakiet SDK automatycznie ustawia parametr responseMimeType na application/json i przekazuje schemat do modelu Gemini hostowanego w chmurze.

Zanim zaczniesz

Kliknij dostawcę Gemini API, aby wyświetlić na tej stronie treści i kod dotyczące tego dostawcy.

Zanim wygenerujesz ustrukturyzowane dane wyjściowe, upewnij się, że masz skonfigurowane te elementy:

  1. Zapoznaj się z przewodnikiem dla początkujących dotyczącym tworzenia środowisk hybrydowych, który obejmuje konfigurowanie projektu w Firebase, pobieranie modelu na urządzeniu i konfigurowanie App Check.

  2. Skonfiguruj wtyczkę Kotlin Symbol Processing (KSP) i dodaj do aplikacji zależność Firebase AI KSP.

    W pliku Gradle modułu (na poziomie aplikacji) (np. <project>/<app-module>/build.gradle.kts) dodaj wtyczkę KSP, wtyczkę serializacji Kotlin i wymagane zależności:

    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:18.1.0")
       implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta07")
       implementation("com.google.firebase:firebase-appcheck-debug:20.0.0")
    
       // Add the Firebase AI KSP processor for schema generation.
       ksp("com.google.firebase:firebase-ai-ksp-processor:17.0.0")
    
       // (Optional) Add kotlinx.serialization JSON library for object decoding.
       implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:LATEST_VERSION")
    }


Przejdź do danych wyjściowych JSON Przejdź do danych wyjściowych typu wyliczeniowego

Dane wyjściowe JSON

Poniższe przykłady dostosowują ogólny przykład danych wyjściowych JSON do wnioskowania hybrydowego (np. PREFER_ON_DEVICE).

W scenariuszu przedstawionym w tych przykładach model generuje listę profili postaci do opowiadania fantasy z uporządkowanymi atrybutami, takimi jak imię, wiek, gatunek i opcjonalne akcesoria.

Schematy odpowiedzi możesz definiować na 2 sposoby:

  • Adnotacje dotyczące kluczowych cech produktu (@Generable i @Guide)

    • Obsługiwane we wszystkich trybach wnioskowania i wymagane w przypadku wnioskowania na urządzeniu i hybrydowego (konkretnie ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).
    • Zdefiniuj klasy danych Kotlin, aby automatycznie generować schematy w czasie kompilacji i deserializować odpowiedzi bezpośrednio do obiektów o silnym typowaniu za pomocą getObject().
  • Metody pomocnicze do ręcznego ustawiania JsonSchema

    • Obsługiwane tylko w przypadku wnioskowania działającego w chmurze (konkretnie ONLY_IN_CLOUD).
    • Ręcznie utwórz obiekt JsonSchema w kodzie bez użycia procesora KSP i odczytaj nieprzetworzony ciąg znaków JSON z response.response.text.

Przykład 1. Używanie adnotacji @Generable i @Guide z KSP

Zdefiniuj data class w Kotlinie z adnotacjami @Serializable i @Generable. Używaj adnotacji @Guide we właściwościach, aby dostarczać modelowi opisy, zakresy wartości lub ograniczenia elementów.

To podejście jest obsługiwane we wszystkich trybach wnioskowania i jest wymagane w przypadku korzystania z modeli na urządzeniu i hybrydowych (w szczególności ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz tego przewodnika, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk wybranego dostawcy Gemini API, aby wyświetlić na tej stronie treści dotyczące tego dostawcy.

W przypadku Kotlina metody w tym pakiecie SDK są funkcjami zawieszania i muszą być wywoływane z zakresu współprogramu.
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"}")
}

Przykład 2. Korzystanie z ręcznych metod pomocniczych JsonSchema

Jeśli Twoja aplikacja korzysta wyłącznie z wnioskowania działającego w chmurze (konkretnie ONLY_IN_CLOUD), możesz ręcznie utworzyć obiekt JsonSchema, używając metod pomocniczych udostępnianych przez pakiet SDK Firebase AI Logic.

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz tego przewodnika, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk wybranego dostawcy Gemini API, aby wyświetlić na tej stronie treści dotyczące tego dostawcy.

W przypadku Kotlina metody w tym pakiecie SDK są funkcjami zawieszania i muszą być wywoływane z zakresu współprogramu.
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)

Dane wyjściowe typu wyliczeniowego

Poniższe przykłady dostosowują ogólny przykład danych wyjściowych typu wyliczeniowego do wnioskowania hybrydowego (np. PREFER_ON_DEVICE).

W scenariuszu dla tych przykładów model klasyfikuje opis filmu, wybierając jeden gatunek ze wstępnie zdefiniowanej listy dozwolonych opcji (drama, comedy lub documentary).

Schematy odpowiedzi możesz definiować na 2 sposoby:

  • Adnotacje KSP (@Generable)

    • Obsługiwane we wszystkich trybach wnioskowania i wymagane w przypadku wnioskowania na urządzeniu i hybrydowego (konkretnie ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).
    • Zdefiniuj typ wyliczeniowy opakowany w data class w Kotlin, aby automatycznie wygenerować schemat i deserializować odpowiedzi bezpośrednio do obiektów o silnym typowaniu za pomocą getObject().
  • Metody pomocnicze do ręcznego JsonSchema

    • Obsługiwane tylko w przypadku wnioskowania działającego w chmurze (konkretnie ONLY_IN_CLOUD).
    • Ręcznie utwórz typ wyliczeniowy JsonSchema za pomocą JsonSchema.enumeration() bez użycia procesora KSP i odczytaj wybrany ciąg znaków z response.response.text.

Przykład 1. Używanie adnotacji @Generable z KSP

Zdefiniuj enum class reprezentujący dozwolone wartości i opakuj go jako właściwość w Kotlin data class z adnotacjami @Serializable i @Generable.

To podejście jest obsługiwane we wszystkich trybach wnioskowania i jest wymagane w przypadku korzystania z modeli na urządzeniu i hybrydowych (w szczególności ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz tego przewodnika, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk wybranego dostawcy Gemini API, aby wyświetlić na tej stronie treści dotyczące tego dostawcy.

W przypadku Kotlina metody w tym pakiecie SDK są funkcjami zawieszania i muszą być wywoływane z zakresu współprogramu.
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")

Przykład 2. Korzystanie z ręcznych metod pomocniczych JsonSchema

Jeśli Twoja aplikacja korzysta wyłącznie z wnioskowania działającego w chmurze (konkretnie ONLY_IN_CLOUD), możesz ręcznie utworzyć typ wyliczeniowy JsonSchema, używając metod pomocniczych udostępnianych przez pakiet SDK Firebase AI Logic.

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz tego przewodnika, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk wybranego dostawcy Gemini API, aby wyświetlić na tej stronie treści dotyczące tego dostawcy.

W przypadku Kotlina metody w tym pakiecie SDK są funkcjami zawieszania i muszą być wywoływane z zakresu współprogramu.
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)


Prześlij opinię o korzystaniu z usługi Firebase AI Logic