전편에서 법령 RAG를 만들었다면, 이제 위험은 만드는 쪽이 아니라 바꾸는 쪽에 있습니다. 법령이 개정되어 문서를 다시 넣고, 답이 딱딱하다고 프롬프트를 다듬고, 더 좋은 모델이 나와 교체하는 — 이 평범한 운영 행위 하나하나가 어제까지 잘 나오던 답을 소리 없이 바꿉니다. 화면에 오류는 안 뜨는데 조문 인용이 슬쩍 빠지는 식이라, 검증 없이는 아무도 모릅니다.
- 질문·근거·기대 요점이 연결된 골든셋을 설계할 수 있습니다.
- 평균 품질 지표와 질문별 단언의 역할을 나눠 회귀 평가할 수 있습니다.
- 변경 전후 결과를 재현하고 하락한 질문의 원인을 추적할 수 있습니다.
- 위험 응답을 중단하고 사람 검토 큐로 보내는 가드레일을 설계할 수 있습니다.
운영 3종
| 장치 | 무엇을 지키나 | 언제 작동하나 |
|---|---|---|
| 1 골든셋 | "정답이 무엇인지"의 기준 | 만들 때 한 번 + 문서 개정 때 갱신 |
| 2 회귀 평가 | 변경 전후의 품질 비교 | 프롬프트·문서·모델을 바꿀 때마다 |
| 3 가드레일 | 개별 답변 한 건의 사고 | 매 응답, 실시간 |
평가는 평균을 지키고, 가드레일은 한 건을 막습니다. 역할이 달라서 둘 다 필요합니다.
1. 골든셋 — 자주 묻는 질문 20개부터
골든셋은 "이 질문엔 이 근거로 이렇게 답해야 한다"의 목록입니다. 거창하게 시작할 것 없이, 실제로 자주 들어온 질문 20개면 충분합니다.
- 실제 질문 로그에서 고르되, 개인정보 점검을 거쳐 신고자·주소 등은 제거합니다.
- 질문마다 정답 근거(조문·출처) 와 기대 답의 요점을 사람이 적습니다 — 이 한 줄이 평가의 기준점이 됩니다.
- 파일로 저장해 버전 관리합니다. 법령이 개정되면 골든셋도 함께 개정하고 확인일을 갱신합니다.
# goldenset.yaml — 질문 · 정답 근거 · 기대 요점 (법령 개정 시 함께 갱신) - q: 소화기 점검 주기는 어떻게 되나요? ground_truth: 소방시설법 시행령 제○조 (출처 링크) must_cite: "제○조" # 답에 반드시 인용돼야 하는 조문 checked_on: 2026-07-03 - q: 자체점검 결과 보고 기한은? ground_truth: 소방시설법 제○조 제○항 (출처 링크) must_cite: "제○조" checked_on: 2026-07-03
한 가지 유혹을 미리 경계해 둡니다. 점수를 올리려고 이 20개 질문에만 답을 맞추면, 골든셋은 통과하는데 정작 그 밖의 질문에서 무너집니다. 시험 범위를 미리 알고 그 문제만 외운 격이라, 골든셋은 늘 대표 표본으로만 다루고 주기적으로 질문을 갈아 줍니다.
2. 회귀 평가 — 두 겹으로
'회귀(回歸)'는 소프트웨어에서 예전엔 되던 것이 어느 순간 다시 안 되는 현상을 뜻합니다. 소방 펌프를 정기 점검하듯, 무언가를 바꾼 뒤 같은 검사를 다시 돌려 되던 것이 여전히 되는지 확인하는 일이 회귀 평가입니다. 원리는 단순합니다 — 답이 바뀌었는지 알려면 바뀌기 전 답을 기록해 둬야 합니다. 골든셋이 그 '기준 답'이고, 회귀 평가는 매 변경마다 새 답을 기준 답에 대 보는 절차입니다. 기준이 없으면 '나빠진 것 같다'는 느낌만 있고 증거가 없습니다.
조용히 바뀐다는 게 어떤 모습인지 가상의 예로 보겠습니다.
[프롬프트 수정 전] 질문: 소화기 점검 주기는? 답변: 소방시설법 시행령 제○조에 따라 … (조문 인용 있음) [말투를 부드럽게 다듬은 뒤] 질문: 소화기 점검 주기는? 답변: 보통 정기적으로 점검하시면 됩니다. (조문이 사라짐)
프롬프트에 "친절하게"를 강조했더니 딱딱한 조문 인용이 밀려난 것입니다. 화면엔 오류가 없고 답도 그럴듯해서, 회귀 평가가 없으면 이 변화를 아무도 눈치채지 못합니다.
겹 1 · Ragas 점수 — 전체 품질의 온도계
전편의 4단 검증을 운영용으로 확장합니다. 핵심은 점수 자체가 아니라 변경 전후의 비교와 하한선입니다.
from ragas import evaluate from ragas.metrics import faithfulness, context_precision # eval_dataset: 골든셋의 question / answer / contexts / ground_truth result = evaluate(dataset=eval_dataset, metrics=[faithfulness, context_precision]) df = result.to_pandas() # 하한선: 이 밑으로 내려가면 배포하지 않는다 (수치는 자기 골든셋으로 정한다) assert df["faithfulness"].mean() >= 0.80, "충실도 하락 — 변경 반영 중단" assert df["context_precision"].mean() >= 0.70, "검색 정밀도 하락 — 청킹·인덱스 확인" # 전후 비교: 지난 결과를 저장해 두고, 점수가 '떨어진 질문'부터 사람이 본다 df.to_csv("eval-2026-07-03.csv", index=False)
겹 2 · promptfoo 단언 — 문장 수준의 안전핀
점수는 평균이라 "이 질문엔 반드시 이 조문이 인용돼야 한다" 같은 개별 규칙을 놓칠 수 있습니다. promptfoo는 질문마다 단언(assert)을 붙여 통과/실패로 끊어 줍니다.
# promptfooconfig.yaml — `promptfoo eval` 로 실행 (npm install -g promptfoo) prompts: - file://rag-prompt.txt providers: - file://rag-answer.py # 내 RAG 파이프라인을 호출하는 스크립트 defaultTest: assert: - type: llm-rubric # 모든 질문 공통: 단정 금지 원칙 value: 처분·과태료·의무 여부를 단정하지 않고 조문 확인을 안내한다 tests: - vars: { query: "소화기 점검 주기는 어떻게 되나요?" } assert: - type: contains # 이 질문엔 이 조문이 반드시 나와야 한다 value: "제○조" - vars: { query: "우리 서 인사 발령 알려줘" } assert: - type: llm-rubric # 범위 밖 질문은 거절해야 정답 value: 문서에 없는 내용이라 답할 수 없다고 안내한다
언제 돌리나 — ① 법령·SOP 문서를 갱신했을 때 ② 프롬프트를 한 글자라도 고쳤을 때 ③ 모델을 교체했을 때 ④ 아무것도 안 바꿔도 주 1회(모델 제공자 쪽 변경 감지). 둘 다 명령 한 줄이라 습관의 문제이지 기술의 문제가 아닙니다.
3. 가드레일 — 마지막 한 건을 막는 문지기
평가를 통과한 시스템도 개별 답변은 빗나갈 수 있습니다. 가드레일은 답이 사용자에게 나가기 직전 위험 신호를 기계적으로 검사해, 걸리면 답 대신 "확인 필요" 안내를 내보냅니다.
import re BLOCK_RULES = [ (re.compile(r"(과태료|처분|벌금).{0,20}(입니다|됩니다|해야 합니다)"), "단정 표현"), (re.compile(r"확인일이 지난 근거"), "낡은 근거"), ] def guardrail(answer: str, cited: list) -> tuple[bool, str]: if not cited: # 근거 없는 답은 내보내지 않는다 return False, "근거 없음" for pattern, reason in BLOCK_RULES: if pattern.search(answer): return False, reason return True, ""
cited의 실제 확인일을 읽거나 오늘 날짜와 비교하지 않습니다- 답변 문자열에
"확인일이 지난 근거"라는 문구가 이미 들어 있을 때만 막습니다 (표면 검사) - 실제 가드레일: 출처별 확인일·개정일을 구조화 필드로 보관하고, 기준일과 비교해 stale 여부를 판정하는 검증을 별도로 구현해야 합니다
규칙 기반으로 시작해도 충분하고, 커지면 안전한 AI 운영 도구의 Guardrails·NeMo Guardrails 같은 전용 도구로 옮깁니다. 개인정보가 답에 섞여 나오는 것까지 막으려면 개인정보 점검의 마스킹을 출력 쪽에도 겁니다.
운영 루틴 한 장
| 언제 | 무엇을 | 통과 기준 |
|---|---|---|
| 문서·프롬프트·모델 변경 시 | Ragas + promptfoo 전체 회귀 | 하한선 이상 + 단언 전부 통과 |
| 주 1회 정기 | 동일 회귀 (변경 없어도) | 지난주 대비 하락 질문 0건 |
| 매 응답 | 가드레일 | 근거 있음 + 차단 규칙 미해당 |
| 분기 1회 | 골든셋 자체 점검 | 개정 법령 반영·낡은 질문 교체 |
설계 판단
평가 장치는 하나의 점수로 통합하기보다 서로 다른 실패를 잡는 겹으로 나눕니다. 어떤 실패를 언제 막아야 하는지가 선택 기준입니다.
| 방식 | 잡는 문제 | 트레이드오프 | 사람이 확인할 것 |
|---|---|---|---|
| 집계 품질 지표 | 전체 응답의 넓은 하락 추세 | 소수의 중요 질문 실패가 평균 안에 숨을 수 있음 | 하락 항목의 원문·검색 결과 |
| 질문별 단언 | 필수 출처·거절·형식 조건 위반 | 조건을 갱신하지 않으면 낡은 테스트가 됨 | 각 단언이 지키려는 업무 위험 |
| 실시간 가드레일 | 사용자에게 나가기 직전의 개별 위험 응답 | 과도 차단과 검토 큐 지연을 관리해야 함 | 차단 이유와 원문 대조 |
평가셋은 출처 스냅샷, 질문 유형, 기대 근거, 필수·거절 조건을 한 항목으로 묶어야 재현됩니다. 실패는 검색·생성·가드레일·평가 픽스처 중 어느 층에서 시작했는지 분류합니다. 회귀 판정은 같은 출처 스냅샷과 설정을 재사용하며, 필수 단언이 하나라도 깨지면 평균과 무관하게 변경 후보를 멈추고 사람이 근거를 확인합니다.
운영 시나리오
다음은 실제 법령·사건을 사용하지 않은 가상 평가 상황입니다. 점수 자체보다 실패한 질문과 차단 이유를 재현하는 과정이 핵심입니다.
가상 시나리오 1: 평균은 유지됐지만 필수 근거가 빠진 경우
- 탐지: 집계 평가는 기준 범위에 남았지만, 항목별 결과에서 특정 질문의 필수 출처가 사라졌습니다.
- 원인 가설: 말투 프롬프트가 길어지면서 근거 표시 지시가 밀렸거나, 평균 지표가 소수의 필수 실패를 가렸다고 봅니다.
- 대응: 배포 후보를 멈추고 해당 질문의 검색 근거와 최종 응답을 나란히 본 뒤, 필수 출처 단언을 회귀셋에 추가합니다.
- 재발 확인: 변경 전·후 환경에서 같은 질문을 재실행하고, 집계 결과와 필수 단언이 모두 통과하며 근거 링크가 원문과 일치하는지 사람이 보고 승인합니다.
가상 시나리오 2: 확인일이 지난 출처가 표면 검사를 통과한 경우
- 탐지: 응답에 출처는 있었고 차단 규칙도 통과했지만, 사람이 출처 기록을 대조하니 실제 확인일이 운영 기준보다 오래됐습니다.
- 원인 가설: 본문 가드는
cited의 날짜를 파싱·비교하지 않고, 답변 안에확인일이 지난 근거라는 특정 문구가 있는지만 검사하므로 낡은 출처가 그 문구 없이 통과했다고 봅니다. - 대응: 해당 응답의 외부 제공을 멈추고 출처별 확인일·개정일을 구조화한 뒤, 기준일과 비교해 stale 출처를 별도 중단 또는 사람 검토 큐로 보냅니다.
- 재발 확인: 기준일 전·후의 합성 출처 메타데이터를 함께 실행해 오래된 출처는 문구와 무관하게 분리되고, 최신 출처는 통과하는지 확인합니다. 이 날짜 검증은 본문 최소 가드 밖에 별도로 구현합니다.
한계와 리스크
| 리스크 | 발생 조건 | 영향 | 완화·사람 승인 |
|---|---|---|---|
| 골든셋 편향 | 빈발하거나 쉽게 통과하는 질문만 남음 | 실제 경계·범위 밖 질문의 품질을 알 수 없음 | 실패·거절·모호한 질문을 함께 구성하고 도메인 담당자가 표본 승인 |
| 평균에 숨은 개별 실패 | 집계 점수만 배포 게이트로 쓸 때 | 중요 질문의 근거 누락이 통과 | 질문별 필수 단언과 하락 목록을 함께 보고 담당자 승인 |
| 가드레일 과도 차단 | 응답 형식·용어가 바뀌었지만 규칙은 예전에 멈춤 | 정상 질문의 응답 지연과 검토 큐 누적 | 차단 이유를 기록하고 정상·위험 픽스처 재생 후 사람이 규칙 변경 승인 |
자주 묻는 질문
Q. 평균 점수가 좋으면 배포해도 되나요?
평균만으로는 부족합니다. 하락한 질문, 필수 단언, 거절해야 할 범위 밖 질문을 함께 봐야 합니다. 근거 누락 한 건이 평균 안에 숨을 수 있습니다.
Q. 골든셋을 한 번 만들면 계속 쓸 수 있나요?
아닙니다. 문서·업무 범위·사용자 질문이 바뀌면 골든셋도 낡습니다. 실패 로그에서 새 유형을 반영하되, 임의로 기대 답을 바꾸지 않고 담당자가 근거를 재확인합니다.
Q. 가드레일에 걸린 답은 삭제하면 되나요?
차단 이유·실행 ID·사용한 규칙을 민감한 본문과 분리해 필요한 기간만 기록해야 원인을 고칠 수 있습니다. 응답 본문의 보관은 소속 기관의 보안·보존 기준을 따릅니다.
Q. 평가자 모델의 판정을 정답으로 써도 되나요?
안 됩니다. 평가자 모델도 틀릴 수 있는 대리 지표입니다. 근거 일치·필수 단언 같은 기계적 검사와 사람 표본 검토를 함께 둡니다.
핵심 정리
- 골든셋은 질문만이 아니라 근거·기대 요점·거절 조건의 묶음입니다.
- 평균 지표와 질문별 단언은 서로 다른 크기의 실패를 보여 줍니다.
- 예제 가드레일의 낡은 근거 검사는 특정 문구를 찾는 표면 검사이므로, 실제 확인일 기반 stale 판정은 구조화 날짜 검증으로 따로 둡니다.
- 가드레일은 막는 규칙이며, 차단 이유와 사람 큐까지 설계해야 운영 장치가 됩니다.
- 배포 판단은 점수 하나가 아니라 하락 질문·필수 조건·사람 검토를 함께 봅니다.
다음 단계
- 법령·SOP RAG 설계: 평가가 보호하는 검색·청킹·근거 생성 계약을 다시 확인합니다.
- AI 출력 검토: 자동 평가를 통과한 답도 외부 제출 전 사람이 확인할 기준을 연결합니다.
- 안전한 AI 운영 도구: 평가·가드레일·추적 도구를 어떤 운영 층에 놓을지 비교합니다.
사람 검토 체크리스트
- [ ] 골든셋의 질문·정답 근거를 사람이 작성했고, 개인정보는 제거했습니다. - [ ] faithfulness·context precision 하한선을 우리 골든셋 기준으로 정했습니다. - [ ] 문서·프롬프트·모델 변경 시 회귀 평가를 돌리는 절차가 문서화돼 있습니다. - [ ] 점수가 떨어진 질문은 배포 전에 사람이 원인을 확인했습니다. - [ ] 가드레일에 걸린 답변 사례를 주기적으로 검토해 규칙을 보강합니다. - [ ] 법령 개정 시 골든셋 갱신 담당자가 지정돼 있습니다.