비정형 텍스트 대신 구조화된 출력용으로 Gemini를 구성하면 추가 처리를 위해 정보를 정확하게 추출하고 표준화할 수 있습니다. 예를 들어 구조화된 출력을 사용하여 이력서에서 정보를 추출하고 표준화하여 구조화된 데이터베이스를 만들 수 있습니다.
Gemini는 JSON 또는 enum 값을 구조화된 출력으로 생성할 수 있습니다.
JSON 생성
Gemini API를 사용하여 JSON을 생성하는 방법에는 두 가지가 있습니다.
- 모델에서 스키마 구성
- 텍스트 프롬프트에 스키마 제공
모델에서 스키마를 구성하는 것은 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>
모델은 프롬프트의 텍스트에서 스키마를 가져오므로 스키마를 표현하는 방법에 약간의 유연성이 있을 수 있습니다. 하지만 이와 같이 스키마를 인라인으로 제공하면 모델은 실제로 JSON을 반환하도록 제약되지 않습니다. 더 결정론적이고 품질이 우수한 응답을 얻으려면 모델에서 스키마를 구성하고 텍스트 프롬프트에서 스키마를 복제하지 마세요.
enum 값 생성
경우에 따라 모델이 옵션 목록에서 하나의 옵션을 선택하도록 할 수 있습니다. 이 동작을 구현하려면 스키마에서 enum을 전달하면 됩니다. enum은 문자열 배열이므로 responseSchema
에서 string
를 사용할 수 있는 모든 위치에서 enum 옵션을 사용할 수 있습니다. JSON 스키마와 마찬가지로 enum을 사용하면 애플리케이션 요구사항을 충족하도록 모델 출력을 제한할 수 있습니다.
예를 들어 악기를 "Percussion"
, "String"
, "Woodwind"
, "Brass"
, "Keyboard"
의 5가지 카테고리 중 하나로 분류하는 애플리케이션을 개발한다고 가정해 보겠습니다. 이 작업을 돕는 enum을 만들 수 있습니다.
다음 예에서는 enum을 responseSchema
로 전달하여 모델이 가장 적절한 옵션을 선택하도록 제한합니다.
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 스키마(스키마)의 하위 집합을 허용합니다.
열거형을 지정하는 다른 두 가지 방법이 있습니다. Literal
를 사용하면 다음과 같은 작업을 할 수 있습니다.
Literal["Percussion", "String", "Woodwind", "Brass", "Keyboard"]
스키마를 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
기본 객관식 문제 외에도 JSON 스키마의 어디서나 enum을 사용할 수 있습니다. 예를 들어 모델에 레시피 제목 목록을 요청하고 Grade
enum을 사용하여 각 제목에 인기도 등급을 부여할 수 있습니다.
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 스키마 정보
responseSchema
매개변수를 사용하여 JSON 출력용 모델을 구성하려면 Schema
객체를 사용하여 구조를 정의해야 합니다. 이 객체는 OpenAPI 3.0 스키마 객체의 일부 하위 집합을 나타내며 propertyOrdering
필드를 추가합니다.
다음은 모든 Schema
필드의 가상 JSON 표현입니다.
{
"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"]
}
Gemini API에서 사용되는 스키마 필드에 관한 전체 문서는 스키마 참조를 참고하세요.
숙박 시설 정렬
Gemini API에서 JSON 스키마를 사용할 때는 속성 순서가 중요합니다. 기본적으로 API는 속성을 알파벳순으로 정렬하며 속성이 정의된 순서를 유지하지 않습니다 (Google 생성형 AI SDK는 이 순서를 유지할 수 있음). 스키마가 구성된 모델에 예시를 제공하는 경우 예시의 속성 순서가 스키마의 속성 순서와 일치하지 않으면 출력이 장황하거나 예상치 못할 수 있습니다.
일관되고 예측 가능한 속성 순서를 보장하려면 선택적 propertyOrdering[]
필드를 사용하면 됩니다.
"propertyOrdering": ["recipeName", "ingredients"]
propertyOrdering[]
: OpenAPI 사양의 표준 필드가 아니며 응답에서 속성의 순서를 결정하는 데 사용되는 문자열 배열입니다. 속성의 순서를 지정한 다음 동일한 순서로 속성이 포함된 예시를 제공하면 결과 품질을 개선할 수 있습니다. propertyOrdering
는 types.Schema
를 수동으로 만드는 경우에만 지원됩니다.
Python의 스키마
Python 라이브러리를 사용하는 경우 response_schema
값은 다음 중 하나여야 합니다.
- 유형 주석에서 사용하는 유형입니다 (Python
typing
모듈 참고). genai.types.Schema
의 인스턴스genai.types.Schema
에 상응하는dict
스키마를 정의하는 가장 쉬운 방법은 Pydantic 유형을 사용하는 것입니다 (이전 예 참고).
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
오류가 발생할 수 있습니다. 복잡성은 긴 속성 이름, 긴 배열 길이 제한, 값이 많은 enum, 선택적 속성이 많은 객체 또는 이러한 요소의 조합에서 비롯될 수 있습니다.유효한 스키마로 이 오류가 발생하면 다음 중 하나 이상을 변경하여 오류를 해결합니다.
- 속성 이름이나 enum 이름을 줄입니다.
- 중첩된 배열을 평탄화합니다.
- 최저 한도 및 최대 한도가 있는 숫자와 같이 제약 조건이 있는 속성 수를 줄입니다.
date-time
과 같이 형식이 복잡한 속성 등 복잡한 제약 조건이 있는 속성 수를 줄입니다.- 선택적 속성 수를 줄입니다.
- enum의 유효한 값 수를 줄입니다.
예상한 결과가 표시되지 않으면 입력 프롬프트에 더 많은 컨텍스트를 추가하거나 응답 스키마를 수정합니다. 예를 들어 구조화된 출력 없이 모델 응답을 검토하여 모델이 응답하는 방식을 확인합니다. 그런 다음 모델 출력에 더 적합하도록 응답 스키마를 업데이트할 수 있습니다.
다음 단계
이제 구조화된 출력을 생성하는 방법을 알아봤으므로 Gemini API 도구를 사용해 보세요.