diff --git a/app/workers/classify_worker.py b/app/workers/classify_worker.py index 723adc6..644e0c7 100644 --- a/app/workers/classify_worker.py +++ b/app/workers/classify_worker.py @@ -309,10 +309,28 @@ async def process(document_id: int, session: AsyncSession) -> None: 1) Legacy: classify() → ai_domain/document_type/ai_tags/ai_confidence/ai_suggestion 2) Legacy: summarize() → ai_summary 3) PR-B B-1: summary_triage (4B) → ai_tldr/ai_bullets/ai_analysis_tier='triage' + + 예외 — source_channel='law_monitor': + 법령은 외부 source-of-truth (law.go.kr) 보유 + immutable + 자동 재수집. + AI 분류는 무가치 + 본문 해석 환각 위험. 26B legacy + 4B triage 전부 skip. + 최소 필드만 세팅 후 return → queue_consumer 가 embed/chunk 자동 chain. + 참고: feedback_category_vs_ai_domain_axis.md, plan stateless-churning-raccoon.md. """ doc = await session.get(Document, document_id) if not doc: raise ValueError(f"문서 ID {document_id}를 찾을 수 없음") + + if doc.source_channel == "law_monitor": + if not doc.ai_domain: + doc.ai_domain = "법령" + if not doc.ai_tags: + doc.ai_tags = ["법령"] + if not doc.importance: + doc.importance = "medium" + await session.commit() + logger.info(f"doc {document_id}: law_monitor → classify skip") + return + if not doc.extracted_text: raise ValueError(f"문서 ID {document_id}: extracted_text가 비어있음") diff --git a/app/workers/tier_backfill.py b/app/workers/tier_backfill.py index 38d9686..3da1493 100644 --- a/app/workers/tier_backfill.py +++ b/app/workers/tier_backfill.py @@ -4,8 +4,11 @@ plan: ~/.claude/plans/swirling-swimming-liskov.md — 백필 장기 운영. 매 30분마다 트리거되어 (KST 00:00~06:00 시간대에만 실제 enqueue): 1. 우선순위 도메인별 NULL 문서 25건씩 classify 큐 재투입 - 2. 우선순위: safety > law > manual - (drive_sync / memo / news 는 별도 판단 — 본 스케줄러 제외) + 2. 우선순위: safety > manual + (drive_sync / memo / news / law_monitor 는 본 스케줄러 제외) + - news/memo: 분야 확정, classify 무가치 (legacy 결정) + - law_monitor: classify_worker 가 진입 시 skip 처리 (plan stateless-churning-raccoon.md). + backfill 에서 enqueue 해도 skip 만 반복되므로 시작부터 제외. 3. classify 큐가 이미 많으면 스킵 (MLX 부하 보호) 사유: @@ -43,9 +46,9 @@ BATCH_SIZE = 25 QUEUE_SKIP_THRESHOLD = 40 # 우선순위 도메인 (첫 번째가 후보 먼저 소진) +# law_monitor 제외: classify_worker 가 진입 시 skip — backfill 무한 루프 방지. DOMAIN_PRIORITY: list[tuple[str, str]] = [ - ("safety", "ai_domain LIKE 'Industrial_Safety%'"), - ("law", "source_channel = 'law_monitor'"), + ("safety", "ai_domain LIKE 'Industrial_Safety%' AND source_channel != 'law_monitor'"), ("manual", "source_channel = 'manual'"), ]