Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
678abfa
feat(extractor): #17 옵션 3 - chunk_id global prefix 자동 부여
TaskerJang May 16, 2026
5d19319
feat(builder): #17 Layer A 적재 + MENTIONS 매핑 함수 추가
TaskerJang May 16, 2026
75c5a8c
feat(scripts): #17 8문서 일괄 적재 스크립트
TaskerJang May 16, 2026
0e2dc79
test(builder): #17 Layer A 적재 + MENTIONS 매핑 단위 테스트 11개
TaskerJang May 16, 2026
985db67
docs(weekly-log): #17 5/16 batch ingest draft
TaskerJang May 16, 2026
21f5eeb
docs(weekly-log): 5/16 sanity hang 박제 + 5/17 디버깅 순서
TaskerJang May 16, 2026
7d86733
docs(weekly-log): SemanticChunker hang 확정 + 5/17 옵션 A/B/C 박제
TaskerJang May 16, 2026
36dd22e
docs(weekly-log): SemanticChunker 본질적 비효율 100% 확정 + 옵션 B fix 한 줄
TaskerJang May 16, 2026
8f0bcb1
feat(chunker): USE_SIMPLE_CHUNKER 환경변수 fallback 추가 (#17)
TaskerJang May 16, 2026
144e25f
docs(weekly-log): 선택지 3 확정 + chunker fix commit 반영
TaskerJang May 16, 2026
bb274d5
docs(weekly-log): 1문서 sanity + Aura 통계 4종 박제 완료
TaskerJang May 16, 2026
7b2d250
docs(weekly-log): 5/16 8문서 풀 적재 완료 결과 박제 (7/8 성공, 71분)
TaskerJang May 16, 2026
f574200
docs(weekly-log): 🎉 8/8 100% 적재 완료! DOC→DOCX 변환 후 2차 성공
TaskerJang May 16, 2026
ae99087
docs(weekly-log): 🎉 Aura Cypher 5종 측정 완료 + NED 한국어 변형 challenge 발견
TaskerJang May 16, 2026
e0d32e6
docs(weekly-log): 🔥 진단 3종 완료 — Entity 라벨 품질 challenge 확정 (발표 진짜 보석!)
TaskerJang May 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
375 changes: 375 additions & 0 deletions docs/weekly-log/2026-05-16-batch-ingest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
# 2026-05-16 — W3 batch ingest (#17)

> Status: **🎉🎉🎉🎉 8/8 100% 적재 + Aura 통계 5종 + NED 3차 진단 확정 → 발표 핵심 발견 박제 완료.**
> 발표 메시지 확정: **선택지 3 — 디버깅 자체를 trade-off 인사이트로**
> ⭐⭐⭐ **진짜 보석 발견**: Entity 추출 라벨 품질 문제 (Company 라벨이 실은 금융 metric)

## 🔥🔥🔥 5/16 진단 3종 — 발표 핵심 발견 (17:39~17:43 측정)

### 진단 1: 미래에셋 4Q 문서의 Entity top 20

```cypher
MATCH (d:Document {filename: "미래에셋증권_4분기_실적보고서.pdf"})
-[:HAS_SECTION]->(:Section)-[:CONTAINS_CHUNK]->(c:Chunk)
-[:MENTIONS]->(e:Entity)
RETURN labels(e)[1] AS type, e.name, count(c) AS chunk_count
ORDER BY chunk_count DESC LIMIT 20;
```

결과 (top 17):

| Type | e.name | chunk_count |
|---------|-----------------------------------------|-------------|
| Company | "공모발행액 23조 7,050억원 (2025년 10월)" | **19** |
| Company | "유상증자 41,186" | 4 |
| Company | "유상증자 77,258" | 4 |
| Company | "금융지주채 발행규모 및 비중..." | 3 |
| Company | "AA등급 이상 회사채 발행 비중 73.0%" | 3 |
| Metric | "유상증자 47,034 (기준: 증권신고서..)" | 3 |
| Company | "시설 목적 회사채 발행 비중 10.7%" | 3 |
| Company | "기업공개 전년동기대비 증감액..." | 2 |
| ... (대부분 Company 인데 금융 수치) | ... |

**🚨 충격적 발견**:
- 미래에셋 4Q 보고서 68청크에서 **회사명이 단 하나도 Company entity 로 추출 안 됨**
- "Company" 로 분류된 entity 들이 실제로는 **금융 metric / 발행 규모 / 비중** 등 수치
- "공모발행액 23조 7,050억원" 이 Company 라벨 + 19 청크 언급 (가장 많이!)
- LLM (Kimi) 이 **entity 추출 시 라벨을 잘못 부여**하고 있음

### 진단 2: 영문/대명사 패턴 검색

```cypher
MATCH (e:Entity:Company)
WHERE e.name CONTAINS "Mirae" OR e.name CONTAINS "당사"
OR e.name CONTAINS "회사" OR e.name CONTAINS "그룹"
RETURN e.name, e.aliases, e.member_count ORDER BY e.member_count DESC LIMIT 20;
```

결과: **회사명 0건**. 모두 "회사채 23조..." 같은 수치 데이터.

→ "당사", "본 회사", "그룹" 같은 대명사로 entity 추출 안 됨 (Kimi 가 무시하거나 다른 카테고리)
→ 영문 "Mirae" 표기로도 추출 안 됨

### 진단 3: 전체 Company entity top 20 (member_count 순)

```cypher
MATCH (e:Entity:Company)
RETURN e.name, e.member_count, e.aliases
ORDER BY e.member_count DESC LIMIT 20;
```

결과 (top 14):

| Rank | e.name (Company 라벨) | member_count |
|------|---------------------------------------------------|--------------|
| 1 | "총계 금액 전년동기대비 증감액..." (NED 4 표기) | **6** |
| 2 | "금융사" | 3 |
| 3 | "일반기업" | 3 |
| 4 | "회사채 발행 규모 23조 6,111억원..." | 2 |
| 5 | "단기채무 12,060만 원 (2024년 1∼10월)" | 2 |
| 6 | "회사채 23조 6,111억원 (전월 대비 16.6%↓...)" | 2 |
| 7 | "한국예탁결제원" | 2 |
| 8 | "금액 전월대비 증감액(증감률) △135 (△41.8%)..." | 2 |
| ... | 모두 금융 metric 또는 일반 카테고리 | ... |

**🚨 더 충격적 발견**:
- **186개 Company entity 중 진짜 회사명은 거의 없음**
- 1~3위가 "총계 금액", "금융사", "일반기업" — 모두 **범주명 또는 metric**
- "한국예탁결제원" 이 7위 — **유일하게 진짜 기관명**
- 회사명이 entity 로 거의 추출 안 됨 → 미래에셋증권 빈 결과의 진짜 원인

### 🎯 진단 종합 — 진짜 발견

> **"GraphRAG 파이프라인의 정직한 한계 발견:
>
> 미래에셋증권 자기 회사 보고서 4개 (1Q~4Q, 150 청크) 적재했지만 'Company' entity 로 단 하나도 잡히지 않음.
>
> 진짜 원인 — Kimi 가 entity 추출 시 'Company' 라벨을 잘못 부여:
> - 금융 metric ('공모발행액 23조 7,050억원') → Company ❌
> - 범주명 ('금융사', '일반기업') → Company ❌
> - 회사명 → 거의 못 잡음 ❌
>
> 즉 GraphRAG 의 가치 (그래프 구조, MENTIONS 1,553) 는 검증됐으나,
> **Entity 추출 품질** 이 별도의 production challenge.
> LLM 프롬프트 엔지니어링 + 후처리 검증이 필수."**

## 🎤 발표 슬라이드 메시지 — 진짜 보석 ⭐⭐⭐

### Before (5/16 17:37 측정 직후 추정)
> "NED 의 한국어 회사명 표기 변형 challenge"

### After (5/16 17:43 진단 3종 확정)
> **"Entity 추출 라벨 품질 challenge — Kimi LLM 이 'Company' 라벨에 회사명이 아닌 금융 metric 을 부여하는 패턴 발견. 186개 Company entity 중 진짜 기관명은 1개. 자기 회사 보고서에 자기 회사명이 entity 로 안 잡히는 정직한 한계."**

### VectorRAG ↔ GraphRAG 보완 관계 증명

| 질의 유형 | VectorRAG | GraphRAG |
|--------------------------------------|-----------|----------|
| "당사 영업이익은?" (대명사 해소) | ◎ 청크 유사도로 답변 | ❌ entity 없음 |
| "회사 X 와 Y 의 공통 리스크는?" | △ LLM 후처리 필요 | ◎ FACES_RISK 그래프 |
| "금융 지표 평균 추이는?" | △ 청크 모음 | ◎ HAS_METRIC 그래프 |
| "이 답변의 출처는?" | △ 청크 ID | ◎ Layer A 추적 |

→ **둘 다 필요한 게 정량 증거로 증명됨**. 발표의 진짜 결론.

## 🏆🏆🏆🏆 5/16 8/8 100% 적재 완료 (16:05 ~ 17:33, 약 76분)

### 1차 적재: 8문서 (16:05~17:19, 71분) — 7/8 성공

| 파일 | 포맷 | 타입 | sec | chunks(T/B) | ent(raw→grp) | rel | mentions | parse | extract | link | neo4j | total | ok |
|---|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---|
| DS투자증권_시황분석_리포트.pdf | pdf | report | 6 | 52/0 | 103→60 | 32 | 102 | 8.4 | 143.5 | 28.5 | 39.0 | 219.4 | ✅ |
| 금융감독원_..._직접금융_조달실적.doc | doc | (unknown) | 0 | 0/0 | 0→0 | 0 | 0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ❌ |
| 농협_2022년_9월말_기준_사업보고서.hwp | **hwp** | filing | 1 | 11/0 | 56→56 | 0 | 56 | 2.5 | 26.4 | 12.4 | 15.3 | 56.6 | ✅ |
| 미래에셋증권_1분기_실적보고서.pdf | pdf | ir | 1 | 28/0 | 131→120 | 17 | 131 | 0.2 | 47.0 | 36.1 | 36.9 | 120.3 | ✅ |
| 미래에셋증권_2분기_실적보고서.pdf | pdf | ir | 1 | 27/0 | 121→116 | 52 | 120 | 0.2 | 53.8 | 29.6 | 38.4 | 121.9 | ✅ |
| 미래에셋증권_3분기_실적보고서.pdf | pdf | ir | 1 | 27/0 | 149→145 | 42 | 149 | **1514.8** | 47.2 | 25.9 | 43.8 | 1631.7 | ✅ |
| 미래에셋증권_4분기_실적보고서.pdf | pdf | ir | 30 | **68/6** | **335→261** | 55 | 329 | **1694.7** | 109.7 | 109.4 | 102.3 | 2016.0 | ✅ |
| 한화투자증권_두산밥캣_기업분석_리포트.pdf | pdf | report | 12 | 15/5 | 42→33 | 31 | 42 | 12.9 | 40.7 | 9.2 | 20.3 | 83.1 | ✅ |

### 2차 적재: DOC → DOCX 변환 후 (17:28~17:33, 5분) — 1/1 성공

| 파일 | 포맷 | 타입 | sec | chunks(T/B) | ent(raw→grp) | rel | mentions | parse | extract | link | neo4j | total | ok |
|---|---|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---|
| 금융감독원_..._직접금융_조달실적.docx | **docx** | **disclosure** | 1 | **49/0** | **275→251** | 26 | **260** | 1.7 | 106.0 | 116.6 | 73.3 | 297.7 | ✅ |

### 🎉 진짜 최종 8/8 100% 총합

| 지표 | 1차 (7문서) | 2차 (1문서) | **총합** |
|---|---|---|---|
| 성공률 | 7/8 (87.5%) | 1/1 (100%) | **8/8 (100%)** 🎉 |
| 소요 시간 | 71분 | 5분 | **76분** |
| 청크 (text) | 228 | 49 | **277** |
| Raw entity | 937 | 275 | **1,212** |
| Grouped entity | 791 | 251 | **1,042** |
| NED compression | 0.84 | 0.91 | **0.86** |
| Relation | 229 | 26 | **255** |
| MENTIONS | 929 | 260 | **1,189** |

## 🎯 5/16 8문서 Aura Cypher 통계 (17:37 측정)

### Q1: 노드 라벨별 (총 610 노드)
```
Chunk 277 / Entity 261 / Section 53 / Table 11 / Document 8
```

### Q2: 관계 타입별 (총 2,451 관계)
```
MENTIONS 1553 / CONTAINS_CHUNK 277 / HAS_METRIC 270 / NEXT 235
HAS_SECTION 53 / FACES_RISK 34 / HAS_OUTLOOK 12 / CONTAINS_TABLE 11
RECOMMENDED_FOR 6 (새 관계 타입)
```

### Q3: Entity 타입별 분포
```
Company 186 (1,220 mentions, but 대부분 metric! → 진단 3 참고)
Metric 69 (297 mentions)
Risk 24 (29 mentions)
Outlook 7 (7 mentions)
```

⚠️ **Company 186개 중 진짜 회사명은 1개 ("한국예탁결제원")** — 진단 3에서 확정.

### Q4: 미래에셋증권 NED — 빈 결과
```
MATCH (e:Entity:Company {name: "미래에셋증권"}) ... → No records
```
→ 진단 3종으로 원인 확정: **Kimi 라벨 부여 문제**.

### Q5: doc_type 분포
```
pdf+ir 4 (미래에셋 1Q~4Q) / pdf+report 2 (DS투자증권 + 한화) / hwp+filing 1 (농협) / docx+disclosure 1 (금감원)
```
**3 포맷 × 4 doc_type** 다양성.

## 🌟 발표 자료 보석 종합 (5/23 슬라이드 시드)

### A. DOC → DOCX 변환 + 재적재 성공 ⭐⭐⭐
LibreOffice headless 변환 → 49 청크 + 251 entity + 260 MENTIONS. 엔지니어링 사이클 완성.

### B. HWP 파서 정상 동작 ⭐
농협 사업보고서 11 청크 적재.

### C. 미래에셋 4분기 풍부 ⭐
68 청크 + 6 표 (Table 첫 적재) + 335→261 entity + 329 MENTIONS.

### D. ⭐⭐⭐ Entity 추출 라벨 품질 challenge (진단 3종 확정!)
- 186개 Company 중 진짜 회사명 1개
- "공모발행액 23조 7,050억원" 같은 metric 이 Company 라벨
- LLM (Kimi) 의 라벨 부여 한계 → 프롬프트 엔지니어링 + 후처리 필요

### E. VectorRAG ↔ GraphRAG 보완 관계 정량 증명
- 자기 회사 보고서에서 회사명 entity 없음 → VectorRAG 의 대명사 해소 강점
- 그래프 traversal 은 GraphRAG 의 강점 (HAS_METRIC 270, FACES_RISK 34)
- **둘 다 필요한 게 정량 증거로 증명됨**

### F. LLM 비결정성
- DS투자증권 2회 추출: 113→55 vs 103→60

### G. doc_type 자동 분류 4가지
report / ir / filing / disclosure

### H. SemanticChunker 본질적 비효율
820자 / 31.3초 → USE_SIMPLE_CHUNKER fallback

## ✅ 5/16 토요일 검증 완료 사항

- ✅ **단위 테스트 11/11 PASS**
- ✅ **PR #45 생성** — 6 commits
- ✅ **8/8 적재 완료** — 76분, 100%
- ✅ **Aura Cypher 5종 측정** — 17:37
- ✅ **진단 3종 완료** — 17:39~17:43, Entity 라벨 품질 확정
- ✅ **새 Aura `9b57188f`** + .env 갱신
- ✅ **LibreOffice 미설치 → 수동 변환 검증**

## 🎯 5/17(일) 시작 가이드 — 진짜 마무리

### Step 1 — PR #45 머지 + 이슈 #17 close (1분)

https://github.com/TaskerJang/doc-graph-agent/pull/45 → **Merge pull request** 버튼.

머지 후:
```cmd
cd C:\Users\taske\doc-graph-agent
git checkout dev
git pull origin dev
git branch -d feat/17-batch-ingest
```

### Step 2 — #18 W4 Text2Cypher 시작

```cmd
git checkout -b feat/18-text2cypher
```

이슈 #18 요구사항:
- `retrieval/text2cypher.py` — LLM 기반 자연어 → Cypher 변환
- 스키마 프롬프트 — 노드/관계 정의 LLM 주입
- 안전장치 — read-only 강제 + LIMIT 100
- 결과 파싱 → 자연어 답변 (LLM 2단계)
- 평가 셋 5개 질문 정성 검증

**5/17 평가 셋 질문 후보** (8문서 그래프 위에서):
1. "DS투자증권 시황분석 리포트에서 언급된 entity 들은? (회사+metric 혼재 검증)"
2. "미래에셋증권 4분기 보고서의 Table 은 몇 개인가?"
3. "보도자료(disclosure) 유형 문서의 entity 들은?"
4. "두산밥캣과 함께 언급된 리스크가 있는가?"
5. "전체 그래프에서 가장 많이 언급된 Company 라벨 entity 5개는? (실제 회사 vs metric 비율 확인)"

5번이 진짜 흥미로움 — Text2Cypher 가 "Company" 라벨 결과를 사용자에게 보여줄 때, 실은 metric 이 섞인 결과라는 challenge.

---

## 작업 범위

PR #44 (#24 Opik 1단계) 머지 직후 진행. 두산밥캣 1청크 파이프라인 → 8문서 전체 확장.

### 변경 사항

**Layer A 적재 추가** (`kg/builder.py`):
- `build_layer_a()` — Document/Section/Chunk/Table MERGE + 4관계
- `link_chunks_to_entities()` — Chunk → Entity `[:MENTIONS]`

**옵션 3 chunk_id global prefix** (`kg/extractor.py`):
- `{chunk_id}__ent_001` 형식 + `make_global_id` / `parse_global_id`

**일괄 처리 스크립트** (`scripts/run_w3_batch.py`):
- 8문서 순회 + stat + stdout 표

**chunker.py USE_SIMPLE_CHUNKER fallback** (commit `8f0bcb1`):
- `RecursiveCharacterTextSplitter` 분기, 기본 OFF

## 🎤 발표 메시지 확정 (5/23) — 선택지 3

> **"동일 chunker 로 비교하려 했으나, CPU 환경에서 SemanticChunker 가 비현실적임을 발견. 운영 비용의 trade-off 를 정량화함. 추가로 LLM Entity 추출의 라벨 품질 challenge 도 발견."**

### 발표 구조 (12슬라이드)

1. 문제 정의
2. SemanticChunker 발견 (820자/31초)
3. 분석 (LangChain sequential)
4. trade-off 표
5. fallback 구현
6. **운영 데이터 (8/8 100%, 76분)**
7. **포맷 다양성 (PDF + HWP + DOCX, 4 doc_type)**
8. **production 의존성 (LibreOffice)** ⭐
9. **그래프 통계 (610 / 2,451 / 1,553)** ⭐
10. **⭐⭐⭐ Entity 라벨 품질 challenge — 186 Company 중 진짜 회사명 1개!**
11. **VectorRAG ↔ GraphRAG 보완 관계 정량 증명** ⭐ NEW!
12. 인사이트 메시지

### "그래서 결국 성능 비교는?" 질문 대응

답변 준비:
- SemanticChunker 원본은 production 환경 후 (Issue #46)
- chunk 정책 동일 유지, Layer 구조 효과 정량화: 1,189 MENTIONS, 0.86 compression
- 4가지 doc_type 자동 분류
- **Entity 라벨 품질** — Kimi 한계 발견, 프롬프트 엔지니어링 + 후처리 필요
- **VectorRAG ↔ GraphRAG 가 보완 관계** 라는 게 정량 증명됨

## 시행착오 박제

5/16 토요일 디버깅 자산 (= 발표 슬라이드 시드):
- ✅ **bge-m3 정상** (108ms/문장)
- ✅ **PDF / OCR / Neo4j / SemanticChunker 초기화 모두 정상**
- ❌ **SemanticChunker.split_text 본질적 비효율** — 820자/31초
- ✅ **USE_SIMPLE_CHUNKER fallback** — commit `8f0bcb1`
- ✅ **8/8 적재 100%** + **Aura 통계 5종** + **진단 3종**
- ✅ **HWP / DOCX 파서 정상**
- ✅ **Table 노드 첫 적재** (11개)
- ✅ **doc_type 4가지 자동 분류**
- ⚠️⚠️⚠️ **Entity 라벨 품질 challenge** — Kimi 가 Company 라벨에 metric 부여
- ⚠️ **NED 한국어 회사명 변형** — 자기 회사 보고서에 자기 회사명 entity 없음
- **Aura Free trial** — 새 인스턴스 `9b57188f`
- **LibreOffice 환경 의존성** — production Docker 가이드
- **MS Store python stub** — `uv run` 영향 없음

### 미래 발견 (#46+)

- **LibreOffice 자동화** — production Docker 이미지 추가
- **OCR 시간 폭증** — 3Q/4Q parse 1500초+ → 캐시 또는 라이브러리 교체
- **OpenAI 마이그레이션** (#46) — SemanticChunker 원본 복원
- **Entity 추출 프롬프트 엔지니어링** ⭐ NEW! — Kimi 의 Company 라벨 품질 개선
- **NED 한국어 후처리** — 회사명 정규화 추가 단계

### local_id 충돌 — 옵션 3 으로 해결

```
adapter.parse_document() → Document.sections[].chunks[].id ("doc1:c0001")
chunks = [{doc_id, chunk_id, section, text}]
↓ extract() — chunk_id prefix
ExtractedEntity.local_id = "doc1:c0001__ent_001"
↓ link_entities() — 청크 간 NED
EntityGroup.members[*].local_id = "doc1:c0001__ent_001"
↓ link_chunks_to_entities()
parse_global_id("doc1:c0001__ent_001") → ("doc1:c0001", "ent_001")
(:Chunk {id:"doc1:c0001"}) -[:MENTIONS]-> (:Entity {group_id:"grp_001"})
```

## 발표 자료 시드 (5/23 용)

| 자료 | 상태 | 출처 |
|---|---|---|
| 1문서 → 8/8 적재 운영 데이터 표 | ✅ 완료 | 본 문서 |
| **🎯 Aura 통계 5종 (8문서, 17:37)** | ✅ 완료 | 본 문서 |
| **🎯 진단 3종 — Entity 라벨 품질** ⭐⭐⭐ | ✅ 완료 | 본 문서 17:43 |
| **🎯 Company 186 중 진짜 회사명 1개 (한국예탁결제원)** | ✅ 완료 | 진단 3 |
| **🎯 자기 회사 보고서에 자기 회사명 없음** | ✅ 완료 | 진단 1+2 |
| **🎯 VectorRAG ↔ GraphRAG 보완 관계 정량 증명** ⭐ NEW! | ✅ 완료 | 본 문서 |
| **🎯 doc_type × format 4×3 다양성** | ✅ 완료 | Q5 |
| Layer A + Layer B + MENTIONS 그래프 시각화 | ⏸️ Aura console 캡처 | 일요일 |
| **🎯 LibreOffice 의존성 발견 + 해소 사이클** | ✅ 완료 | 본 문서 |
| `@track` 으로 자동 수집된 trace | ✅ Opik UI 확인 가능 | Opik UI |
| **🎯 미래에셋 4분기 — 68 청크 + 6 표 + 261 entity** | ✅ 완료 | 본 문서 |
| **🎯 LLM 비결정성 — DS투자증권 2회 추출 차이** | ✅ 완료 | 본 문서 |
| **🎯 SemanticChunker 본질적 비효율 (820자/31초)** | ✅ 완료 | 본 문서 |
| **🎯 USE_SIMPLE_CHUNKER fallback 코드** | ✅ 완료 | commit `8f0bcb1` |

## 관련

- PR: #45 (5/17 일요일 머지 예정)
- 의존: ✅ PR #44 (#24 Opik 1단계)
- 후속: #18 Text2Cypher (Layer A 적재된 풍성한 그래프 위에서)
- 미래: #46 OpenAI 마이그레이션, #47 회사 발표 (6/1), [신규] Entity 추출 프롬프트 개선
Loading