구조화된 출력
구조화된 출력 (Structured Outputs)
채팅 모델이 보통은 평범한 텍스트를 돌려주는데, 애플리케이션이 응답에서 특정 필드를 읽어야 한다면 파싱이 쉽지 않죠. 구조화된 출력을 지원하는 모델은 여러분이 지정한 아무 스키마에나 맞는 JSON을 돌려줘서, 재시도나 취약한 파싱 없이 코드에서 바로 읽을 수 있어요. 스키마는 채팅 완성 요청의 response_format 키로 전달해요.
지원 모델
구조화된 출력을 지원하는 모델의 최신 목록은 서버리스 모델 및 전용 모델 추론 카탈로그에서 확인할 수 있어요.
기본 예시
음성 녹음의 대본을 모델에 넘겨, 요약을 이런 모양으로 돌려달라고 해볼게요.
{
"title": "A title for the voice note",
"summary": "A short one-sentence summary of the voice note",
"actionItems": ["Action item 1", "Action item 2"]
}
구조를 강제하려면 모델에 JSON Schema를 주면 돼요. JSON Schema를 손으로 쓰는 건 지루하니 헬퍼 라이브러리를 쓰길 권해요. 파이썬은 Pydantic, TypeScript는 Zod를 사용해요.
스키마를 시스템 프롬프트에 넣고 response_format 키로도 전달해요.
import json
import together
from pydantic import BaseModel, Field
client = together.Together()
# Define the schema for the output
class VoiceNote(BaseModel):
title: str = Field(description="A title for the voice note")
summary: str = Field(
description="A short one sentence summary of the voice note."
)
actionItems: list[str] = Field(
description="A list of action items from the voice note"
)
def main():
transcript = (
"Good morning! It's 7:00 AM, and I'm just waking up. Today is going to be a busy day, "
"so let's get started. First, I need to make a quick breakfast. I think I'll have some "
"scrambled eggs and toast with a cup of coffee. While I'm cooking, I'll also check my "
"emails to see if there's anything urgent."
)
# Call the LLM with the JSON schema
extract = client.chat.completions.create(
messages=[
{
"role": "system",
"content": f"The following is a voice message transcript. Only answer in JSON and follow this schema {json.dumps(VoiceNote.model_json_schema())}.",
},
{
"role": "user",
"content": transcript,
},
],
model="Qwen/Qwen3.5-9B",
reasoning={"enabled": False},
response_format={
"type": "json_schema",
"json_schema": {
"name": "voice_note",
"schema": VoiceNote.model_json_schema(),
},
},
)
output = json.loads(extract.choices[0].message.content)
print(json.dumps(output, indent=2))
return output
main()
curl -X POST https://api.together.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ***" \
-d '{
"messages": [
{ "role": "system", "content": "The following is a voice message transcript. Only answer in JSON." },
{ "role": "user", "content": "Good morning! It's 7:00 AM, and I'm just waking up..." }
],
"model": "Qwen/Qwen3.5-9B",
"reasoning": {"enabled": false},
"response_format": {
"type": "json_schema",
"json_schema": { "name": "voice_note", "schema": { ... } }
}
}'
모델은 스키마와 일치하는 출력으로 응답해요.
{
"title": "Morning Routine",
"summary": "Starting the day with a quick breakfast and checking emails",
"actionItems": [
"Cook scrambled eggs and toast",
"Brew a cup of coffee",
"Check emails for urgent messages"
]
}
모델에게 지시하기
모델에게 JSON으로만 답하라고 알려주고, 스키마의 평문 복사본을 프롬프트(시스템 프롬프트 또는 사용자 메시지)에 꼭 포함하세요. 이 지시는 response_format 파라미터로 스키마를 넘기는 것과 별개로, 추가로 보내는 거예요.
"JSON으로 응답하라"는 명시적 지시, 프롬프트 속 스키마 텍스트, 그리고 response_format 설정이 합쳐지면 매번 일관되고 유효한 JSON을 얻을 수 있어요.
정규식 (Regex) 예시
JSON 모드를 지원하는 모든 모델은 정규식 모드도 지원해요. 아래 예시는 정규식으로 감정 분류를 세 라벨 중 하나로 제한하고 있어요.
import together
client = together.Together()
completion = client.chat.completions.create(
model="meta-llama/Llama-3.3-70B-Instruct-Turbo",
messages=[
{
"role": "system",
"content": "You are an AI-powered expert specializing in classifying sentiment. You will be provided with a text, and your task is to classify its sentiment as positive, neutral, or negative.",
},
{"role": "user", "content": "Wow. I loved the movie!"},
],
response_format={
"type": "regex",
"pattern": "(positive|neutral|negative)",
},
)
print(completion.choices[0].message.content)
구조화된 출력은 reasoning 모델에서도 동작해요. 그리고 비전 모델과 결합하면 이미지에서 타입이 있는 데이터를 추출할 수도 있어요.
문제 해결
생성된 JSON이 잘려 나오거나, 이상한 문자가 섞이거나, 파싱에 실패한다면 보통 두 가지 원인 중 하나예요.
토큰 한도: 모델이 구조를 완성하기 전에 출력 예산을 다 쓸 수 있어요. 보내는 max_tokens를 모델 상한과 비교해 보고, 응답에서 finish_reason이 length인지 확인하세요. 모델이 잘라내면 스키마가 아무리 좋아도 JSON이 불완전해져요(끝나지 않은 문자열, 닫히지 않은 괄호). max_tokens를 올리거나 스키마를 단순화하세요.
잘못된 예시 JSON: 프롬프트에 예시 JSON 객체를 넣으면 모델이 그 예시를 그대로 따르는데, 문법 오류까지 그대로 따라가요. 프롬프트에 넣는 JSON은 사용 전에 반드시 검증하세요. 나쁜 예시의 전형적 증상은 끝나지 않은 문자열, 반복되는 줄바꿈, 반복되는 키, 또는 finish_reason: stop으로 갑자기 멈추는 출력이에요.
Together playground에서 스키마 테스트
Together 모델 플레이그라운드에서 스키마와 프롬프트의 변형을 테스트해 볼 수 있어요. 오른쪽 사이드바의 Response format 드롭다운을 열고 JSON을 선택한 뒤 Add schema를 눌러 스키마를 붙여넣으면 돼요.
더 알아보기 (Learn more)
- 채팅 완성 파라미터 —
response_format외 다른 파라미터를 함께 보려면 여기를 봐요. - 채팅 완성 보내기 — 기본 호출부터 스트리밍까지 익혀요.
- 채팅 완성 API 레퍼런스 —
response_format의 전체 스키마를 확인해요.