fix(rag): S3 NLI unavailable — hypothesis char budget + token-count fallback retry #184
Reference in New Issue
Block a user
Delete Branch "fix/s3-nli-model-unavailable-diagnose"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
요약
S3 dogfood query 의
nli_model_unavailableconsistent fail (313s) 의 root cause = mDeBERTa-v3 tokenizer 의TruncationStrategy::OnlyFirst+ 949-token hypothesis. hypothesis 단독이 max_length cap (512) 을 단독 초과 → premise 를 0 까지 잘라도 tokenizer 가 fit 불가 → wirenli_model_unavailable로 over-classified.Fix Option A — char-budget + token-count fallback retry + RC1-residual trait dispatch 정합. KR safe (token-count retry path) + graceful fallback (regression 0).
설계: docs/superpowers/specs/2026-05-26-s3-nli-model-unavailable-diagnose-spec.md (4 round APPROVE)
계획: docs/superpowers/plans/2026-05-26-s3-nli-model-unavailable-diagnose-plan.md (3 round ACCEPT)
변경 사항
kebab-nli
NliVerifiertrait 확장:hypothesis_token_count(&str) -> Result<usize>method 추가 + default implOk(0)(backward-compat forMockNliVerifier).OnnxNliVerifier::HYPOTHESIS_TOKEN_BUDGET = 256inherent const.OnnxNliVerifier::hypothesis_token_countoverride — trait impl block 안 에 위치 (round-3 critic RC1-residual closure: inherent block 이면 vtable 미등록 →&dyn NliVerifierdispatch 시 defaultOk(0)호출 → KR silent NO-OP).score_long_en_hypothesis_returns_err_without_pipeline_truncation+hypothesis_token_count_dispatches_correctly_via_dyn_trait(vtable dispatch pin vialet v_dyn: &dyn NliVerifier = &v;).kebab-rag
MAX_NLI_HYPOTHESIS_CHARS_INITIAL = 1200+MAX_NLI_HYPOTHESIS_CHARS_MIN = 150const.pub(crate) fn truncate_chars(s, budget) -> (String, bool)pure-fn — chars-only truncation arithmetic.pub fn truncate_hypothesis_for_nli_with_budget(verifier, hypothesis)retry helper — char budget 절반화 (1200 → 600 → 300 → 150) + min floor 시 gracefulbail!.ask_multi_hopstep 8.5 hook 의 callsite 수정: hypothesis-side truncate hook + explicitmatch+return self.refuse_nli_model_unavailable(...)패턴 (round-2 plan critic CRITICAL #1 closure:?사용 금지 — wireerror.v1으로 빠지면 graceful fallback 약속 위반).SpyNliVerifier신규 helper (closure-based, 2-arg constructor: score_fn + token_count_fn).long_en_synth_answer_truncated_before_nli_call(Right direction pin) +long_kr_synth_answer_retries_with_smaller_budget(KR safety + retry count) +unrelenting_token_overflow_falls_through_to_unavailable(graceful fallback).pipeline.rs::#[cfg(test)] mod tests.tasks/HOTFIXES.md
신규 dated entry
## 2026-05-26 — S3 NLI unavailable — hypothesis truncate + token-count fallback(date-top convention, HOTFIX #15 직후, fb-41 우산 외부). Symptom / Root cause / Action / Amends 4-block. HOTFIX 번호 부여 안 함 (production behavior fix, fixture-issue HOTFIX #15 와 다름).OMC team review process
핵심 발견 (round-by-round):
?propagation 모순 — graceful fallback 약속 정면 위반. 4 round spec review 가 missed 한 control-flow trace 결함. + MAJOR #2-4 (file count / helper 부재 / step 11 ambiguity).검증
cargo test -p kebab-nli -j 1→ 11/11 pass + 7 ignored default skip.cargo test -p kebab-rag -j 1→ 전체 pass (3 new mock multi_hop + 4 new boundary + 회귀 0).cargo test --workspace --no-fail-fast -j 1→ 1313 pass (+7 new), 0 failed. 회귀 0 (HOTFIX #15 이미 fixed, no remaining flaky).cargo clippy --workspace --all-targets -j 1 -- -D warningsclean (type_complexity allow on Arc aliases — closure-based spy 필수).Manual smoke + Dogfood retest (사용자 머지 후)
cargo test -p kebab-nli --test inference -- --ignored --test-threads=1— 신규 2 ignored test 의 manual smoke (network + model download + vtable dispatch RC1-residual pin).nli_threshold > 0guard 사전 확인 + S3 EN + KR query retest →nli_verification_failed또는 null (NOTnli_model_unavailable) 확인.비범위
MAX_NLI_PREMISE_CHARS = 1600도 KR-heavy chunks 에서 동일 risk. 별 task §6 #1 후보 (v0.18.x candidate).RUST_LOG=debug+ log file path) — 별 docs task §6 #7.RefusalReason::NliInputTooLong신규 variant — 별 wire schema task §6 #3.시험 항목 (Test Plan)
--ignoredsmoke (사용자 또는 후속 dogfood task).Assisted-by: Claude Code
회차 1 — S3 NLI unavailable fix 검토.
OMC team
s3-nli-unavailable-diagnose의 4 round spec + 3 round plan review 누적 closure 결과 — 본 PR 의 코드가 spec + plan 의 검증된 design 정확 reflect.칭찬 (산문):
RC1-residual silent NO-OP 회피 명시적 pin —
OnnxNliVerifier::hypothesis_token_count가 trait impl block 안 에 위치 + spec §5.1 Test 7 의 vtable dispatch (let v_dyn: &dyn NliVerifier = &v;) 가 inherent-only 배치 regression 시 deterministic fail. round-3 spec critic 가 발견한 Rust trait dispatch micro-semantic 결함이 production code 에 자동 정합.?propagation 금지의 graceful fallback 약속 보존 — round-2 plan critic 가 발견한 CRITICAL #1:?사용 시 wireerror.v1으로 빠짐 (graceful fallback 약속 위반). 본 PR 의 callsite 가 explicitmatch { Ok(x) => x, Err(e) => return self.refuse_nli_model_unavailable(...) }패턴 + 기존v.score()Err 분기와 대칭. wireanswer.v1 + NliModelUnavailable refusal유지 보장.KR safety token-count fallback retry — round-1 critic 가 발견한 KR-extreme density (1200 chars × 1 char/token > 512 cap) 가 char budget 절반화 retry (1200 → 600 → 300 → 150) + min floor 시 graceful fallback 으로 해결. 사용자 (한국어 화자) 의 KR corpus 사용 시 fix 가 silent NO-OP 가 안 됨.
SpyNliVerifier 의 closure-based 2-arg constructor — round-2 verifier 가 발견한 Caveat (struct field-in-impl-block + Arc field mutation 불가) 모두 해결.
new<F, G>(score_fn, count_fn)패턴이 test 의 3 mock 시뮬레이션 (EN long / KR retries / unrelenting fallback) 모두 cover.NliVerifier trait 의 default impl backward-compat —
hypothesis_token_countdefaultOk(0)가 기존MockNliVerifier무수정 통과 보장. round-2 verifier Caveat 2 closure 의 zero-churn 정합.HOTFIXES.md 의 date-top convention + sibling pattern —
## 2026-05-26 — S3 NLI unavailable ...level-1 dated entry 가 HOTFIX #15 의 sibling. HOTFIX 번호 부여 안 함 (production behavior fix 의 정확한 분류).9 test 의 multi-layer regression pin — §5.1 vtable dispatch (코드 수준 RC1-residual pin) + §5.2 pure-fn (산술 회귀) + §5.3 mock multi-hop (integration retry path + Right direction + graceful fallback). 모든 critical risk 가 deterministic test 로 enforced.
추가 actionable 없음. 1313 tests pass + 0 failed + clippy clean. Wire / Cargo 영향 0.
머지 OK. 머지 후 dogfood EN + KR retest 진행 — spec §5.4 의 사전 guard (
nli_threshold > 0) 확인 후 S3 본래 케이스 + KR long-answer 시뮬레이션 →nli_model_unavailable부재 + 실nli_scorefinite float 확인.다음 step: 머지 후 작업 2 (architectural defer items — kebab-normalize 흡수 / Extractor dispatch unification / kebab-source-fs dep lightening).