פלט מובנה

אפשר להגדיר את Gemini כך שיפיק פלט מובנה במקום טקסט לא מובנה, וכך יאפשר חילוץ מדויק וסטנדרטיזציה של מידע לצורך עיבוד נוסף. לדוגמה, אפשר להשתמש בפלט מובנה כדי לחלץ מידע קורות חיים, ולקבוע סטנדרטים כדי ליצור מסד נתונים מובנה.

Gemini יכול ליצור JSON או ערכים של Enumeration כפלט מובנה.

יצירת קובץ JSON

יש שתי דרכים ליצור קובץ JSON באמצעות Gemini API:

  • הגדרת סכימה במודל
  • הצגת סכימה בהנחיה בטקסט

הגדרת סכימה במודל היא הדרך המומלצת ליצירת 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>

מכיוון שהמודל מקבל את הסכימה מהטקסט בהנחיה, יכול להיות שתהיה לכם גמישות מסוימת לגבי האופן שבו אתם מייצגים את הסכימה. עם זאת, כשמציינים סכימת שורה לצד השורה (inline) כזו, המודל לא מוגבל להחזיר JSON. כדי לקבל תגובה deterministית יותר באיכות גבוהה יותר, צריך להגדיר סכימה במודל ולא להכפיל את הסכימה בהנחיית הטקסט.

יצירת ערכי enum

במקרים מסוימים, יכול להיות שתרצו שהמודל יבחר אפשרות אחת מתוך רשימה של אפשרויות. כדי להטמיע את ההתנהגות הזו, אפשר להעביר enum בסכימה. אפשר להשתמש באפשרות של enum בכל מקום שבו אפשר להשתמש ב-string ב-responseSchema, כי enum הוא מערך של מחרוזות. בדומה לסכימה של JSON, משתנה מוגדר מראש מאפשר להגביל את הפלט של המודל כך שיתאים לדרישות של האפליקציה.

לדוגמה, נניח שאתם מפתחים אפליקציה לסיווג כלי נגינה לאחת מחמש הקטגוריות הבאות: "Percussion",‏ "String",‏ "Woodwind",‏ "Brass" או "Keyboard". תוכלו ליצור enum כדי לעזור לכם לבצע את המשימה הזו.

בדוגמה הבאה, מעבירים enum בתור responseSchema, ומגבילים את המודל לבחור באפשרות המתאימה ביותר.

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

ספריית Python תתרגם את הצהרות הסוג של ה-API. עם זאת, ה-API מקבל קבוצת משנה של הסכימה של OpenAPI 3.0 (Schema).

יש עוד שתי דרכים לציין את המניין. אתם יכולים להשתמש ב-Literal:

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

אפשר גם להעביר את הסכימה כ-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

בנוסף לבעיות פשוטות של בחירה מרובה, אפשר להשתמש ב-enum בכל מקום בסכימה של JSON. לדוגמה, אפשר לבקש מהמודל רשימה של שמות מתכונים ולהשתמש ב-enum של Grade כדי לתת לכל שם דירוג פופולריות:

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)

התגובה עשויה להיראות כך:

[
  {
    "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, וגם מוסיף שדה 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"]
}

במאמר חומר עזר בנושא Schema מפורט מידע מלא על שדות ה-Schema כפי שהם משמשים ב-Gemini API.

סדר הנכסים

כשעובדים עם סכימות JSON ב-Gemini API, חשוב לשים לב לסדר המאפיינים. כברירת מחדל, ה-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 (כפי שמוצג בדוגמה הקודמת):

Python
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 בהגדרת המשתמש. הגישה הזו מאפשרת לציין את שמות המפתחות ולהגדיר סוגים שונים לערכי המפתחות המשויכים לכל אחד מהמפתחות, כולל מבנים בתצוגת עץ.

שיטות מומלצות

כשמשתמשים בסכימת תגובה, כדאי להביא בחשבון את השיקולים והשיטות המומלצות הבאים:

  • גודל הסכימה של התשובה נספר במסגרת המגבלה על אסימוני הקלט.
  • כברירת מחדל, השדות הם אופציונליים, כלומר המודל יכול לאכלס את השדות או לדלג עליהם. אפשר להגדיר שדות לפי הצורך כדי לאלץ את המודל לספק ערך. אם אין מספיק הקשר בהנחיה להזנת הקלט המשויכת, המודל יוצר תשובות בעיקר על סמך הנתונים שבהם הוא אומן.
  • סכימה מורכבת עלולה לגרום לשגיאה מסוג InvalidArgument: 400. המורכבות יכולה לנבוע משמות מאפיינים ארוכים, מגבלות אורך ארוכות של מערכי נתונים, מערכים של ערכים רבים, מאובייקטים עם הרבה מאפיינים אופציונליים או משילוב של הגורמים האלה.

    אם השגיאה הזו מופיעה עם סכימה תקינה, מבצעים אחת או יותר מהשינויים הבאים כדי לפתור את השגיאה:

    • מקצרים את שמות הנכסים או שמות המאפיינים המפורטים.
    • יישור מערכים בתצוגת עץ.
    • צמצום מספר המאפיינים עם אילוצים, כמו מספרים עם מגבלות מינימום ומקסימום.
    • צמצום מספר הנכסים עם אילוצים מורכבים, כמו נכסים בפורמטים מורכבים כמו date-time.
    • צמצום מספר המאפיינים האופציונליים.
    • צמצום מספר הערכים התקינים של מערכות ערכים מוגדרות מראש.
  • אם התוצאות לא תואמות לציפיות שלכם, מוסיפים הקשר נוסף להנחיות הקלט או משנים את הסכימה של התשובות. לדוגמה, אפשר לבדוק את התשובה של המודל בלי פלט מובנה כדי לראות איך הוא מגיב. לאחר מכן תוכלו לעדכן את הסכימה של התשובות כך שתתאים טוב יותר לפלט של המודל.

המאמרים הבאים

אחרי שלמדתם איך ליצור פלט מובנה, כדאי לנסות להשתמש בכלים של Gemini API: