튜토리얼
Week 6: GraphRAG

Week 6. 지식 그래프 기반 RAG (GraphRAG)

Vector + Graph 하이브리드 검색, Sub-graph 추출, LLM 컨텍스트 주입


학습 목표

이 튜토리얼을 완료하면 다음을 할 수 있습니다:

  • GraphRAG의 원리와 장점 이해
  • Vector + Graph 하이브리드 검색 구현
  • Sub-graph 추출을 통한 컨텍스트 주입
  1. LlamaIndex, LangChain과 통합

핵심 개념

1. 왜 GraphRAG인가?

"도서관 검색" 비유: 벡터 vs 그래프

도서관에서 정답을 찾는다고 상상해보세요.

  • 벡터 검색(기존 RAG)책 표지나 제목이 비슷한 책을 찾는 것과 같습니다. "애플(사과)" 책을 찾으려다가 "애플(회사)" 책을 집을 수도 있습니다. 문맥이 비슷하면 헷갈립니다. (Fuzzy Search)
  • GraphRAG인용 색인(Citation Index) 을 보는 것과 같습니다. 책을 찾은 뒤, 책 안에 적힌 정확한 참고문헌을 따라갑니다. "잡스" 페이지에서 연결된 "워즈니악" 링크를 따라가는 것이죠. 명확하고 구조적입니다. (Graph Traversal)

GraphRAG는 이 둘을 결합합니다. 벡터로 입구를 찾고, 그래프로 지도를 탐험합니다.

기존 RAG의 한계

질문: "크리스토퍼 놀란이 감독한 영화들의 공통 배우는?"

벡터 검색: 의미적으로 유사한 청크 반환
→ 개별 영화 정보는 있지만, 관계 파악 어려움

GraphRAG: 구조화된 관계 탐색
→ Nolan → 영화들 → 배우들 → 교집합

GraphRAG 아키텍처

질문 → Query Rewriting → Hybrid Retrieval → Sub-graph 추출 → LLM 응답

                    ┌─────────┴─────────┐
                    ↓                   ↓
              Vector Search      Graph Traversal
                    │                   │
                    └─────────┬─────────┘

                       Context Fusion

2. Sub-graph 추출

from neo4j import GraphDatabase
 
def extract_subgraph(driver, entity, depth=2):
    """특정 엔티티 주변의 서브그래프 추출"""
    with driver.session() as session:
        result = session.run("""
            MATCH path = (start)-[*1..$depth]-(connected)
            WHERE start.name = $entity
            RETURN nodes(path) AS nodes, relationships(path) AS rels
        """, entity=entity, depth=depth)
 
        nodes = set()
        edges = []
        for record in result:
            for node in record["nodes"]:
                nodes.add((node.id, dict(node)))
            for rel in record["rels"]:
                edges.append({
                    "source": rel.start_node.id,
                    "target": rel.end_node.id,
                    "type": rel.type
                })
 
        return {"nodes": list(nodes), "edges": edges}

3. 하이브리드 검색

from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Neo4jVector
 
class HybridRetriever:
    def __init__(self, driver, embeddings):
        self.driver = driver
        self.vector_store = Neo4jVector.from_existing_graph(
            embeddings,
            search_type="hybrid",
            node_label="Document",
            text_node_properties=["text"],
            embedding_node_property="embedding"
        )
 
    def retrieve(self, query, k=5):
        # 1. 벡터 검색
        vector_results = self.vector_store.similarity_search(query, k=k)
 
        # 2. 엔티티 추출 및 그래프 검색
        entities = self._extract_entities(query)
        graph_results = []
        for entity in entities:
            subgraph = extract_subgraph(self.driver, entity)
            graph_results.append(subgraph)
 
        # 3. 결과 통합
        return self._fuse_results(vector_results, graph_results)

4. Microsoft GraphRAG 비교

기능직접 구현MS GraphRAG
커뮤니티 탐지수동Leiden 알고리즘
요약 생성없음계층적 요약
글로벌 쿼리제한적Map-Reduce 지원
설정유연함파이프라인 고정

5. LlamaIndex 통합

from llama_index.core import KnowledgeGraphIndex
from llama_index.graph_stores.neo4j import Neo4jGraphStore
 
graph_store = Neo4jGraphStore(
    username="neo4j",
    password="password",
    url="bolt://localhost:7687",
)
 
index = KnowledgeGraphIndex.from_documents(
    documents,
    graph_store=graph_store,
    include_embeddings=True,
)
 
query_engine = index.as_query_engine(
    include_text=True,
    response_mode="tree_summarize",
)
 
response = query_engine.query("크리스토퍼 놀란 영화의 공통점은?")

면접 질문 맛보기

Q: GraphRAG가 Vector RAG보다 좋은 경우는?

  • 관계 기반 질문: "A와 B의 관계는?"
  • 다중 홉 추론: "A의 친구의 친구는?"
  • 집계 질문: "모든 X의 공통점은?"
  • 시간순 정보: "A 이후에 발생한 사건들은?"

더 많은 면접 질문은 Premium Interviews (opens in a new tab)에서 확인하세요.


🎬 프로젝트: 영화 추천 지식그래프

진행 현황

Week주제프로젝트 마일스톤
1온톨로지 입문✅ 영화 도메인 설계 완료
2RDF & RDFS✅ 영화 10편 RDF 변환 완료
3OWL & 추론✅ 추론 규칙 적용 완료
4지식 추출✅ 영화 100편 자동 수집 완료
5Neo4j✅ 그래프 DB 구축 완료
6GraphRAG자연어 질의 시스템 구축
7온톨로지 에이전트새 영화 자동 업데이트
8도메인 확장의료/법률/금융 케이스
9서비스 배포API + 대시보드

Week 6 마일스톤: GraphRAG로 자연어 영화 추천

"놀란 감독 스타일의 SF 영화 추천해줘"라는 자연어 질문에 답할 수 있는 시스템을 구축합니다.

GraphRAG 아키텍처:

사용자 질문: "놀란 감독 스타일의 SF 영화 추천해줘"
    ↓ LLM (질문 분석)
의도: 추천, 조건: 감독=놀란 스타일, 장르=SF
    ↓ Cypher 생성
MATCH (d:Person {name: "Christopher Nolan"})-[:DIRECTED]->(m:Movie)
      -[:HAS_GENRE]->(:Genre {name: "Sci-Fi"})
RETURN m.title
    ↓ Neo4j 실행
["Inception", "Interstellar", "Tenet"]
    ↓ LLM (응답 생성)
"놀란 감독의 SF 영화로는 인셉션, 인터스텔라, 테넷이 있습니다."

하이브리드 검색:

  • Vector Index: 영화 줄거리 임베딩
  • Graph Index: 관계 기반 탐색
  • 결합: 의미적 유사성 + 구조적 연결

프로젝트 노트북에서 자연어로 영화를 추천받는 챗봇을 구현합니다.

프로젝트 노트북에서는 다음을 직접 구현합니다:

  • LangChain + Neo4j 연동 설정
  • 자연어 → Cypher 쿼리 자동 변환
  • "놀란 스타일 SF 영화 추천" 질문 처리
  • Vector + Graph 하이브리드 검색

9주 후 완성되는 것: "놀란 감독 스타일의 SF 영화 추천해줘"라고 물으면, 지식그래프에서 감독-장르-평점 관계를 추론하고 자연어로 답변하는 AI 에이전트


실습 노트북

이론을 더 깊이 탐구하고 싶다면:

실습 노트북에서는 추가로 다음 내용을 다룹니다:

  • Microsoft GraphRAG vs LangChain 비교
  • 커뮤니티 탐지 및 요약 생성
  • 커스텀 Retriever 구현
  • 대화 컨텍스트 관리

다음: Week 7: 온톨로지 에이전트