Uporządkowane dane wyjściowe

Możesz skonfigurować Gemini tak, aby zamiast nieuporządkowanego tekstu generował on dane uporządkowane, co umożliwia precyzyjne wyodrębnianie i standardyzację informacji na potrzeby dalszego przetwarzania. Możesz na przykład użyć uporządkowanego wyjścia, aby wyodrębnić informacje z CV i ujednolicić je w celu utworzenia uporządkowanej bazy danych.

Gemini może generować dane wyjściowe w postaci JSON lub wartości typu wyliczeniowego.

Generowanie pliku JSON

Istnieją 2 sposoby generowania pliku JSON za pomocą interfejsu Gemini API:

  • Konfigurowanie schematu w modelu
  • Podanie schematu w promptach tekstowych

Konfigurowanie schematu w modelu to zalecany sposób generowania danych w formacie JSON, ponieważ ogranicza model do generowania danych w tym formacie.

Konfigurowanie schematu (zalecane)

Aby ograniczyć model do generowania danych w formacie JSON, skonfiguruj responseSchema. Model będzie wtedy odpowiadać na dowolny prompt, zwracając dane wyjściowe w formacie JSON.

Python

from google import genai
from pydantic import BaseModel

class Recipe(BaseModel):
    recipe_name: str
    ingredients: list[str]

client = genai.Client(api_key="GOOGLE_API_KEY")
response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents="List a few popular cookie recipes, and include the amounts of ingredients.",
    config={
        "response_mime_type": "application/json",
        "response_schema": list[Recipe],
    },
)
# Use the response as a JSON string.
print(response.text)

# Use instantiated objects.
my_recipes: list[Recipe] = response.parsed

JavaScript

import { GoogleGenAI, Type } from "@google/genai";

const ai = new GoogleGenAI({ "GOOGLE_API_KEY" });

async function main() {
  const response = await ai.models.generateContent({
    model: "gemini-2.0-flash",
    contents:
      "List a few popular cookie recipes, and include the amounts of ingredients.",
    config: {
      responseMimeType: "application/json",
      responseSchema: {
        type: Type.ARRAY,
        items: {
          type: Type.OBJECT,
          properties: {
            recipeName: {
              type: Type.STRING,
            },
            ingredients: {
              type: Type.ARRAY,
              items: {
                type: Type.STRING,
              },
            },
          },
          propertyOrdering: ["recipeName", "ingredients"],
        },
      },
    },
  });

  console.log(response.text);
}

main();

Przeczytaj

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, &genai.ClientConfig{
        APIKey:  "GOOGLE_API_KEY",
        Backend: genai.BackendGeminiAPI,
    })
    if err != nil {
        log.Fatal(err)
    }

    config := &genai.GenerateContentConfig{
        ResponseMIMEType: "application/json",
        ResponseSchema: &genai.Schema{
            Type: genai.TypeArray,
            Items: &genai.Schema{
                Type: genai.TypeObject,
                Properties: map[string]*genai.Schema{
                    "recipeName": {Type: genai.TypeString},
                    "ingredients": {
                        Type:  genai.TypeArray,
                        Items: &genai.Schema{Type: genai.TypeString},
                    },
                },
                PropertyOrdering: []string{"recipeName", "ingredients"},
            },
        },
    }

    result, err := client.Models.GenerateContent(
        ctx,
        "gemini-2.0-flash",
        genai.Text("List a few popular cookie recipes, and include the amounts of ingredients."),
        config,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result.Text())
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GOOGLE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
      "contents": [{
        "parts":[
          { "text": "List a few popular cookie recipes, and include the amounts of ingredients." }
        ]
      }],
      "generationConfig": {
        "responseMimeType": "application/json",
        "responseSchema": {
          "type": "ARRAY",
          "items": {
            "type": "OBJECT",
            "properties": {
              "recipeName": { "type": "STRING" },
              "ingredients": {
                "type": "ARRAY",
                "items": { "type": "STRING" }
              }
            },
            "propertyOrdering": ["recipeName", "ingredients"]
          }
        }
      }
}' 2> /dev/null | head

Dane wyjściowe mogą wyglądać tak:

[
  {
    "recipeName": "Chocolate Chip Cookies",
    "ingredients": [
      "1 cup (2 sticks) unsalted butter, softened",
      "3/4 cup granulated sugar",
      "3/4 cup packed brown sugar",
      "1 teaspoon vanilla extract",
      "2 large eggs",
      "2 1/4 cups all-purpose flour",
      "1 teaspoon baking soda",
      "1 teaspoon salt",
      "2 cups chocolate chips"
    ]
  },
  ...
]

Podanie schematu w promptach tekstowych

Zamiast konfigurować schemat, możesz podać go w języku naturalnym lub w pseudokodzie w promptach tekstowych. Nie zalecamy tej metody, ponieważ może ona generować dane wyjściowe o gorszej jakości, a model nie jest ograniczony do przestrzegania schematu.

Oto ogólny przykład schematu podanego w promptach tekstowych:

List a few popular cookie recipes, and include the amounts of ingredients.

Produce JSON matching this specification:

Recipe = { "recipeName": string, "ingredients": array<string> }
Return: array<Recipe>

Ponieważ model otrzymuje schemat z tekstu w promptach, możesz mieć pewną elastyczność w sposobie jego reprezentowania. Gdy jednak podasz schemat w postaci inline, jak w tym przykładzie, model nie będzie musiał zwracać danych w formacie JSON. Aby uzyskać bardziej deterministyczne odpowiedzi o wyższej jakości, skonfiguruj schemat na modelu i nie powielaj go w promptach tekstowych.

Generowanie wartości typu wyliczeniowego

W niektórych przypadkach możesz chcieć, aby model wybrał jedną opcję z listy opcji. Aby zaimplementować to zachowanie, możesz przekazać w schemacie typ enum. Opcji wyliczeniowej możesz używać wszędzie tam, gdzie w elementach string możesz użyć wartości string, ponieważ jest to tablica ciągów znaków.responseSchema Podobnie jak schemat JSON, enumeracja umożliwia ograniczenie danych wyjściowych modelu do wymagań aplikacji.

Załóżmy na przykład, że tworzysz aplikację do klasyfikowania instrumentów muzycznych do jednej z 5 kategorii: "Percussion", "String", "Woodwind", "Brass" lub „"Keyboard"”. Aby ułatwić to zadanie, możesz utworzyć typ wyliczeniowy.

W tym przykładzie jako parametr responseSchema przekazujesz typ enum, ograniczając model do wyboru najbardziej odpowiedniej opcji.

Python

from google import genai
import enum

class Instrument(enum.Enum):
  PERCUSSION = "Percussion"
  STRING = "String"
  WOODWIND = "Woodwind"
  BRASS = "Brass"
  KEYBOARD = "Keyboard"

client = genai.Client(api_key="GEMINI_API_KEY")
response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents='What type of instrument is an oboe?',
    config={
        'response_mime_type': 'text/x.enum',
        'response_schema': Instrument,
    },
)

print(response.text)
# Woodwind

Biblioteka Pythona przetłumaczy deklaracje typów interfejsu API. Interfejs API akceptuje jednak podzbiór schematu OpenAPI 3.0 (Schemat).

Wyliczenie można określić na 2 inne sposoby. Możesz użyć Literal:

Python

Literal["Percussion", "String", "Woodwind", "Brass", "Keyboard"]

Możesz też przekazać schemat w formacie JSON:

Python

from google import genai

client = genai.Client(api_key="GEMINI_API_KEY")
response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents='What type of instrument is an oboe?',
    config={
        'response_mime_type': 'text/x.enum',
        'response_schema': {
            "type": "STRING",
            "enum": ["Percussion", "String", "Woodwind", "Brass", "Keyboard"],
        },
    },
)

print(response.text)
# Woodwind

Oprócz podstawowych problemów z wieloma odpowiedziami możesz używać enumeracji w dowolnym miejscu w schemacie JSON. Możesz na przykład poprosić model o listę tytułów przepisów i użyć enumeracji Grade, aby nadać każdemu tytułowi ocenę popularności:

Python

from google import genai

import enum
from pydantic import BaseModel

class Grade(enum.Enum):
    A_PLUS = "a+"
    A = "a"
    B = "b"
    C = "c"
    D = "d"
    F = "f"

class Recipe(BaseModel):
  recipe_name: str
  rating: Grade

client = genai.Client(api_key="GEMINI_API_KEY")
response = client.models.generate_content(
    model='gemini-2.0-flash',
    contents='List 10 home-baked cookie recipes and give them grades based on tastiness.',
    config={
        'response_mime_type': 'application/json',
        'response_schema': list[Recipe],
    },
)

print(response.text)

Odpowiedź może wyglądać tak:

[
  {
    "recipe_name": "Chocolate Chip Cookies",
    "rating": "a+"
  },
  {
    "recipe_name": "Peanut Butter Cookies",
    "rating": "a"
  },
  {
    "recipe_name": "Oatmeal Raisin Cookies",
    "rating": "b"
  },
  ...
]

Informacje o schematach JSON

Konfigurowanie modelu na potrzeby danych wyjściowych w formacie JSON za pomocą parametru responseSchema polega na definiowaniu struktury za pomocą obiektu Schema. Ten obiekt reprezentuje wybrany podzbiór obiektu Schema OpenAPI 3.0, a także dodaje pole propertyOrdering.

Oto reprezentacja w pseudo-formacie JSON wszystkich pól Schema:

{
  "type": enum (Type),
  "format": string,
  "description": string,
  "nullable": boolean,
  "enum": [
    string
  ],
  "maxItems": integer,
  "minItems": integer,
  "properties": {
    string: {
      object (Schema)
    },
    ...
  },
  "required": [
    string
  ],
  "propertyOrdering": [
    string
  ],
  "items": {
    object (Schema)
  }
}

Type schematu musi być jednym z typów danych OpenAPI lub ich unionem (za pomocą anyOf). W przypadku każdego Type prawidłowy jest tylko podzbiór pól. Poniższa lista mapuje każdy typ Type na podzbiór pól, które są prawidłowe w przypadku tego typu:

  • string -> enum, format, nullable
  • integer -> format, minimum, maximum, enum, nullable
  • number -> format, minimum, maximum, enum, nullable
  • boolean -> nullable
  • array -> minItems, maxItems, items, nullable
  • object -> properties, required, propertyOrdering, nullable

Oto kilka przykładowych schematów z prawidłowymi kombinacjami typu i pola:

{ "type": "string", "enum": ["a", "b", "c"] }

{ "type": "string", "format": "date-time" }

{ "type": "integer", "format": "int64" }

{ "type": "number", "format": "double" }

{ "type": "boolean" }

{ "type": "array", "minItems": 3, "maxItems": 3, "items": { "type": ... } }

{ "type": "object",
  "properties": {
    "a": { "type": ... },
    "b": { "type": ... },
    "c": { "type": ... }
  },
  "nullable": true,
  "required": ["c"],
  "propertyOrdering": ["c", "b", "a"]
}

Pełną dokumentację pól schematu, które są używane w Gemini API, znajdziesz w dokumentacji schematu.

Sortowanie obiektów

Gdy pracujesz z schematami JSON w interfejsie Gemini API, ważna jest kolejność właściwości. Domyślnie interfejs API sortuje właściwości alfabetycznie i nie zachowuje kolejności, w jakiej są one zdefiniowane (chociaż pakiety SDK Google Gen AI mogą zachować tę kolejność). Jeśli podajesz modelowi przykłady z skonfigurowanym schematem, a kolejność właściwości przykładów nie jest zgodna z kolejnością właściwości schematu, wynik może być niespójny lub nieoczekiwany.

Aby zapewnić spójne i przewidywalne sortowanie właściwości, możesz użyć opcjonalnego pola propertyOrdering[].

"propertyOrdering": ["recipeName", "ingredients"]

propertyOrdering[] – nie jest to standardowe pole w specyfikacji OpenAPI – to tablica ciągów znaków służąca do określania kolejności właściwości w odpowiedzi. Określając kolejność właściwości, a następnie podając przykłady z tymi samymi właściwościami, możesz potencjalnie poprawić jakość wyników. propertyOrdering jest obsługiwana tylko wtedy, gdy types.Schema jest tworzona ręcznie.

Schematy w Pythonie

Jeśli używasz biblioteki Python, wartość response_schema musi być jedną z tych:

Najprostszym sposobem zdefiniowania schematu jest użycie typu Pydantic (jak w poprzednim przykładzie):

Python

config={'response_mime_type': 'application/json',
        'response_schema': list[Recipe]}

Gdy używasz typu Pydantic, biblioteka Pythona tworzy dla Ciebie schemat JSON i wysyła go do interfejsu API. Więcej przykładów znajdziesz w dokumentacji biblioteki Pythona.

Biblioteka Pythona obsługuje schematy zdefiniowane za pomocą tych typów (gdzie AllowedType to dowolny dozwolony typ):

  • int
  • float
  • bool
  • str
  • list[AllowedType]
  • AllowedType|AllowedType|...
  • W przypadku typów uporządkowanych:
    • dict[str, AllowedType]. Ta adnotacja deklaruje, że wszystkie wartości w słowniku mają ten sam typ, ale nie określa, które klucze powinny być uwzględnione.
    • Zdefiniowane przez użytkownika modele analityczne. Dzięki temu możesz określić nazwy kluczy i zdefiniować różne typy wartości powiązanych z poszczególnymi kluczami, w tym struktury zagnieżdżone.

Sprawdzone metody

Podczas korzystania ze schematu odpowiedzi pamiętaj o tych kwestiach i zaleceniach:

  • Rozmiar schematu odpowiedzi jest wliczany do limitu tokenów wejściowych.
  • Domyślnie pola są opcjonalne, co oznacza, że model może je wypełnić lub pominąć. Możesz ustawić pola jako wymagane, aby wymusić podanie wartości przez model. Jeśli w powiązanym promptzie nie ma wystarczającego kontekstu, model generuje odpowiedzi głównie na podstawie danych, na których był trenowany.
  • Złożony schemat może spowodować błąd InvalidArgument: 400. Złożoność może wynikać z długich nazw właściwości, długich limitów długości tablic, typów enumeracji z wiele wartościami, obiektów z wiele opcjonalnych właściwości lub kombinacji tych czynników.

    Jeśli ten błąd wystąpi w przypadku prawidłowego schematu, wprowadź co najmniej jedną z tych zmian, aby go naprawić:

    • Skróć nazwy właściwości lub nazwy typów wyliczenia.
    • spłaszczania zagnieżdżonych tablic.
    • Zmniejsz liczbę właściwości z ograniczeniami, takimi jak minimalne i maksymalne limity liczb.
    • Zmniejsz liczbę właściwości z zaawansowanymi ograniczeniami, np. właściwości z zaawansowanymi formatami, takimi jak date-time.
    • Zmniejsz liczbę właściwości opcjonalnych.
    • Zmniejsz liczbę prawidłowych wartości w przypadku typów wyliczeniowych.
  • Jeśli nie widzisz oczekiwanych wyników, dodaj więcej kontekstu do promptów dotyczących danych wejściowych lub zmodyfikuj schemat odpowiedzi. Możesz na przykład sprawdzić odpowiedź modelu bez danych wyjściowych w formacie ustrukturyzowanym, aby zobaczyć, jak model reaguje. Następnie możesz zaktualizować schemat odpowiedzi, aby lepiej pasował do danych wyjściowych modelu.

Co dalej?

Teraz, gdy już wiesz, jak generować uporządkowane dane wyjściowe, możesz spróbować użyć narzędzi interfejsu Gemini API: