feat(eval): 변형 일관성(query-paraphrase robustness) 평가 프레임워크 #193

Merged
altair823 merged 12 commits from feat/paraphrase-robustness-eval into main 2026-05-30 01:12:29 +00:00
Owner

요약

같은 의미를 다른 표현(동의어·풀어쓴 문장·한/영)으로 물어도 검색 품질이 일관되는지 직접 측정하는 평가 프레임워크를 kebab-eval 에 추가한다. 선행 cross-script 실험이 "겹침(overlap)"이라는 프록시 지표를 최적화하다 헛돈 교훈을 반영해, 처방을 만들기 전에 진짜 지표(변형 간 일관성)를 재는 도구를 먼저 세운다.

핵심은 GoldenQuery.group 으로 같은 의도의 여러 표현을 묶고, 그룹 내 recall@narrow(10) vs recall@pool(50) 대비로 각 변형을 Ok / MisRanked(A: 정답이 pool엔 있고 top-10 밖 → 재정렬 후보) / Missing(B: pool에도 없음 → 어휘격차) 로 분류하는 것이다. 이 진단이 처방 방향(near-tie 흡수 vs 쿼리/문서 확장)을 가른다.

설계: docs/superpowers/specs/2026-05-29-query-paraphrase-robustness-eval-design.md
계획: docs/superpowers/plans/2026-05-29-query-paraphrase-robustness-eval.md

변경 내용

  • GoldenQuery.group: Option<String> (additive, #[serde(default)]) + loader 그룹 정합성 검증(같은 group → 동일 expected_doc_ids, 위반 시 bail).
  • kebab-eval::variant 모듈 — 변형 일관성 메트릭(recall_spread/worst/A·B dominant/fully_consistent/pool_possibly_truncated) + (A)/(B) 분류 + 마크다운/JSON 렌더.
  • runnerconfig_snapshot_jsoneval_k 추가 → variant 진단이 eval_k < pool_k(50) 인 run 에서 조용히 무력화되지 않도록 compute_variant_consistency_with_config 가 bail.
  • kebab eval variants <run_id> [--json] CLI 서브커맨드.
  • 진단/딥리서치/PoC 핸드오프 문서.

비범위 / 회귀 위험

  • eval 전용·additive. 기존 AggregateMetrics(hit@k/MRR/recall) 경로 불변 — group=None 쿼리는 기존과 동일하게 처리된다(회귀 가드 테스트 포함). 검색/임베딩/색인 동작 변경 없음, wire schema 불변. Phase 2(처방)는 별도 PR.

검증

  • cargo test -p kebab-eval 녹색 (변형 일관성 3 + H1/M1 회귀 3 + 그룹 정합성 + 기존 metrics/loader/compare/runner 전부).
  • cargo clippy -p kebab-eval -p kebab-cli --all-targets -- -D warnings 녹색 (err+warn 0).
  • main 위 cherry-pick 단독 빌드 검증 (rerank 실험 코드와 분리 — 이 PR 은 eval 프레임워크만).
  • 실 dogfood KB(8그룹×32변형) 측정으로 (A)/(B) 진단 동작 확인 + raw search 독립 재현.

시험 항목 (Test Plan)

  • kebab eval run --mode hybrid --k 50kebab eval variants <run_id> 가 그룹별 recall_spread/A/B/pool 표를 출력
  • --k 10 run 에 대해 eval variants 가 pool truncation 으로 bail (조용한 오답 방지)
  • --json 출력이 VariantConsistencyReport 구조와 일치

Assisted-by: Claude Code

## 요약 같은 의미를 다른 표현(동의어·풀어쓴 문장·한/영)으로 물어도 검색 품질이 일관되는지 **직접 측정**하는 평가 프레임워크를 `kebab-eval` 에 추가한다. 선행 cross-script 실험이 "겹침(overlap)"이라는 프록시 지표를 최적화하다 헛돈 교훈을 반영해, 처방을 만들기 전에 진짜 지표(변형 간 일관성)를 재는 도구를 먼저 세운다. 핵심은 `GoldenQuery.group` 으로 같은 의도의 여러 표현을 묶고, 그룹 내 `recall@narrow(10)` vs `recall@pool(50)` 대비로 각 변형을 `Ok` / `MisRanked`(A: 정답이 pool엔 있고 top-10 밖 → 재정렬 후보) / `Missing`(B: pool에도 없음 → 어휘격차) 로 분류하는 것이다. 이 진단이 처방 방향(near-tie 흡수 vs 쿼리/문서 확장)을 가른다. 설계: docs/superpowers/specs/2026-05-29-query-paraphrase-robustness-eval-design.md 계획: docs/superpowers/plans/2026-05-29-query-paraphrase-robustness-eval.md ## 변경 내용 - `GoldenQuery.group: Option<String>` (additive, `#[serde(default)]`) + loader 그룹 정합성 검증(같은 group → 동일 `expected_doc_ids`, 위반 시 bail). - `kebab-eval::variant` 모듈 — 변형 일관성 메트릭(recall_spread/worst/A·B dominant/fully_consistent/pool_possibly_truncated) + (A)/(B) 분류 + 마크다운/JSON 렌더. - `runner` 의 `config_snapshot_json` 에 `eval_k` 추가 → variant 진단이 `eval_k < pool_k(50)` 인 run 에서 조용히 무력화되지 않도록 `compute_variant_consistency_with_config` 가 bail. - `kebab eval variants <run_id> [--json]` CLI 서브커맨드. - 진단/딥리서치/PoC 핸드오프 문서. ## 비범위 / 회귀 위험 - eval 전용·additive. 기존 `AggregateMetrics`(hit@k/MRR/recall) 경로 불변 — group=None 쿼리는 기존과 동일하게 처리된다(회귀 가드 테스트 포함). 검색/임베딩/색인 동작 변경 없음, wire schema 불변. Phase 2(처방)는 별도 PR. ## 검증 - `cargo test -p kebab-eval` 녹색 (변형 일관성 3 + H1/M1 회귀 3 + 그룹 정합성 + 기존 metrics/loader/compare/runner 전부). - `cargo clippy -p kebab-eval -p kebab-cli --all-targets -- -D warnings` 녹색 (err+warn 0). - main 위 cherry-pick 단독 빌드 검증 (rerank 실험 코드와 분리 — 이 PR 은 eval 프레임워크만). - 실 dogfood KB(8그룹×32변형) 측정으로 (A)/(B) 진단 동작 확인 + raw search 독립 재현. ## 시험 항목 (Test Plan) - [ ] `kebab eval run --mode hybrid --k 50` 후 `kebab eval variants <run_id>` 가 그룹별 recall_spread/A/B/pool 표를 출력 - [ ] `--k 10` run 에 대해 `eval variants` 가 pool truncation 으로 bail (조용한 오답 방지) - [ ] `--json` 출력이 `VariantConsistencyReport` 구조와 일치 Assisted-by: Claude Code
altair823 added 10 commits 2026-05-30 00:58:05 +00:00
목표 재정의: 한/영 overlap → 같은 의미의 다양한 표현(동의어·다른 어휘·풀어쓴
문장·한영)에서 일관된 답변 품질. 지난 reranker 실험이 overlap 프록시 최적화로
헛돈 교훈 반영 — 처방 전 진짜 지표(변형 일관성)를 직접 재는 평가부터.

Phase 1(본 spec 구현): kebab-eval golden suite에 변형 그룹(intent group) +
변형 일관성 메트릭(recall_spread, answer_consistency) + recall@pool vs recall@k로
(A)순위출렁/(B)어휘격차 자동 판별. Phase 2(처방)는 측정 결과 게이트 뒤 조건부.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5개 task: (1) GoldenQuery.group + 그룹 정합성 검증, (2) 변형 일관성 메트릭
모듈 + A/B(순위출렁/어휘격차) 분류, (3) kebab eval variants CLI, (4) dogfood
golden 변형 그룹 큐레이션, (5) 측정 + 진단 리포트. TDD bite-sized, 완성 코드.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8그룹×4변형(dogfood) 측정: groups=8 A_dominant=2 B_dominant=4 spread@10=0.750.
진단 — 문제는 한/영이 아니라 어휘 거리(영어 풀어쓴 문장도 miss, 일부 한국어는 OK).
B(어휘격차, recall@50=0, rerank 불가) 우세 → 쿼리 확장/번역 처방 신호. A(순위출렁)는
cap_theorem/vector_database 2그룹뿐. "측정 먼저" 논제 정량 검증(rerank 단독은 부분해법).
Phase 2 처방 결정 대기.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deep-research 워크플로(104 agent, 5각도, 22소스, 25 claim 3-vote 검증, 22 confirmed/3 killed).
결론: 색인시 doc-side expansion(doc2query)이 pool-miss 최선책 — pool 자체를 키우고
per-query 지연 ~0(색인시 1회), 정확매칭 보존(별도 필드 append). 단 vanilla mt5는 같은언어라
한/영 갭은 색인시 KO↔EN 대체 query 생성 필요. query-side(HyDE=거부된 per-query LLM,
Vector-PRF=recall 주장 기각)는 부적합. 검증은 기존 variant eval 로 가능.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
딥리서치(104 agent): 어휘격차 pool-miss 최선책 = 색인시 doc-side expansion.
PoC(dogfood KB): recall@50=0 이던 3쿼리가 별칭 추가로 rank1~2 부활(hybrid+vector,
골든 verbatim 아님=일반화). 핵심 미검증 고리 실 corpus 정량 확인.
Phase 2 = 색인시 doc-side expansion(KO↔EN 번역 별칭) → 별도 FTS5 필드 → RRF, flag off.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-30 01:00:08 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — 설계·테스트 견고, actionable 1건(README sync).

좋은 점

  • (A)/(B) 분류를 recall@narrow vs recall@pool 대비로 정의한 게 진단 목적에 정확히 맞고, per-task 리뷰에서 H1(POOL_K=50 vs eval run --k 기본 10 → A 영원히 안 나옴)을 측정 전에 잡아 eval_k 스냅샷 + bail + pool_possibly_truncated 플래그로 막은 흐름이 인상적이다. 회귀 테스트로 고정한 것도 좋다.
  • group=None 경로·AggregateMetrics 불변 회귀 가드, eval_k 누락(구버전 run) 시 안전 skip — backward-compat 처리가 꼼꼼하다.
  • answer_okmetrics.rs groundedness(error 가드 + 빈 must_contain/forbidden vacuous-true 방지)와 정렬한 것도 sibling 메트릭 일관성 측면에서 옳다.

[MEDIUM] README 명령 표 sync 누락

  • 이 PR 은 신규 서브커맨드 kebab eval variants <run_id> [--json] 를 추가하는데 README.md 의 명령 표(line 96 | kebab eval run / compare | golden query 회귀 측정 |)가 갱신되지 않았다. CLAUDE.md 의 README-sync 규칙("새 kebab <subcommand> → 명령 표 갱신")에 해당한다.
  • 같은 줄에 기존 aggregate 도 빠져 있으니 함께 보강 권장: run / aggregate / compare / variants + 설명에 "변형 일관성 진단" 추가.
  • README 가 diff 에 없어 inline 대신 summary 로 표기.

나머지(코드 로직·테스트·docs)는 머지 가능 수준. 위 1건 반영 후 APPROVE 예정.

회차 1 — 설계·테스트 견고, actionable 1건(README sync). **좋은 점** - (A)/(B) 분류를 `recall@narrow` vs `recall@pool` 대비로 정의한 게 진단 목적에 정확히 맞고, per-task 리뷰에서 H1(`POOL_K=50` vs `eval run --k` 기본 10 → A 영원히 안 나옴)을 측정 *전에* 잡아 `eval_k` 스냅샷 + bail + `pool_possibly_truncated` 플래그로 막은 흐름이 인상적이다. 회귀 테스트로 고정한 것도 좋다. - `group=None` 경로·`AggregateMetrics` 불변 회귀 가드, `eval_k` 누락(구버전 run) 시 안전 skip — backward-compat 처리가 꼼꼼하다. - `answer_ok` 를 `metrics.rs` groundedness(error 가드 + 빈 must_contain/forbidden vacuous-true 방지)와 정렬한 것도 sibling 메트릭 일관성 측면에서 옳다. **[MEDIUM] README 명령 표 sync 누락** - 이 PR 은 신규 서브커맨드 `kebab eval variants <run_id> [--json]` 를 추가하는데 `README.md` 의 명령 표(line 96 `| kebab eval run / compare | golden query 회귀 측정 |`)가 갱신되지 않았다. CLAUDE.md 의 README-sync 규칙("새 `kebab <subcommand>` → 명령 표 갱신")에 해당한다. - 같은 줄에 기존 `aggregate` 도 빠져 있으니 함께 보강 권장: `run / aggregate / compare / variants` + 설명에 "변형 일관성 진단" 추가. - README 가 diff 에 없어 inline 대신 summary 로 표기. 나머지(코드 로직·테스트·docs)는 머지 가능 수준. 위 1건 반영 후 APPROVE 예정.
altair823 added 1 commit 2026-05-30 01:00:38 +00:00
claude-reviewer-01 approved these changes 2026-05-30 01:01:05 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 2 — 회차 1 지적(README 명령 표 sync) 반영 확인. APPROVE.

1529e6d 에서 kebab eval run / aggregate / compare / variants 로 표를 보강하고 variants 의 (A)/(B) 진단 + --json 을 설명에 추가했다. 누락됐던 aggregate 도 함께 채워 명령 표가 실제 서브커맨드와 일치한다.

남은 actionable 없음. 정리하면:

  • 코드: group 정합성 → variant 메트릭/A·B 분류 → CLI, 전부 테스트·clippy 녹색. H1(pool truncation) 사전 차단 + 회귀 테스트 고정이 이 PR 의 백미.
  • 회귀 위험: eval 전용·additive, 기존 AggregateMetrics·검색·wire schema 불변.
  • 문서: spec/plan/handoff/research + README sync 완비.

머지 가능.

회차 2 — 회차 1 지적(README 명령 표 sync) 반영 확인. APPROVE. `1529e6d` 에서 `kebab eval run / aggregate / compare / variants` 로 표를 보강하고 `variants` 의 (A)/(B) 진단 + `--json` 을 설명에 추가했다. 누락됐던 `aggregate` 도 함께 채워 명령 표가 실제 서브커맨드와 일치한다. 남은 actionable 없음. 정리하면: - 코드: group 정합성 → variant 메트릭/A·B 분류 → CLI, 전부 테스트·clippy 녹색. H1(pool truncation) 사전 차단 + 회귀 테스트 고정이 이 PR 의 백미. - 회귀 위험: eval 전용·additive, 기존 AggregateMetrics·검색·wire schema 불변. - 문서: spec/plan/handoff/research + README sync 완비. 머지 가능.
altair823 added 1 commit 2026-05-30 01:10:44 +00:00
README 의 괴물 셀(ingest 2891→544, search 2952→687, ask 1244→415, tui 2300→453자)을
"무엇 + 핵심 flag + 포인터"로 축소. 빠진 구조 detail 은 ARCHITECTURE 로 이전:
- symbol path 형식에 Go/Java/Kotlin/C/C++ 추가 + code chunk provenance(citation.kind/code_lang/repo)
- Markdown title 자동 채움 순서(md-frontmatter-v2)
- RAG groundedness 검증(mDeBERTa-v3 XNLI, nli_threshold gate) 결정 행 신설
- TUI 행을 P9-1~4 완료 + F1 cheatsheet 로 최신화 (stale "진행 예정" 제거)
flag 망라는 --help, TUI 키는 in-app F1 cheatsheet(권위 런타임 소스)로 위임 — stale 방지.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-30 01:11:30 +00:00
claude-reviewer-01 left a comment
Member

회차 3 — 사용자 요청으로 README 슬림 + ARCHITECTURE 동기화 추가 (b6ad947). 검토 완료, APPROVE.

이 회차는 코드가 아니라 문서 정리다. PR 범위가 "eval 프레임워크 + 문서 정리"로 넓어졌으나, 사용자가 한 PR 에 묶기를 명시적으로 요청한 의도된 결합이다(결함 아님).

검토 결과:

  • README 명령 표의 괴물 셀 4개(ingest/search/ask/tui, 합 ~9.3KB → ~2KB)를 "무엇 + 핵심 flag + 포인터"로 축소. 망라적 flag 는 --help, TUI 키는 in-app F1 cheatsheet 로 위임 — 정적 문서가 런타임 권위 소스를 중복·stale 하게 떠안던 구조를 해소했다.
  • 내용 손실 없음: 빠진 구조 detail 이 ARCHITECTURE 로 실제 이전됨 — symbol path 형식에 Go/Java/Kotlin/C/C++ 추가 + code chunk provenance, Markdown title 자동 채움(md-frontmatter-v2), NLI groundedness 검증(mDeBERTa-v3, nli_threshold gate) 결정 행 신설. 표 행 형식(3-pipe) 전부 정상, Mermaid 무손상.
  • ARCHITECTURE TUI 행의 stale "P9-2/3/4 진행 예정" → "P9-1~4 완료 + F1 cheatsheet" 로 최신화.
  • README 포인터(ARCHITECTURE 「핵심 기술 결정」 표 / --help / wire-schema) 정합.

actionable 없음. eval 프레임워크(회차 1~2 APPROVE) + 문서 정리 모두 머지 가능.

회차 3 — 사용자 요청으로 README 슬림 + ARCHITECTURE 동기화 추가 (`b6ad947`). 검토 완료, APPROVE. 이 회차는 코드가 아니라 문서 정리다. PR 범위가 "eval 프레임워크 + 문서 정리"로 넓어졌으나, 사용자가 한 PR 에 묶기를 명시적으로 요청한 의도된 결합이다(결함 아님). 검토 결과: - README 명령 표의 괴물 셀 4개(ingest/search/ask/tui, 합 ~9.3KB → ~2KB)를 "무엇 + 핵심 flag + 포인터"로 축소. 망라적 flag 는 `--help`, TUI 키는 in-app `F1` cheatsheet 로 위임 — 정적 문서가 런타임 권위 소스를 중복·stale 하게 떠안던 구조를 해소했다. - **내용 손실 없음**: 빠진 구조 detail 이 ARCHITECTURE 로 실제 이전됨 — symbol path 형식에 Go/Java/Kotlin/C/C++ 추가 + code chunk provenance, Markdown title 자동 채움(md-frontmatter-v2), NLI groundedness 검증(mDeBERTa-v3, nli_threshold gate) 결정 행 신설. 표 행 형식(3-pipe) 전부 정상, Mermaid 무손상. - ARCHITECTURE TUI 행의 stale "P9-2/3/4 진행 예정" → "P9-1~4 완료 + F1 cheatsheet" 로 최신화. - README 포인터(ARCHITECTURE 「핵심 기술 결정」 표 / `--help` / wire-schema) 정합. actionable 없음. eval 프레임워크(회차 1~2 APPROVE) + 문서 정리 모두 머지 가능.
altair823 merged commit 01a03463a6 into main 2026-05-30 01:12:29 +00:00
altair823 deleted branch feat/paraphrase-robustness-eval 2026-05-30 01:12:31 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#193