6a85087b83
전 로컬 LLM 관통 '이드' persona substrate 의 Document Server 측 빌드(W2~W4). 설계 = PKM eid-persona-substrate(r1~r3 수렴) / impl = eid-persona-impl. W2 — compose + 표면 배선: - app/eid/compose.py: persona→rules→overlay→task 단일 system 문자열 + 정적 ROUTE_MAP (런타임 sniffing 아님) + rules 부재 fail-loud · persona 부재 quiet · overflow fail-loud. - 자유-prose 3 표면(react_ask·study_subject_note·study_question_explanation) 중복 정체성· generic 정책 trim + compose 배선(AIClient 에 additive system 파라미터). 도메인 calibration 보존. - STRICT JSON 기계류(briefing_comparative·digest_topic)는 persona-ZERO 동결(불변식 #3). - app/prompts/substrate/: persona(외부 컴파일 산출물 vendor) + rules(생성 가드 서브셋) + overlay 5. W3 — migration + 워커 + study_diagnosis: - migration 301~305: eid_* append-only 원장(약점/복습초안/회고) + approval_requests(가변 큐) + 일정 파생뷰 2. - app/workers/study_weakness.py: study_question_progress.pattern_state 집계로 약점 derived 산출 (LLM 0) + bounded tier(watch/review/focus). nightly cron. - study_diagnosis 표면: 최신 스냅샷을 코치 언어로 번역(약점 판정은 코드, LLM 은 블록 값만 인용). W4-1 — egress 코드층 박탈: - app/eid/ai.py EidAIClient: 이드 표면 = call_primary(내부 MLX) only. 외부 LLM fallback 경로 구조적 봉쇄(call_fallback raise · 자동 fallback 제거 · 외부 endpoint 차단). egress 워커는 분리 유지. load-bearing 정정 3(환경 grounding 강제, 설계 회귀 아님): - rules = 운영 ruleset 전체 → 생성 가드 서브셋(HTML 산출물 룰이 study task 와 충돌). - append-only = REVOKE → CREATE RULE DO INSTEAD NOTHING(단일 owner role 은 REVOKE 무효 + migration 검증기가 plpgsql BEGIN 거부) + actor/source_* NOT NULL 스탬프. - 이드 LLM 봉쇄 = path discipline → EidAIClient 구조화. 검증: eid 순수 단위테스트 30 통과 + py_compile + migration 검증기 모사 + egress 적대감사 COMPLETE. DB/LLM/httpx 의존 테스트(append-only RULE·EidAIClient·E2E)는 staging(Docker) 가동. W4-2 네트워크 belt 은 조건부 보류(코드층 1차 충분, P0-3② 원격 실측 후 hard-gate 시 승격). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.8 KiB
Python
85 lines
4.8 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
|
|
|
|
# ─── 이드 substrate wired 표면 prompt 버전 (W2-2) ─────────────────────
|
|
# persona+rules substrate(system 메시지) 주입 + 중복 정체성·generic 정책 라인 trim → 본문 변경.
|
|
# ★ 미배선 (declared, NOT yet consumed): 위 sibling(ASK/ANALYZE)과 달리 이 3 표면은 현재
|
|
# prompt_version 을 기록하는 telemetry 경로가 없다 — /ask/react 는 이벤트 미기록,
|
|
# study_subject_note·study_question_explanation 도 telemetry 미기록(grep prompt_version = 0).
|
|
# 따라서 지금은 *버전 레지스트리 문서*일 뿐이고 bump 는 end-to-end 비가시. 실제 record(=모듈
|
|
# docstring 의 '여기 상수만 참조' 컨벤션 충족)는 W3 telemetry 배선 때. 그 전엔 본문 변경 사실의
|
|
# 문서화 용도로만 둔다(소비처 없음을 명시).
|
|
# 전후 동등성: 정체성/generic정책만 빠지고 검색·계산·출력 동작 보존(staging 1회 스냅샷 검증 항목).
|
|
EID_REACT_ASK_VERSION: str = "react_ask.v2-eid-substrate" # 미배선(W3 telemetry)
|
|
EID_SUBJECT_NOTE_VERSION: str = "study_subject_note.v2-eid-substrate" # 미배선(W3 telemetry)
|
|
EID_QUESTION_EXPLANATION_VERSION: str = "study_question_explanation.v2-eid-substrate" # 미배선(W3 telemetry)
|
|
|
|
|
|
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)
|