Structured Outputs
구조화된 출력은 디코딩 중 AI 모델의 응답을 JSON Schema와 같은 스키마로 제한하므로 애플리케이션이 모든 응답을 안정적으로 파싱할 수 있습니다.
구조화된 출력은 미리 정의된 형식을 따르도록 제약된 모델 응답으로, 보통 필수 키와 유형, 허용 값을 지정하는 JSON 스키마를 사용하므로 소프트웨어가 별도 정리 없이 모든 응답을 파싱할 수 있습니다. 대규모 언어 모델(LLM)에 JSON을 요청하면 대체로 따르지만, 문장을 덧붙이거나 키의 철자를 틀리거나 객체를 완성하기 전에 출력을 멈출 수 있으며, 이 중 어느 하나라도 응답을 읽는 프로그램을 중단시킵니다. 구조화된 출력은 제약 디코딩으로 이러한 위험을 제거합니다. 생성 단계마다 추론 엔진은 스키마에 맞는 출력을 유지하는 토큰만 허용합니다. OpenAI는 2024년 8월 API에 이 기능을 추가하면서, 구조화된 출력을 적용한 gpt-4o-2024-08-06이 복잡한 JSON 스키마 준수 평가에서 100%를 기록했다고 밝혔습니다. 이는 기능을 적용하지 않은 GPT-4(gpt-4-0613)의 40% 미만과 비교됩니다.
JSON 모드와 구조화된 출력 비교#
제공업체 API는 두 가지 수준의 보장을 제공합니다. OpenAI가 2023년 11월 도입한 JSON 모드는 응답이 구문상 올바른 JSON임을 보장할 뿐이므로 키가 누락되거나 잘못된 이름으로 작성될 수 있습니다. 구조화된 출력은 응답이 제공된 스키마와 일치하도록 보장합니다. OpenAI의 Structured Outputs API에서는 개발자가 Python의 Pydantic 모델이나 JavaScript의 Zod 객체로 스키마를 정의하며, 거부 응답은 형식을 깨뜨리지 않고 별도 필드로 전달됩니다. Anthropic의 Claude 구조화된 출력은 각 스키마를 문법으로 컴파일합니다. 스키마를 처음 사용할 때 지연 시간이 늘어나지만, 컴파일된 문법은 24시간 동안 캐시됩니다. 두 제공업체 모두 JSON Schema의 하위 집합만 지원합니다. 예를 들어 Anthropic은 재귀 스키마나 minimum과 같은 숫자 제한을 지원하지 않습니다.
제약 디코딩의 작동 방식#
각 단계에서 LLM은 어휘에 있는 모든 토큰의 점수, 즉 로짓을 생성하고, 디코딩은 결과 소프트맥스 분포에서 토큰을 선택합니다. 제약 디코딩은 형식을 깨뜨리는 모든 토큰의 점수를 먼저 음의 무한대로 설정하므로 해당 토큰은 선택될 수 없습니다. Brandon Willard와 Rémi Louf는 대규모 언어 모델을 위한 효율적인 가이드 생성에서 이를 효율적으로 수행하는 방법을 보였습니다. 정규 표현식이나 JSON Schema를 유한 상태 기계로 컴파일하고, 어휘에 대해 한 번 구축한 인덱스에 각 상태에서 유효한 토큰을 나열해 매 단계마다 조회만 수행합니다. 오픈 소스 Outlines 라이브러리가 이 방법을 구현하며, vLLM과 같은 서빙 엔진은 오픈 모델용 문법 기반 생성을 제공합니다.
다음 예제는 Hugging Face Transformers의 GPT-2에 이 아이디어를 직접 적용합니다. 중괄호, 키, 따옴표와 같은 스키마의 고정 텍스트는 코드가 작성하며, 각 값에서 모델은 스키마가 허용하는 토큰만 선택할 수 있습니다.
import json
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")
prompt = "Review: The battery died after two days and support never replied.\nJSON:"
# 제약 없는 그리디 디코딩: 응답을 스키마에 맞추도록 강제하는 요소가 없습니다
ids = tokenizer(prompt, return_tensors="pt").input_ids
free = model.generate(ids, max_new_tokens=16, do_sample=False, pad_token_id=tokenizer.eos_token_id)
print("free:", repr(tokenizer.decode(free[0, ids.shape[1] :])))
def choose(text, options):
"""Return the option GPT-2 scores highest after text, with every other token masked out."""
logits = model(tokenizer(text, return_tensors="pt").input_ids).logits[0, -1]
allowed = torch.tensor([tokenizer.encode(option)[0] for option in options])
masked = torch.full_like(logits, float("-inf"))
masked[allowed] = logits[allowed]
return tokenizer.decode(masked.argmax())
# 제약 디코딩: 스키마가 키를 작성하고 모델은 허용된 값만 선택할 수 있습니다
with torch.no_grad():
text = prompt + ' {"sentiment": "'
text += choose(text, ["positive", "negative"]) + '", "stars": '
text += choose(text, ["1", "2", "3", "4", "5"]) + "}"
print("constrained:", json.loads(text[len(prompt) :]))이 코드는 free: ' The battery died after two days and support never replied.\n\nJSON: The'과 constrained: {'sentiment': 'positive', 'stars': 1}을 출력합니다. GPT-2를 제약 없이 실행하면 JSON 대신 리뷰를 반복하지만, 제약 버전은 항상 파싱됩니다. 파싱된 결과는 이 기법의 한계도 보여줍니다. 1억 2,400만 개 파라미터의 모델은 배터리가 방전되고 지원팀이 응답하지 않는 상황을 별점 1점으로 평가했습니다. 스키마는 형식을 고정했지만, 그 안의 값은 여전히 모델 자체의 판단에서 나왔습니다.
활용 사례와 절충점#
- 데이터 추출: 인보이스, 계약서 또는 이메일에서 이름, 날짜, 합계, 항목을 추출해 데이터베이스 행에 직접 입력합니다.
- 함수 호출: 도구 호출은 도구의 매개변수를 스키마로 사용하는 구조화된 출력입니다. OpenAI 및 Anthropic API의 엄격한 도구 사용은 도구 인수에도 같은 보장을 적용합니다.
- 에이전트 워크플로: 라우팅 결정을 열거형 값으로 표현하고, 프롬프트 체인의 단계 사이에 전달되는 중간 결과를 유형이 지정된 객체로 표현합니다.
- 비전-언어 모델: 탐지 결과를 레이블과 박스 좌표 목록으로 반환해 시각화 또는 평가 코드에서 바로 사용할 수 있습니다.
Ultralytics Platform의 클래스 프롬프트 기반 스마트 어노테이션은 마지막 유형의 출력을 사용합니다. OpenAI, Anthropic, Google 등의 공급자가 제공하는 비전 모델에 데이터셋의 클래스를 탐지하도록 요청하고, 반환된 각 객체를 편집 가능한 바운딩 박스로 추가합니다. 따라서 각 응답에는 클래스 이름과 코드로 파싱할 수 있는 형식의 좌표가 포함되어야 합니다. 이러한 모델은 신뢰도 점수를 반환하지 않으므로, 모델을 선택하면 Platform에서 신뢰도 및 IoU 설정이 숨겨집니다. VLM 리더보드는 실제 데이터셋에서 이러한 모델이 객체를 얼마나 정확하게 탐지하는지 비교하고, 각 모델이 나열한 순서대로 박스의 순위를 매깁니다.
엄격한 형식은 추론 작업의 정확도를 떨어뜨릴 수 있습니다. 자유롭게 말해도 될까요?에서 Zhi Rui Tam과 동료들은 형식 제약이 있을 때 LLM 추론 성능이 크게 저하되며, 제약이 엄격할수록 하락 폭도 커진다는 사실을 발견했습니다. OpenAI API는 스키마에 나열된 순서대로 키를 생성하므로, 일반적인 해결책은 답변 필드 앞에 자유 형식 추론 필드를 배치해 모델이 제약된 답변을 확정하기 전에 연쇄 사고를 작성하도록 하는 것입니다.










