Kết quả có cấu trúc

Bạn có thể định cấu hình Gemini để xuất dữ liệu có cấu trúc thay vì văn bản không có cấu trúc, cho phép trích xuất và chuẩn hoá thông tin một cách chính xác để xử lý thêm. Ví dụ: bạn có thể sử dụng đầu ra có cấu trúc để trích xuất thông tin từ sơ yếu lý lịch, chuẩn hoá thông tin đó để tạo cơ sở dữ liệu có cấu trúc.

Gemini có thể tạo JSON hoặc giá trị enum dưới dạng đầu ra có cấu trúc.

Tạo JSON

Có 2 cách để tạo JSON bằng Gemini API:

  • Định cấu hình giản đồ trên mô hình
  • Cung cấp một giản đồ trong câu lệnh dạng văn bản

Định cấu hình giản đồ trên mô hình là cách được đề xuất để tạo JSON, vì cách này hạn chế mô hình xuất JSON.

Định cấu hình giản đồ (nên dùng)

Để hạn chế mô hình tạo JSON, hãy định cấu hình responseSchema. Sau đó, mô hình sẽ phản hồi mọi câu lệnh bằng đầu ra ở định dạng JSON.

Python

from google import genai
from pydantic import BaseModel

class Recipe(BaseModel):
    recipe_name: str
    ingredients: list[str]

client = genai.Client()
response = client.models.generate_content(
    model="gemini-2.5-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

JavaScript

import { GoogleGenAI, Type } from "@google/genai";

const ai = new GoogleGenAI({});

async function main() {
  const response = await ai.models.generateContent({
    model: "gemini-2.5-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();

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

    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.5-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())
}

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' \
-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

Đầu ra có thể như sau:

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

Cung cấp một giản đồ trong câu lệnh dạng văn bản

Thay vì định cấu hình một giản đồ, bạn có thể cung cấp giản đồ dưới dạng ngôn ngữ tự nhiên hoặc mã giả trong một câu lệnh dạng văn bản. Bạn không nên sử dụng phương pháp này vì phương pháp này có thể tạo ra đầu ra có chất lượng thấp hơn và vì mô hình không bị ràng buộc phải tuân theo lược đồ.

Sau đây là ví dụ chung về một giản đồ được cung cấp trong câu lệnh dạng văn bản:

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>

Vì mô hình lấy giản đồ từ văn bản trong câu lệnh, nên bạn có thể linh hoạt trong cách biểu thị giản đồ. Nhưng khi bạn cung cấp một giản đồ nội tuyến như thế này, mô hình sẽ không thực sự bị hạn chế trả về JSON. Để có phản hồi chất lượng cao và mang tính xác định hơn, hãy định cấu hình một giản đồ trên mô hình và không sao chép giản đồ trong câu lệnh văn bản.

Tạo giá trị enum

Trong một số trường hợp, bạn có thể muốn mô hình chọn một lựa chọn duy nhất trong danh sách các lựa chọn. Để triển khai hành vi này, bạn có thể truyền một enum trong giản đồ của mình. Bạn có thể sử dụng một lựa chọn enum ở bất cứ nơi nào bạn có thể sử dụng string trong responseSchema, vì enum là một mảng gồm các chuỗi. Giống như giản đồ JSON, enum cho phép bạn giới hạn đầu ra của mô hình để đáp ứng các yêu cầu của ứng dụng.

Ví dụ: giả sử bạn đang phát triển một ứng dụng để phân loại nhạc cụ thành một trong 5 danh mục: "Percussion", "String", "Woodwind", "Brass" hoặc ""Keyboard"". Bạn có thể tạo một enum để hỗ trợ tác vụ này.

Trong ví dụ sau, bạn sẽ truyền một enum làm responseSchema, hạn chế mô hình chọn lựa chọn phù hợp nhất.

Python

from google import genai
import enum

class Instrument(enum.Enum):
  PERCUSSION = "Percussion"
  STRING = "String"
  WOODWIND = "Woodwind"
  BRASS = "Brass"
  KEYBOARD = "Keyboard"

client = genai.Client()
response = client.models.generate_content(
    model='gemini-2.5-flash',
    contents='What type of instrument is an oboe?',
    config={
        'response_mime_type': 'text/x.enum',
        'response_schema': Instrument,
    },
)

print(response.text)
# Woodwind

JavaScript

import { GoogleGenAI, Type } from "@google/genai";

const ai = new GoogleGenAI({});

const response = await ai.models.generateContent({
    model: "gemini-2.5-flash",
    contents: "What type of instrument is an oboe?",
    config: {
      responseMimeType: "text/x.enum",
      responseSchema: {
        type: Type.STRING,
        enum: ["Percussion", "String", "Woodwind", "Brass", "Keyboard"],
      },
    },
  });

console.log(response.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' \
    -d '{
          "contents": [{
            "parts":[
              { "text": "What type of instrument is an oboe?" }
            ]
          }],
          "generationConfig": {
            "responseMimeType": "text/x.enum",
            "responseSchema": {
              "type": "STRING",
              "enum": ["Percussion", "String", "Woodwind", "Brass", "Keyboard"]
            }
          }
    }'

Thư viện Python sẽ dịch các khai báo loại cho API. Tuy nhiên, API này chấp nhận một tập hợp con của giản đồ OpenAPI 3.0 (Giản đồ).

Có 2 cách khác để chỉ định một phép liệt kê. Bạn có thể sử dụng Literal: ```

Python

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

Bạn cũng có thể truyền giản đồ dưới dạng JSON:

Python

from google import genai

client = genai.Client()
response = client.models.generate_content(
    model='gemini-2.5-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

Ngoài các bài toán trắc nghiệm cơ bản, bạn có thể sử dụng một enum ở bất kỳ vị trí nào trong một giản đồ JSON. Ví dụ: bạn có thể yêu cầu mô hình đưa ra danh sách tiêu đề công thức và sử dụng một enum Grade để cho mỗi tiêu đề một điểm phổ biến:

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()
response = client.models.generate_content(
    model='gemini-2.5-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)

Phản hồi có thể như sau:

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

Giới thiệu về giản đồ JSON

Việc định cấu hình mô hình cho đầu ra JSON bằng cách sử dụng tham số responseSchema dựa vào đối tượng Schema để xác định cấu trúc của mô hình. Đối tượng này đại diện cho một tập hợp con được chọn của Đối tượng lược đồ OpenAPI 3.0, đồng thời thêm trường propertyOrdering.

Sau đây là một biểu diễn giả định về JSON của tất cả các trường 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 của giản đồ phải là một trong các Kiểu dữ liệu OpenAPI hoặc một tổ hợp của các kiểu đó (bằng cách sử dụng anyOf). Chỉ một tập hợp con của các trường là hợp lệ cho mỗi Type. Danh sách sau đây liên kết từng Type với một nhóm nhỏ các trường hợp lệ cho loại đó:

  • 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

Dưới đây là một số lược đồ mẫu cho thấy các tổ hợp kiểu và trường hợp lệ:

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

Để xem tài liệu đầy đủ về các trường Giản đồ khi được dùng trong Gemini API, hãy xem Tài liệu tham khảo về giản đồ.

Sắp xếp tài sản

Khi bạn làm việc với giản đồ JSON trong Gemini API, thứ tự của các thuộc tính là rất quan trọng. Theo mặc định, API sắp xếp các thuộc tính theo bảng chữ cái và không giữ nguyên thứ tự xác định các thuộc tính (mặc dù Google Gen AI SDK có thể giữ nguyên thứ tự này). Nếu bạn đang cung cấp các ví dụ cho mô hình có một lược đồ được định cấu hình và thứ tự thuộc tính của các ví dụ không nhất quán với thứ tự thuộc tính của lược đồ, thì đầu ra có thể dài dòng hoặc không mong muốn.

Để đảm bảo thứ tự nhất quán và có thể dự đoán của các thuộc tính, bạn có thể sử dụng trường propertyOrdering[] không bắt buộc.

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

propertyOrdering[] – không phải là một trường tiêu chuẩn trong quy cách OpenAPI – là một mảng gồm các chuỗi dùng để xác định thứ tự của các thuộc tính trong phản hồi. Bằng cách chỉ định thứ tự của các thuộc tính rồi cung cấp ví dụ có các thuộc tính theo cùng thứ tự đó, bạn có thể cải thiện chất lượng của kết quả. propertyOrdering chỉ được hỗ trợ khi bạn tạo types.Schema theo cách thủ công.

Giản đồ trong Python

Khi bạn sử dụng thư viện Python, giá trị của response_schema phải là một trong những giá trị sau:

  • Một loại, như bạn sẽ sử dụng trong chú giải kiểu (xem mô-đun typing của Python)
  • Một phiên bản của genai.types.Schema
  • dict tương đương với genai.types.Schema

Cách dễ nhất để xác định một lược đồ là dùng một loại Pydantic (như trong ví dụ trước):

Python

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

Khi bạn sử dụng một loại Pydantic, thư viện Python sẽ tạo một lược đồ JSON cho bạn và gửi lược đồ đó đến API. Để xem thêm ví dụ, hãy xem tài liệu về thư viện Python.

Thư viện Python hỗ trợ các giản đồ được xác định bằng các loại sau (trong đó AllowedType là mọi loại được phép):

  • int
  • float
  • bool
  • str
  • list[AllowedType]
  • AllowedType|AllowedType|...
  • Đối với các loại có cấu trúc:
    • dict[str, AllowedType]. Chú thích này khai báo tất cả các giá trị từ điển đều thuộc cùng một loại, nhưng không chỉ định những khoá cần được đưa vào.
    • Mô hình Pydantic do người dùng xác định. Phương pháp này cho phép bạn chỉ định tên khoá và xác định các loại khác nhau cho các giá trị được liên kết với từng khoá, bao gồm cả các cấu trúc lồng nhau.

Hỗ trợ Giản đồ JSON

Giản đồ JSON là một quy cách gần đây hơn so với OpenAPI 3.0, mà đối tượng Giản đồ dựa trên đó. Chúng tôi hỗ trợ Giản đồ JSON dưới dạng bản xem trước bằng cách sử dụng trường responseJsonSchema. Trường này chấp nhận mọi Giản đồ JSON với các giới hạn sau:

  • Chỉ hoạt động với Gemini 2.5.
  • Mặc dù bạn có thể truyền tất cả các thuộc tính của JSON Schema, nhưng không phải thuộc tính nào cũng được hỗ trợ. Hãy xem tài liệu để biết thêm thông tin chi tiết về trường này.
  • Bạn chỉ có thể dùng các giá trị tham chiếu đệ quy làm giá trị của một thuộc tính đối tượng không bắt buộc.
  • Các tham chiếu đệ quy được mở ra ở một mức độ hữu hạn, dựa trên kích thước của lược đồ.
  • Những giản đồ chứa $ref không được chứa bất kỳ thuộc tính nào khác ngoài những thuộc tính bắt đầu bằng $.

Sau đây là ví dụ về cách tạo một JSON Schema bằng Pydantic và gửi nó đến mô hình:

curl "https://generativelanguage.googleapis.com/v1alpha/models/\
gemini-2.5-flash:generateContent" \
    -H "x-goog-api-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

Khi sử dụng SDK, bạn chưa thể truyền trực tiếp JSON Schema.

Các phương pháp hay nhất

Hãy lưu ý những điểm cần cân nhắc và phương pháp hay nhất sau đây khi bạn sử dụng giản đồ phản hồi:

  • Kích thước của giản đồ phản hồi được tính vào giới hạn mã thông báo đầu vào.
  • Theo mặc định, các trường là không bắt buộc, nghĩa là mô hình có thể điền sẵn các trường hoặc bỏ qua chúng. Bạn có thể đặt các trường là bắt buộc để buộc mô hình cung cấp một giá trị. Nếu không có đủ ngữ cảnh trong câu lệnh đầu vào được liên kết, thì mô hình sẽ tạo câu trả lời chủ yếu dựa trên dữ liệu mà mô hình được huấn luyện.
  • Một giản đồ phức tạp có thể dẫn đến lỗi InvalidArgument: 400. Độ phức tạp có thể đến từ tên thuộc tính dài, giới hạn độ dài mảng dài, các enum có nhiều giá trị, các đối tượng có nhiều thuộc tính không bắt buộc hoặc sự kết hợp của các yếu tố này.

    Nếu bạn gặp lỗi này với một giản đồ hợp lệ, hãy thực hiện một hoặc nhiều thay đổi sau đây để giải quyết lỗi:

    • Rút ngắn tên thuộc tính hoặc tên enum.
    • Làm phẳng các mảng lồng nhau.
    • Giảm số lượng thuộc tính có các ràng buộc, chẳng hạn như số có giới hạn tối thiểu và tối đa.
    • Giảm số lượng thuộc tính có các ràng buộc phức tạp, chẳng hạn như thuộc tính có định dạng phức tạp như date-time.
    • Giảm số lượng thuộc tính không bắt buộc.
    • Giảm số lượng giá trị hợp lệ cho các enum.
  • Nếu bạn không thấy kết quả như mong đợi, hãy thêm ngữ cảnh vào câu lệnh đầu vào hoặc sửa đổi giản đồ phản hồi. Ví dụ: xem xét phản hồi của mô hình mà không có đầu ra có cấu trúc để xem cách mô hình phản hồi. Sau đó, bạn có thể cập nhật giản đồ phản hồi để phù hợp hơn với đầu ra của mô hình. Để biết thêm các mẹo khắc phục sự cố về đầu ra có cấu trúc, hãy xem hướng dẫn khắc phục sự cố.

Bước tiếp theo

Giờ đây, khi đã biết cách tạo đầu ra có cấu trúc, bạn có thể muốn thử sử dụng các công cụ Gemini API: