fix(search): DS RAG LLM_TIMEOUT_MS align 15s/3s → 30s/10s (B-3 Synthesis-Timeout-Calibration-1)

PR-Hermes-Docsrv-Search-1 closure 측정 (synthesis_ms=30~48s / ev_ms=15005 /
query_analyze 45s) 으로 15s LLM_TIMEOUT 빈발 timeout 확인. Mac mini 26B 동시
호출 (gate Semaphore 1 직렬화 후에도 evidence + synthesis + classifier +
query_analyzer + verifier 가 sequential 누적) 시 각 호출 30s 까지 필요.

5곳 변경:
- synthesis_service.LLM_TIMEOUT_MS 15000 → 30000
- evidence_service.LLM_TIMEOUT_MS 15000 → 30000
- verifier_service.LLM_TIMEOUT_MS 3000 → 10000
- query_analyzer.LLM_TIMEOUT_MS 15000 → 30000
- search.py:522 classifier wait_for 15.0 → 30.0 (classifier_service align)
- search.py:641 verifier wait_for 4.0 → 10.0 (verifier_service align)

classifier (이전 PR 에서 30s 로 align 완료) 와 동일 정책 — outer wait_for
가 inner LLM_TIMEOUT_MS 를 override 하지 않도록 align.

ask 응답 latency 상한 ↑ 의도된 trade-off — 안정성 (refusal_gate
conservative_refuse 회피 + grounding/verifier 정상 동작) 우선.

영향: PR-1 fixture 회귀 0 예상 (이전 timeout 이 새 한도 안). B-1 Throughput-1
(priority queue / 모델 분리) 별 PR 진입 시 latency 본격 단축 검토.
This commit is contained in:
Hyungi Ahn
2026-05-17 08:01:22 +09:00
parent 117597c8aa
commit 73f328cb65
5 changed files with 10 additions and 6 deletions
+6 -2
View File
@@ -518,8 +518,10 @@ async def ask(
# 거의 모든 classifier 호출 timeout → conservative_refuse(no_classifier) 경로. 15s 로 상향 — classifier
# 가 실제 작동하도록 (단, ask 전체 응답 시간 상한 영향: ev_ms + max(classifier_wait, evidence_extract) +
# synth_ms + verifier 누적).
# 2026-05-17 B-3: 15s 도 동시 부하 시 부족 (classifier_service LLM_TIMEOUT_MS 30s 와 misalign).
# 30s 로 align → classifier 동작 안정. ask 응답 latency 상한 ↑ 의도.
try:
classifier_result = await asyncio.wait_for(classifier_task, timeout=15.0)
classifier_result = await asyncio.wait_for(classifier_task, timeout=30.0)
except (asyncio.TimeoutError, Exception):
classifier_result = ClassifierResult("timeout", None, [], [], 0.0)
@@ -637,8 +639,10 @@ async def ask(
verifier_task = asyncio.create_task(
verify(q, sr.answer or "", evidence)
)
# 2026-05-17 B-3: 4s outer wait_for 가 verifier_service LLM_TIMEOUT_MS (10s) 를 override
# → classifier 와 동일 패턴 (search.py:522 가 6s→15s swap 했던 case). 10s 로 align.
try:
verifier_result = await asyncio.wait_for(verifier_task, timeout=4.0)
verifier_result = await asyncio.wait_for(verifier_task, timeout=10.0)
except (asyncio.TimeoutError, Exception):
verifier_result = VerifierResult("timeout", [], 0.0)
+1 -1
View File
@@ -78,7 +78,7 @@ SPAN_MIN_CHARS = 80 # 이 미만이면 window enlarge
SPAN_ENLARGE_TARGET = 120 # enlarge 시 재윈도우 target_chars
SPAN_MAX_CHARS = 300 # 이 초과면 cut (synthesis token budget 보호)
LLM_TIMEOUT_MS = 15000
LLM_TIMEOUT_MS = 30000 # 2026-05-17 B-3: 15s 시 ev_ms=15005 timeout 빈발 — classifier (30s) 와 align
PROMPT_VERSION = "v2-triage" # B-2: primary(26B MLX) → triage path 전환. PR #20 이후 triage/primary 동일 endpoint (Mac mini 26B).
# 확장 여지 — None 이면 비활성 (baseline). 실측 후 0.8 등으로 켠다.
+1 -1
View File
@@ -44,7 +44,7 @@ logger = setup_logger("query_analyzer")
PROMPT_VERSION = "v2" # prompts/query_analyze.txt 축소판
CACHE_TTL = 86400 # 24h
CACHE_MAXSIZE = 1000
LLM_TIMEOUT_MS = 15000 # async 구조 (background), 동기 경로 금지
LLM_TIMEOUT_MS = 30000 # 2026-05-17 B-3: 동시 부하 시 query_analyze 45s 측정 (fastapi log) — 15s 부족, classifier (30s) 와 align. async 구조 (background), 동기 경로 금지
# ↑ 실측: gemma-4-26b-a4b-it-8bit MLX, 축소 프롬프트(prompt_tok=802) 7~11초.
# generation이 dominant (max_tokens 무효, 자연 EOS ~289 tok 생성).
# background 실행이라 15초도 안전. 상향 필요 시 여기서만 조정.
+1 -1
View File
@@ -40,7 +40,7 @@ logger = setup_logger("synthesis")
# ─── 상수 (plan 영구 룰) ─────────────────────────────────
PROMPT_VERSION = "v2"
LLM_TIMEOUT_MS = 15000
LLM_TIMEOUT_MS = 30000 # 2026-05-17 B-3: 15s 시 동시 부하 (Mac mini 26B classifier+evidence+synthesis serialized) 빈발 timeout — classifier (30s) 와 align
CACHE_TTL = 3600 # 1h (answer 는 원문 변경에 민감 → query_analyzer 24h 보다 짧게)
CACHE_MAXSIZE = 300
MAX_ANSWER_CHARS = 600
+1 -1
View File
@@ -31,7 +31,7 @@ if TYPE_CHECKING:
logger = setup_logger("verifier")
LLM_TIMEOUT_MS = 3000
LLM_TIMEOUT_MS = 10000 # 2026-05-17 B-3: 3s 시 동시 부하 시 verifier 빈발 skip → grounding 약화. Mac mini 26B 가 verifier-style 짧은 LLM call 도 concurrent 호출 시 3s 초과 빈번 — 10s 로 raise
CIRCUIT_THRESHOLD = 5
CIRCUIT_RECOVERY_SEC = 60