Per impostazione predefinita, Gemini genera testo non strutturato, ma puoi limitare il modello a rispondere con un'uscita strutturata, ovvero JSON o un valore di un enum. Questa funzionalità di output strutturato è particolarmente utile quando devi estrarre informazioni da dati non strutturati ed elaborarli per il consumo da parte di un'applicazione. Ad esempio, puoi utilizzare la funzionalità per estrarre informazioni standardizzate dai curriculum e creare un database con queste informazioni. In alternativa, puoi estrarre gli ingredienti dalle ricette e mostrare un link a un sito web di un supermercato per ogni ingrediente.
Questa guida mostra come generare un'uscita strutturata utilizzando l'API Gemini.
Generazione di JSON
Esistono due modi per generare JSON utilizzando l'API Gemini:
- Configura uno schema sul modello
- Fornire uno schema in un prompt di testo
La configurazione di uno schema nel modello è il modo consigliato per generare JSON, poiché vincola il modello a generare output JSON.
Configurazione di uno schema
Per vincolare il modello a generare JSON, configura un responseSchema
. Il modello risponderà quindi a qualsiasi prompt con un output in formato 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
L'output potrebbe avere il seguente aspetto:
[
{
"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"
]
},
...
]
Fornire uno schema in un prompt di testo
Anziché configurare uno schema, puoi fornirne uno in linguaggio naturale o pseudocodice in un prompt di testo. Questo metodo è sconsigliato, perché potrebbe produrre output di qualità inferiore e perché il modello non è vincolato a seguire lo schema.
Ecco un esempio generico di uno schema fornito in un prompt di testo:
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>
Poiché il modello recupera lo schema dal testo nel prompt, potresti avere un po' di flessibilità nella rappresentazione dello schema. Tuttavia, se fornisci uno schema in linea come questo, il modello non è effettivamente vincolato a restituire JSON. Per una risposta più deterministica e di qualità superiore, configura uno schema sul modello e non duplicarlo nel prompt di testo.
Schemi JSON
Quando configuri il modello in modo che restituisca una risposta JSON, utilizzi un oggetto Schema
per definire la forma dei dati JSON. Schema
rappresenta un sottoinsieme selezionato dell'oggetto schema OpenAPI 3.0 e aggiunge anche un campo propertyOrdering
.
Ecco una rappresentazione pseudo-JSON di tutti i campi 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)
}
}
Il Type
dello schema deve essere uno dei tipi di dati di OpenAPI o un'unione di questi tipi (utilizzando anyOf
). Per ogni Type
è valido solo un sottoinsieme di campi.
L'elenco seguente mappa ogni Type
a un sottoinsieme di campi validi per quel 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
Ecco alcuni esempi di schemi che mostrano combinazioni di tipo e campo valide:
{ "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"]
}
Per la documentazione completa dei campi dello schema come vengono utilizzati nell'API Gemini, consulta il riferimento allo schema.
Ordinamento delle proprietà
Quando utilizzi gli schemi JSON nell'API Gemini, l'ordine delle proprietà è importante. Per impostazione predefinita, l'API ordina le proprietà in ordine alfabetico e non conserva l'ordine in cui sono definite (anche se gli SDK di IA generativa di Google potrebbero conservare questo ordine). Se fornisci esempi al modello con uno schema configurato e l'ordinamento delle proprietà degli esempi non è coerente con l'ordinamento delle proprietà dello schema, l'output potrebbe essere sconnesso o inaspettato.
Per garantire un ordinamento coerente e prevedibile delle proprietà, puoi utilizzare il
campo facoltativo propertyOrdering[]
.
"propertyOrdering": ["recipeName", "ingredients"]
propertyOrdering[]
, che non è un campo standard nella specifica OpenAPI, è un array di stringhe utilizzato per determinare l'ordine delle proprietà nella risposta. Se specifichi l'ordine delle proprietà e fornisci esempi con le proprietà nello stesso ordine, puoi potenzialmente migliorare la qualità dei risultati. propertyOrdering
è supportato solo quando crei manualmente
types.Schema
.
Schemi in Python
Questa sezione fornisce ulteriori indicazioni su come utilizzare gli schemi JSON con la libreria Python.
Quando utilizzi la libreria Python, il valore di response_schema
deve essere uno
tra i seguenti:
- Un tipo, come quello che utilizzeresti in un'annotazione del tipo (vedi il
modulo
typing
di Python) - Un'istanza di
genai.types.Schema
- L'equivalente in
dict
digenai.types.Schema
Il modo più semplice per definire uno schema è con un tipo Pydantic (come mostrato nell'esempio precedente):
config={'response_mime_type': 'application/json',
'response_schema': list[Recipe]}
Quando utilizzi un tipo Pydantic, la libreria Python crea uno schema JSON per te e lo invia all'API. Per altri esempi, consulta la documentazione della libreria Python.
La libreria Python supporta gli schemi definiti con i seguenti tipi (dove
AllowedType
è un tipo consentito):
int
float
bool
str
list[AllowedType]
AllowedType|AllowedType|...
- Per i tipi strutturati:
dict[str, AllowedType]
. Questa annotazione dichiara che tutti i valori del dizionario sono dello stesso tipo, ma non specifica quali chiavi devono essere incluse.- Modelli Pydantic definiti dall'utente. Questo approccio consente di specificare i nomi delle chiavi e di definire tipi diversi per i valori associati a ciascuna delle chiavi, incluse le strutture nidificate.
Generazione di valori enum
In alcuni casi, potresti volere che il modello scelga una singola opzione da un elenco di opzioni. Per implementare questo comportamento, puoi passare un enum nello schema. Puoi utilizzare un'opzione enum ovunque sia possibile utilizzare un string
in responseSchema
, perché un enum è un array di stringhe. Come uno schema JSON, un enumerato consente di limitare l'output del modello in modo da soddisfare i requisiti dell'applicazione.
Ad esempio, supponiamo che tu stia sviluppando un'applicazione per classificare gli strumenti musicali in una delle cinque categorie: "Percussion"
, "String"
, "Woodwind"
, "Brass"
o ""Keyboard"
". Potresti creare un enum per aiutarti a svolgere questa attività.
Nell'esempio seguente, viene passato un enum come responseSchema
, costringendo il modello a scegliere l'opzione più appropriata.
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
La libreria Python tradurrà le dichiarazioni di tipo per l'API. Tuttavia, l'API accetta un sottoinsieme dello schema OpenAPI 3.0 (Schema).
Esistono altri due modi per specificare un'enumerazione. Puoi utilizzare un
Literal
:
Literal["Percussion", "String", "Woodwind", "Brass", "Keyboard"]
Puoi anche passare lo schema come 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
Oltre ai problemi di base a scelta multipla, puoi utilizzare un enum in qualsiasi punto di uno schema JSON. Ad esempio, potresti chiedere al modello un elenco di titoli di ricette e
utilizzare un enum Grade
per assegnare a ogni titolo un voto di popolarità:
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)
La risposta potrebbe avere il seguente aspetto:
[
{
"recipe_name": "Chocolate Chip Cookies",
"rating": "a+"
},
{
"recipe_name": "Peanut Butter Cookies",
"rating": "a"
},
{
"recipe_name": "Oatmeal Raisin Cookies",
"rating": "b"
},
...
]
Considerazioni
Quando utilizzi uno schema di risposta, tieni presenti le seguenti considerazioni e best practice:
- Le dimensioni dello schema di risposta vengono conteggiate ai fini del limite di token di input.
- Per impostazione predefinita, i campi sono facoltativi, il che significa che il modello può compilarli o saltarli. Puoi impostare i campi come obbligatori per forzare il modello a fornire un valore. Se il contesto nel prompt di input associato non è sufficiente, il modello genera risposte principalmente in base ai dati su cui è stato addestrato.
Uno schema complesso può generare un errore
InvalidArgument: 400
. La complessità può essere dovuta a nomi di proprietà lunghi, limiti di lunghezza degli array, enum con molti valori, oggetti con molte proprietà facoltative o una combinazione di questi fattori.Se ricevi questo errore con uno schema valido, apporta una o più delle seguenti modifiche per risolverlo:
- Abbrevia i nomi delle proprietà o degli enum.
- Appiattisci gli array nidificati.
- Riduci il numero di proprietà con vincoli, ad esempio numeri con limiti minimi e massimi.
- Riduci il numero di proprietà con vincoli complessi, ad esempio proprietà con formati complessi come
date-time
. - Riduci il numero di proprietà facoltative.
- Riduci il numero di valori validi per gli enum.
Se non vedi i risultati che ti aspetti, aggiungi altro contesto ai prompt di input o rivedi lo schema di risposta. Ad esempio, esamina la risposta del modello senza output strutturato per vedere come risponde. Puoi quindi aggiornare lo schema di risposta in modo che si adatti meglio all'output del modello.
Passaggi successivi
Ora che hai imparato a generare output strutturato, ti consigliamo di provare a utilizzare gli strumenti dell'API Gemini: