Sorties structurées

Vous pouvez configurer les modèles Gemini pour qu'ils génèrent des réponses conformes à un schéma JSON fourni. Cette fonctionnalité garantit des résultats prévisibles et analysables, assure la sécurité du format et du type, permet la détection programmatique des refus et simplifie l'ingénierie des requêtes.

L'utilisation de sorties structurées est idéale pour un large éventail d'applications :

  • Extraction de données : extraire des informations spécifiques à partir d'un texte non structuré, comme des noms, des dates et des montants à partir d'une facture.
  • Classification structurée : classez du texte dans des catégories prédéfinies et attribuez des libellés structurés (par exemple, en catégorisant les commentaires des clients par sentiment et par thème).
  • Workflows agentiques : générez des données structurées qui peuvent être utilisées pour appeler d'autres outils ou API, comme créer une fiche de personnage pour un jeu ou remplir un formulaire.

En plus de la prise en charge du schéma JSON dans l'API REST, les SDK Google GenAI pour Python et JavaScript facilitent également la définition des schémas d'objet à l'aide de Pydantic et Zod, respectivement. L'exemple ci-dessous montre comment extraire des informations à partir d'un texte non structuré conforme à un schéma défini dans le code.

Cet exemple montre comment extraire des données structurées à partir de texte à l'aide de types de schéma JSON de base tels que object, array, string et integer.

Python

from google import genai
from pydantic import BaseModel, Field
from typing import List, Optional

class Ingredient(BaseModel):
    name: str = Field(description="Name of the ingredient.")
    quantity: str = Field(description="Quantity of the ingredient, including units.")

class Recipe(BaseModel):
    recipe_name: str = Field(description="The name of the recipe.")
    prep_time_minutes: Optional[int] = Field(description="Optional time in minutes to prepare the recipe.")
    ingredients: List[Ingredient]
    instructions: List[str]

client = genai.Client()

prompt = """
Please extract the recipe from the following text.
The user wants to make delicious chocolate chip cookies.
They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
For the best part, they'll need 2 cups of semisweet chocolate chips.
First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
onto ungreased baking sheets and bake for 9 to 11 minutes.
"""

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=prompt,
    config={
        "response_mime_type": "application/json",
        "response_json_schema": Recipe.model_json_schema(),
    },
)

recipe = Recipe.model_validate_json(response.text)
print(recipe)

JavaScript

import { GoogleGenAI } from "@google/genai";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";

const ingredientSchema = z.object({
  name: z.string().describe("Name of the ingredient."),
  quantity: z.string().describe("Quantity of the ingredient, including units."),
});

const recipeSchema = z.object({
  recipe_name: z.string().describe("The name of the recipe."),
  prep_time_minutes: z.number().optional().describe("Optional time in minutes to prepare the recipe."),
  ingredients: z.array(ingredientSchema),
  instructions: z.array(z.string()),
});

const ai = new GoogleGenAI({});

const prompt = `
Please extract the recipe from the following text.
The user wants to make delicious chocolate chip cookies.
They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
For the best part, they'll need 2 cups of semisweet chocolate chips.
First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
onto ungreased baking sheets and bake for 9 to 11 minutes.
`;

const response = await ai.models.generateContent({
  model: "gemini-2.5-flash",
  contents: prompt,
  config: {
    responseMimeType: "application/json",
    responseJsonSchema: zodToJsonSchema(recipeSchema),
  },
});

const recipe = recipeSchema.parse(JSON.parse(response.text));
console.log(recipe);

Go

package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    prompt := `
  Please extract the recipe from the following text.
  The user wants to make delicious chocolate chip cookies.
  They need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,
  1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,
  3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.
  For the best part, they'll need 2 cups of semisweet chocolate chips.
  First, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,
  baking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar
  until light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry
  ingredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons
  onto ungreased baking sheets and bake for 9 to 11 minutes.
  `
    config := &genai.GenerateContentConfig{
        ResponseMIMEType: "application/json",
        ResponseJsonSchema: map[string]any{
            "type": "object",
            "properties": map[string]any{
                "recipe_name": map[string]any{
                    "type":        "string",
                    "description": "The name of the recipe.",
                },
                "prep_time_minutes": map[string]any{
                    "type":        "integer",
                    "description": "Optional time in minutes to prepare the recipe.",
                },
                "ingredients": map[string]any{
                    "type": "array",
                    "items": map[string]any{
                        "type": "object",
                        "properties": map[string]any{
                            "name": map[string]any{
                                "type":        "string",
                                "description": "Name of the ingredient.",
                            },
                            "quantity": map[string]any{
                                "type":        "string",
                                "description": "Quantity of the ingredient, including units.",
                            },
                        },
                        "required": []string{"name", "quantity"},
                    },
                },
                "instructions": map[string]any{
                    "type":  "array",
                    "items": map[string]any{"type": "string"},
                },
            },
            "required": []string{"recipe_name", "ingredients", "instructions"},
        },
    }

    result, err := client.Models.GenerateContent(
        ctx,
        "gemini-2.5-flash",
        genai.Text(prompt),
        config,
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result.Text())
}

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
    -H "x-goog-api-key: $GEMINI_API_KEY" \
    -H 'Content-Type: application/json' \
    -X POST \
    -d '{
      "contents": [{
        "parts":[
          { "text": "Please extract the recipe from the following text.\nThe user wants to make delicious chocolate chip cookies.\nThey need 2 and 1/4 cups of all-purpose flour, 1 teaspoon of baking soda,\n1 teaspoon of salt, 1 cup of unsalted butter (softened), 3/4 cup of granulated sugar,\n3/4 cup of packed brown sugar, 1 teaspoon of vanilla extract, and 2 large eggs.\nFor the best part, they will need 2 cups of semisweet chocolate chips.\nFirst, preheat the oven to 375°F (190°C). Then, in a small bowl, whisk together the flour,\nbaking soda, and salt. In a large bowl, cream together the butter, granulated sugar, and brown sugar\nuntil light and fluffy. Beat in the vanilla and eggs, one at a time. Gradually beat in the dry\ningredients until just combined. Finally, stir in the chocolate chips. Drop by rounded tablespoons\nonto ungreased baking sheets and bake for 9 to 11 minutes." }
        ]
      }],
      "generationConfig": {
        "responseMimeType": "application/json",
        "responseJsonSchema": {
          "type": "object",
          "properties": {
            "recipe_name": {
              "type": "string",
              "description": "The name of the recipe."
            },
            "prep_time_minutes": {
                "type": "integer",
                "description": "Optional time in minutes to prepare the recipe."
            },
            "ingredients": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "name": { "type": "string", "description": "Name of the ingredient."},
                  "quantity": { "type": "string", "description": "Quantity of the ingredient, including units."}
                },
                "required": ["name", "quantity"]
              }
            },
            "instructions": {
              "type": "array",
              "items": { "type": "string" }
            }
          },
          "required": ["recipe_name", "ingredients", "instructions"]
        }
      }
    }'

Exemple de réponse :

{
  "recipe_name": "Delicious Chocolate Chip Cookies",
  "ingredients": [
    {
      "name": "all-purpose flour",
      "quantity": "2 and 1/4 cups"
    },
    {
      "name": "baking soda",
      "quantity": "1 teaspoon"
    },
    {
      "name": "salt",
      "quantity": "1 teaspoon"
    },
    {
      "name": "unsalted butter (softened)",
      "quantity": "1 cup"
    },
    {
      "name": "granulated sugar",
      "quantity": "3/4 cup"
    },
    {
      "name": "packed brown sugar",
      "quantity": "3/4 cup"
    },
    {
      "name": "vanilla extract",
      "quantity": "1 teaspoon"
    },
    {
      "name": "large eggs",
      "quantity": "2"
    },
    {
      "name": "semisweet chocolate chips",
      "quantity": "2 cups"
    }
  ],
  "instructions": [
    "Preheat the oven to 375°F (190°C).",
    "In a small bowl, whisk together the flour, baking soda, and salt.",
    "In a large bowl, cream together the butter, granulated sugar, and brown sugar until light and fluffy.",
    "Beat in the vanilla and eggs, one at a time.",
    "Gradually beat in the dry ingredients until just combined.",
    "Stir in the chocolate chips.",
    "Drop by rounded tablespoons onto ungreased baking sheets and bake for 9 to 11 minutes."
  ]
}

Streaming

Vous pouvez diffuser des sorties structurées, ce qui vous permet de commencer à traiter la réponse au fur et à mesure de sa génération, sans avoir à attendre que la sortie complète soit disponible. Cela peut améliorer les performances perçues de votre application.

Les blocs diffusés seront des chaînes JSON partielles valides, qui pourront être concaténées pour former l'objet JSON final et complet.

Python

from google import genai
from pydantic import BaseModel, Field
from typing import Literal

class Feedback(BaseModel):
    sentiment: Literal["positive", "neutral", "negative"]
    summary: str

client = genai.Client()
prompt = "The new UI is incredibly intuitive and visually appealing. Great job. Add a very long summary to test streaming!"

response_stream = client.models.generate_content_stream(
    model="gemini-2.5-flash",
    contents=prompt,
    config={
        "response_mime_type": "application/json",
        "response_json_schema": Feedback.model_json_schema(),
    },
)

for chunk in response_stream:
    print(chunk.candidates[0].content.parts[0].text)

JavaScript

import { GoogleGenAI } from "@google/genai";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";

const ai = new GoogleGenAI({});
const prompt = "The new UI is incredibly intuitive and visually appealing. Great job! Add a very long summary to test streaming!";

const feedbackSchema = z.object({
  sentiment: z.enum(["positive", "neutral", "negative"]),
  summary: z.string(),
});

const stream = await ai.models.generateContentStream({
  model: "gemini-2.5-flash",
  contents: prompt,
  config: {
    responseMimeType: "application/json",
    responseJsonSchema: zodToJsonSchema(feedbackSchema),
  },
});

for await (const chunk of stream) {
  console.log(chunk.candidates[0].content.parts[0].text)
}

Compatibilité avec le schéma JSON

Pour générer un objet JSON, définissez response_mime_type sur application/json dans la configuration de génération et fournissez un response_json_schema. Le schéma doit être un schéma JSON valide qui décrit le format de sortie souhaité.

Le modèle génère ensuite une réponse qui est une chaîne JSON syntaxiquement valide correspondant au schéma fourni. Lorsque vous utilisez des sorties structurées, le modèle génère des sorties dans le même ordre que les clés du schéma.

Le mode de sortie structurée de Gemini est compatible avec un sous-ensemble de la spécification JSON Schema.

Les valeurs suivantes de type sont acceptées :

  • string : pour le texte.
  • number : pour les nombres à virgule flottante.
  • integer : pour les nombres entiers.
  • boolean : pour les valeurs "true"/"false".
  • object : pour les données structurées avec des paires clé/valeur.
  • array : pour les listes d'éléments.
  • null : pour autoriser une propriété à être nulle, incluez "null" dans le tableau de types (par exemple, {"type": ["string", "null"]}).

Ces propriétés descriptives aident à guider le modèle :

  • title : brève description d'une propriété.
  • description : description plus longue et plus détaillée d'une propriété.

Propriétés spécifiques au type

Pour les valeurs object :

  • properties : objet dans lequel chaque clé est un nom de propriété et chaque valeur est un schéma pour cette propriété.
  • required : tableau de chaînes listant les propriétés obligatoires.
  • additionalProperties : contrôle si les propriétés non listées dans properties sont autorisées. Il peut s'agir d'une valeur booléenne ou d'un schéma.

Pour les valeurs string :

  • enum : liste un ensemble spécifique de chaînes possibles pour les tâches de classification.
  • format : spécifie une syntaxe pour la chaîne, par exemple date-time, date ou time.

Pour les valeurs number et integer :

  • enum : liste un ensemble spécifique de valeurs numériques possibles.
  • minimum : valeur inclusive minimale.
  • maximum : valeur maximale incluse.

Pour les valeurs array :

  • items : définit le schéma de tous les éléments du tableau.
  • prefixItems : définit une liste de schémas pour les N premiers éléments, ce qui permet d'utiliser des structures de type tuple.
  • minItems : nombre minimal d'éléments dans le tableau.
  • maxItems : nombre maximal d'éléments dans le tableau.

Compatibilité des modèles

Les modèles suivants sont compatibles avec les sorties structurées :

Modèle Sorties structurées
Gemini 2.5 Pro ✔️
Gemini 2.0 Flash ✔️
Gemini 2.5 Flash-Lite ✔️
Gemini 2.0 Flash ✔️*
Gemini 2.0 Flash-Lite ✔️*

* Notez que Gemini 2.0 nécessite une liste propertyOrdering explicite dans l'entrée JSON pour définir la structure préférée. Vous trouverez un exemple dans ce livre de recettes.

Sorties structurées et appels de fonction

Les sorties structurées et l'appel de fonction utilisent des schémas JSON, mais à des fins différentes :

Fonctionnalité Cas d'utilisation principal
Sorties structurées Mise en forme de la réponse finale à l'utilisateur. Utilisez cette option lorsque vous souhaitez que la réponse du modèle soit dans un format spécifique (par exemple, pour extraire des données d'un document et les enregistrer dans une base de données).
Appel de fonction Prendre des mesures pendant la conversation Utilisez cette option lorsque le modèle doit vous demander d'effectuer une tâche (par exemple, "get current weather") avant de pouvoir fournir une réponse définitive.

Bonnes pratiques

  • Descriptions claires : utilisez le champ description de votre schéma pour fournir des instructions claires au modèle sur ce que représente chaque propriété. C'est essentiel pour guider la sortie du modèle.
  • Typage fort : utilisez des types spécifiques (integer, string, enum) chaque fois que possible. Si un paramètre a un ensemble limité de valeurs valides, utilisez un enum.
  • Prompt engineering : indiquez clairement dans votre requête ce que vous souhaitez que le modèle fasse. Par exemple, "Extrais les informations suivantes du texte…" ou "Classe cette réponse selon le schéma fourni…".
  • Validation : bien que la sortie structurée garantisse un code JSON syntaxiquement correct, elle ne garantit pas que les valeurs sont sémantiquement correctes. Validez toujours le résultat final dans le code de votre application avant de l'utiliser.
  • Gestion des erreurs : implémentez une gestion des erreurs robuste dans votre application pour gérer de manière optimale les cas où la sortie du modèle, bien que conforme au schéma, peut ne pas répondre aux exigences de votre logique métier.

Limites

  • Sous-ensemble de schéma : toutes les fonctionnalités de la spécification du schéma JSON ne sont pas prises en charge. Le modèle ignore les propriétés non compatibles.
  • Complexité du schéma : l'API peut refuser les schémas très volumineux ou profondément imbriqués. Si vous rencontrez des erreurs, essayez de simplifier votre schéma en raccourcissant les noms de propriétés, en réduisant l'imbrication ou en limitant le nombre de contraintes.