118f32f9b1
PR #20 (2026-05-14, GPU LLM 제거 + Mac mini 26B MLX 흡수) 의 swap 이 backends.json + 코드 주석/docstring 까지 따라가지 못한 표현 잔재 정리. - app/ai/client.py: AIClient docstring 및 call_triage / call_fallback docstring 의 "4B Ollama" → "Mac mini 26B MLX" / "현재는 triage 와 동일 엔드포인트" → "Claude Sonnet 4 API (PR #20 swap 완료)" - app/core/config.py: triage/primary/fallback 주석 통합 + Phase 3.5 classifier/verifier 주석에 PR #20 endpoint 명시 (history 보존) - app/services/search/{llm_gate,classifier_service,verifier_service, evidence_service}.py: "fallback(Ollama)" / "Ollama concurrent OK" / "triage(4B Ollama)" 표현을 Mac mini 26B MLX endpoint 기준으로 정정 + concurrent 안전성 별 검토 마커 추가 - app/services/digest/summarizer.py: "MLX hang/Ollama stall 방어" → "MLX hang / fallback Claude API stall 방어" - app/services/prompt_versions.py: SUMMARY_TRIAGE_TASK + ASK_PROMPT_VERSION 주석의 "4B Ollama" / "4B gemma Ollama" → Mac mini 26B MLX - app/workers/classify_worker.py: B-1 tier triage docstring 정정 코드 동작 변경 0 (주석/docstring 만). embed_worker / study_question_embed_worker 의 "Ollama bge-m3" 표현은 사실 정확이라 유지. 검증: - ollama list → bge-m3:latest 잔존 (embedding owner) - /api/embeddings probe → 1024-dim 200 OK - fastapi embed/ollama error 0 (last 10min) - document.hyungi.net 200 plan: ~/.claude/plans/4-stateless-dongarra.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
3.5 KiB
Python
72 lines
3.5 KiB
Python
"""프롬프트/모델 버전 상수 — telemetry 기록용 (Phase E.1)
|
|
|
|
목적: ask_events / analyze_events 에 prompt_version 과 model_name 을 기록해서
|
|
튜닝 전/후 비교와 실험 분기를 식별 가능하게 함.
|
|
|
|
규칙:
|
|
- 프롬프트 파일이 의미 있게 바뀌면 해당 상수 문자열을 bump (예: v1-400char → v2-600char)
|
|
- 하드코딩 금지. 파이프라인은 여기 상수만 참조.
|
|
- 모델명은 런타임 config(settings.ai.primary.model)에서 읽어서 resolve_primary_model() 사용.
|
|
|
|
E.3 배포 타임라인:
|
|
- v1-400char → 현재 (search_synthesis.txt 17행 "400 characters max")
|
|
- v2-600char → E.3 배포 시 bump (동일 파일 "600 characters max")
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
# ─── ask (/search/ask) 프롬프트 버전 ─────────────────────────
|
|
# synthesis_service.py 가 로드하는 app/prompts/search_synthesis.txt 기준
|
|
# v3-evidence-triage: evidence 추출을 triage path 로 전환 (B-2). PR #20 이후 triage/primary 동일
|
|
# Mac mini 26B endpoint — path 분리는 prompt 레벨. synthesis 는 search_synthesis.txt 사용. 프롬프트 자체는 v2-600char
|
|
# 그대로지만 evidence LLM 경로 변경을 분리 추적하기 위해 bump.
|
|
ASK_PROMPT_VERSION: str = "search_synthesis.v3-evidence-triage"
|
|
|
|
# ─── /analyze 프롬프트 버전 ──────────────────────────────────
|
|
# documents.py analyze 라우트가 로드하는 app/prompts/document_analyze.txt 기준
|
|
ANALYZE_PROMPT_VERSION: str = "document_analyze.v1"
|
|
|
|
# ─── PR-B B-1: summary tier 분할 task 이름 ─────────────────────
|
|
# classify_worker / deep_summary_worker 가 PR-A 정책 템플릿 + policy_version 해시
|
|
# 조합으로 analyze_events.prompt_version 을 기록한다. (예: "p3a_short_summary@abc123")
|
|
SUMMARY_TRIAGE_TASK: str = "p3a_short_summary" # Mac mini 26B MLX (config.yaml ai.models.triage)
|
|
SUMMARY_DEEP_TASK: str = "p3c_deep_summary" # 26B MLX
|
|
|
|
|
|
def resolve_primary_model() -> str | None:
|
|
"""런타임 config에서 primary 모델명을 resolve.
|
|
|
|
settings.ai 가 미구성이면 None.
|
|
telemetry 기록은 None 허용 (측정 필드는 nullable).
|
|
"""
|
|
try:
|
|
from core.config import settings
|
|
|
|
if settings.ai and settings.ai.primary:
|
|
return settings.ai.primary.model
|
|
except Exception:
|
|
pass
|
|
return None
|
|
|
|
|
|
# ─── Policy-layer prompt version helper (PR-A) ──────────────────────
|
|
# domain_policy.yaml + 정책 template 의 결합 해시로 automatic version 산출.
|
|
# analyze_events.policy_version 컬럼에 기록되어 drift 추적.
|
|
#
|
|
# 기존 ASK_PROMPT_VERSION / ANALYZE_PROMPT_VERSION 상수는 그대로 유지 — PR-B 에서
|
|
# 정책 렌더된 프롬프트로 전환 시 compute_policy_version() 결과로 대체할지 병기할지 결정.
|
|
|
|
def compute_policy_version(
|
|
task: str, *, policy_path: str | None = None
|
|
) -> str:
|
|
"""sha256(yaml_bytes + template_bytes)[:12] — deterministic hash.
|
|
|
|
task: policy template 이름 (예: 'p3a_short_summary'). app/prompts/policy/ 하위.
|
|
policy_path: override (테스트용). None 이면 loader 기본값.
|
|
|
|
import 지연 — app.policy 는 아직 worker 경로에서 쓰지 않는다 (PR-A 런타임 격리).
|
|
"""
|
|
from policy.prompt_render import policy_version as _pv
|
|
|
|
return _pv(task, policy_path=policy_path)
|