This commit is contained in:
lasta
2026-05-22 00:22:03 +09:00
parent 8d77bc659f
commit d841fb823a
49 changed files with 2732 additions and 3763 deletions

View File

@@ -0,0 +1,415 @@
# Phase 7. Hybrid Rule + LLM Extraction
작성일: 2026-05-21
범위: `ontology_platform`에 포함된 product backend, 특히 `crawler_platform/app/core/extractor`, crawl/research API, Review/Page Analysis UI.
주의: 이 phase는 OntoCast core engine을 바꾸지 않는다. 룰 기반 product extraction과 LLM JSON extraction을 product backend 레벨에서 결합한다. `/process` OntoCast workflow는 후처리/RDF 변환 후보로만 연결한다.
## 목표
룰 기반 추출의 장점인 빠름, 비용 없음, 예측 가능성, 명확한 패턴 인식을 살리고, LLM 추출의 장점인 의미 해석, 타입 추론, 관계 추출, 한국어/비정형 문장 대응력을 더한다.
핵심 원칙:
- 룰은 먼저 실행되는 baseline extractor이자 검증 가드레일이다.
- LLM은 의미 추출기이며, evidence/ontology/source zone 검증을 통과해야 한다.
- LLM 실패는 전체 실패가 아니라 rule fallback으로 처리한다.
- 룰과 LLM이 같은 claim을 찾으면 신뢰도를 올린다.
- 룰과 LLM이 충돌하면 자동 승인하지 않고 review로 보낸다.
## 현재 기준선
현재 확인된 동작:
- `ont_platform/api/routes/extraction.py`
- `/api/v1/extract/url`, `/api/v1/process/url`, `/process/url`
- `LightweightExtractor(use_llm=False)` 고정
- 룰 기반 기초 후보만 생성
- `ont_platform/core/crawler/jobs.py`
- `/api/v1/crawl/jobs`
- `LightweightExtractor(use_llm=False)` 고정
- 기본 수집 + 기초 후보 저장
- `crawler_platform/app/core/extractor/factory.py`
- `provider in {"openai", "ollama", "lm_studio"}`이면 `LLMJsonExtractor`
- 그 외에는 domain별 rule extractor
- `crawler_platform/app/core/extractor/ai_provider.py`
- LLM primary, compact retry, JSON repair, rule fallback이 이미 일부 존재
- LLM 결과에 rule claim을 merge하는 `_merge_rule_fallback_claims()`가 이미 존재
- `crawler_platform/app/core/extractor/validation.py`
- evidence zone, ontology predicate, source zone, confidence breakdown 검증이 존재
- `web/frontend/src/pages/CrawlPage.tsx`, `ResearchPage.tsx`
- request type에는 `extractor_provider` 필드가 있으나 화면에서 선택 UI는 없음
## Phase 7.1 Baseline Audit
목표: 기존 동작을 깨지 않기 위해 현재 추출 결과와 저장 구조를 고정한다.
작업:
- `rule_based`, `lm_studio`, `openai`, `ollama` provider별 request/response 샘플을 만든다.
- crawl, crawl-site, research/run 경로에서 extractor가 어떻게 선택되는지 문서화한다.
- `Claim`, `Entity`, `ExtractionLog`에 저장되는 `extractor_name`, `provider`, `metadata_json`, `confidence_breakdown` 구조를 샘플로 기록한다.
- LM Studio가 꺼진 상태, 켜진 상태, 모델명 누락 상태를 각각 재현한다.
주요 파일:
- `crawler_platform/app/core/extractor/factory.py`
- `crawler_platform/app/core/extractor/ai_provider.py`
- `crawler_platform/app/core/extractor/rule_based.py`
- `crawler_platform/app/core/database/repository.py`
- `crawler_platform/app/api/routes.py`
완료 기준:
- 기존 `rule_based``lm_studio` 동작이 재현 가능하다.
- 최소 1개 상품 페이지 fixture로 rule 결과와 LLM 결과 샘플이 있다.
- LM Studio 장애 시 현재 fallback 결과가 확인되어 있다.
## Phase 7.2 Extraction Mode Contract
목표: provider와 실행 전략을 분리한다.
현재 문제:
- `extractor_provider`가 provider이면서 실행 전략 역할도 한다.
- 사용자는 rule only, LLM only, hybrid, compare를 명시적으로 선택할 수 없다.
제안 계약:
```json
{
"extraction_mode": "hybrid",
"extractor_provider": "lm_studio",
"extractor_model": "deepseek-r1-distill-qwen-7b",
"extractor_base_url": "http://localhost:1234/v1",
"fallback_to_rules": true
}
```
지원 mode:
- `rule_only`: rule extractor만 실행
- `llm_only`: LLM extractor만 실행, fallback 선택 가능
- `hybrid`: rule 먼저 실행, LLM 실행, 병합/검증
- `compare`: rule 결과와 LLM 결과를 모두 보존하고 차이를 metadata/log에 저장
호환성:
- 기존 `extractor_provider: "rule_based"``extraction_mode="rule_only"`로 해석한다.
- 기존 `extractor_provider: "lm_studio" | "openai" | "ollama"`는 당분간 `extraction_mode="hybrid"`로 해석한다.
- 기존 UI가 provider를 보내지 않는 경우 기본값은 `hybrid + lm_studio`로 유지한다.
수정 파일:
- `crawler_platform/app/api/routes.py`
- `web/frontend/src/lib/api/crawl.ts`
- `web/frontend/src/lib/api/research.ts`
완료 기준:
- 기존 요청이 깨지지 않는다.
- 새 요청 필드로 `rule_only`, `llm_only`, `hybrid`, `compare`가 구분된다.
- API response/log에 실제 실행 mode가 남는다.
## Phase 7.3 Hybrid Extractor
목표: 명시적인 `HybridExtractor`를 추가한다.
신규 파일:
- `crawler_platform/app/core/extractor/hybrid.py`
실행 순서:
1. domain에 맞는 rule extractor 실행
2. LLM extractor 실행
3. entity dedupe
4. claim dedupe
5. rule-LLM agreement 계산
6. conflict 계산
7. metadata에 extraction mode와 comparison 결과 기록
8. validation pipeline으로 전달
필수 metadata:
```json
{
"extraction_mode": "hybrid",
"rule_entity_count": 12,
"rule_claim_count": 8,
"llm_entity_count": 15,
"llm_claim_count": 13,
"agreement_claim_count": 6,
"rule_only_claim_count": 2,
"llm_only_claim_count": 7,
"conflict_claim_count": 1
}
```
병합 규칙:
- 동일 subject/predicate/object claim은 하나로 합친다.
- rule과 LLM이 모두 찾은 claim은 `agreement="rule_and_llm"`로 표시한다.
- rule만 찾은 claim은 `agreement="rule_only"``claim_kind="rule_candidate"`로 표시한다.
- LLM만 찾은 claim은 evidence 검증 전까지 `agreement="llm_only"`로 표시한다.
- 같은 subject/predicate인데 object가 다르면 `conflict_status="rule_llm_conflict"`로 표시하고 review로 보낸다.
수정 파일:
- `crawler_platform/app/core/extractor/factory.py`
- `crawler_platform/app/core/extractor/ai_provider.py`
- `crawler_platform/app/core/extractor/base.py`
완료 기준:
- `extractor_provider="hybrid"` 또는 `extraction_mode="hybrid"`로 실행 가능하다.
- LLM 실패 시 rule 결과만으로 성공 response가 나온다.
- rule/LLM agreement가 claim metadata에 남는다.
## Phase 7.4 Confidence And Validation Upgrade
목표: LLM hallucination을 줄이고, rule agreement를 신뢰도에 반영한다.
현재 confidence 구성:
- `llm_confidence`
- `schema_confidence`
- `evidence_confidence`
- `ontology_confidence`
- `source_zone_confidence`
- `source_trust`
- `final_confidence`
추가 항목:
```json
{
"rule_confidence": 0.75,
"rule_agreement_confidence": 0.95,
"llm_confidence": 0.82,
"evidence_confidence": 0.95,
"ontology_confidence": 0.95,
"source_zone_confidence": 0.9,
"final_confidence": 0.89
}
```
정책:
- rule+LLM agreement가 있으면 confidence bonus를 준다.
- LLM-only claim은 evidence가 없으면 자동 승인하지 않는다.
- source zone을 찾지 못한 claim은 review로 보낸다.
- ontology에 없는 predicate는 reject한다.
- rule-only claim은 기본적으로 `rule_candidate`로 남긴다.
- 충돌 claim은 `review_required=true`로 남긴다.
수정 파일:
- `crawler_platform/app/core/ontology/relation_schema.py`
- `crawler_platform/app/core/extractor/validation.py`
- `crawler_platform/app/core/database/repository.py`
완료 기준:
- Review 화면에서 `confidence_breakdown.rule_agreement_confidence`를 볼 수 있다.
- evidence 없는 LLM-only claim이 `validated_claim`으로 자동 저장되지 않는다.
- rule+LLM 일치 claim은 더 높은 final confidence를 받는다.
## Phase 7.5 Compare Mode
목표: rule 결과와 LLM 결과를 나란히 비교하여 품질 튜닝에 사용한다.
작업:
- `compare` mode에서 rule bundle과 LLM bundle을 모두 실행한다.
- 최종 저장은 병합 결과로 하되, `ExtractionLog.raw_output`에 원본 두 결과를 보존한다.
- Page Analysis에서 diff summary를 표시한다.
diff category:
- `both_agree`
- `rule_only`
- `llm_only`
- `conflict`
- `rejected_by_validation`
UI 표시:
- Page Analysis: page별 extractor run 요약, rule/LLM candidate count, conflict count
- Review: claim detail에서 agreement badge 표시
수정 파일:
- `crawler_platform/app/core/database/models.py`
- `crawler_platform/app/core/database/repository.py`
- `crawler_platform/app/api/routes.py`
- `web/frontend/src/pages/PageAnalysisPage.tsx`
- `web/frontend/src/pages/ReviewPage.tsx`
- `web/frontend/src/lib/api/platform.ts`
완료 기준:
- 같은 페이지에서 rule과 LLM의 차이를 확인할 수 있다.
- `llm_only``conflict` claim을 review에서 필터링할 수 있다.
## Phase 7.6 UI Controls
목표: 사용자가 화면에서 mode/provider/model/base URL을 선택할 수 있게 한다.
대상 화면:
- Crawl Page
- Research Page
추가 컨트롤:
- Extraction mode select
- Rule only
- Hybrid
- LLM only
- Compare
- LLM provider select
- LM Studio
- OpenAI
- Ollama
- Model input
- Base URL input
- Fallback to rules toggle
- Optional model list refresh button
동작:
- mode가 `rule_only`이면 provider/model/base URL 입력을 숨긴다.
- provider가 `lm_studio`이면 기본 base URL은 `http://localhost:1234/v1`이다.
- provider가 `ollama`이면 기본 base URL은 `http://localhost:11434/api/chat`이다.
- 모델 목록은 `/extractors/models`를 사용한다.
수정 파일:
- `web/frontend/src/pages/CrawlPage.tsx`
- `web/frontend/src/pages/ResearchPage.tsx`
- `web/frontend/src/lib/api/crawl.ts`
- `web/frontend/src/lib/api/research.ts`
완료 기준:
- UI에서 mode/provider/model/base URL을 지정할 수 있다.
- 지정한 값이 `/crawl-site/by-project`, `/research/run/by-project` 요청에 포함된다.
- rule only 선택 시 LM Studio가 꺼져 있어도 작업이 시작된다.
## Phase 7.7 Smart Routing Policy
목표: 모든 페이지에 LLM을 쓰지 않고 가치 있는 페이지에 집중한다.
정책:
- `ProductPage`: hybrid 기본
- `BrandStoryPage`: hybrid 기본
- `ReviewPage`: hybrid 또는 llm_only
- `CategoryPage`: rule_only 또는 skip LLM
- `SearchPage`: skip LLM
- `BoardPage`: rule_only 또는 review 후보
- 본문 길이가 너무 짧으면 rule_only
- rule 결과가 충분하고 deterministic field만 필요한 경우 LLM 생략 가능
- research goal이 있으면 LLM 우선
추가 설정:
```json
{
"llm_page_types": ["ProductPage", "BrandStoryPage", "ReviewPage"],
"skip_llm_page_types": ["CategoryPage", "SearchPage"],
"min_clean_text_chars_for_llm": 300,
"max_llm_pages_per_job": 30
}
```
수정 파일:
- `crawler_platform/app/core/crawler/site_crawler.py`
- `crawler_platform/app/core/crawler/pipeline.py`
- `crawler_platform/app/core/research/graph_research_loop.py`
완료 기준:
- LLM 호출 수가 page type 정책에 따라 제한된다.
- 중요 페이지는 hybrid 추출을 받는다.
- crawl job metadata에 LLM skipped reason이 남는다.
## Phase 7.8 OntoCast `/process` Handoff
목표: product crawl/research 결과를 OntoCast RDF 변환과 연결한다.
역할 분리:
- product crawl/research: web acquisition, entity/claim 후보 수집
- validation/review: claim 품질 관리
- `/process`: 검증된 문서나 claim 묶음을 RDF/Turtle로 정리하는 후처리
작업:
- validated claim 묶음을 OntoCast input JSON으로 변환한다.
- 프로젝트 단위 또는 selected document 단위로 `/process`를 호출할 수 있게 한다.
- `/process` 결과 Turtle을 export/graph view와 연결한다.
완료 기준:
- 사용자가 검증된 claim subset을 RDF/Turtle로 내보낼 수 있다.
- `/process`는 모든 crawl page마다 자동 실행되지 않는다.
- 비용 큰 LLM workflow는 명시적 후처리로만 실행된다.
## Phase 7.9 Tests And Observability
목표: rule/LLM/hybrid/compare 동작을 재현 가능하게 만든다.
테스트:
- rule only는 LM Studio 없이 통과
- llm only는 mock LLM으로 deterministic response 검증
- hybrid는 rule+LLM agreement metadata 생성
- LLM 실패 시 fallback으로 성공
- evidence 없는 LLM-only claim은 자동 승인되지 않음
- conflict claim은 review_required가 true
- UI payload에 mode/provider/model/base URL 포함
관측성:
- ExtractionLog에 mode/provider/model/base URL 저장
- job metadata에 LLM call count, fallback count, skipped count 저장
- Review/Page Analysis에서 agreement/fallback/conflict를 표시
완료 기준:
- local LM Studio가 꺼져 있어도 rule/hybrid fallback 테스트가 통과한다.
- mock LLM 기반 테스트가 CI에서 안정적으로 돈다.
- crawl/research 결과에서 어떤 extractor가 어떤 이유로 사용됐는지 추적 가능하다.
## 최종 Acceptance Gate
- [ ] UI에서 Rule only, Hybrid, LLM only, Compare 선택 가능
- [ ] Hybrid mode가 rule baseline과 LLM semantic extraction을 병합
- [ ] LLM 장애 시 rule fallback으로 job이 실패하지 않음
- [ ] evidence 없는 LLM-only claim이 자동 validated로 들어가지 않음
- [ ] rule+LLM agreement가 confidence에 반영됨
- [ ] conflict claim이 review_required로 표시됨
- [ ] Page Analysis에서 rule/LLM 비교 결과 확인 가능
- [ ] Review에서 extraction method, agreement, confidence breakdown 확인 가능
- [ ] `/process`는 후처리 RDF 변환 경로로 분리 유지
## 권장 구현 순서
1. Phase 7.1 Baseline Audit
2. Phase 7.2 Extraction Mode Contract
3. Phase 7.3 Hybrid Extractor
4. Phase 7.4 Confidence And Validation Upgrade
5. Phase 7.6 UI Controls
6. Phase 7.5 Compare Mode
7. Phase 7.7 Smart Routing Policy
8. Phase 7.8 OntoCast `/process` Handoff
9. Phase 7.9 Tests And Observability

View File

@@ -87,3 +87,14 @@ FILE: ./26_05_19_engine_respect_plan/phase_06_001_maintenance_loop_operations.md
2) Analyst/Researcher/Curator/Auditor/Fixer/Advisor 梨낆엫 ?뺤쓽 [?꾨즺]
3) `auth`, `audit`, `billing`, `realtime` 珥덉븞 紐⑤뱢???댁쁺 寃쎄퀎 ?뺣━ [?꾨즺]
4) destructive fix???щ엺 ?뱀씤 寃뚯씠?몃? 諛섎뱶???듦낵?섎룄濡??ㅺ퀎 [?꾨즺]
---
PHASE 7. Hybrid Rule + LLM Extraction
FILE: ./26_05_19_engine_respect_plan/phase_07_001_hybrid_rule_llm_extraction.md
1) rule baseline, LLM extraction, fallback, validation, Review UI 흐름을 기준선으로 고정 [신규]
2) `rule_only`, `llm_only`, `hybrid`, `compare` extraction mode 계약 정의 [신규]
3) product backend에 명시적 HybridExtractor와 rule/LLM agreement metadata 추가 [신규]
4) confidence breakdown에 rule agreement와 conflict/review 정책 반영 [신규]
5) Crawl/Research UI에서 mode/provider/model/base URL 선택 지원 [신규]