graph
This commit is contained in:
@@ -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
|
||||
@@ -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 선택 지원 [신규]
|
||||
|
||||
Reference in New Issue
Block a user