본문 바로가기
C.W.K.
Stream
Lesson 07 of 07 · published

Structured Outputs 와 Batch API

~22 min · structured-outputs, pydantic, batch

Level 0Tokenizer
0 XP0/54 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

'JSON 으로 답해줘'라는 프롬프트만으로는 구조를 보장할 수 없어. 모델이 설명, code fence, 뒤쪽 문장을 덧붙이면 방어적인 parsing 과 재시도가 필요해져. Structured outputresponse_format 에 Pydantic schema 를 넣어 허용할 응답 구조를 정해.

프롬프트보다 강한 이유

schema 는 server 에서 강제돼. 구조에 맞지 않는 출력은 API 가 받아들이지 않고 다시 생성하게 하며, 호출 코드는 검증된 Pydantic instance 를 받아. 별도의 방어적 parsing 을 크게 줄일 수 있어.

Batch API 는 기다리는 대신 50% 할인돼

수만 개의 prompt 를 처리해야 하지만 사용자가 즉시 기다리는 작업이 아니라면 Batch API 를 검토해. JSONL 을 올리면 최대 24 시간 안에 처리되고 결과 JSONL 을 받을 수 있으며 비용은 50% 할인돼. 채팅에는 맞지 않지만 eval, dataset 생성, moderation backfill 에 잘 맞아.

두 방식을 직접 비교해봐

같은 작업을 프롬프트만으로 JSON 을 요구하는 방식과 response_format 방식으로 각각 실행해 실패율을 재봐. 보통 프롬프트만 쓰면 1~3%가 실패하지만 response_format 은 거의 0에 가까워. 작은 실패율도 운영 환경에서는 반복되는 경고와 복구 작업이 되므로 구조를 강제하는 가치가 드러날 거야.

Code

Pydantic 으로 response_format structured output·python
from pydantic import BaseModel
from openai import OpenAI

client = OpenAI()

class ResearchSummary(BaseModel):
    title: str
    key_findings: list[str]
    conclusion: str
    confidence_score: float

# Using responses.parse() for structured output
response = client.responses.parse(
    model="gpt-5.4",
    input="Summarize the key findings of quantum computing research.",
    text_format=ResearchSummary,
)
summary: ResearchSummary = response.output_parsed
print(summary.title)
print(summary.key_findings)
Batch API: submit + poll + retrieve·python
import json
from openai import OpenAI

client = OpenAI()

# 1. Create JSONL batch file
requests = [
    {"custom_id": f"request-{i}", "method": "POST", "url": "/v1/responses",
     "body": {"model": "gpt-5.4", "input": f"Summarize: {text}"}}
    for i, text in enumerate(texts)
]
with open("batch_input.jsonl", "w") as f:
    for req in requests:
        f.write(json.dumps(req) + "\\n")

# 2. Upload → Create batch → Poll → Retrieve
with open("batch_input.jsonl", "rb") as f:
    batch_file = client.files.create(file=f, purpose="batch")
batch = client.batches.create(
    input_file_id=batch_file.id,
    endpoint="/v1/responses",
    completion_window="24h",
)

External links

Exercise

Pydantic 모델 RecipeCard{title:str, prep_min:int, ingredients:list[str], steps:list[str]} 를 정의해. 레시피 다섯 개를 (1) response_format 과 (2) 직접 만든 프롬프트 + json.loads 로 각각 받은 뒤 실패율을 비교해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.