이어지는 실습 프로젝트¶
이 코스의 예제를 한 번 보고 버리지 않도록, 같은 합성 코퍼스와 질문 세트를 Part 1부터 캡스톤까지 계속 사용한다. 이름은 pharma-mini다. 실제 의학 지식이나 복약 안내가 아니라 그래프 구조를 연습하기 위해 만든 데이터다.
1. 먼저 파일 세 개를 받는다¶
documents.jsonl— 제품 노트 3개와 논문 초록 3개ontology.yaml— 허용 엔티티·관계와 출처 필드question-set.jsonl— 정답과 근거 문서를 포함한 6개 질문
저장소를 복제했다면 모두 examples/pharma-mini/ 아래에 있다. 문서에는 한국어와 영어 텍스트가 함께 들어 있으므로 text_ko 또는 text_en 하나를 골라 쓴다.
git clone https://github.com/desty/study-graphrag.git
cd study-graphrag
head -n 2 examples/pharma-mini/documents.jsonl
2. 도메인과 온톨로지¶
코퍼스에는 다음 두 개의 작은 연결망이 있다.
Drug ─contains→ Ingredient Paper ─cites→ Paper
├──treats→ Condition ├──usesDataset→ Dataset
└──manufacturedBy→ Organization └──evaluates→ Drug
허용 타입은 6개씩이다.
| 엔티티 | 관계 | 출처 |
|---|---|---|
Drug, Ingredient, Condition, Organization, Paper, Dataset |
contains, treats, manufacturedBy, evaluates, cites, usesDataset |
모든 엣지에 source_id, source_text |
처음부터 이 목록을 정답으로 외우는 게 목적은 아니다. Ch 4에서 질문을 보고 직접 스키마를 만든 뒤, 제공된 ontology.yaml과 비교한다.
3. 컴피턴시 질문과 검색 경로¶
질문 세트는 일부러 세 종류를 같은 수로 섞었다.
| 유형 | 예시 | 필요한 경로 |
|---|---|---|
| factual | 아스피린의 성분은? | 한 문서 또는 Drug → Ingredient |
| multihop | 아스피린과 같은 성분을 포함하는 다른 약은? | Drug → Ingredient ← Drug |
| global | 코퍼스의 두 핵심 주제는? | 두 커뮤니티 요약을 종합 |
따라서 GraphRAG가 무조건 이기도록 만든 벤치마크가 아니다. factual 질문에서는 잘 튜닝한 벡터 검색이 충분해야 하며, multihop/global에서 그래프가 추가 비용만큼 값을 내는지를 확인한다.
정확한 개수나 합계를 묻는 질문은 별도다. 예를 들어 “가장 많은 약이 치료하는 질환은?”은 생성형 global search가 아니라 Cypher의 count(DISTINCT ...) 같은 직접 집계 쿼리로 풀고, 답변 생성은 결과 설명에만 쓴다.
4. 파트마다 남길 산출물¶
작업 파일은 버전 관리에서 제외한 work/pharma-mini/에 둔다고 가정한다.
| 구간 | 할 일 | 산출물 |
|---|---|---|
| Part 1 | 질문을 factual/multihop/global로 분류 | question-analysis.md |
| Part 2 | 컴피턴시 질문에서 타입·제약 도출 | ontology.yaml |
| Part 3 | 트리플 추출, 검수, Neo4j 적재 | triples.jsonl, load.cypher, review.csv |
| Part 4 | 벡터·로컬·글로벌 검색을 같은 질문으로 실행 | retrieval-results.jsonl |
| Part 5 | 정답성·근거·지연·비용 비교 | results.csv, decision.md |
| 캡스톤 | 처음부터 재현하고 한계를 기록 | README.md와 실행 스크립트 |
triples.jsonl의 최소 계약은 다음과 같다. LLM이 만든 문장을 그대로 믿지 말고, source_id로 원문을 다시 찾을 수 있어야 한다.
{"subj":"Aspirin","subj_type":"Drug","rel":"contains","obj":"Acetylsalicylic acid","obj_type":"Ingredient","source_id":"doc-001","source_text":"..."}
5. 완료 기준¶
- 6개 질문마다 정답과 근거 문서를 보지 않고 검색을 먼저 실행했다.
- 추출한 모든 트리플이 온톨로지의 허용 타입을 통과한다.
- 답변에서 사용한 트리플을 원문
source_id까지 역추적할 수 있다. - 벡터 RAG와 GraphRAG가 같은 코퍼스·질문·생성 모델을 사용한다.
- 정확도뿐 아니라 검색 지연과 모델 호출량도 기록한다.
- “어떤 질문을 어느 검색기로 보낼지”를
decision.md에 근거와 함께 남긴다.
6. 실제 로컬 실행 결과¶
저장소에는 Neo4j 2026.06.0과 로컬 SmolLM2 360M으로 실행한 results-local.csv와 decision.md가 들어 있다. 이 결과는 범용 벤치마크가 아니라 파이프라인 검증 기록이다.
- 스키마 가드레일 추출: micro precision 0.923, micro recall 0.706
- factual: vector와 graph 모두 answer match 1.000
- multihop: vector 0.250, graph 1.000
- global: graph는 근거 문서를 모두 회수했지만, 작은 생성 모델이 한 커뮤니티를 누락한 질문이 있었다
핵심은 GraphRAG가 항상 이겼다는 숫자가 아니다. 추출 재현율, 근거 회수율, 답변 완전성은 서로 다른 실패 지점이라는 점을 같은 실행에서 확인한 것이다. 재현 명령은 examples/pharma-mini/README.md에 있다.
이제 Ch 1에서 질문 여섯 개를 먼저 분류하자. 제공된 정답은 평가할 때까지 열어보지 않는 편이 좋다.