Skip to main content
Glama
db-inlee

RAG Regression Gate

by db-inlee

RAG Regression Gate (MCP)

CI Python 3.11+

What this is — RAG 운영자를 위한 진단 도구: "무엇이 회귀했나"(run_gate)와 "지금 뭘 고쳐야 하나"(analyze_failures)를 둘 다 답한다. 단순 "점수 하락"이 아니라 실패모드(retrieval_miss·hallucination 등)를 본다. RAG를 실행하지 않고 이미 만들어진 run-log를 소비·판정한다(ADR-001). (baseline의 answerable 정확도 20%는 측정 대상일 뿐 — 산출물은 게이트의 분별력.)

Inputs — baseline·candidate 각 디렉토리의 run.jsonl + attribution.jsonl (+ baseline noise_band.json). 필드·타입·예시(스키마 계약): docs/artifact_contract.md.

OutputsPASS / WARN / FAIL + exit_code(FAIL=1 → CI 머지 차단) + 실패모드 귀인(무엇이 유의하게 회귀했나) + 룰 기반 제안. 노이즈밴드 + 부트스트랩으로 "유의한 회귀만", 거짓경보 0건(같은 config 재실행은 항상 PASS — ADR-002). CI에서 PR에 보이는 모습: examples/pr_comment.md.

30-second demo — ↓ 아래 섹션(LLM·임베딩·GPU 없이 PASS/FAIL 재현).

Architecture — 판정 코어 app/core는 프레임워크 무관, CLI · MCP · REST API 3종 인터페이스가 포트-어댑터로 같은 코어를 호출(같은 입력 → 같은 판정, 5중 일치). 통계는 pydantic만. ↓ "아키텍처"·"REST API" 섹션, ADR-004.

Why not DART-specific — 엔진은 도메인을 모르고 4개 플러그인이 도메인 의존부를 담당. 3도메인(DART 한국 금융 100 / 영어 위키 20 / Allganize 한국 법률·공공 40, 외부 공개 gold)에서 엔진 git diff = 0 실증. DART는 레퍼런스 인스턴스일 뿐. → ADR-003 · docs/portability.md.

Limitationsgold(평가셋) 전제(reference-free는 범위 밖); 위키·Allganize는 인터페이스 검증용 미니 인스턴스(20·40문항, 방향성 증거 — DART 100이 메인 레퍼런스); Allganize는 문서 단위 매칭이라 DART(페이지/표)보다 거침. ↓ "적용 범위와 한계".


30초 데모 — CI 없이 로컬에서 게이트가 막는 것을 재현

게이트는 LLM·임베딩·GPU 없이 동작한다(pydantic만 필요). candidate의 채점·귀인 결과 (run.jsonl + attribution.jsonl)를 baseline과 통계 비교할 뿐이다.

pip install -r requirements-gate.txt   # pydantic 하나

# ① 중립 변경(noise r2, 무변화) → 통과
python scripts/run_gate.py --baseline examples/baseline --candidate examples/demo_neutral
#   → 🟢 GATE: PASS   (exit 0)

# ② 회귀(top_k 5→1, 검색 약화) → 차단
python scripts/run_gate.py --baseline examples/baseline --candidate examples/demo_regression
#   → 🔴 GATE: FAIL   (exit 1)
#      ❌ retrieval_miss 65→73 유의 증가 (CI [+2, +14]) → 검색 회귀
#      ❌ 정답 정확도(grounded) 0.20→0.08 유의 하락 (CI [-0.20, -0.06])

CI에서는 이 exit 1이 머지를 막는다(GitHub branch protection의 Required check).

코퍼스에 대해: data/corpus/extracted/의 코퍼스는 DART 공시 가공본이라 저작권상 repo에 포함하지 않는다. **full RAG(인덱싱~생성)**를 재현하려면 DART에서 해당 보고서 PDF를 받아 data/corpus/raw/에 두고 python scripts/extract_tables.py를 실행하면 된다. 단, 헤드라인인 게이트 데모(PASS/FAIL)는 코퍼스 없이 examples/만으로 재현된다(위 30초 데모).


Related MCP server: groundcheck

MCP 서버 — Claude/Cursor에서 "두 실행 비교해줘"

같은 게이트를 MCP 도구로 노출한다 — 두 도구(run_gate + analyze_failures)로. Claude Desktop/Cursor 같은 클라이언트가 이를 호출해 회귀 판정·실패모드 진단·개선 힌트를 받는다.

두 도구의 역할 — "무엇이 회귀했나" + "지금 뭐가 안 되나"

운영자는 두 가지를 묻는다. 이 서버는 그 둘을 각각 다른 도구로 답한다.

run_gate

analyze_failures

답하는 질문

"무엇이 회귀했나?" (변경 후 깨진 것)

"지금 뭐가 안 되고, 뭘 먼저 고칠까?" (현재 약점)

입력

두 실행(baseline ↔ candidate)

한 실행(run_dir)

하는 일

통계적 회귀 판정 + 원인 config 역추적

병목 단계·약한 슬라이스 진단 + 개선 힌트

산출

PASS/WARN/FAIL + 유의하게 회귀한 실패모드

실패 분포·병목 단계·슬라이스별 약점·RAGAS 환산·개선 우선순위

공통

둘 다 운영자가 "다음에 뭘 할지" 를 알게 한다 — 한쪽은 회귀 진단, 한쪽은 개선 진단.

analyze_failures의 핵심 가치 한 줄: 점수만 보는 게 아니라 어느 슬라이스가 어느 단계 (검색/생성/그라운딩/거부)에서 막히는지를 짚어, 운영자가 무엇부터 손볼지 방향을 잡게 한다. — 즉 개선을 대신 해주는 게 아니라 개선 힌트를 준다.

운영 사이클 — 두 도구가 맞물리는 순환:

 analyze_failures   →   운영자가 개선 적용   →   run_gate            →  (개선 성공 시)
 (약점·병목 진단,        (검색/청킹/프롬프트…       (그 변경이 회귀 없이      → 그게 새 baseline
  개선 힌트)              운영자가 직접 수정)         개선됐는지 검증)            으로 채택
        ↑                                                                    │
        └────────────  운영 중 회귀 발생 시 재진단  ←───────────────────────────┘
            run_gate("무엇이 깨졌나") + analyze_failures("어디가 문제인가") → 반복

진단(analyze_failures)으로 방향을 잡고 → 운영자가 고치고 → 검증(run_gate)으로 회귀 없는 개선임을 확인하면 그게 새 baseline이 된다. 운영 중 회귀가 나면 다시 두 도구로 재진단 — 이 순환을 반복한다.

정직성: 두 도구 모두 개선을 대신 수행하거나 "개선됐다"고 보장하지 않는다. 약점을 짚어주는 진단·힌트 역할이고, 실제 개선은 운영자가, 그 효과 검증은 **run_gate**가 한다.

pip install ".[mcp]"        # fastmcp는 옵션 extra (게이트 코어는 여전히 pydantic만)
python -m app.mcp.server    # stdio MCP 서버 실행

Claude Desktop / Cursor의 mcpServers 설정에 등록:

{
  "mcpServers": {
    "rag-regression-gate": {
      "command": "python",
      "args": ["-m", "app.mcp.server"],
      "cwd": "/absolute/path/to/rag_regression"
    }
  }
}

사용 시나리오: Claude에게 "이 두 RAG 실행 비교해줘"(baseline/candidate 디렉토리 경로) → run_gate(baseline_dir, candidate_dir) 호출 → PASS/WARN/FAIL + 부트스트랩 CI + 실패모드 진단 + 제안 (GateResult)을 돌려준다. 입력은 단순 경로 문자열(게이트 CLI와 동일 계약), 출력은 구조화된 Pydantic.

run_gate("examples/baseline", "examples/demo_regression")
 → verdict=FAIL, exit_code=1
   regressions: retrieval_miss 65→73 (CI [+2,+14]), 정답정확도 0.20→0.08
   suggestions: "[retrieval_miss] 검색 단계 회귀 … 원인 후보: top_k 5→1 → 우선 되돌림(top_k 1→5) 검토 …"

제안은 "검토 후보"지 "정답"이 아니다. LLM이 생성하지 않고 룰 기반 카탈로그 (docs/remediation_catalog.md: 실패모드→단계→기법 + config diff 역추적)로 결정적으로 만든다. suggestion-only — 게이트는 config를 자동 수정/실행하지 않으며, 모든 제안에 "사람이 적용 후 이 게이트로 재검증" 문구가 붙는다. MCP 계층은 통계 로직을 한 줄도 재구현하지 않고 기존 엔진(detectgate)을 호출만 한다 → CLI와 수치 동일.

analyze_failures — 단일 실행 진단 (run_gate의 짝)

run_gate두 실행을 비교(회귀 감지)한다면, analyze_failures한 실행을 진단한다 — "바꿨더니 나빠졌나?" 가 아니라 "지금 어디가 약하고, 뭘 먼저 손볼까?" 에 답한다. 운영자의 두 번째 니즈(성능을 올려야 할 때)를 위한 도구다. run_dir 하나만 받는다(비교 대상이 없으니 통계 검정 없음).

analyze_failures("examples/baseline")
 → failure_distribution: {retrieval_miss: 65, correct: 34, hallucination: 1}
   bottleneck: retrieval ("retrieval_miss가 65건으로 가장 큰 병목")
   groundedness: grounded 17 / unsupported 2 (맞았지만 근거 미실재 = 리스크)
   ragas_equivalent: context_recall 0.19, faithfulness 0.89, answer_correctness 0.20
   improvement_priorities: ① 검색(top_k↑·청크 축소) ② 표값 슬라이스 집중 … (적용 후 run_gate로 검증)

RAGAS 환산 (judge 없이 결정적, 차별점) — RAGAS의 친숙한 지표를 우리의 결정적 측정으로 환산한다. LLM judge 호출이 없어 같은 입력엔 같은 값(재현 가능):

RAGAS 개념

우리 결정적 측정

비고

context_recall

retrieval_success_strict (gold 근거 ⊆ retrieved)

judge 없음

faithfulness

grounded / (grounded + unsupported)

judge 없음

answer_correctness

answerable_accuracy (grounded 기준)

judge 없음

context_precision

의도적 생략: precomputed attribution(gold-free)만으론 산출 불가

answer_relevancy

의도적 생략: judge 필요 → 결정성과 충돌

gold-free·결정적: analyze_failures는 precomputed attribution.jsonl(케이스별 boolean)만 집계한다 — eval_cases.jsonl(gold)을 다시 읽지 않으므로 Phase 6의 gold 제거를 되돌리지 않는다. 새 통계/채점 로직 0. suggestion-only + 닫힌 루프: 개선 우선순위는 "검토 후보"이며, analyze_failures(약점 파악) → 개선 적용 → run_gate(개선 검증)로 닫는다.


REST API — 같은 코어를 부르는 3번째 인터페이스

CLI · MCP에 더해 FastAPI REST 서비스로도 노출한다. 셋 다 프레임워크 중립 코어(app/core/)를 호출하므로 같은 입력 → 같은 판정(CLI == MCP == API). API 층은 fastapi/uvicorn만 의존하고 통계 로직을 재구현하지 않는다(게이트 코어는 여전히 pydantic만).

포트-어댑터 구조: 판정·통계 코어(app/core/)는 프레임워크를 모르고, 각 어댑터가 자기 프로토콜로 그 코어를 노출한다 — CLI(scripts/run_gate.py) / MCP(app/mcp/, fastmcp) / REST(app/api/, fastapi). 새 인터페이스를 붙여도 코어는 그대로. 인터페이스 3종 = 같은 엔진의 3가지 접근.

엔드포인트

설명

GET /health

헬스체크 → {"status":"ok","version":...}

POST /evaluate

두 run(baseline↔candidate) 비교 → PASS/WARN/FAIL (run_gate 코어)

POST /analyze

단일 run 진단 → 병목·슬라이스·RAGAS·우선순위 (analyze_failures 코어)

GET /docs·/redoc

OpenAPI 자동 문서(Swagger/ReDoc)

입력은 run 아티팩트 디렉토리 경로(attribution.jsonl (+baseline noise_band.json)) — CLI/MCP와 동일 계약. 필드·타입·예시(입출력 스키마)는 docs/artifact_contract.md에 정의(테스트로 강제). 에러는 명확한 상태코드: 404(경로/파일 없음) · 422(필드 누락·타입오류·깨진 JSONL).

pip install -r requirements-api.txt          # gate(pydantic) + fastapi + uvicorn
uvicorn app.api.main:app --port 8000         # /docs 에서 바로 호출 가능

# 회귀 판정 (CLI/MCP와 동일 수치)
curl -s localhost:8000/evaluate -H 'content-type: application/json' \
  -d '{"baseline_dir":"examples/allganize_baseline","candidate_dir":"examples/allganize_candidate"}'
#   → {"verdict":"FAIL","exit_code":1,"regressions":[{"metric":"answerable_accuracy","delta":-0.25,...}], ...}

# 단일 run 진단
curl -s localhost:8000/analyze -H 'content-type: application/json' \
  -d '{"run_dir":"examples/allganize_baseline"}'
#   → {"bottleneck_stage":"grounding","failure_distribution":{...},"ragas_equivalent":{...}, ...}

Docker (경량 — LLM/임베딩/torch 없음):

docker build -t rag-gate-api .
docker run -p 8000:8000 rag-gate-api
curl localhost:8000/health     # {"status":"ok","version":"0.1.0"}

범위: 이 API는 run-log/attribution을 받아 게이트 판정·진단을 노출하는 평가 서비스다. RAG 실행 자체(무거운 인덱싱/LLM)는 범위 밖 — 사용자 RAG가 run-log를 내보내면 게이트가 소비한다(run-log 계약).

★ 5중 일치 (같은 입력 → 같은 판정): 게이트 수치는 5개 경로에서 동일하다 — 독립 부트스트랩(교차검증용 재구현) = CLI = in-memory(detect()) = MCP = REST API. 앞 셋(엔진 결정성)에 더해 MCP·API가 같은 코어를 부르므로 인터페이스가 수치를 왜곡하지 않는다. CLI == MCP == API는 scripts/verify_api_equivalence.py가 같은 입력 (allganize baseline/candidate)에 대해 verdict·exit_code·전 메트릭·전 필드 동일을 출력해 증명한다.


메타 평가 — "분별 있게 반응한다" (Phase 5, config만 바꿔 생성)

동일 baseline에 config 한 개씩만 바꿔 게이트에 통과시킨 결과(임계 조작 없음):

변경

answerable_acc

retrieval_miss

게이트

진단

(baseline)

0.20

65

A. top_k 5→1

0.20→0.08

65→73

🔴 FAIL

검색 회귀

B. reranker off→on

0.20→0.19

65→60

🟡 WARN

개선 효과 없음

C. overlap 150→155

0.20→0.19

65→66

🟡 WARN

중립(경계)

  • A 진짜 회귀 → 잡음. B "좋아질 줄 알았던" reranker → 데이터상 유의한 개선 없음(WARN), 게이트가 유의한 개선이 아님을 정확히 판정 — 이게 회귀 게이트의 존재 이유. C 중립 → FAIL 회피.

  • 위 표가 핵심이며 CI·유의성은 게이트가 그대로 출력. 전체 분석: reports/demo_summary.md.


오해 3가지에 대한 답 (의도적 프레이밍)

1. "정확도 20%면 RAG가 별로 아닌가?" — 이 프로젝트의 산출물은 정확도가 아니라 게이트의 분별력이다. baseline은 튜닝 안 한 측정 기준점일 뿐. 20%든 80%든, 게이트가 해야 할 일은 "변경이 이걸 유의하게 악화시켰는가"를 정직하게 판정하는 것이고, 위 메타 평가가 그걸 증명한다.

2. "100문항은 표본이 작아 노이즈 아닌가?" — 맞다. 그래서 노이즈를 정직하게 다룬다:

  • 노이즈 밴드: 같은 config를 5회 반복 실행해 "가만히 있어도 흔들리는 범위"를 데이터로 측정(이 repo에선 결정적이라 밴드≈0, 불안정 케이스 0).

  • 부트스트랩 신뢰구간: 케이스 단위 paired 리샘플링으로 차이의 95% CI를 구해, CI가 0을 벗어나고(통계적 유의) 노이즈 밴드(±1 case floor)도 넘을 때만 회귀로 판정. 둘 중 하나만이면 WARN.

  • 결과: 같은 config 재실행(거짓경보 테스트)은 회귀 0건, 합성/실제 회귀는 FAIL.

3. "DART 전용 아닌가?" — 회귀 엔진(노이즈밴드·부트스트랩·게이트·judge검증·실패모드 귀인)은 도메인 무관이고, DART(평가셋·표추출·한국어 숫자정규화·표 도메인 taxonomy)는 레퍼런스 인스턴스다. 경계와 MCP 인터페이스 후보(EvalSet/RAG Adapter/Scoring Plugin/Taxonomy): docs/portability.md.


차별점

  • 실패모드 진단: "점수 하락"이 아니라 retrieval_miss/hallucination/over_answer 중 무엇이 유의하게 회귀했는지 귀인. retrieval_miss는 gold 근거 ↔ 검색 청크 매칭으로 judge 없이 결정적 판정.

  • judge 신뢰성 검증: 본문 채점 LLM(gpt-4o)을 gold로 검증 — 정답/오답 probe로 judge_accuracy = 0.987(혼동행렬 포함). 미묘 변형 probe까지 써서 거짓 고득점을 방지. → reports/judge_validation.json.

  • 채점 전략: judge는 선택적·검증 후 사용: 숫자/표값은 단위 정규화(조·억) + ±0.1% 허용오차로 judge 없이 결정적, 답없음은 거부 문구 매칭으로 결정적, retrieval_miss는 gold 근거 ⊆ 검색 청크로 결정적. judge는 본문(서술형)에만 쓰고 그조차 gold로 검증(0.933→0.987). 회귀 게이트는 '같은 입력엔 같은 판정' 이 생명이라 temperature=0+seed로 노이즈밴드 std=0을 달성했고, 비결정성의 표면적을 본문으로 좁혔다.

  • RAGAS 대비: RAGAS는 훌륭한 범용 RAG 평가 프레임워크다. 우리는 그걸 부정하는 게 아니라, 'CI 회귀 게이트' 목적상 결정성을 우선했다 — 개념은 빌리되(groundedness 등) 측정은 가능한 한 결정적으로. judge 한 번의 흔들림이 PASS/FAIL을 뒤집으면 게이트로 못 쓰기 때문. (설계 근거 전문: docs/JOURNEY.md — 설계 결정)

  • groundedness 분리: 맞은 답도 정답값이 검색 근거에 실재(grounded)하는지 확인. 암기/운으로 맞은 unsupported_correct는 헤드라인 정확도에서 분리(모델 암기력이 RAG 점수를 부풀리지 않게).

  • no_answer 착시 방어: answerable 정확도와 no_answer 정확도를 항상 짝으로 보고(전부 거부하는 시스템이 들통나도록).

  • 통계적 정직 + 거짓경보 0건: 노이즈밴드 + 부트스트랩으로 "유의한 회귀만" FAIL. 같은 config 재실행은 항상 PASS(거짓경보 0건)로 게이트 신뢰성 검증 — 데모용 임계 조작 없음.

  • 도메인 범용성 실증(3도메인): DART(한국 금융) / 영어 위키 QA / Allganize(한국 법률·공공, 외부 공개 gold)에서 같은 게이트 작동, 엔진 코드 0줄 변경(git diff = 0). ★ Allganize는 우리가 만들지 않은 남의 gold이고 병목이 DART와 정반대(검색 vs 생성/그라운딩) — 같은 analyze_failures가 DART엔 top_k↑, Allganize엔 citation을 처방한다(더 강한 범용성 증거). 단 위키·Allganize는 인터페이스 검증용 미니 인스턴스(20·40문항)이고 DART(100문항)가 메인 레퍼런스다. Allganize는 문서 단위 매칭이라 DART보다 거칠고 스캔 이미지 문서는 제외. 출처: datalama/RAG-Evaluation-Dataset-KO(MIT). → docs/portability.md §5.

적용 범위와 한계

이 엔진은 gold(평가셋)를 전제로 한다. 가진 gold의 종류에 따라 작동 범위가 갈린다:

  • 정답 + 근거 라벨(DART) → accuracy · retrieval_miss · groundedness 전 기능(gold 근거 ⊆ retrieved, 결정적).

  • 정답만(근거 라벨 없음 — 더 흔함) → accuracy 작동, retrieval_miss는 '정답 텍스트가 검색 청크에 있나' 로 대체 가능(위키 wiki_value_present가 이 방식).

  • 정답조차 없음(reference-free)범위 밖. 정답 없이 옳고 그름을 판정하려면 judge 의존이 불가피해 우리의 결정성 원칙과 충돌한다.

왜 한계가 아니라 정의인가: 회귀 감지는 본질적으로 비교 기준이 있어야 성립한다 — 고정 평가셋 없이 '깨졌다' 를 판단하는 건 원리적으로 불가능하다. 따라서 평가셋 전제는 '회귀 게이트'의 정의에 내재한 조건이다(promptfoo·RAGAS의 reference 기반 평가도 같은 전제). → 상세 docs/JOURNEY.md — 설계 결정, docs/portability.md.


아키텍처 — 게이트(가벼움)와 RAG 실행(무거움) 분리

[무거움 — CI 밖/선택]                         [가벼움 — CI 안, 활성]
 인덱싱(bge-m3 2.2GB) + 100케이스 LLM           게이트: run-log+attribution을 baseline과
 + gpt-4o judge  →  run-log + attribution  ──▶  부트스트랩 비교 → PASS/WARN/FAIL (pydantic만)
  • 모델 1(현재): 무거운 RAG는 CI 밖에서 실행, candidate 산출물을 PR에 첨부. CI는 게이트만(.github/workflows/regression-gate.yml).

  • 모델 2(전환 경로): generate-candidate.yml(Job 1, 스켈레톤)의 트리거를 pull_request로 바꾸고 게이트로 핸드오프하면 완전 자동 — 게이트 로직은 한 줄도 안 바뀐다.

테스트

python -m pytest -q56 passed (LLM·임베딩 없이; 게이트는 결정적이라 기대값을 정확히 박는다). 부품 테스트(scorer/judge/table_extract)에 더해 게이트 행동 자체를 검증한다:

파일

무엇을 고정하나

test_gate_behavior.py

회귀 FAIL / 동일 run PASS / 노이즈 floor·경계 WARN (거짓경보 0건)

test_interface_equivalence.py

코어 == REST API == detect_paths 동치, API의 fastmcp 비의존

test_generic_adapter.py

Generic 어댑터가 전용 어댑터를 정확히 재현(GoldMatcher/EvalProvider/value_present)

test_noise_floor_domain.py

floor가 런타임 모집단(40·100) 사용 — denom 하드코딩 회귀 방지

test_attribution_contract.py

gold-free 판정 + attribution 필수 8필드(artifact_contract.md 강제)

구조

app/rag/        수집·표추출·청킹·인덱싱·pipeline (DART/RAG)
app/evaluator/  scorer · judge · validate_judge · attribution · metrics · case_eval
app/regression/ detect(부트스트랩) · gate(PASS/WARN/FAIL)   ← 도메인 무관 엔진(3개 도메인 공유)
app/interfaces.py  플러그인 Protocol 4종(+화이트리스트)   app/adapters/  dart · wiki · allganize · generic 구현체
app/core/       service(run_gate 코어) · analyze(analyze_failures 코어) · suggest(룰 제안)  ← 프레임워크 중립 코어
app/mcp/        server   ← 인터페이스① MCP 어댑터(fastmcp, 옵션 extra) — app/core 호출
app/api/        main · schemas   ← 인터페이스② REST 어댑터(fastapi/uvicorn) — app/core 호출
scripts/        run_gate(인터페이스③ CLI) · run_eval · run_attribution · measure_noise · *_gate_demo · demo_generic · verify_api_equivalence
examples/       baseline / demo_* / wiki_* / allganize_baseline · allganize_candidate · allganize_generic  (게이트 입력 데모)
data/wiki_eval/ SQuAD 2.0 발췌(20문항, CC BY-SA 4.0)   data/allganize_eval/ Allganize 법률·공공 발췌(40문항)+코퍼스+라이선스(MIT)
reports/        원본 산출물(메트릭·노이즈밴드·judge검증·시나리오)   gate_runs/ 는 게이트 부산물
docs/           adr/(설계 결정 기록 4종) · portability(엔진 vs 도메인 경계 + 3도메인 실증 + 범용성 절감) · interfaces(플러그인 설계) · remediation_catalog(제안 근거) · artifact_contract(입출력 스키마 계약)
Dockerfile      REST API 컨테이너(경량 — pydantic+fastapi+uvicorn, LLM/임베딩 없음)

인터페이스 3종 = 같은 코어: 판정·통계는 app/core/(프레임워크 무관)에 한 번만 있고, ① MCP(app/mcp) ② REST API(app/api) ③ CLI(scripts/run_gate.py)가 포트-어댑터로 그 코어를 노출한다 — 같은 입력 → 같은 판정.

표추출의 알려진 한계는 KNOWN_ISSUES.md. (빌드 티켓·불변 규칙·기획 등 내부 작업 문서는 공개 범위에서 제외.)

검증으로 실제 잡은 결함들(연도누락·환각·채점 false negative·judge 무효 probe·암기정답·가짜 retrieval_miss·음수기준 증가율 등)과 그 수정 기록: docs/JOURNEY.md.

설계 결정(왜 이렇게 만들었나) — 결정·대안·트레이드오프: docs/adr/ (run-log 기반 게이트 / bootstrap+noise band / 도메인 어댑터 / MCP는 인터페이스).

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server for a modular RAG system that enables natural language question answering over enterprise documents with intent-aware routing, adaptive retrieval, and citation-backed responses.
    -
  • A
    license
    A
    quality
    B
    maintenance
    An MCP server that lets any AI agent evaluate RAG outputs -- faithfulness scoring, hallucination detection, and retrieval quality metrics -- with zero API keys, using MCP sampling.
    6
    MIT