Qwen 구조화 출력: JSON Schema로 출력 형태 고정하기
Qwen 구조화 출력: JSON Schema로 출력 형태 고정하기
정보 추출이나 구조화 데이터 생성에서 모델이 ```json 래퍼 같은 부가 텍스트를 섞으면 파싱이 깨져요. 구조화 출력을 켜면 모델이 항상 유효한 JSON 문자열을 반환하고, JSON Schema 모드는 출력 구조와 타입까지 정밀하게 고정해서 별도 검증·재시도 없이 쓸 수 있게 해줍니다. 이 문서는 두 모드의 차이와 응답 형식 설정을 안내해요.
두 가지 모드
| 기능 | JSON Object 모드 | JSON Schema 모드 |
|---|---|---|
| 유효한 JSON 출력 | Yes | Yes |
| 스키마를 엄격히 따름 | No | Yes |
| 지원 모델 | 대부분의 Qwen, Kimi, GLM, DeepSeek | 일부 모델만 |
response_format 설정 |
{"type": "json_object"} |
{"type": "json_schema", "json_schema": {…, "strict": true}} |
| 프롬프트 요구사항 | 반드시 "JSON" 포함 | 명시적으로 기술 권장 |
| 사용 사례 | 유연한 JSON 출력 | 정밀한 스키마 검증 |
JSON Object 모드는 유효한 JSON 문자열을 보장하지만 특정 구조까지는 보장하지 않아요. 쓰는 방법은 두 가지 조건을 지키면 되죠.
- 요청 본문의
response_format을{"type": "json_object"}로 설정 - system 또는 user 메시지에 "JSON"이라는 단어(대소문자 무관)를 포함
"JSON" 단어가 없으면 API가 이렇게 거부해요: 'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.
JSON Schema 모드는 지정한 구조를 따르는 출력을 보장해요. response_format을 {"type": "json_schema", "json_schema": {…, "strict": true}}로 설정하세요. 이 모드에서는 프롬프트에 "JSON" 키워드가 필요 없습니다.
지원 모델 요약
JSON Object는 대부분의 Qwen 텍스트 생성 모델(Qwen3.8/3.7/3.6/3.5 계열, Qwen-Turbo(비-thinking) 등), Qwen-Coder 계열, Qwen-Long 계열, Qwen3.8 오픈소스 계열, 그리고 kimi-k3, kimi-k2-thinking, glm-5.1, deepseek-v4-pro-0813 같은 서드파티 모델에서 지원돼요.
⚠️ "비-thinking 모드"로 분류된 모델은 thinking 모드에서 response_format을 {"type": "json_object"}로 설정해도 오류는 나지 않지만, 구조화 출력이 효과를 발휘하지 않을 수 있어요. 이런 모델에서 확실히 유효한 JSON을 얻으려면 FAQ의 2단계 보정법을 쓰세요.
JSON Schema는 Qwen3.8-Max 계열, Qwen3.8-Flash 계열, Qwen3.7-Max 계열, Qwen3.7-Plus 계열, Qwen3.7-Flash 계열에서 지원돼요.
시작하기 (JSON Object 모드)
프로필에서 이름과 나이를 추출하는 예시예요. response_format={"type": "json_object"}만 추가하면 됩니다.
from openai import OpenAI
import os
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="qwen3.8-max",
messages=[
{"role": "system", "content": "Extract the user's name and age, and return them in JSON format"},
{"role": "user", "content": "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is [email protected]"},
],
response_format={"type": "json_object"},
)
print(completion.choices[0].message.content)
응답은 이렇게 옵니다.
{
"name": "Alex Brown",
"age": 34
}
JSON Object 모드는 키 이름이나 필드 타입을 안정적으로 보장하지 않기 때문에 프롬프트·호출에 따라 결과가 달라질 수 있어요. 구조를 반드시 고정해야 하면 JSON Schema 모드를 쓰세요.
thinking 모드에서 구조화 출력 얻기 (2단계 보정)
"비-thinking 모드" 라벨이 붙은 모델은 thinking이 켜지면 엄밀히 유효한 JSON이 아닌 내용을 반환할 수 있어요. 이때는 두 단계로 접근합니다.
- 1단계: thinking 모드로 고품질 출력을 얻기. 이 예시는
response_format을 의도적으로 생략한 폴백인데,stream=True가 필수예요. 청크의delta.content를 누적해json_string을 만듭니다. - 2단계:
json.loads(json_string)로 파싱을 시도해 유효하면 그대로 쓰고, 실패하면 구조화 출력을 지원하는 저비용 모델(예: 비-thinking의qwen-flash에enable_thinking: False)로response_format={"type": "json_object"}을 걸어 고쳐달라고 합니다.
더 알아보기
- thinking 모드: Thinking
- 첫 호출: Generate text
- 오류 메시지 대응: Error messages