docs(search): DS-Synthesis-Timeout-Calibration-1 (B-3) closure 보고서
5곳 LLM_TIMEOUT_MS + 2곳 outer wait_for align (classifier 30s 와 동일 정책). synthesis/evidence/verifier/query_analyzer 모두 동시 부하 시 30s 까지 필요. Regression fixture 결과: 10/10 HTTP 200 + 5/5 search + 3/3 failure injection 모두 PASS (회귀 0). 응답 시간 +4~20s 증가 (안정성 ↑ 의도된 trade-off). p95 12s gate 는 여전히 FAIL — B-1 Throughput-1 (priority queue / 모델 분리) 별 plan 으로 latency 단축 방향 진입.
This commit is contained in:
@@ -0,0 +1,124 @@
|
|||||||
|
# DS-Synthesis-Timeout-Calibration-1 (B-3) Closure Report
|
||||||
|
|
||||||
|
**Date**: 2026-05-17
|
||||||
|
**Plan 카테고리**: B-3 (PR-Hermes-Polymorphic-Rossum 후속, DS RAG 측 별 트랙)
|
||||||
|
**범위**: DS RAG 파이프라인 5 stage 의 LLM_TIMEOUT_MS / outer wait_for align (Mac mini 26B serialized concurrent load 대응)
|
||||||
|
**Commit**: `73f328c`
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
PR-Hermes-Docsrv-Search-1 closure 시점 측정 (`synthesis_ms=30~48s` / `ev_ms=15005` / `query_analyze=45s`) 으로 기존 LLM_TIMEOUT_MS 15s / 3s 가 동시 부하 시 빈발 timeout. classifier (30s) 는 PR-1 closure 에서 이미 align 됐으나 다른 service 들 (synthesis / evidence / verifier / query_analyzer) 은 misaligned 잔존. 본 PR 이 5곳 동시 raise + 2곳 outer wait_for align.
|
||||||
|
|
||||||
|
## Root cause (재확인)
|
||||||
|
|
||||||
|
Mac mini 26B single-inference + `get_mlx_gate()` Semaphore(1) 직렬화 후 DS RAG 파이프라인 5 stage 가 sequential 누적:
|
||||||
|
- query_analyzer → evidence + classifier (parallel) → synthesis → verifier
|
||||||
|
- 각 stage 가 30s 까지 wait 후에야 다음 진행
|
||||||
|
- 15s LLM_TIMEOUT 시 절반 stage 가 timeout → fallback path 발화 (refusal_gate / verifier skip)
|
||||||
|
|
||||||
|
## 변경 사항
|
||||||
|
|
||||||
|
5 timeout constants + 2 outer wrappers:
|
||||||
|
|
||||||
|
| 파일 | line | 변경 |
|
||||||
|
|---|---|---|
|
||||||
|
| `app/services/search/synthesis_service.py` | 43 | `LLM_TIMEOUT_MS 15000 → 30000` |
|
||||||
|
| `app/services/search/evidence_service.py` | 81 | `LLM_TIMEOUT_MS 15000 → 30000` |
|
||||||
|
| `app/services/search/verifier_service.py` | 34 | `LLM_TIMEOUT_MS 3000 → 10000` |
|
||||||
|
| `app/services/search/query_analyzer.py` | 47 | `LLM_TIMEOUT_MS 15000 → 30000` |
|
||||||
|
| `app/api/search.py` | 522 | `wait_for(classifier_task, 15.0 → 30.0)` |
|
||||||
|
| `app/api/search.py` | 641 | `wait_for(verifier_task, 4.0 → 10.0)` |
|
||||||
|
|
||||||
|
**기존 정합**:
|
||||||
|
- classifier_service.LLM_TIMEOUT_MS = 30000 (PR-Hermes-Docsrv-Search-1 closure 시 이미 raised)
|
||||||
|
- ai.classifier.timeout = 30 (config.yaml, 같이 align 완료)
|
||||||
|
|
||||||
|
## Regression 검증 (PR-1 Layer 1 fixture re-run, 완료)
|
||||||
|
|
||||||
|
**전체 결과 (Pre-B-3 vs Post-B-3)**:
|
||||||
|
|
||||||
|
| 항목 | Pre-B-3 | Post-B-3 | 회귀 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| docsrv_ask HTTP 200 | 10/10 | **10/10** | ✅ 0 |
|
||||||
|
| docsrv_search HTTP 200 | 5/5 | **5/5** | ✅ 0 |
|
||||||
|
| Failure injection 3건 | 3/3 PASS | **3/3 PASS** (401 / 000 / refused) | ✅ 0 |
|
||||||
|
| classifier ok 비율 | 10/10 | 10/10 | ✅ 0 |
|
||||||
|
| min | 8.8s | 13.2s | +4.4s |
|
||||||
|
| p50 | 10.6s | **23.2s** | +12.6s |
|
||||||
|
| mean | 15.0s | **25.8s** | +10.8s |
|
||||||
|
| p95 | 34.8s | **50.7s** | +15.9s (ASME outlier) |
|
||||||
|
| max | 34.8s | **50.7s** | +15.9s |
|
||||||
|
|
||||||
|
**Per-query 비교**:
|
||||||
|
|
||||||
|
| Query | Pre-B-3 | Post-B-3 | Δ |
|
||||||
|
|---|---|---|---|
|
||||||
|
| ask-a1-memo-hit | 9.3s | 13.2s | +3.9s |
|
||||||
|
| ask-a2-voice | 13.0s | 19.9s | +6.9s |
|
||||||
|
| ask-a3-bridge | 10.1s | 22.0s | +11.9s |
|
||||||
|
| ask-b1-asme | 30.7s | **50.7s** | **+20.0s** (이전 timeout 부근, 끝까지 완료) |
|
||||||
|
| ask-b2-drift | 11.5s | 30.5s | +19.0s |
|
||||||
|
| ask-b3-digest | 10.4s | 25.6s | +15.2s |
|
||||||
|
| ask-c1-today | 34.8s | 30.5s | -4.3s |
|
||||||
|
| ask-c2-decision | 10.6s | 23.2s | +12.6s |
|
||||||
|
| ask-d1-secret | 10.5s | 20.7s | +10.2s |
|
||||||
|
| ask-d2-noexist | 8.8s | 21.8s | +13.0s |
|
||||||
|
|
||||||
|
**해석**:
|
||||||
|
- 응답 시간 +4~20s 증가 — 의도된 trade-off (timeout fallback path 대신 끝까지 completion)
|
||||||
|
- classifier ok 정상 path 100% (conservative_refuse 회피)
|
||||||
|
- functional 변화 0 (verdict, citations, sources, refused 모두 동일 패턴)
|
||||||
|
- p95 12s gate 는 여전히 FAIL (이전부터 ASME outlier 로 fail, B-3 가 안정성 우선이라 latency 더 증가 — B-1 Throughput-1 진입 시 단축 검토)
|
||||||
|
|
||||||
|
## 결정 사항
|
||||||
|
|
||||||
|
1. **B-3 = SHIPPED**:
|
||||||
|
- 5곳 LLM_TIMEOUT + 2곳 outer wait_for align 완료
|
||||||
|
- Mac mini 26B concurrent saturation 대응 완성 (classifier 외 4 service)
|
||||||
|
- functional 회귀 0, latency +4~20s (안정성 ↑ 의도된 trade-off)
|
||||||
|
|
||||||
|
2. **B-1 (Throughput-1) = 별 plan 으로 분리**:
|
||||||
|
- 본 B-3 가 latency 증가 방향 — B-1 이 latency 단축 방향 (priority queue / 모델 분리)
|
||||||
|
- architecture 변경이라 별 plan + 사용자 검토 필수
|
||||||
|
- 후보: (a) `asyncio.PriorityQueue` (user ask priority 0 / background priority 100) (b) Mac mini 4B 모델 추가 로드 (triage 만 분리) (c) GPU Ollama 4B 재도입 (PR #20 reverse)
|
||||||
|
|
||||||
|
3. **B-2 (Classifier-Threshold-Tune-1) = 1주 query 로그 대기**:
|
||||||
|
- 사용자 실제 query 패턴 + rerank score 분포 측정 후 `CONSERVATIVE_WEAK=0.35` recalibration
|
||||||
|
- 진입 = 2026-05-24 (1주 baseline) 이후
|
||||||
|
|
||||||
|
## File changes
|
||||||
|
|
||||||
|
- `app/services/search/synthesis_service.py` (line 43)
|
||||||
|
- `app/services/search/evidence_service.py` (line 81)
|
||||||
|
- `app/services/search/verifier_service.py` (line 34)
|
||||||
|
- `app/services/search/query_analyzer.py` (line 47)
|
||||||
|
- `app/api/search.py` (line 522, 641)
|
||||||
|
|
||||||
|
총 5 file, 6 timeout constants/wrappers 변경.
|
||||||
|
|
||||||
|
## 7일 안전망 (2026-05-24)
|
||||||
|
|
||||||
|
- git revert `73f328c` (단일 commit 으로 묶임)
|
||||||
|
- 별 백업 파일 0 (git history 가 안전망)
|
||||||
|
|
||||||
|
## 검증 commands (재실행)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 회귀 fixture
|
||||||
|
ssh macmini "bash ~/.hermes/fixtures/pr_search1_layer1.sh"
|
||||||
|
|
||||||
|
# DS 로그 (classifier ok 비율)
|
||||||
|
ssh gpu "cd ~/Documents/code/hyungi_Document_Server && \
|
||||||
|
docker compose logs --since=5m fastapi | grep -E 'classifier (ok|error|timeout)' | tail -10"
|
||||||
|
|
||||||
|
# Hermes E2E (Curl-Refine-2 확인 + 회귀 0)
|
||||||
|
ssh macmini "HERMES_DOCSRV_TOKEN=... && hermes chat -s docsrv_ask -q '내 자료에서 voice memo 찾아줘'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 후속 트랙
|
||||||
|
|
||||||
|
| 우선 | 트랙 | 진입 |
|
||||||
|
|---|---|---|
|
||||||
|
| **P2** | DS-Mac-mini-26B-Throughput-1 (B-1) | architecture 변경 plan 필요 — priority queue / 모델 분리 비교 |
|
||||||
|
| **대기** | DS-Classifier-Threshold-Tune-1 (B-2) | 2026-05-24 1주 query 로그 baseline 후 |
|
||||||
|
| (선택) | LLM_TIMEOUT_MS centralization | 5 service 가 각자 상수 보유 — 공통 config 항목 (`ai.llm_timeout_default: 30`) 도입 검토. P3 |
|
||||||
Reference in New Issue
Block a user