feat(ai): B-1 summary tier 분할 — triage(4B) + deep_summary(26B)
PR-A policy 레이어를 재사용하여 classify_worker 에 tier triage 경로를 추가.
Legacy ai_summary / ai_domain / ai_suggestion 은 유지 (회귀 0), tldr/bullets/
detail/inconsistencies 는 별도 필드로 분리.
Migrations (156~160):
- 156 documents: ai_tldr, ai_bullets, ai_detail_summary, ai_inconsistencies,
ai_analysis_tier 5컬럼
- 157 process_stage 에 'deep_summary' ADD VALUE 단독 (Postgres 동일 트랜잭션
제약 회피)
- 158 processing_queue.payload JSONB (envelope 전달)
- 159 analyze_events 에 tier + suppressed_reason
- 160 suppressed_reason partial index
Models/ORM:
- Document: 5컬럼 Mapped 추가
- ProcessingQueue: deep_summary enum 확장 + payload 필드, enqueue_stage 에
payload 옵션
- AnalyzeEvent: PR-A shadow 6컬럼 + PR-B tier/suppressed_reason
Workers:
- classify_worker: 기존 legacy 경로 뒤에 _run_tier_triage 추가.
- _match_subject_domain(doc, text): source_channel + 본문 keywords + ai_domain
prefix 로 PR-A policy 의 subject_domain 이름 결정 (category 매칭 금지).
- R1 TriageOutput pydantic + JSON 깨짐 fallback (triage_json_invalid).
- R2 _check_backlog_guard(): 30분 window ratio > threshold OR pending 초과면
soft escalate suppress. hard escalate 는 통과.
- R3 _slice_text_ranges(): 260k 초과 시 head 120k + mid 20k + tail 120k 3조각.
- escalate 시 EscalationEnvelope 구성 + {envelope, subject_domain} payload 로
deep_summary enqueue.
- deep_summary_worker (신규): queue payload 에서 envelope + subject_domain 읽기 →
render_26b("p3c_deep_summary", subject_domain) + MLX 호출 (llm_gate Semaphore(1)
경유) → ai_detail_summary + ai_inconsistencies 저장 + ai_analysis_tier='deep'.
_filter_inconsistencies 로 허용 kind (version_drift / procedure_conflict /
source_conflict / missing_basis) 만 통과 — 구매/계약 kind drop.
- queue_consumer: workers dict 에 deep_summary 추가 + BATCH_SIZE=1. next_stages
는 건드리지 않음 — classify → embed/chunk 는 그대로, deep_summary 는 독립 체인.
Telemetry:
- record_analyze_event: subject_domain / risk_flags / escalation_reasons /
confidence / policy_version / shadow_would_route_to / tier / escalated_to_26b /
suppressed_reason 파라미터 확장. classify/deep worker 가 mode="summary_triage"
또는 "summary_deep" 로 기록.
API:
- DocumentResponse 에 ai_tldr / ai_bullets / ai_detail_summary /
ai_inconsistencies / ai_analysis_tier 5필드 노출.
Prompts:
- classify.txt 에 DEPRECATED 주석만 추가 (파일 유지 — rollback 경로 보존).
- PR-A 의 app/prompts/policy/p3a_short_summary.txt (4B) 와 p3c_deep_summary.txt
(26B) 를 그대로 사용. 내 소유의 summary_triage.txt / summary_deep.txt 는 중복
이라 별도 커밋에서 제거하지 않고 바로 생성 전 삭제.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
-- 156_ai_analysis_cols.sql
|
||||
-- PR-B B-1: documents 에 4B triage / 26B deep 분할 컬럼 추가.
|
||||
-- plan: ~/.claude/plans/swirling-swimming-liskov.md
|
||||
--
|
||||
-- ai_tldr / ai_bullets → summary_triage 산출 (4B, 상시)
|
||||
-- ai_detail_summary / ai_inconsistencies → summary_deep 산출 (26B, escalation)
|
||||
-- ai_analysis_tier → 'triage' | 'deep' — 현재 문서가 어느 tier 까지 처리됐는지
|
||||
-- ai_summary (legacy TEXT) → ai_tldr 을 복제하여 backward compat
|
||||
--
|
||||
-- 주의: _run_migrations 는 asyncpg exec_driver_sql 로 단일 prepared statement — ALTER TABLE
|
||||
-- 의 다중 ADD COLUMN 절은 단일 statement 라 허용. enum ADD VALUE 는 별도 (157).
|
||||
|
||||
ALTER TABLE documents
|
||||
ADD COLUMN IF NOT EXISTS ai_tldr TEXT,
|
||||
ADD COLUMN IF NOT EXISTS ai_bullets JSONB,
|
||||
ADD COLUMN IF NOT EXISTS ai_detail_summary TEXT,
|
||||
ADD COLUMN IF NOT EXISTS ai_inconsistencies JSONB,
|
||||
ADD COLUMN IF NOT EXISTS ai_analysis_tier TEXT;
|
||||
@@ -0,0 +1,13 @@
|
||||
-- 157_queue_stage_deep_summary.sql
|
||||
-- PR-B B-1: processing_queue.stage enum 에 'deep_summary' 추가.
|
||||
-- plan: ~/.claude/plans/swirling-swimming-liskov.md §B-1
|
||||
--
|
||||
-- PostgreSQL 제약: ALTER TYPE ADD VALUE 는 새 값을 같은 트랜잭션 안에서 사용할 수 없다.
|
||||
-- (unsafe use of new value of enum type)
|
||||
-- 따라서 이 migration 은 enum 확장만 단독으로 처리하고, processing_queue.payload 컬럼
|
||||
-- 추가는 158 로 분리. classify_worker 가 deep_summary 를 enqueue 하는 시점엔 157 이
|
||||
-- 이미 별도 트랜잭션으로 commit 돼 있다.
|
||||
--
|
||||
-- audio/video 파이프와 동일 패턴 (147~151 참조).
|
||||
|
||||
ALTER TYPE process_stage ADD VALUE IF NOT EXISTS 'deep_summary';
|
||||
@@ -0,0 +1,13 @@
|
||||
-- 158_processing_queue_payload.sql
|
||||
-- PR-B B-1: processing_queue 에 payload JSONB 컬럼 추가.
|
||||
-- plan: ~/.claude/plans/swirling-swimming-liskov.md §B-1
|
||||
--
|
||||
-- deep_summary stage 가 EscalationEnvelope (from_stage / escalation_reasons /
|
||||
-- risk_flags / distilled_context / original_pointers / synthesis_directives / ...)
|
||||
-- 를 payload 로 싣고 전달. 다른 stage 는 NULL.
|
||||
--
|
||||
-- 157 의 enum ADD VALUE 가 별도 트랜잭션으로 commit 된 뒤에만 실행돼야 한다.
|
||||
-- (asyncpg migrations 러너가 파일 순서대로 단일-statement 실행하므로 안전.)
|
||||
|
||||
ALTER TABLE processing_queue
|
||||
ADD COLUMN IF NOT EXISTS payload JSONB;
|
||||
@@ -0,0 +1,18 @@
|
||||
-- 159_analyze_events_pr_b_tier.sql
|
||||
-- PR-B B-1: analyze_events 에 실제 호출 tier + suppressed_reason 추가.
|
||||
-- plan: ~/.claude/plans/swirling-swimming-liskov.md §B-1 R2
|
||||
--
|
||||
-- PR-A (153) 이 shadow_would_route_to 로 "정책이 제안한 tier" 는 이미 기록.
|
||||
-- 여기서는 PR-B 가 실제로 호출한 tier 와, R2 backlog guard 로 suppress 된 이유를 추가.
|
||||
--
|
||||
-- tier : 'triage' | 'primary' | 'fallback' — classify_worker / deep_summary_worker /
|
||||
-- evidence_service / synthesis_service 가 실제 호출 시 기록.
|
||||
-- suppressed_reason : 'backlog_guard(ratio=0.42,pending=7)' 등. escalation 판정이 soft 였으나
|
||||
-- backlog guard 로 suppress 된 건을 사후 디버깅 하기 위해 별도 컬럼화.
|
||||
-- dashboard "Backlog Suppression (24h)" 카드의 소스.
|
||||
--
|
||||
-- 단일 statement (ALTER TABLE 다중 ADD COLUMN 은 허용). 인덱스는 160 으로 분리.
|
||||
|
||||
ALTER TABLE analyze_events
|
||||
ADD COLUMN IF NOT EXISTS tier TEXT,
|
||||
ADD COLUMN IF NOT EXISTS suppressed_reason TEXT;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- 160_analyze_events_pr_b_idx.sql
|
||||
-- PR-B B-1: suppressed_reason partial index (backlog guard 발생 조회용).
|
||||
-- plan: ~/.claude/plans/swirling-swimming-liskov.md §B-1 R2
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_analyze_events_suppressed
|
||||
ON analyze_events (created_at)
|
||||
WHERE suppressed_reason IS NOT NULL;
|
||||
Reference in New Issue
Block a user