Generowanie danych strukturalnych na potrzeby funkcji hybrydowych w aplikacjach na Androida

Firebase AI Logic


Gemini modele domyślnie zwracają odpowiedzi w postaci nieustrukturyzowanego tekstu. W niektórych przypadkach wymagany jest jednak tekst ustrukturyzowany (np. JSON lub wyliczenia). Możesz na przykład używać odpowiedzi do innych zadań, które wymagają ustalonego schematu danych.

Aby mieć pewność, że wygenerowane dane wyjściowe modelu zawsze będą zgodne z określonym schematem, możesz zdefiniować schemat, który działa jak plan odpowiedzi modelu. Dzięki temu możesz bezpośrednio wyodrębniać dane z danych wyjściowych modelu, co ogranicza potrzebę przetwarzania końcowego.

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

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

  • Ogranicz sposób, w jaki model może odpowiadać podczas zadań klasyfikacji.
    Możesz na przykład sprawić, że model będzie dodawać adnotacje do tekstu określonym zestawem etykiet (np. określonym zestawem typów wyliczeniowych, takich jak positive i negative), a nie etykietami generowanymi przez model (które mogą mieć pewien stopień zmienności, np. good, positive, negative lub bad).

Z tego artykułu dowiesz się, jak generować ustrukturyzowane dane wyjściowe (np. JSON i wyliczenia) w hybrydowych rozwiązaniach dla aplikacji na Androida.

Przejdź do danych wyjściowych JSON Przejdź do danych wyjściowych wyliczeń

Konfiguracja ustrukturyzowanych danych wyjściowych

Generowanie ustrukturyzowanych danych wyjściowych (np. JSON i wyliczeń) 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 Kotlinie z procesorem KSP. Schematy ręczne i bezpośrednie adnotacje enum class nie są obsługiwane.
    • Gdy wnioskowanie jest przeprowadzane 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 przełączy się na wnioskowanie w chmurze, pakiet SDK automatycznie ustawi wartość responseMimeType na application/json i przekaże schemat do modelu Gemini hostowanego w chmurze.
  • W przypadku wnioskowania tylko w chmurze (ONLY_IN_CLOUD):

    • Obsługuje zarówno adnotacje @Generable (zalecane), jak i schematy ręczne (utworzone za pomocą metod pomocniczych JsonSchema).
    • Pakiet SDK automatycznie ustawi wartość responseMimeType na application/json i przekaże schemat do modelu Gemini hostowanego w chmurze.

Zanim zaczniesz

Kliknij swojego dostawcę Gemini API, aby wyświetlić na tej stronie treści i kod specyficzne dla dostawcy.

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

  1. Postępuj zgodnie z przewodnikiem dla początkujących dotyczącym tworzenia hybrydowych rozwiązań, który obejmuje konfigurowanie projektu w Firebase, pobieranie modelu na urządzenie 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ę Kotlin Serialization 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.0.0")
       implementation("com.google.firebase:firebase-ai-ondevice:16.0.0-beta06")
       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 wyliczeń

Dane wyjściowe JSON

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

W scenariuszu tych przykładów model generuje listę profili postaci do opowiadania fantasy z ustrukturyzowanymi atrybutami, takimi jak imię, wiek, gatunek i opcjonalne akcesoria.

Schematy odpowiedzi możesz zdefiniować na 2 sposoby:

  • Adnotacje KSP (@Generable i @Guide)

    • Obsługiwane we wszystkich trybach wnioskowania i wymagane w przypadku wnioskowania na urządzeniu i wnioskowania hybrydowego (w szczególności ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).
    • Zdefiniuj klasy danych w Kotlinie, aby automatycznie generować schematy w czasie kompilacji i deserializować odpowiedzi bezpośrednio do obiektów z silnym typowaniem za pomocą funkcji getObject().
  • Ręczne metody pomocnicze JsonSchema

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

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

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

To podejście jest obsługiwane we wszystkich trybach wnioskowania i jest wymagane w przypadku rozwiązań na urządzeniu i rozwiązań 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, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk Gemini APIdostawcy interfejsu Gemini API, aby na tej stronie wyświetlały się treści specyficzne dla dostawcy.

W przypadku języka Kotlin metody w tym pakiecie SDK są funkcjami zawieszającymi 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. Używanie ręcznych metod pomocniczych JsonSchema

Jeśli Twoja aplikacja używa tylko wnioskowania działającego w chmurze (w szczególności, ONLY_IN_CLOUD), możesz ręcznie utworzyć JsonSchema za pomocą metod pomocniczych udostępnianych przez Firebase AI Logic pakiet SDK.

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk Gemini APIdostawcy interfejsu Gemini API, aby na tej stronie wyświetlały się treści specyficzne dla dostawcy.

W przypadku języka Kotlin metody w tym pakiecie SDK są funkcjami zawieszającymi 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 tych przykładów model klasyfikuje opis filmu, wybierając jeden gatunek z predefiniowanej listy dozwolonych opcji (drama, comedy lub documentary).

Schematy odpowiedzi możesz zdefiniować na 2 sposoby:

  • Adnotacje KSP (@Generable)

    • Obsługiwane we wszystkich trybach wnioskowania i wymagane w przypadku wnioskowania na urządzeniu i wnioskowania hybrydowego (w szczególności ONLY_ON_DEVICE, PREFER_ON_DEVICE i PREFER_IN_CLOUD).
    • Zdefiniuj wyliczenie opakowane w klasę data class w Kotlinie, aby automatycznie wygenerować schemat i deserializować odpowiedzi bezpośrednio do obiektów z silnym typowaniem za pomocą funkcji getObject().
  • Ręczne metody pomocnicze JsonSchema

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

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

Zdefiniuj enum class reprezentującą dozwolone wartości i opakuj ją jako właściwość w klasie data class w Kotlinie z adnotacjami @Serializable i @Generable.

To podejście jest obsługiwane we wszystkich trybach wnioskowania i jest wymagane w przypadku rozwiązań na urządzeniu i rozwiązań 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, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk Gemini APIdostawcy interfejsu Gemini API, aby na tej stronie wyświetlały się treści specyficzne dla dostawcy.

W przypadku języka Kotlin metody w tym pakiecie SDK są funkcjami zawieszającymi 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. Używanie ręcznych metod pomocniczych JsonSchema

Jeśli Twoja aplikacja używa tylko wnioskowania działającego w chmurze (w szczególności, ONLY_IN_CLOUD), możesz ręcznie utworzyć typ wyliczeniowy JsonSchema za pomocą metod pomocniczych udostępnianych przez pakiet Firebase AI Logic SDK.

Zanim wypróbujesz ten przykład, wykonaj czynności opisane w sekcji Zanim zaczniesz, aby skonfigurować projekt i aplikację.
W tej sekcji klikniesz też przycisk dostawcy interfejsu Gemini API, aby na tej stronie wyświetlały się treści specyficzne dla dostawcy.
Gemini API

W przypadku języka Kotlin metody w tym pakiecie SDK są funkcjami zawieszającymi 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 Firebase AI Logic