품질 게이트
- 게이트가 보는 지표
- 10
- 하나라도 하한 아래면 머지되지 않습니다
- 기준선
- 30 × 3
- 문항 × 실행 · 2026-10-27
- 변동폭보다 좁은 하한
- 0
- 하한이 운을 재고 있지 않습니다
지표 · 하한 · 여유
여유가 3회 변동폭보다 좁으면 그 하한은 품질이 아니라 운을 잽니다(ADR-004). 둘을 나란히 둡니다.
| 지표 | 측정 | 하한 | 여유 | 허용 하락폭 | 3회 변동폭 |
|---|---|---|---|---|---|
| answer_evidence_precision | 1 | 0.95 | 0.05 | 0.02 | 0 |
| answer_evidence_recall | 1 | 0.99 | 0.01 | 0.02 | 0 |
| answer_failure_rate | 0 | ≤ 0.1333 | 0.133 | 0.1 | 0 |
| hit_at_k | 1 | 0.5 | 0.5 | — | 0 |
| ragas_context_precision_stable_families | 1 | 0.85 | 0.15 | — | 0 |
| ragas_faithfulness | 0.998 | 0.8 | 0.198 | — | 0.006 |
| recall_at_k | 1 | 0.48 | 0.52 | — | 0 |
| reciprocal_rank | 1 | 0.48 | 0.52 | — | 0 |
| retrieval_precision | 1 | 0.7 | 0.3 | 0.05 | 0 |
| retrieval_recall | 1 | 0.9 | 0.1 | 0.05 | 0 |
하한을 그 값으로 정한 이유
- answer_evidence_recall
- 답을 만든 사례만 보면 세 실행 모두 1.0000(변동폭 0)입니다. 그래서 좁게 둘 수 있고, 이것이 이 게이트의 본 규칙입니다.
- answer_failure_rate
- 낮은 쪽이 좋은 지표입니다. 관측 범위 0.0333~0.1000의 최대에 사례 한 건을 더했습니다. 3회차가 정확히 0.1000이었으므로 이전 상한 0.10은 경계에 걸터앉은 값이었습니다.
- hit_at_k
- 구조적으로 2/3 근처가 상한입니다(author·topcited 12건은 Text2Cypher가 답합니다, ADR-008). 게다가 변동폭이 0.166이라 n=30에서는 작은 회귀를 구별할 수 없습니다. 하한은 파국만 잡습니다. **그리고 이 지표가 재는 것이 순위 품질이 아니라는 것을 2026-10-19에 측정했습니다**(ADR-033): 답변 조회의 ORDER BY가 30건 중 24건에서 제목 알파벳순이고, retrieved_ids 집합이 30/30에서 골드 집합과 정확히 같습니다. 즉 1위는 '제목의 첫 글자'이고 1.0000은 '목록이 전부 골드'라는 뜻입니다. 지우지는 않습니다 - 검색이 깨지면 내려가므로 회귀 탐지기로는 유효합니다.
- no_drop_on_rank_metrics
- 순위 지표의 관측 변동폭이 커서 허용폭을 두지 않습니다. 관측값: {"answer_evidence_precision": 0.0, "answer_evidence_recall": 0.0, "answer_failure_rate": 0.0667, "completed_cases": 2.0, "hit_at_k": 0.166, "recall_at_k": 0.143, "reciprocal_rank": 0.1488}
- ragas_faithfulness
- **파국만 잡는 하한입니다.** 5회 관측 0.9833 / 0.9667 / 0.9500 / 0.9000 / 0.9806이고 변동폭은 4회에서 0.0833이 된 뒤 5회에서도 0.0833입니다(2회 0.0167, 3회 0.0333에서 넓어진 뒤 멈췄습니다). 이 지표의 집계는 **사례별 0/1 판정의 개수**이고(한 건 = 1/30 = 0.0333), 그 0점은 답변 품질을 따라가지 않습니다 - reference-01의 답변이 1회차와 4회차에서 사실상 같은데 1.0000에서 0.0000으로 뒤집혔습니다(EXPERIMENTS 11-13절). 작은 회귀는 구별할 수 없으므로 하한은 심은 결함 수준(0.0000~0.6100, 11-10절)만 잡게 0.80에 둡니다. **2026-10-19(ADR-043) 저장소의 모든 실행으로 다시 셌습니다 — 12회입니다.** 세 코드 상태(resolve 3회, routed 3회, study_full 6회)의 집단별 변동폭은 0.0344 / 0.0167 / 0.0917이고, 정상이던 실행 중 최악은 **0.9000**(ragas_study_full_run4)으로 하한까지 0.1000 남습니다. 결함을 심으면 0.4025·0.4192로 내려가 하한이 걸립니다. 그래서 하한 0.80은 그대로 두고 **표본을 더 늘리지 않습니다** — 재서 결정이 바뀌지 않습니다(reports/ragas_floor_basis.json).
- ragas_context_precision_stable_families
- **가족 집합을 한 번 좁혔고, 다시 좁히지 않습니다.** 처음에는 3회 관측으로 author·citing·topcited를 골랐는데, citing-06이 4회차에, citing-02가 5회차에 0.1667로 무너져 변동폭이 0.0000 -> 0.0463 -> 0.0926으로 계속 넓어졌습니다. citing을 빼면 author·topcited 12사례가 5회 전부 1.0000(변동폭 0.0000)입니다. citing이 움직이는 이유는 그 질문에서 에이전트가 가져오는 문맥 개수가 실행마다 달라지고, 이 지표가 **답변에 의존**하기 때문입니다(11-10절). 하한은 그래도 파국용 0.85로 둡니다 - '변동폭이 0이다'라는 전제는 이미 두 번 깨졌고, 같은 전제에 좁은 하한을 다시 얹지 않습니다. **author나 topcited가 무너지면 하한을 또 내리는 대신 이 지표를 게이트에서 뺍니다.** 하한을 관측에 맞춰 반복해 내리면 게이트가 장식이 됩니다. **2026-10-19(ADR-043) 12회 전부 1.0000입니다**(변동폭 0.0000). 상수에 걸린 하한은 게이트가 아니므로 결함을 심어 확인했습니다 — author·topcited의 사례별 값이 [0.0, 1.0, 0.0, 1.0]이 되어 집계가 **0.5000**으로 내려가고 하한 0.85가 걸립니다. `context_relevance`를 뺀 이유(ADR-021: 결함에서도 1.0000)와 **갈라지는 지점**입니다.
- no_drop_on_ragas
- RAGAS 지표에는 허용폭도 사례별 규칙도 두지 않습니다. 사례별 판정이 같은 답변에서도 0과 1을 왕복하고(reference-01: 1,1,1,0 / coauthor-02: 1,0,1,0 / citing-06의 context_precision: 1,1,1,0.1667) 집계는 그 개수이므로, n=30에서 작은 회귀를 변동과 구별할 수 없습니다. 구별할 수 없는 값에 규칙을 붙이면 규칙이 아니라 숫자입니다.
- ragas_judge_model
- 기준선의 RAGAS 값은 이 판정 모델로 쟀습니다. 다른 모델로 잰 점수를 같은 표에 올리면 모수가 다른 값을 비교하게 됩니다(metrics_split과 같은 규칙). 2026-10-17에 CI가 OPENAI_MODEL을 넘기지 않아 실제로 그 일이 있었고, 그래서 게이트가 막습니다.
- answer_evidence_precision
- 0.99에서 0.95로 **넓혔습니다**(2026-10-18). 라우팅(ADR-024) 뒤 재측정에서 3회 중 한 번 `citing-03`이 시드 논문 자신을 근거에 넣어 precision이 0.6667이 됐고, 30건 집계가 (29 + 0.6667)/30 = 0.9889로 하한 0.9900을 0.0011 넘겼습니다. 즉 **기준선을 만든 실행이 그 기준선에 걸립니다.** 관측 변동폭 0.0111이 하한까지의 여유 0.0063보다 커서, 0.99는 품질이 아니라 변동을 막는 하한입니다(90 사례-실행 중 1건 -> 30건 실행이 빨개질 확률 약 28%). 0.95는 같은 사례 4~5건까지 견디고 계통적 고장은 여전히 막습니다. **근본 원인은 따로 고칩니다**: 제목을 arxiv_id로 바꾸는 중간 조회의 행이 `evidence_ids`에 시드를 담고, 그것이 (1) `retrieved_ids` 1위를 차지해 reciprocal_rank 상한을 0.7000으로 묶고 (2) RAGAS context_precision을 절반으로 깎고 (3) 드물게 답변 근거로 새어 나옵니다. 중간 조회 결과를 근거와 분리하면 셋이 한 번에 풀리지만 지표 정의가 바뀌어 기준선을 다시 써야 하므로 다음 주기로 둡니다.
- retrieval_precision
- **순서에 의존하지 않는 지표라서 하한이 뜻을 가집니다**(ADR-033). 세 상태를 쟀습니다 - 그래프 경로 1.0000(3회, 변동폭 0.0000) / 2026-10-16 라우팅 전 0.7908 / 같은 보고서의 vector_only 0.0083. 재난은 세 번째입니다: 그래프 질문이 그래프 경로로 가지 않는 상태. 0.70은 그것을 확실히 잡고(0.0083), 라우팅 전의 섞인 상태(0.7908)는 잡지 않습니다 - 그 상태는 나빴지만 답변 근거는 1.000이었고 우리가 이미 고쳤습니다. 측정값 1.0000과 같게 두지 않는 이유는 ADR-004와 같습니다.
- retrieval_recall
- 같은 세 상태에서 1.0000 / 0.9667 / 0.0111입니다. 라우팅 전 0.9667이 하한을 넘지 않아야 합니다 - 그때의 문제는 **못 찾은 것이 아니라 너무 많이 찾은 것**이었고(집합 recall 1.0000인데 recall_at_k 0.1667), 그 구별이 이 지표를 더한 이유 자체입니다. 그래서 0.90입니다: 골드를 10% 넘게 놓치면 답변이 맞을 수 없습니다.
- drop_on_set_metrics_but_not_rank_metrics
- 순위 지표에는 허용폭을 두지 않고(아래 no_drop_on_rank_metrics) 집합 지표에는 둡니다. 차이는 **측정된 변동폭**입니다 - 집합 지표는 90 사례-실행(3회x30건) 전부에서 1.0000이고 변동폭 0.0000입니다. 조회가 돌려준 집합에 대한 순수 집합 연산이라, 흔들릴 여지가 모델이 다른 질의를 고르는 경우뿐입니다. 0.05의 뜻은 '사례 세 건이 초과 조회를 시작했다'입니다 (한 건이 2편 골드에 7편을 돌려주면 그 건 0.2857, 30건 평균 0.9762 -> 하락 0.0238이므로 한두 건은 통과하고 세 건에서 걸립니다). 이 규칙이 있어야 ADR-024가 찾은 회귀(1.0000 -> 0.8244)를 게이트가 잡습니다 - 하한 0.70만으로는 지나갑니다.
- ragas_floor_basis
- 두 하한의 근거를 **게이트가 보는 양**으로 셉니다. `evals.ragas_spread`의 METRICS는 RAGAS 원래 지표이고, 전체 가족 평균 context_precision은 약 0.70인데 게이트의 하한은 author·topcited만의 평균(1.0000)에 걸려 있습니다. 전체 평균의 변동폭을 하한의 근거로 읽으면 다른 양을 근거로 삼는 것이므로, `--floors`가 가족을 좁힌 뒤 셉니다.
RAGAS 하한이 무언가를 막는지 — 결함을 심어 확인
물을 것은 "평균이 하한보다 큰가"가 아닙니다(ADR-004·ADR-043). 정상이던 실행 중 최악이 하한을 넘는가, 그리고 결함을 심으면 걸리는가입니다. 둘째가 아니면 그 하한은 상수에 걸려 있습니다.
| 지표 | 하한 | 본 실행 | 최악 정상 실행 | 하한까지 여유 | 최악도 넘는가 | 결함을 심으면 | 그때 걸리는가 |
|---|---|---|---|---|---|---|---|
| ragas_context_precision_stable_families | 0.85 | 12 | 1 | 0.15 | 예 | 0.5000, 0.5000 | 예 |
| ragas_faithfulness | 0.8 | 12 | 0.9 | 0.1 | 예 | 0.4025, 0.4192 | 예 |
이 점수를 낸 프롬프트
sha256 앞 12자입니다. 지문이 다르면 다른 프롬프트이고, 게이트의 prompt_version 규칙이 막습니다 — git_sha로는 대신할 수 없습니다(ADR-018·ADR-041).
| 프롬프트 | 기준선 | 지금 코드 | 같은가 |
|---|---|---|---|
| AGENT_SYSTEM | 6ee7f3264a2e | 6ee7f3264a2e | 예 |
| CYPHER_RULES | 0fc2226dcb49 | 0fc2226dcb49 | 예 |
| JUDGE_CONTENT | c09bb82b3769 | c09bb82b3769 | 예 |
| TRANSLATE_TO_ENGLISH | 1af68d2a119f | 1af68d2a119f | 예 |
| TRANSLATE_TO_KOREAN | 130e2c8cb43c | 130e2c8cb43c | 예 |
규칙 — 하나라도 걸리면 머지되지 않습니다
| cases | 기준선과 같은 사례 집합을 돌렸는가 |
| scoring_error | 채점 함수가 죽은 건이 없는가 (0이어야 함) |
| floor | 지표가 절대 하한 이상인가 |
| drop | 기준선 대비 하락이 허용폭 이하인가 |
| stable_case | 기준선에서 만점이던 사례가 이번에도 통과하는가 |
| judge_model | RAGAS를 기준선과 같은 모델이 채점했는가 |
| prompt_version | 답을 만든 프롬프트 본문이 기준선과 같은가 |
분야별 — 분야마다 6문항 × 3회
검색·근거 지표는 다섯 분야 모두 1.0이고 실패는 0건입니다. 이 문항으로는 그 지표에서 분야를 가르지 못합니다. 분야끼리 다른 것은 RAGAS뿐이고, context_precision은 "게이트"가 "예"인 분야만 봅니다(ADR-017).
| 분야 | n | hit@5 | 근거 재현율 | 실패율 | faithfulness | answer_relevancy | context_precision | 게이트 |
|---|---|---|---|---|---|---|---|---|
| 저자 | 6×3 | 1 | 1 | 0 | 0.954 (0.92~1.00) | 0.872 (0.81~0.91) | 1.000 | 예 |
| 인용한 논문 | 6×3 | 1 | 1 | 0 | 1.000 | 0.888 (0.85~0.91) | 0.500 | 아니오 |
| 공저자 | 6×3 | 1 | 1 | 0 | 0.989 (0.97~1.00) | 0.820 (0.75~0.90) | 0.528 (0.50~0.56) | 아니오 |
| 참고문헌 | 6×3 | 1 | 1 | 0 | 1.000 | 0.735 (0.67~0.79) | 0.500 | 아니오 |
| 최다 피인용 | 6×3 | 1 | 1 | 0 | 0.982 (0.94~1.00) | 0.865 (0.86~0.87) | 1.000 | 예 |
관련 논문 변형 비교 — 미래 라벨 과제
| 변형 | recall@5 | hit@5 | MRR | 배포 대비 recall@5 (95% 구간) |
|---|---|---|---|---|
| cocited 배포 | 0.2791 | 0.5679 | 0.4623 | — |
| gbm | 0.1861 | 0.5113 | 0.3842 | -0.0930 [-0.1053, -0.0805] |
| ppr | 0.175 | 0.1852 | 0.0896 | -0.1041 [-0.1131, -0.0960] |
| vector | 0.1391 | 0.4684 | 0.3374 | -0.1400 [-0.1568, -0.1228] |
| adapter_cite | 0.1381 | 0.467 | 0.336 | -0.1410 [-0.1579, -0.1239] |
| adapter_cocite | 0.138 | 0.4677 | 0.3351 | -0.1411 [-0.1581, -0.1237] |
연결 정도로 나누면
집계만 보면 두 체제가 섞입니다(ADR-037). 시드의 인용 간선 수로 나눈 recall@5입니다.
| 시드 | 수 | 비율 | cocited | ppr | vector | adapter_cite | adapter_cocite | gbm |
|---|---|---|---|---|---|---|---|---|
| 간선 0개 | 1112 | 80.8% | 0.1227 | 0.0000 | 0.1227 | 0.1227 | 0.1228 | 0.1111 |
| 간선 1~4개 | 251 | 18.2% | 0.9832 | 0.9561 | 0.2154 | 0.2101 | 0.2088 | 0.5252 |
| 간선 5개 이상 | 14 | 1.0% | 0.0793 | 0.0713 | 0.0793 | 0.0651 | 0.0793 | 0.0618 |
평가 하네스 밖에서 지키는 선
- 관련 논문 슬롯 · related_recall_at_k (cocited) — 측정 0.8892, 하한 0.5검사: tests/test_related_slot.py
- 모델 승격 · graph-text-gbm — 측정 0.6513, 하한 0.6검사: pipeline/model_registry.py --judge
재서 기각한 모델
무엇을 쓰는지만큼 무엇을 왜 안 쓰는지가 이 저장소의 내용입니다.
- 선형 어댑터 (인용 쌍 학습) 관련 논문recall@5 0.1120 대 공동인용 0.8892 · ADR-029
- 선형 어댑터 (공동인용 재학습) 관련 논문0.1064 — '목표가 달랐다'를 닫음 · ADR-030
- 로컬 임베딩 (SPECTER) 벡터 검색recall@10 0.1296 대 0.2019 · EXPERIMENTS 11-5
- GPU 전체 파인튜닝 임베딩넘지 못함 · EXPERIMENTS 11-6
- 선형 어댑터 (미래 라벨) 관련 논문벡터 대비 다섯 중 넷이 0 포함 · ADR-036
- graph-text-gbm (재정렬기) 관련 논문집계 1위인데 양쪽 집단에서 다 짐 · ADR-037
- BGE-M3 (568M 다국어) 임베딩간선 0개 집단에서 −0.0334, bge-base보다도 −0.0232 · ADR-046
- Qwen3-Embedding-0.6B (595M) 임베딩−0.0073 (0 제외), bge-base와는 구별 안 됨 — 크기가 사는 것이 없음 · ADR-049
- bge-reranker-v2-m3 (교차 인코더) 관련 논문코사인 대비 −0.0359 (0 제외). 풀 상한 0.2690인데 0.0868 · ADR-051
전체 기록: docs/MODELS.md · 결정 기록