Por padrão, o Gemini gera texto não estruturado, mas você pode restringir o modelo para responder com saída estruturada, seja JSON ou um valor de um tipo enumerado. Esse recurso de saída estruturada é particularmente útil quando você precisa extrair informações de dados não estruturados e processá-las para consumo por um aplicativo. Por exemplo, você pode usar o recurso para extrair informações padronizadas de currículos e criar um banco de dados com essas informações. Ou você pode extrair ingredientes de receitas e mostrar um link para um site de compras de alimentos para cada ingrediente.
Este guia mostra como gerar uma saída estruturada usando a API Gemini.
Geração de JSON
Há duas maneiras de gerar JSON usando a API Gemini:
- Configurar um esquema no modelo
- Fornecer um esquema em um comando de texto
Configurar um esquema no modelo é a maneira recomendada de gerar JSON, porque ele restringe o modelo a gerar JSON.
Como configurar um esquema
Para restringir o modelo a gerar JSON, configure um responseSchema
. O modelo
vai responder a qualquer comando com saída formatada em 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
A saída pode ser semelhante a esta:
[
{
"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"
]
},
...
]
Como fornecer um esquema em uma solicitação de texto
Em vez de configurar um esquema, você pode fornecer um esquema como linguagem natural ou pseudocódigo em um comando de texto. Esse método não é recomendado porque pode produzir uma saída de qualidade inferior e porque o modelo não é restrito a seguir o esquema.
Confira um exemplo genérico de um esquema fornecido em uma solicitação de texto:
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>
Como o modelo recebe o esquema do texto no comando, você pode ter alguma flexibilidade na representação do esquema. No entanto, quando você fornece um esquema inline como esse, o modelo não é limitado a retornar JSON. Para uma resposta mais determinística e de melhor qualidade, configure um esquema no modelo e não duplique o esquema no comando de texto.
Esquemas JSON
Ao configurar o modelo para retornar uma resposta JSON, você usa um objeto Schema
para definir a forma dos dados JSON. O Schema
representa um subconjunto
selecionado do
objeto de esquema da OpenAPI 3.0
e também adiciona um campo propertyOrdering
.
Confira uma representação pseudo-JSON de todos os campos 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)
}
}
O Type
do esquema precisa ser um dos tipos de dados da OpenAPI ou uma união desses tipos (usando anyOf
). Apenas um subconjunto de campos é válido para cada Type
.
A lista a seguir mapeia cada Type
para um subconjunto dos campos válidos para
esse tipo:
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
Confira alguns exemplos de esquemas que mostram combinações válidas de tipo e campo:
{ "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"]
}
Para conferir a documentação completa dos campos do esquema conforme eles são usados na API Gemini, consulte a Referência do esquema.
Ordenação de propriedades
Ao trabalhar com esquemas JSON na API Gemini, a ordem das propriedades é importante. Por padrão, a API ordena as propriedades em ordem alfabética e não preserva a ordem em que as propriedades são definidas, embora os SDKs do Google Gen AI possam preservar essa ordem. Se você estiver fornecendo exemplos ao modelo com um esquema configurado e a ordem das propriedades dos exemplos não for consistente com a ordem das propriedades do esquema, a saída poderá ser incoerente ou inesperada.
Para garantir uma ordenação consistente e previsível das propriedades, use o
campo propertyOrdering[]
opcional.
"propertyOrdering": ["recipeName", "ingredients"]
propertyOrdering[]
, que não é um campo padrão na especificação da OpenAPI, é uma matriz de strings usada para determinar a ordem das propriedades na resposta. Ao especificar a ordem das propriedades e fornecer exemplos com
propriedades nessa mesma ordem, você pode melhorar a qualidade dos
resultados. O propertyOrdering
só é aceito quando você cria manualmente o
types.Schema
.
Esquemas em Python
Esta seção oferece orientações adicionais sobre como trabalhar com esquemas JSON usando a biblioteca Python.
Ao usar a biblioteca Python, o valor de response_schema
precisa ser um
destes:
- Um tipo, como você usaria em uma anotação de tipo (consulte o módulo
typing
do Python). - Uma instância de
genai.types.Schema
- O
dict
equivalente agenai.types.Schema
A maneira mais fácil de definir um esquema é com um tipo Pydantic (como mostrado no exemplo anterior):
config={'response_mime_type': 'application/json',
'response_schema': list[Recipe]}
Quando você usa um tipo Pydantic, a biblioteca Python cria um esquema JSON para você e o envia à API. Para mais exemplos, consulte os documentos da biblioteca do Python.
A biblioteca Python oferece suporte a esquemas definidos com os seguintes tipos (em que
AllowedType
é qualquer tipo permitido):
int
float
bool
str
list[AllowedType]
AllowedType|AllowedType|...
- Para tipos estruturados:
dict[str, AllowedType]
. Essa anotação declara que todos os valores do dicionário são do mesmo tipo, mas não especifica quais chaves devem ser incluídas.- Modelos do Pydantic definidos pelo usuário. Essa abordagem permite especificar os nomes das chaves e definir tipos diferentes para os valores associados a cada uma das chaves, incluindo estruturas aninhadas.
Como gerar valores de tipo enumerado
Em alguns casos, talvez você queira que o modelo escolha uma única opção de uma lista de opções. Para implementar esse comportamento, transmita um tipo enumerado no esquema. É
possível usar uma opção de tipo enumerado em qualquer lugar em que você possa usar um string
no
responseSchema
, porque um tipo enumerado é uma matriz de strings. Assim como um esquema JSON, um
enum permite restringir a saída do modelo para atender aos requisitos do
aplicativo.
Por exemplo, suponha que você esteja desenvolvendo um aplicativo para classificar
instrumentos musicais em uma das cinco categorias: "Percussion"
, "String"
,
"Woodwind"
, "Brass"
ou ""Keyboard"
". Você pode criar um tipo enumerado para ajudar
com essa tarefa.
No exemplo abaixo, você transmite um tipo enumerado como
responseSchema
, restringindo o modelo para escolher a opção mais adequada.
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
A biblioteca Python vai traduzir as declarações de tipo para a API. No entanto, a API aceita um subconjunto do esquema da OpenAPI 3.0 (Esquema).
Há duas outras maneiras de especificar uma enumeração. Você pode usar um
Literal
:
Literal["Percussion", "String", "Woodwind", "Brass", "Keyboard"]
Também é possível transmitir o esquema como 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
Além de problemas básicos de múltipla escolha, você pode usar um tipo enumerado em qualquer lugar em um esquema
JSON. Por exemplo, você pode pedir ao modelo uma lista de títulos de receitas e
usar um tipo enumerado Grade
para dar a cada título uma nota de popularidade:
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)
A resposta pode ser assim:
[
{
"recipe_name": "Chocolate Chip Cookies",
"rating": "a+"
},
{
"recipe_name": "Peanut Butter Cookies",
"rating": "a"
},
{
"recipe_name": "Oatmeal Raisin Cookies",
"rating": "b"
},
...
]
Considerações
Considere as seguintes considerações e práticas recomendadas ao usar um esquema de resposta:
- O tamanho do esquema de resposta é contabilizado no limite de tokens de entrada.
- Por padrão, os campos são opcionais, o que significa que o modelo pode preenchê-los ou pular. É possível definir campos conforme necessário para forçar o modelo a fornecer um valor. Se não houver contexto suficiente no comando de entrada associado, o modelo gera respostas principalmente com base nos dados em que foi treinado.
Um esquema complexo pode resultar em um erro
InvalidArgument: 400
. A complexidade pode vir de nomes de propriedades longos, limites de comprimento de matriz longos, enumerações com muitos valores, objetos com muitas propriedades opcionais ou uma combinação desses fatores.Se você receber esse erro com um esquema válido, faça uma ou mais das seguintes mudanças para resolver o problema:
- Encurte os nomes de propriedades ou de tipos enumerados.
- Nivelar matrizes aninhadas.
- Reduza o número de propriedades com restrições, como números com limites mínimo e máximo.
- Reduza o número de propriedades com restrições complexas, como
propriedades com formatos complexos, como
date-time
. - Reduza o número de propriedades opcionais.
- Reduza o número de valores válidos para tipos enumerados.
Se você não está vendo os resultados esperados, inclua mais contexto aos comandos de entrada ou revise seu esquema de resposta. Por exemplo, revise a resposta do modelo sem saída estruturada para conferir como o modelo responde. Depois, você pode atualizar o esquema de resposta para que ele se ajuste melhor à saída do modelo.
A seguir
Agora que você aprendeu a gerar saída estruturada, tente usar as ferramentas da API Gemini: