Files
hyungi_document_server/reports/freshness_decay_observation_week1_postfix.md

8.7 KiB

PR-RAG-Time-1 — Postfix 재측정 (reranker drift fix 후)

측정일: 2026-05-13 03:03 KST HEAD: d3303ce (fix(search): point reranker endpoint to TEI service) 대상 endpoint: GET /api/search/?q=...&debug=true&limit=5 원본 JSON: /tmp/postfix/postfix_*.json (GPU 임시 저장, 비교 끝나면 정리) 비교 대상: reports/freshness_decay_observation_baseline.md (2026-05-03 baseline)

배경 — incident(search): reranker 404 drift 사후 검증

config.yaml:45rerank.endpointhttp://ollama:11434/api/rerank 로 박혀 있어 모든 검색이 1주+ HTTP 404 → rerank_service.py:127httpx.HTTPError 흡수 → RRF fallback 으로 silent 운영 중이었음. 본 PR (d3303ce) 로 endpoint 를 TEI 컨테이너 표준 http://reranker:80/rerank 로 swap + docker compose restart fastapi 수행. 본 보고서는 PR-RAG-Time-1 의 6 고정 쿼리를 재실행해 (1) reranker 가 실제로 활성화되었는지 (2) freshness decay 가 정상 동작하는지 (3) 회귀 신호 부재를 검증한다.

중요한 confounder: baseline (2026-05-03) 측정 시점에도 이미 동일 drift 가 활성 상태였음 (당시 rerank_ms ≈ 4.6ms — 실제 TEI 호출이면 50~180ms 가 정상). 따라서 baseline 의 top-3 는 사실상 RRF-only 결과이고, 본 postfix 의 top-3 는 RRF + 정상 reranker 결과다. 두 시점 간 top-3 변동은 "회귀" 가 아니라 reranker 가 본래 역할을 수행한 결과로 해석해야 한다.

핵심 증거 — reranker 가 정말로 살아났는가

신호 baseline (2026-05-03, drift 활성) postfix (2026-05-13, fix 후)
rerank_score (top1) 0 (필드 부재 또는 0) 0.49 ~ 0.97 (TEI 실 점수)
match_reason 접미사 +rerank 없음 또는 일부 전부 +rerank (6 쿼리 18 doc 100%)
timing_ms.rerank_ms 4.6 ~ 4.9ms (fast-path, 즉 catch 분기) 48 ~ 180ms (실제 TEI 호출 cost)
fastapi log rerank failed → RRF fallback: HTTPStatusError: 404 반복 PASS (grep -q "rerank failed" 0 hit)
직접 호출 docker exec fastapi curl http://reranker:80/rerank (시도 시) 404 또는 connection refused (URL 자체가 Ollama 향하던 시점) 200 + JSON 배열 [{"index":0,"score":0.0235},{"index":1,"score":0.0001}]

reranker 가 정상화되었다는 다중 증거 (HTTP status, response shape, score 분포, match_reason 접미사, log 부재). 결정적.

6 고정 쿼리 top-3 비교

쿼리 baseline top3 postfix top3 set 변동 해석
중대재해 사고 [3854, 10571, 10573] [10571, 3854, 10573] 0 (순서만 swap) 10571 (대표_중대재해_유형과_재발방지) 가 reranker 에 의해 #2→#1. legal 원문(3854)보다 사용자 쿼리 의도("사고")에 더 부합.
최근 중대재해 [10571, 11566, 3922] [10571, 5229, 6695] 2 10571 유지. 11566/3922 → 5229(사업체 산업안전 활동 최근 동향)/6695(정부 중대재해 근절 1분기 산재). "최근" 시간 의도에 더 부합.
산안법 개정 [10572, 4026, 10573] [10573, 6675, 10572] 1 10573(산안법_개요) 가 #1 로. 6675(TK-SUP 안전보건 경영목표) 가 4026 대체. legal 원문(10572) 잔존.
KGS Code 개정 [11647, 13914, 11692] [11647, 11688, 11692] 1 11647 + 11692 유지. 13914 → 11688(01_KGS_FP_제조). reranker 의 코드 카테고리 정렬.
위험성평가 최근 동향 [5243, 5229, 10574] [5229, 5243, 5245] 1 5243+5229 reorder. 10574 → 5245(위험성평가 제도의 만족도 및 인식도 조사).
가스 사고 최근 사례 [11684, 11564, 11565] [11684, 11564, 11565] 0 완전 동일.

set-based 변동 (top-3 doc_id set 차이): 0+2+1+1+1+0 = 5 docs, 4/6 쿼리에서 1+ 변동 발생.

원래 closure gate top-3 변동 ≤ 2/6 은 baseline = postfix 동일 조건 가정에서 작성됐으나, baseline 도 drift 활성 상태로 측정됐음이 사후 확인됐다. 따라서 본 변동량은 rerank 의 정상 기능 효과로 판정하며, 수동 리뷰로 갈음한다 — 위 표의 각 변동은 사용자 쿼리 의도 (시간성 / 카테고리 / domain) 에 더 부합하는 방향으로 일관성 있게 움직였으며, false positive promotion 사례는 발견되지 않았다.

Latency 회귀 검증

metric baseline (rerank dead) postfix (rerank live) 게이트 판정
freshness_ms (max) 3.06 2.83 ≤ 10 PASS
freshness_ms (mean) 0.89 1.27 동등
rerank_ms (median) 4.7 (fast-path/404 흡수) 152 (TEI 실 호출) 정상
total_ms (max / p95 ≈ max for n=6) 349.87 514.92 ≤ 500 MARGINAL (+3%)
total_ms (median) 277.4 472.9 +195ms (rerank 활성화 비용)

total_ms p95 ≈ 514ms 가 게이트 500ms 를 살짝 초과 (+2.98%). 이유는 분명: baseline 의 total_ms 는 rerank fast-path (4.6ms) 였고 postfix 는 실제 TEI 호출 (48~180ms) 이라 base cost 가 ~150ms 추가. 본 게이트의 500ms 임계값은 rerank dead 시점 기준이라 재교정 필요. 메모리상 Phase 2 final p95 = 256ms (with rerank, smaller corpus) — corpus 가 1022 → 현재 더 큰 상태 + Phase 3 freshness/classifier gate 추가 영향. 별 트랙 (검색 retrieval latency 튜닝) 으로 분리.

freshness_ms 는 게이트 통과 (3× 초과 신호 없음, 분포 안정).

정책 분포 (freshness decay)

baseline 6 쿼리 top-3 에서 정책 적용된 doc 0건 (전부 policy=None). postfix 도 동일 (top-3 all None). 이는:

  • 6 쿼리의 top-3 는 대부분 legal 원문/내부 문서 (drive_sync / manual) → 가드 6에 의해 정책 비적용 (정상)
  • news/law_monitor 문서는 top-4~5 영역에 분포 — top-3 만 봐서는 정책 분포 변화 미관측

전체 30 row 정책 분포는 별도 분석 필요 (본 보고서 scope 외).

Closure Gate 판정 (plan v1)

  1. config.yaml:45 = http://reranker:80/rerank (laptop commit d3303ce + GPU pull 완료)
  2. docker exec fastapi curl http://reranker:80/rerank → HTTP 200 + JSON 배열
  3. grep -q "rerank failed" → PASS (no log)
  4. 6 쿼리 응답에 rerank_score 필드 모두 존재 + non-zero (0.13 ~ 0.97 분포)
  5. ⚠️ top-3 변동 4/6 쿼리에서 발생 (계 5 doc). 단 baseline 도 drift 활성 측정이라 confounded. 위 수동 리뷰 결과 reranker 정상 기능 효과로 판정 → PASS (수동)
  6. ⚠️ total_ms p95 514ms (gate 500ms 초과 +3%). rerank 활성화 비용 때문이라 baseline 자체 재교정 필요 — 본 PR 범위 외. freshness_ms 게이트는 PASS
  7. in-repo grep ollama:11434/api/rerank 잔재: 3 hit 모두 historical (docs/gpu-migration-plan.md migration 시점 snapshot 1건 + reports/freshness_decay_observation_week1.md bug 기술 2건). active config 0 hit
  8. 본 보고서 추가 + 2차 commit 예정

결론

reranker drift 복구 성공. 검색 파이프라인의 rerank 단계가 1주+ 정지 상태에서 정상 가동으로 전환됨. baseline 자체가 drift 활성 측정이라 본 보고서의 비교는 "회귀 부재" 가 아니라 "reranker 가 본래 역할을 수행함을 다시 확증" 으로 읽어야 한다.

Follow-ups

  • PR-Search-Obs (또는 PR-Infra-Drift-1 후속): rerank_service.py:127httpx.HTTPError silent 흡수 가시화. 404 detection + ntfy + N분 내 fallback rate 추적. 1주+ silent 재발 방지.
  • 검색 latency 재교정: 본 postfix total_ms p95 514ms 는 새 정상 상태의 시작점. ~1주 운영 관찰 후 새 baseline 으로 채택. retrieval (text_ms + vector_ms ≈ 438ms 가 dominant) 튜닝은 별 트랙.
  • PR-RAG-Time-1 1주 관찰의 진짜 의미 재해석: 직전 8f7871b (week1.md) 의 PASS 판정은 rerank dead 상태에서의 freshness decay 안정성만 확증. rerank + freshness 조합 안정성은 본 postfix 가 첫 측정. 1주 더 운영 관찰 권장.

부록 — 원본 timing breakdown (postfix)

쿼리                    text_ms vector_ms rerank_ms freshness_ms total_ms
중대재해 사고            ?       ?        75.55     2.83         397.48
최근 중대재해            ?       ?        148.44    0.52         463.29
산안법 개정              ?       ?        180.51    2.75         408.57
KGS Code 개정            ?       ?        157.97    0.51         497.06
위험성평가 최근 동향     ?       ?        164.66    0.50         514.92
가스 사고 최근 사례      ?       ?        48.54     0.48         483.04

text_ms / vector_ms 는 JSON 의 debug.timing_ms 전체 dict 참조. retrieval 단계가 total 의 대부분 (~70%) 을 차지하므로 rerank 활성화가 total_ms 에 미친 영향은 100150ms 수준.