Структурированный вывод

Вы можете настроить Gemini для структурированного вывода вместо неструктурированного текста, что позволит точно извлекать и стандартизировать информацию для дальнейшей обработки. Например, вы можете использовать структурированный вывод для извлечения информации из резюме, стандартизировать их для создания структурированной базы данных.

Gemini может генерировать значения JSON или enum в качестве структурированного вывода.

Генерация JSON

Существует два способа генерации JSON с использованием API Gemini:

  • Настройте схему на модели
  • Предоставьте схему в текстовом запросе

Настройка схемы на основе модели является рекомендуемым способом генерации JSON, поскольку она ограничивает модель выводом JSON.

Настройка схемы (рекомендуется)

Чтобы ограничить модель генерацией JSON, настройте responseSchema . Затем модель будет отвечать на любой запрос выводом в формате JSON.

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
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();
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())
}
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

Вывод может выглядеть так:

[
  {
    "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"
    ]
  },
  ...
]

Предоставление схемы в текстовом приглашении

Вместо настройки схемы вы можете предоставить схему в виде естественного языка или псевдокода в текстовом приглашении. Этот метод не рекомендуется , поскольку он может привести к низкому качеству вывода, а также поскольку модель не ограничена следованием схеме.

Вот общий пример схемы, представленной в текстовом приглашении:

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>

Поскольку модель получает схему из текста в приглашении, у вас может быть некоторая гибкость в том, как вы представляете схему. Но когда вы предоставляете схему в строке, как это, модель фактически не ограничена возвращением JSON. Для более детерминированного, более качественного ответа настройте схему в модели и не дублируйте схему в текстовом приглашении.

Генерация значений перечисления

В некоторых случаях вам может понадобиться, чтобы модель выбирала один вариант из списка вариантов. Чтобы реализовать это поведение, вы можете передать enum в вашей схеме. Вы можете использовать enum-опцию везде, где вы могли бы использовать string в responseSchema , поскольку enum — это массив строк. Как и схема JSON, enum позволяет вам ограничивать вывод модели в соответствии с требованиями вашего приложения.

Например, предположим, что вы разрабатываете приложение для классификации музыкальных инструментов по одной из пяти категорий: "Percussion" , "String" , "Woodwind" , "Brass" или « "Keyboard" ». Вы можете создать перечисление, чтобы помочь с этой задачей.

В следующем примере вы передаете перечисление в качестве responseSchema , ограничивая модель выбором наиболее подходящего варианта.

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

Библиотека Python будет переводить объявления типов для API. Однако API принимает подмножество схемы OpenAPI 3.0 ( Schema ).

Есть два других способа указать перечисление. Вы можете использовать Literal :

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

И вы также можете передать схему как JSON:

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

Помимо основных задач с множественным выбором, вы можете использовать перечисление в любом месте схемы JSON. Например, вы можете запросить у модели список названий рецептов и использовать перечисление Grade , чтобы присвоить каждому названию оценку популярности:

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)

Ответ может выглядеть так:

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

О схемах JSON

Конфигурирование модели для вывода JSON с использованием параметра responseSchema опирается на объект Schema для определения его структуры. Этот объект представляет собой выбранное подмножество объекта OpenAPI 3.0 Schema , а также добавляет поле propertyOrdering .

Вот псевдо-JSON-представление всех полей 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 схемы должен быть одним из типов данных OpenAPI или объединением этих типов (с использованием anyOf ). Для каждого Type допустимо только подмножество полей. Следующий список сопоставляет каждый Type с подмножеством полей, которые допустимы для этого типа:

  • 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

Вот несколько примеров схем, показывающих допустимые комбинации типа и поля:

{ "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"]
}

Полную документацию по полям схемы, используемым в API Gemini, см. в справочнике по схеме .

Заказ недвижимости

При работе со схемами JSON в API Gemini важен порядок свойств. По умолчанию API упорядочивает свойства в алфавитном порядке и не сохраняет порядок, в котором они определены (хотя SDK Google Gen AI могут сохранять этот порядок). Если вы предоставляете примеры для модели с настроенной схемой, а порядок свойств примеров не соответствует порядку свойств схемы, вывод может быть беспорядочным или неожиданным.

Чтобы обеспечить последовательный и предсказуемый порядок свойств, можно использовать необязательное поле propertyOrdering[] .

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

propertyOrdering[] – нестандартное поле в спецификации OpenAPI – это массив строк, используемый для определения порядка свойств в ответе. Указывая порядок свойств и затем предоставляя примеры со свойствами в том же порядке, вы можете потенциально улучшить качество результатов. propertyOrdering поддерживается только при ручном создании types.Schema .

Схемы в Python

При использовании библиотеки Python значение response_schema должно быть одним из следующих:

  • Тип, который вы бы использовали в аннотации типа (см. модуль typing Python)
  • Экземпляр genai.types.Schema
  • dict эквивалент genai.types.Schema

Самый простой способ определить схему — использовать тип Pydantic (как показано в предыдущем примере):

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

При использовании типа Pydantic библиотека Python создает для вас схему JSON и отправляет ее в API. Дополнительные примеры см. в документации библиотеки Python .

Библиотека Python поддерживает схемы, определенные со следующими типами (где AllowedType — любой разрешенный тип):

  • int
  • float
  • bool
  • str
  • list[AllowedType]
  • AllowedType|AllowedType|...
  • Для структурированных типов:
    • dict[str, AllowedType] . Эта аннотация объявляет все значения словаря одним и тем же типом, но не указывает, какие ключи должны быть включены.
    • Пользовательские модели Pydantic . Этот подход позволяет указывать имена ключей и определять различные типы для значений, связанных с каждым из ключей, включая вложенные структуры.

Поддержка схемы JSON

JSON Schema — более поздняя спецификация, чем OpenAPI 3.0, на которой основан объект Schema . Поддержка JSON Schema доступна в качестве предварительного просмотра с использованием поля responseJsonSchema , которое принимает любую JSON Schema со следующими ограничениями:

  • Работает только с Gemini 2.5.
  • Хотя все свойства JSON Schema могут быть переданы, не все из них поддерживаются. Подробнее см. в документации к полю.
  • Рекурсивные ссылки могут использоваться только в качестве значения необязательного свойства объекта.
  • Рекурсивные ссылки развертываются до конечной степени, в зависимости от размера схемы.
  • Схемы, содержащие $ref не могут содержать никаких свойств, кроме тех, которые начинаются с $ .

Вот пример создания схемы JSON с помощью Pydantic и ее отправки в модель:

curl "https://generativelanguage.googleapis.com/v1alpha/models/\
gemini-2.5-flash-preview-05-20:generateContent?key=$GEMINI_API_KEY" \
    -H 'Content-Type: application/json' \
    -d @- <<EOF
{
  "contents": [{
    "parts":[{
      "text": "Please give a random example following this schema"
    }]
  }],
  "generationConfig": {
    "response_mime_type": "application/json",
    "response_json_schema": $(python3 - << PYEOF
from enum import Enum
from typing import List, Optional, Union, Set
from pydantic import BaseModel, Field, ConfigDict
import json

class UserRole(str, Enum):
    ADMIN = "admin"
    VIEWER = "viewer"

class Address(BaseModel):
    street: str
    city: str

class UserProfile(BaseModel):
    username: str = Field(description="User's unique name")
    age: Optional[int] = Field(ge=0, le=120)
    roles: Set[UserRole] = Field(min_items=1)
    contact: Union[Address, str]
    model_config = ConfigDict(title="User Schema")

# Generate and print the JSON Schema
print(json.dumps(UserProfile.model_json_schema(), indent=2))
PYEOF
)
  }
}
EOF

Прямая передача схемы JSON при использовании SDK пока не поддерживается.

Лучшие практики

При использовании схемы ответа учитывайте следующие соображения и передовые практики:

  • Размер вашей схемы ответа учитывается при расчете лимита входных токенов.
  • По умолчанию поля являются необязательными, то есть модель может заполнять поля или пропускать их. Вы можете задать поля как обязательные, чтобы заставить модель предоставить значение. Если в соответствующем запросе ввода недостаточно контекста, модель генерирует ответы в основном на основе данных, на которых она была обучена.
  • Сложная схема может привести к ошибке InvalidArgument: 400 Сложность может быть вызвана длинными именами свойств, большими ограничениями длины массива, перечислениями со многими значениями, объектами с большим количеством необязательных свойств или комбинацией этих факторов.

    Если вы получили эту ошибку при допустимой схеме, внесите одно или несколько из следующих изменений, чтобы устранить ошибку:

    • Сократите имена свойств или перечислений.
    • Сглаживание вложенных массивов.
    • Сократите количество свойств с ограничениями, например, чисел с минимальными и максимальными пределами.
    • Сократите количество свойств со сложными ограничениями, например, свойств со сложными форматами, такими как date-time .
    • Сократите количество необязательных свойств.
    • Уменьшите количество допустимых значений для перечислений.
  • Если вы не видите ожидаемых результатов, добавьте больше контекста в ваши входные запросы или измените схему ответа. Например, просмотрите ответ модели без структурированного вывода, чтобы увидеть, как модель реагирует. Затем вы можете обновить схему ответа, чтобы она лучше соответствовала выводу модели.

Что дальше?

Теперь, когда вы научились генерировать структурированный вывод, вы можете попробовать использовать инструменты API Gemini: