Skip to content

[Feat] P1 — Entity 추출 프롬프트 재설계 (Metric 라벨 + Few-shot + 후처리 검증) #56

Description

@TaskerJang

요약

W6 80 QA 측정 결과, Entity 추출 단계의 LLM이 긴 한국어 명사구를 고유명사로 오인하는 패턴이 발견됨. 80 QA 중 40+ 건의 부진이 이 단일 원인으로 설명됨.

numerical 23건 + filter_agg 4건 회복 — Hybrid 우선순위 P1 🔥.

동기 — 측정 결과로 진단한 root cause

Neo4j 직접 조회

MATCH (n:Company) RETURN n.name LIMIT 30

30개 중 0개가 실제 회사명. 모두 Metric (수치/지표) 인데 Company 라벨로 박힘:

 1. "공모발행액 23조 7,050억원 (2025년 10월)"        ← Metric ❌ Company
 2. "주식 발행 규모 939억원 (2025.10)"              ← Metric ❌ Company
 3. "회사채 발행 규모 23조 6,111억원 (2025년 10월)"   ← Metric ❌ Company
 ...
15. "AA등급 이상 회사채 발행 비중 73.0%"             ← Metric ❌ Company

진짜 회사 (두산밥캣, 미래에셋증권, 한화투자증권) 는 Company 라벨로 저장되어 있지 않음.

영향 QA 패턴

QA Pattern 영향 건수 증상
numerical 23 "ROE / 영업이익 / OPM" 같은 수치 entity 가 Metric 노드로 안 박힘 → graph 답변 불가
filter_agg 4 corpus-wide 집계 시 Metric 라벨이 없어 GROUP BY 불가
1hop, intersection ~13 회사명이 잘못 박혀서 entity 매칭 0건

평가셋 작성 시점에 이미 예상한 문제

graph_040 메타 질문이 정확히 이 한계를 ground truth로 박아둠:

"그래프에서 Company 라벨로 분류된 'AA등급 이상 회사채 발행 비중 73.0%'는 실제 회사명인가?"

W3 Entity Extraction 학습 시점에 이 위험을 직감 → 평가셋에 메타 질문으로 남김 → W6 측정에서 정확한 진단으로 확인됨.

변경 사항 (예정)

1. kg/prompts/extractor_v2.md (신규)

기존 extractor_v1.md 를 v2로 교체. 핵심 차이:

  • Few-shot 5개 추가 — 본인 측정에서 실패한 entity 들을 실제 예시로 박음
    • "공모발행액 23조 7,050억원" → {label: "Metric", name: "공모발행액", value: "23조 7,050억원"}
    • "AA등급 이상 회사채 발행 비중 73.0%" → {label: "Metric", value: "73.0%"}
    • "두산밥캣" → {label: "Company"}
    • "ROE 8.5%" → {label: "Metric", name: "ROE", value: "8.5%"}
    • "미래에셋증권의 2분기 영업이익" → {label: "Metric", name: "영업이익", company: "미래에셋증권", period: "2Q25"}
  • 라벨 disambiguation 규칙[수치+단위] 패턴이 포함되면 무조건 Metric, 회사명은 영문자/한글 고유명사로 제한
  • 출력 schema 강화 — Metric 의 경우 name, value, unit, period, company 필드 필수

2. kg/extractor.py (수정)

  • v2 프롬프트 path 박기
  • 후처리 검증 layer 추가:
    • validate_entity_label() — Company 라벨 박힌 entity 중 수치 패턴 포함 → Metric 으로 재분류
    • _NUMERIC_PATTERNS\d+%, \d+(조|억|만)원, \d+(개|건|명)
  • 검증 실패 시 LLM 재호출 (최대 2회)

3. Metric 노드 + HAS_METRIC 관계 (P2와 함께)

본 이슈는 프롬프트 설계만 다루고, 라벨 교정은 #57 (P2) 에서 처리. 새로 적재되는 entity는 본 PR로 정상, 기존 그래프는 P2 쿼리로 교정.

DoD

  • extractor_v2.md few-shot 5개 박힘 (numerical / filter_agg 영역 커버)
  • validate_entity_label() 박혀서 수치 패턴 → Metric 강제 박힘
  • dry-run: scripts/run_qa_eval.py --limit 10 --qa-set graphrag 박혀서 entity 라벨 분포 개선 확인
  • 재인덱싱 후 Cypher: MATCH (n:Company) RETURN n.name LIMIT 30 — 30개 모두 진짜 회사명 박혀있어야

검증 방법

# 1. extractor v2 박은 후 재인덱싱
uv run python scripts/run_ingestion.py
uv run python scripts/load_graph.py

# 2. Neo4j audit 쿼리 실행
uv run python scripts/explore_graph.py --json eval/dataset/graph_meta_v2.json

# 3. graph_meta_v2.json vs graph_meta.json 비교 — Company / Metric 라벨 분포

예상 효과

메트릭 Before (W6) After (P1 적용) 회복 영역
numerical Correctness 1.30 3.0+ 23건
filter_agg Correctness 1.60 3.0+ 4건
Faithful (전체) 5.0% 20~30%

레퍼런스

우선순위

🔥 P1 — Hybrid 로드맵 최상위 우선순위. P2 (라벨 교정) 와 함께 진행해야 효과 발현.


Refs #20 (Layer C), #51 (Routing), W6 measurement results

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions