구조화된 출력(Structured output)이 세 번 실패했습니다. 세 번째 실패가 우리에게 '운영 준비
요약
계약 추출 에이전트 운영 중 발생한 세 번의 실패 사례를 통해, 단순한 스키마 검증을 넘어선 '운영 준비 완료(operator-ready)'의 진정한 의미를 다룹니다. 구조적 일치성과 내용의 정확성을 분리하고, 재시도 로직이 잘못된 추측을 정답으로 변환하는 위험성을 경고합니다.
핵심 포인트
- 스키마 검증은 구조적 일치성만 보장할 뿐 내용의 정확성을 보장하지 않음
- 스키마 유효성과 필드 신뢰도를 분리하여 로깅하고 관리해야 함
- 재시도 루프가 모델의 불확실성을 그럴듯한 거짓 정보로 바꿀 수 있음
- 에이전트 설계 시 예상치 못한 조건에서의 행동 양식을 고려해야 함
구조화된 출력(Structured output)이 세 번 실패했습니다. 세 번째 실패가 우리에게 "운영 준비 완료(operator-ready)"가 무엇을 의미하는지 가르쳐 주었습니다.
지난 분기에 우리는 기업 법무팀을 위한 계약 추출 에이전트(contract-extraction agent)를 출시했습니다. 스키마 검증(Schema validation) 통과율은 97%였습니다. 테스트 단계에서 인간 검토자들은 출력 품질에 만족했습니다. 배포는 순조롭게 진행되었습니다.
그러다 문제가 발생했습니다. 세 번이나 말이죠. 완전히 다른 세 가지 방식으로 말입니다.
처음 두 번의 실패는 더 나은 프롬프트(prompts)와 더 엄격한 스키마(schemas)로 해결했습니다. 하지만 세 번째 실패는 앞선 두 번이 가르쳐 주지 못한 것을 가르쳐 주었습니다. 바로 "운영 준비 완료(operator-ready)"란 기술적인 체크리스트가 아니라는 사실입니다. 그것은 당신이 설계하지 않은 조건 하에서 에이전트가 어떻게 행동하는지에 대한 주장입니다.
첫 번째 실패: 검증의 역설 (the validation paradox)
2주 차. 임대차 계약서가 들어왔는데, 갱신 조항이 산문(prose) 형태가 아닌 표(table) 형식으로 되어 있었습니다. 우리의 추출기(extractor)는 특정 JSON 경로에서 갱신 조건을 찾도록 되어 있었습니다. 표 형식은 스키마를 다르게 채웠습니다. 검증은 통과되었습니다. 하지만 추출된 갱신 날짜는 2년이나 틀려 있었습니다.
돌이켜보면 해결책은 명확했습니다. 추출 전에 정형화된 형식으로 변환하는 정규화(normalization) 단계를 추가하는 것이었습니다. 하지만 교훈은 그보다 더 날카로웠습니다.
스키마 검증(Schema validation)은 출력의 형태(shape)를 알려줄 뿐, 내용이 정확한지는 알려주지 않습니다. 올바른 키(keys)와 올바른 타입(types)을 가진 JSON 객체라도 여전히 잘못된 값을 포함할 수 있습니다. 우리의 97% 검증 성공률은 잘못된 것을 측정하고 있었습니다. 그것은 내용의 정확성(content accuracy)이 아니라 구조적 일치성(structure conformance)을 측정하고 있었던 것입니다.
이 실패 이후, 우리는 검증을 두 가지 신호로 분리했습니다: 스키마 유효성(schema validity, 객체에 필수 필드가 있는가)과 필드 신뢰도(field confidence, 내용이 정확하다는 증거가 있는가). 우리는 두 가지를 모두 로깅(logging)하기 시작했습니다. 출력은 두 신호가 모두 임계값(threshold)을 넘었을 때만 신뢰됩니다.
두 번째 실패: 거짓말을 하는 재시도 루프 (the retry loop that lies)
1개월 차. 우리가 테스트 세트(test set)로 훈련시키지 않았던 계약서 형식에서 특정 조항 유형이 나타났습니다. 추출기는 첫 번째 시도에서 스키마 검증(schema validation)에 실패했습니다. 우리의 재시도 로직(retry logic)이 작동하여 누락된 필드를 모델이 추론한 기본값(defaults)으로 채웠고, 세 번째 시도에서 검증을 통과했습니다.
출력 결과는 올바르게 보였습니다. 하지만 내용은 틀렸습니다. 추론된 기본값(defaults)은 그럴듯한 값이었지만, 실제 계약(contract) 내용과는 일치하지 않았습니다.
어떠한 경고(alert)도 발생하지 않았습니다. 사람의 검토(human review)도 트리거되지 않았습니다. 이 오류는 3주 후, 법무 팀이 서명된 계약서의 불일치를 발견했을 때 비로소 드러났습니다.
이것이 바로 재시도 역설(retry paradox)입니다. 재시도 루프(retry loop)는 불확실성을 처리하도록 설계되었지만, 실제로는 "모델이 모른다"를 "모델이 자신 있게 추측했다"로 변환해 버립니다. 스키마(schema)는 그 차이를 전혀 알지 못합니다.
해결책: 내용(content) 누락으로 인해 재시도가 실패하는 경우(형식(format) 문제가 아닌 경우), 올바른 동작은 기본값 채우기가 아니라 사람의 검토 플래그(human-review flag)를 세우는 것입니다. 검증을 통과하는 잘못된 값보다는 "이 조항을 확신을 가지고 추출할 수 없습니다"라고 출력하는 것이 더 나은 결과입니다.
우리는 재시도 로직(retry logic)을 변경하여 형식 실패(재시도 및 재형식화)와 내용 실패(검토를 위한 플래그 설정)를 구분하도록 했습니다. 그 결과, 사람의 검토 비율은 높아졌고, 소리 없는 오류(silent error) 비율은 0으로 떨어졌습니다.
세 번째 실패: 운영자(operator)의 데이터
이 문제는 이해하는 데 더 오랜 시간이 걸렸습니다.
6주가 지났을 무렵, 법무 팀이 최근 인수한 자회사로부터 새로운 계약서 묶음이 도착했습니다. 계약 구조가 다르고, 조항 명명 규칙(clause naming conventions)이 다르며, 언어 패턴도 달랐습니다. 우리의 추출 정확도는 학습 코퍼스(training-corpus) 계약서의 94%에서 인수된 자회사의 계약서 61%로 떨어졌습니다.
우리는 개발 과정에서 해당 자회사의 문서를 단 한 장도 본 적이 없었습니다. 우리의 테스트 스위트(test suite) 역시 마찬가지였습니다.
이것이 바로 분포 변화(distribution shift) 문제입니다. 그리고 이것이 바로 '운영 준비 완료(operator-ready)'가 아니라는 실제 정의입니다.
운영 준비 완료(Production-ready)는 에이전트가 테스트했던 입력을 처리할 수 있음을 의미합니다. 운영 준비 완료(Operator-ready)는 에이전트가 운영자가 실제로 제공할 입력을 처리할 수 있음을 의미합니다. 이 둘은 동일한 집합이 아닙니다.
해결책은 더 나은 모델이나 더 나은 프롬프트(prompt)가 아니었습니다. 그것은 프로세스의 변화였습니다. 운영자에게 업무를 넘기기 전에, 에이전트를 운영자 자신의 문서 샘플에 실행하여 해당 코퍼스(corpus)에 대한 정확도를 구체적으로 측정하고, SLA(서비스 수준 협약) 수치를 약속하기 전에 기준점(baseline)을 설정하는 것이었습니다.
이제 우리는 인수인계 전 체크리스트(pre-handoff checklist)의 일부로 운영자의 코퍼스(corpus)에서 50개의 문서를 요구합니다. 합성 데이터(synthetic data)가 아닙니다. 우리의 데이터도 아닙니다. 바로 그들의 데이터입니다. 만약 이 50개 문서에 대한 정확도가 우리의 훈련 코퍼스(training corpus)에 대한 정확도와 비슷하지 않다면, 그 원인을 파악할 때까지 인수인계는 지연됩니다.
이 세 가지 실패의 공통점
세 가지 모두 우리의 평가 스위트(eval suite)에서는 보이지 않았습니다. 하지만 적절한 진단 도구가 있었다면 세 가지 모두 확인할 수 있었습니다.
패턴은 이렇습니다. 우리의 평가는 우리의 최선의 사례(우리의 데이터, 우리의 테스트 세트, 우리의 형식 가정)를 측정하고 있었습니다. '운영 준비 완료(operator-ready)'란 운영자의 사례를 측정하는 것을 의미합니다. 이 둘은 서로 다른 측정 문제입니다.
우리가 인수인계 전 프로세스에 추가한 세 가지는 다음과 같습니다:
- 모든 출력에 대한 필드 수준의 신뢰도 점수 산정 (단순한 스키마 유효성(schema validity)뿐만 아니라)
- 재시도 로직(retry logic)에서 콘텐츠 실패(content-failure)와 형식 실패(format-failure)의 분리 (조용히 실패하지 말고, 명확하게 실패를 알릴 것)
- 서비스 시작(go-live) 전 운영자 코퍼스 샘플링 (그들의 실제 데이터에서 추출한 50개의 문서를 수동으로 검토)
이 중 어느 것도 표준적인 "운영 준비 완료(production-ready)" 체크리스트에는 포함되어 있지 않습니다. 이것들은 '운영 준비 완료(operator-ready)' 체크리스트에 들어있는 항목들입니다.
이에 대해 반론을 제기한다면
이러한 실패에 대한 일반적인 반응은 "그저 더 많은 훈련 데이터를 추가하라" 또는 "운영자의 코퍼스로 미세 조정(fine-tune)하라"는 것입니다. 그것은 장기적으로는 올바른 해결책입니다. 하지만 단기적인 해답은 아닙니다.
미세 조정(Fine-tuning)은 몇 주가 걸리며 라벨링 예산이 필요합니다. 이미 시작된 운영자 파일럿(pilot) 프로젝트에는 그러한 여유가 없습니다. 더 빠른 경로는 정확도 수치를 약속한 후에 목표치를 놓치는 것이 아니라, 정확도 수치를 약속하기 전에 분포 변화(distribution shift)를 이해하는 것입니다.
또한 현재의 "검증(validation)만으로 충분하다"는 접근 방식에 대한 강점(steelman)도 존재합니다. 구조화되고 예측 가능한 입력을 사용하는 저위험(low-stakes) 사용 사례의 경우, 스키마 검증(schema validation)만으로도 정말 충분합니다. 추출하려는 모든 계약서가 동일한 템플릿에서 나온다면, 형식 준수(format conformance)와 콘텐츠 정확도(content accuracy)는 매우 높은 상관관계를 갖기 때문입니다.
문제는 기업 운영자(enterprise operators)가 단 하나의 템플릿만을 사용하는 경우가 거의 없다는 점입니다. 저희의 추출기(extractor)를 배포한 법무 팀은 14개의 서로 다른 거래 상대방(counterparties)으로부터 계약서를 관리하며, 각 상대방은 저마다의 관례를 가지고 있습니다. 검증(Validation)만으로는 언제든 실패할 수밖에 없었습니다.
제가 인정하는 부분은 이 문제가 엔지니어링 문제인 만큼이나 데이터 문제이기도 하다는 점입니다. 운영자별로 라벨링된 코퍼스(labeled corpora)를 구축하는 데 투자하는 팀은, '운영 준비 완료(operator-ready)'를 단 한 번의 배포 결정으로 취급하는 팀보다 실질적으로 훨씬 더 나은 결과를 얻을 것입니다. 저희는 그 부분에 충분히 일찍 투자하지 못했습니다. 두 번째와 세 번째의 실패는 부분적으로 그에 따른 비용이었습니다.
운영 준비 완료(Operator-ready)는 도달하는 상태가 아닙니다. 그것은 실행하는 프로세스입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기