본문 바로가기
/ 학습 / 안내서 / LLM·프롬프트
L3 심화 · 7분 읽기

RAG 운영, 골든셋 회귀 평가와 가드레일

예방안전팀 2026.07.03 갱신 RAG를 만들어 운영 단계에 들어선 담당자·연구자
#RAG#평가#회귀테스트#가드레일

전편에서 법령 RAG를 만들었다면, 이제 위험은 만드는 쪽이 아니라 바꾸는 쪽에 있습니다. 법령이 개정되어 문서를 다시 넣고, 답이 딱딱하다고 프롬프트를 다듬고, 더 좋은 모델이 나와 교체하는 — 이 평범한 운영 행위 하나하나가 어제까지 잘 나오던 답을 소리 없이 바꿉니다. 화면에 오류는 안 뜨는데 조문 인용이 슬쩍 빠지는 식이라, 검증 없이는 아무도 모릅니다.

이 안내서를 끝내면 자주 묻는 질문으로 골든셋을 만들고, 무언가를 바꿀 때마다 Ragas 점수와 promptfoo 단언을 회귀로 돌리고, 최후 방어선으로 위험 답변을 가드레일로 차단할 수 있습니다.

운영 3종

장치무엇을 지키나언제 작동하나
1 골든셋"정답이 무엇인지"의 기준만들 때 한 번 + 문서 개정 때 갱신
2 회귀 평가변경 전후의 품질 비교프롬프트·문서·모델을 바꿀 때마다
3 가드레일개별 답변 한 건의 사고매 응답, 실시간

평가는 평균을 지키고, 가드레일은 한 건을 막습니다. 역할이 달라서 둘 다 필요합니다.

1. 골든셋 — 자주 묻는 질문 20개부터

골든셋은 "이 질문엔 이 근거로 이렇게 답해야 한다"의 목록입니다. 거창하게 시작할 것 없이, 실제로 자주 들어온 질문 20개면 충분합니다.

YAML
# goldenset.yaml — 질문 · 정답 근거 · 기대 요점 (법령 개정 시 함께 갱신)
- q: 소화기 점검 주기는 어떻게 되나요?
  ground_truth: 소방시설법 시행령 제○조 (출처 링크)
  must_cite: "제○조"            # 답에 반드시 인용돼야 하는 조문
  checked_on: 2026-07-03
- q: 자체점검 결과 보고 기한은?
  ground_truth: 소방시설법 제○조 제○항 (출처 링크)
  must_cite: "제○조"
  checked_on: 2026-07-03

2. 회귀 평가 — 두 겹으로

겹 1 · Ragas 점수 — 전체 품질의 온도계

전편의 4단 검증을 운영용으로 확장합니다. 핵심은 점수 자체가 아니라 변경 전후의 비교하한선입니다.

PYTHON
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)을 붙여 통과/실패로 끊어 줍니다.

YAML
# 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. 가드레일 — 마지막 한 건을 막는 문지기

평가를 통과한 시스템도 개별 답변은 빗나갈 수 있습니다. 가드레일은 답이 사용자에게 나가기 직전 위험 신호를 기계적으로 검사해, 걸리면 답 대신 "확인 필요" 안내를 내보냅니다.

PYTHON
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, ""

규칙 기반으로 시작해도 충분하고, 커지면 안전한 AI 운영 도구의 Guardrails·NeMo Guardrails 같은 전용 도구로 옮깁니다. 개인정보가 답에 섞여 나오는 것까지 막으려면 개인정보 점검의 마스킹을 출력 쪽에도 겁니다.

운영 루틴 한 장

언제무엇을통과 기준
문서·프롬프트·모델 변경 시Ragas + promptfoo 전체 회귀하한선 이상 + 단언 전부 통과
주 1회 정기동일 회귀 (변경 없어도)지난주 대비 하락 질문 0건
매 응답가드레일근거 있음 + 차단 규칙 미해당
분기 1회골든셋 자체 점검개정 법령 반영·낡은 질문 교체
▸ 소방 활용 포인트
법령 개정·프롬프트 수정 후에도 답변 품질이 유지되는지 5분 만에 확인하고, 처분·과태료 단정 같은 위험 답변이 현장 대원·민원인에게 나가기 전에 기계적으로 차단합니다. 평가 점수가 떨어진 질문 목록은 그대로 개선 작업 목록이 됩니다.

사람 검토 체크리스트

TEXT
- [ ] 골든셋의 질문·정답 근거를 사람이 작성했고, 개인정보는 제거했습니다.
- [ ] faithfulness·context precision 하한선을 우리 골든셋 기준으로 정했습니다.
- [ ] 문서·프롬프트·모델 변경 시 회귀 평가를 돌리는 절차가 문서화돼 있습니다.
- [ ] 점수가 떨어진 질문은 배포 전에 사람이 원인을 확인했습니다.
- [ ] 가드레일에 걸린 답변 사례를 주기적으로 검토해 규칙을 보강합니다.
- [ ] 법령 개정 시 골든셋 갱신 담당자가 지정돼 있습니다.
⚠️ 흔한 실수
점수는 대리 지표입니다 — 골든셋에 없는 질문은 지켜 주지 못하고, 골든셋 자체도 법령처럼 낡습니다. 평가가 전부 통과해도 "AI 답변은 참고용, 최종 판단은 공식 원문으로"라는 제출 전 1분 점검의 원칙은 그대로 유지하세요.