outputguard
요약
outputguard는 LLM이 생성하는 구조화된 출력(JSON, YAML 등)의 파싱 오류 문제를 해결하는 라이브러리입니다. 이 도구는 출력을 자동으로 유효성 검사하고, 복구하며, 필요시 재시도하여 안정적인 데이터 처리를 가능하게 합니다. 다양한 형식과 LLM의 비정형적 출력 패턴에 대응할 수 있는 15가지 복구 전략을 제공합니다.
핵심 포인트
- LLM의 불안정한 구조화된 출력을 자동으로 처리합니다.
- 유효성 검사(Validate), 복구(Repair), 재시도(Retry) 기능을 통합 제공합니다.
- JSON 외에도 YAML, TOML, Python 리터럴 등 다양한 형식에 대응 가능합니다.
- 개발자가 파서와 정규 표현식으로 해결하던 문제를 간소화합니다.
outputguard
깨진 LLM 구조화된 출력을 다루는 어려움에서 벗어나세요. 자동으로 유효성 검사(Validate), 복구(Repair), 재시도(Retry)합니다.
문제점 (The Problem)
LLM은 끊임없이 깨진 구조화된 출력을 생성합니다. JSON이 가장 흔한 경우이지만, 모델은 강제 JSON 설정이 꺼져 있을 때 YAML, TOML, Python 스타일 리터럴을 반환하기도 하며, 마크다운 펜스(markdown fences), 주석, 후행 쉼표(trailing commas), NaN, 잘린 객체(truncated objects) 등 사용자가 요청한 데이터 주변에 유용한 해설을 붙이기도 합니다. 모든 AI 애플리케이션은 결국 동일한 취약한 파서 + try/except + 정규 표현식(regex)의 연속을 작성하게 됩니다.
해결책 (The Solution)
import outputguard
schema = {
...
```json
{'name': 'Alice', 'age': 30,}
```"""
result = outputguard.validate_and_repair(llm_output, schema)
print(result.valid) # True
...
15가지 복구 전략, JSON Schema 유효성 검사, 재시도 프롬프트 생성 기능, 그리고 CLI를 통해 이제 JSON, YAML, TOML, Python 리터럴, 그리고 자동 감지된 강제-JSON-비활성화 출력에 대응할 수 있습니다.
설치 (Installation)
pip install outputguard
또는 uv를 사용하여:
uv add outputguard
문서화 (Documentation)
빠른 개요는 README로 시작하고, 정확한 동작 방식, API 시그니처 또는 명령어 예제가 필요할 때는 집중적인 가이드를 사용하세요:
- API 가이드 - 적절한 함수를 선택하고 결과 객체를 이해하세요.
- 시작하기 - 첫 번째 검증(validation), 복구(repair), 재시도(retry), 보호된 생성(guarded generation), 그리고 CLI 워크플로우.
- 개념 - 파싱, 검증, 복구, 재시도 및 형식 뒤에 숨겨진 정신적 모델(mental model).
- 형식 가이드 - JSON, YAML, TOML, Python 리터럴,
auto, 그리고forced-json-off. - 보호된 생성 가이드 - 검증, 복구, 재시도 및 관찰 가능성(observability)으로 LLM 호출을 감싸기.
- 배치 처리 가이드 - 한 번의 호출 또는 CLI에서 여러 출력을 검증하거나 복구하기.
- CLI 가이드 - 명령어, 플래그, 예시 및 종료 코드.
- 레시피 - 앱, 평가(evals), CI, 그리고 개인 정보 보호에 민감한 재시도를 위한 복사 붙여넣기 패턴.
- 문제 해결 - 일반적인 증상 및 수정 방법.
- 2.0으로 마이그레이션 - 호환성 참고 사항 및 채택 체크리스트.
- 변경 로그 - 릴리스 노트 및 2.0 마이그레이션 참고 사항.
2.0에서 새로워진 점 (What's New in 2.0)
OutputGuard 2.0은 JSON을 기본 경로로 유지하므로, 기존의 1.x 코드는 새로운 옵션을 전달하지 않고도 계속 작동합니다. 새로운 기능들은 선택적(opt-in)입니다:
- `format=
복구 전용 (Repair Only)
파싱 가능한 구조화된 출력만 필요하고 스키마가 없을 때:
result = outputguard.repair(broken_json)
print(result.text) # 기본적으로 깨끗한 JSON 문자열을 반환
print(result.strategies_applied) # ['fix_booleans', 'fix_commas']
검증 전용 (Validate Only)
복구를 시도하지 않고 구조화된 출력을 스키마와 비교하여 확인할 때:
result = outputguard.validate(llm_output, schema)
for error in result.errors:
print(f"{error.path}: {error.message}")
...
재시도 루프 (Retry Loop)
복구만으로는 충분하지 않을 때, 수정 프롬프트를 생성하여 LLM에 다시 전송합니다:
import outputguard
def get_structured_output(llm, prompt, schema, max_retries=3):
...
재시도 프롬프트는 LLM에게 무엇이 잘못되었는지 정확히 알려줍니다. 어떤 필드가 누락되었는지, 어떤 타입이 잘못되었는지, 그리고 스키마가 무엇을 기대하는지 말입니다. 모든 LLM 제공업체와 작동합니다. 기본적으로 이전 모델 출력을 Original output: 아래에 포함하며, 메시지 기록 없이 재시도 프롬프트를 원할 때는 include_message_history=False를 전달하세요.
가드 생성 (Guarded Generation)
프로덕션 재시도 루프에는 guarded_generate()를 사용하여 어떠한 LLM 클라이언트든 제공업체 종속성 추가 없이 래핑하는 것이 좋습니다:
import outputguard
result = outputguard.guarded_generate(...)
guarded_generate()는 각 생성을 검증하고, 가능한 경우 복구하며, 목표화된 재시도 프롬프트를 생성기에 다시 공급하고, 관찰 가능성을 위해 모든 시도를 반환합니다. 엄격한 검증 전용 루프를 위해서는 repair=False를 전달하고, 이전 모델 출력을 재시도 프롬프트에서 제외하려면 include_message_history=False를 사용하며, 유효하지 않은 출력일 경우 예외(GuardedGenerationError)를 발생시키려면 throw_on_failure=True를 사용하세요.
비동기 클라이언트는 동일한 옵션으로 guarded_generate_async()를 사용할 수 있습니다.
지원 형식 (Supported Formats)
JSON이 기본값으로 유지되므로 기존 코드는 계속 작동합니다. 다른 데이터 형식을 파싱하고 복구하려면 format=을 전달하세요:
yaml_result = outputguard.validate_and_repair(
"```yaml\nname: Alice\nage: 30\n```",
schema,
format="yaml",
)
...
지원되는 입력 형식은 json, yaml/yml, toml, python/python-literal, auto, 그리고 forced-json-off입니다.
배치 처리 (Batch Processing)
피처 세트(fixture sets), 평가 출력(eval outputs), 또는 로그를 검증할 때 배치 헬퍼(batch helpers)를 사용하세요:
batch = outputguard.validate_batch(outputs, schema, repair=True, format="auto")
print(batch.summary)
# BatchSummary(total=..., valid=..., invalid=..., repaired=..., ...)
...
CLI (Command Line Interface)
# 스키마를 사용하여 JSON 유효성 검사
outputguard validate output.json -s schema.json
...
수정하는 내용 (What It Fixes)
15가지 전략이 순서대로 적용됩니다. 대부분은 JSON 계열의 오류(malformations)를 목표로 하며, strip_fences와 같은 일반적인 전략은 YAML, TOML, Python literal 출력물을 JSON으로 변환하지 않고도 펜스 처리된(fenced) 출력을 수정합니다.
| # | 전략 (Strategy) | 이전 (Before) | 이후 (After) |
|---|---|---|---|
| 1 | fix_encoding | Ċ{ĊĠ"a":Ġ1Ċ} | {"a": 1} |
| ... |
288개 실제 LLM 모델 테스트
저희는 OpenRouter의 모든 텍스트 생성 모델 — 40개 이상의 제공업체에 걸친 288개 모델을 대상으로 outputguard를 테스트했습니다.
결과: 100% 성공률. 모든 모델의 출력은 유효한 JSON이거나 성공적으로 복구되었습니다.
| 개수 (Count) | |
|---|---|
| 테스트된 모델 수 | 288 |
| ... |
복구된 63개의 출력물은 자동으로 수정되었으며, 주로 strip_fences (마크다운 코드 펜스(markdown code fences)가 #1 LLM JSON 문제임), extract_json, fix_truncated, 그리고 fix_encoding이 사용되었습니다.
<details> <summary><strong >강조된 모델 결과</strong > (클릭하여 확장)</summary>API 응답 오류(토크나이저 손상, 잘린 스트리밍 등)로 인해 4개 모델은 테스트에서 제외되었으며, 이는 JSON 문제가 아닙니다.
| Model | Provider | Result | Fix Applied |
|---|---|---|---|
| GPT-5 Mini | OpenAI | ✅ Clean | — |
| ... |
모든 288개의 원본 모델 출력물은 테스트 피처(test fixtures)로 커밋되어 있습니다.
python -m tests.real_model_runner sweep을 실행하여 모든 모델에 대해 직접 재테스트할 수 있습니다.
테스트 스위트 (Test Suite)
**9가지 테스트 차원(testing dimensions)**에 걸친 2,001개 테스트:
설정 (Configuration)
OutputGuard 클래스를 사용하여 어떤 전략이 실행될지 세밀하게 제어할 수 있습니다:
from outputguard import OutputGuard
# 엄격 모드 — 콘텐츠가 아닌 형식만 수정합니다.
...
```yaml
name: Alice
age: 30
```", schema)
RepairReport
디버깅 및 관찰 가능성을 위해, RepairReport는 어떤 일이 일어났는지 전체 분석을 제공합니다:
from outputguard.report import RepairReport
report = RepairReport(
...
**신뢰도 점수 (Confidence scoring)**는 0.0에서 1.0 사이의 휴리스틱입니다. 더 많은 전략이 필요하거나 텍스트가 많이 변경될수록 이 점수는 낮아집니다. 수리(repair)를 신뢰할지 아니면 재시도(retry)로 에스컬레이션할지 결정하는 데 유용합니다.
API 참조 (API Reference)
모듈 레벨 함수 (Module-level Functions)
| 함수 | 반환값 | 설명 |
|---|---|---|
validate(text, schema, format="json") | ValidationResult | 스키마에 맞춰 구조화된 출력을 검증합니다. |
| ... |
클래스 (Classes)
| 클래스 | 설명 |
|---|---|
OutputGuard | 전략 선택, 재시도 제한 및 기본 format을 갖춘 설정 가능한 파이프라인입니다. |
| ... |
예외 (Exceptions)
| 예외 | 설명 |
|---|---|
OutputGuardError | 기본 예외입니다. |
| ... |
CLI 참조 (CLI Reference)
outputguard [COMMAND] [OPTIONS]
| 명령어 | 설명 |
|---|---|
validate INPUT -s SCHEMA | 스키마에 맞춰 구조화된 출력을 검증합니다. |
| ... | |
모든 명령어는 데이터 형식을 위한 --input-format, 기계가 읽을 수 있는 명령어 출력을 위한 -f json, 파일에 쓰기 위한 -o FILE, 그리고 stdin에서 읽기를 위한 - INPUT을 허용합니다. |
왜 outputguard인가? (Why outputguard?)
json.loads() + regex | outputguard | |
|---|---|---|
| 수리 전략 | 직접 구현해야 함 | 15개, 테스트 및 순서 지정됨 |
| ... |
예시 (Examples)
전체 실행 가능한 스크립트는 examples/ 디렉터리에서 확인하세요:
- basic_usage.py — 핵심 유효성 검사(validate)/수정(repair) 워크플로우
- retry_loop.py — 수정 프롬프트를 사용한 재시도 패턴
- guarded_generation.py — 제공업체에 구애받지 않는(Provider-agnostic) 가드 생성(guarded generation)
- custom_pipeline.py — 사용자 정의 전략 구성
- batch_processing.py — 통계와 함께 여러 출력 처리
기여 (Contributing)
기여를 환영합니다. 변경하고 싶은 내용에 대해 먼저 이슈(issue)를 열어 논의해 주세요.
git clone https://github.com/ndcorder/outputguard.git
cd outputguard
uv sync --dev
...
TypeScript / JavaScript
JS/TS 버전을 찾고 계신가요? **outputguard-js**를 확인해 보세요. 동일한 핵심 API 형태이며, TypeScript 네이티브입니다.
라이선스 (License)
AI 자동 생성 콘텐츠
본 콘텐츠는 GitHub Claude Ecosystem의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기