문단 클릭 = 시작 위치 선택 · 재생은 우하단 버튼/P (재생 중 클릭 = 점프)

5주차 — Graph RAG와 Neo4j 지식 그래프 (리랭킹 구현 · MS GraphRAG 인덱싱 · Neo4j 적재 · 로컬/글로벌 검색)

기존 RAG가 답하지 못하는 "여러 청크를 관통하는 질문"을 풀기 위해, MS GraphRAG로 문서에서 엔티티·관계·커뮤니티를 자동 추출하고 그 산출물을 Neo4j에 적재해 로컬/글로벌 검색까지 직접 구현하라 — GraphRAG는 대규모 운영체가 아니라 그래프 DB에 넣을 데이터를 만들어 주는 "문서 파서"다.


0. 사전 필수 용어 (선행지식)

  1. 엔티티(Entity)와 관계(Relationship) — 그래프에서 독립적인 정보를 나타내는 최소 단위가 엔티티(노드), 엔티티 사이의 연결이 관계(간선)다. 비유하면 인물 관계도의 "인물"과 그 사이의 "화살표"다. 본문 3장 전체와 4장 Step 4의 적재 코드에서 쓰인다.
  2. RAG(Retrieval Augmented Generation, 검색 증강 생성) — LLM이 답하기 전에 관련 문서를 검색해 프롬프트에 넣어 주는 구조. 비유하면 "오픈북 시험"이다. 2장의 한계 논의가 이 구조를 전제로 한다.
  3. 크로스 인코더(Cross-Encoder) — 쿼리와 문서를 한 쌍으로 함께 넣어 상호작용까지 평가하는 유사도 모델. 각자 벡터를 만들어 나중에 비교하는 임베딩 방식보다 정밀하다. 비유하면 두 사람을 같은 방에서 면접 보는 것과 각자 자기소개서만 읽는 것의 차이다. 3장 A절 리랭킹에서 쓰인다.
  4. 맵-리듀스(Map-Reduce) — 데이터 조각마다 같은 처리를 적용(맵)한 뒤 결과를 하나로 합치는(리듀스) 처리 패턴. 비유하면 조별 조사 후 전체 종합 발표다. 3장 F절 글로벌 검색과 4장 Step 4의 구현이 이 패턴이다.
  5. Cypher — Neo4j의 그래프 질의 언어. SQL이 표를 다루듯 Cypher는 노드-관계 패턴((a)-[:REL]->(b))을 다룬다. 4장 Step 4의 적재·조회 전부가 Cypher다.

선행지식이 부족하면 AI 엔지니어링 EP17 (컨텍스트 증강과 RAG) 학습자료를 먼저 보고, Cypher 입문은 Neo4j 공식 문서(https://neo4j.com/docs/)를 참조하라.


1. 주제 정의

이 강의(뉴런데브 RAG 실전 5주차)는 두 부분으로 구성된다.

  • 앞부분 — 리랭킹 완결: 지난 주에 다루지 못한 리랭킹 실습(practice4-7)을 마무리한다.
  • 본론 — Graph RAG: 기존 RAG의 한계를 극복하는 지식 그래프 접근을 개괄하고, MS GraphRAG로 문서에서 지식 그래프를 자동 생성 → Neo4j에 적재 → 로컬/글로벌 검색 직접 구현까지 전 과정을 실습한다.

실습 노트북 구성:

노트북 주제
practice4-7 LLM 기반 리랭킹 — 크로스 인코더(Qwen3-Reranker-0.6B) 직접 구현
practice5-1 GraphRAG 설치·환경 설정 — LM Studio · settings.yaml · working_directory
practice5-2 지식 그래프 구축 실행 — graphrag index · parquet 산출물 확인
practice5-3 GraphRAG 질의 — 로컬 검색 vs 글로벌 검색 CLI 비교
practice5-4 GraphRAG 산출물(parquet)을 Neo4j에 적재 — batched_import · Cypher
practice5-5 Neo4j 기반 로컬/글로벌 검색 직접 구현 — 벡터 인덱스 · 맵-리듀스

📚 참고: 실습 대상 문서는 조지 게어 헨리(George Garr Henry)의 『How to Invest Money』(1908, 텍스트 약 150KB)다. 사용 OSS는 Microsoft GraphRAG(https://github.com/microsoft/graphrag), Neo4j(APOC·Graph Data Science 플러그인), Hugging Face transformers다.


2. 풀려는 문제

  • 문제 1 — 정보 연결의 어려움: "이 문서의 주요 주제는 무엇인가요?"는 임베딩 유사도로 찾을 수 있는 질문이 아니다. 여러 청크를 관통하는 인사이트가 필요하다.
  • 문제 2 — 대규모 데이터 이해의 한계: "10년간 보고서를 바탕으로 조직 변화를 설명해달라" — 단편적 지식이 아니라 전체 청크를 관통하는 지식·관계성을 인식해야 답할 수 있다. 기존 RAG로는 안 된다.
  • 문제 3 — 에이전트 도움 없이 스스로 해결하는 RAG: Agentic AI는 여러 턴에 걸쳐 도구를 호출해 파편 정보를 수집·병합하므로 위 질문이 문제가 되지 않는다. 그러나 에이전트의 도움 없이 시스템 스스로 해결하는 RAG를 만들려면 기존 방식으로는 한계가 명확하다. RAG 연구 자체가 "모델이 스스로 취합하지 못하던 시절, 시스템이 어떻게 정보를 모아 줄까"에서 출발한 것이다.
  • 문제 4 — 그래프 DB에 넣을 데이터 만들기: 그래프 DB 도입의 최대 난관은 DB에 넣을 엔티티·관계 레코드를 만드는 작업 자체다. 문서 뭉치에서 이걸 수작업으로 구축하는 것은 사실상 불가능한 수준의 노동이다. 이 파이프라인을 자동화해 주는 것이 MS GraphRAG의 존재 이유다.

✅ 확인: 문제 1·2의 예시 질문이 왜 임베딩 유사도 검색으로 해결되지 않는지 스스로 설명할 수 있는지 점검하라. (힌트: 답의 근거가 한 청크에 없다.)


3. 핵심 개념·구조

A. 리랭킹(Re-ranking) — 임베딩 검색의 후처리

  • 임베딩 모델과 리랭커는 일반적으로 시리즈로 함께 출시된다. 자기가 고른 임베딩 모델과 짝이 되는 리랭커를 함께 쓰는 것이 중요하다.
  • LM Studio 같은 플랫폼에는 크로스 인코더(리랭커) API가 없어 직접 구현해야 한다. Hugging Face transformers의 AutoModelForSequenceClassificationAutoTokenizer로 모델을 로드해 크로스 인코더를 돌린다.
  • 크로스 인코더 계열은 (쿼리, 도큐먼트) 두 인자를 쌍으로 받아 유사도를 평가하고 랭킹 점수(score)를 반환한다.
  • 자기만의 검색 기능은 BaseRetriever를 상속받아 리트리버로 만들고 원래 체인에 끼워 넣으면 된다. practice4-7의 RerankingRetriever는 앙상블 검색기를 1차 후보 검색기로 감싸고, 그 결과를 리랭커로 좁힌다:
reranked_docs = reranking_documents(QUESTION, unique_candidates, top_n=2)
  • 효과: 리랭킹을 적용하면 검색 결과가 훨씬 정확해진다.

💡 실무 노하우: 리랭커를 제대로 이해하려면 대조 학습(Contrastive Learning)과 크로스 인코더 개념 이해가 선행돼야 한다. 실무에서는 각 리트리버의 후보 수를 최종 반환 개수보다 넉넉히 크게 잡아 합친 뒤 재순위화한다.

B. 그래프 DB의 구조 — 엔티티·관계·속성

  • 'Apple'과 'iPhone'이 엔티티, 둘을 잇는 '개발'이 관계다. 관계에 이름을 줄 수 있을 뿐 아니라, 엔티티에도(출시일·운영체제 등) 관계에도 추가 속성(메타데이터)을 부여할 수 있다.
  • 관계가 명시돼 있으면 삼단논법("A는 B고 B는 C면 A는 C다")처럼 그래프 연결을 따라 논리적으로 추론할 수 있다. 예: 애플–스티브 잡스, 스티브 잡스–픽사 두 연결로부터 스티브 잡스를 공통점으로 두고 애플과 픽사 사이의 관계를 유추한다.
  • LLM이 매번 어휘 사이의 관계를 유추해야 하는 것과 달리, 그래프는 사전에 설정해 둔 관계를 이용해 어떤 관계인지 논리적으로 추적한다.

C. MS GraphRAG 구축 파이프라인

원본 문서에서 지식 그래프까지: 청킹 → 그래프 변환 → 그래프 증강 → 커뮤니티 요약을 전부 자동화한다.

  1. 청킹 — 자체 토크나이저의 토큰 수 기반 고정 분할. 600토큰 수준이 좋다는 가이드가 있고, 중간 오버랩을 둔다.
  2. 엔티티·관계 추출 — LLM에 프롬프트와 청크를 던져 추출하게 한다. 현대 모델은 그래프 데이터를 충분히 학습해 잘해 준다. 단, 8B·13B급으로 될 거라 생각하지 말고 30B 이상, 되도록 100B·200B급을 써라.
  3. 글리닝(gleaning) — 같은 청크와 이미 추출된 엔티티·관계를 다시 던지며 "빠진 것·잘못된 것을 고쳐 다시 추출해 봐"를 반복하면 같은 청크에서 더 많은 엔티티·관계를 찾아낸다. 모델이 약하던 시절(책 출간 2024년 초반 기준)의 보완 기법으로, 강의는 현대 고성능 모델에서는 상당수 이런 기법이 무력화됐다고 평가한다.
  4. 엔티티 통합 — 같은 엔티티가 중복 추출되면(예: 일론 머스크 2건) 설명을 요약·병합해 하나로 만든다. 그래프 통합이라 부르지만 실질은 엔티티 통합이다.
  5. 주장(claim) 추출 — 청크에서 시간 등 부가 정보가 명시된 사실 요약 문장을 뽑는다(공변량/covariate라는 표현의 실체).
  6. 커뮤니티 탐지(Community Detection) — 밀접하게 연결된 엔티티 그룹을 찾아 묶는다. Louvain·Leiden 알고리즘 — LLM이 아니라 그래프의 노드·연결 특성에 대한 수학적 계산이다. 알고리즘 상수를 조절해 더 크거나 작은 범위로 묶어 여러 단계(level) 계층을 만든다.
  7. 그래프 임베딩Node2Vec: Word2Vec 알고리즘을 그대로 활용해, 어휘 대신 노드 간 연결성(문맥)을 학습해 밀집 벡터를 만든다. 코사인 유사도·내적으로 노드 유사도를 평가할 수 있게 된다.
  8. 커뮤니티 요약 — 커뮤니티는 결국 엔티티·관계의 묶음일 뿐이므로, 그 안의 엔티티·관계 디스크립션을 LLM에 던져 "문장으로 만들어 봐" 해서 요약 리포트를 만든다. 이 리포트가 있어야 커뮤니티 단위로 타고 들어가 검색할 수 있다.

D. 왜 커뮤니티인가

개별 노드만 존재하는 거대한 그래프는 너무 복잡해서 검색이 안 된다. 적절한 노드 그룹(커뮤니티)을 만들어 그룹 단위로 검색한 뒤 드릴 다운해야 한다. 핵심은 그룹핑을 LLM이 아니라 수학적 계산으로 할 수 있다는 점이다.

E. 로컬 검색 vs 글로벌 검색

로컬 검색 (local) 글로벌 검색 (global)
출발점 질문과 관련 있는 엔티티 커뮤니티 리포트 전체
방식 엔티티에 연결된 청크·관계·리포트 수집 리포트를 맵-리듀스로 훑어 종합
적합 질문 특정 인물·조직 등 명시적 질문 문서 전체를 아우르는 포괄적 질문

F. GraphRAG의 위치 — 문서 파서

MS GraphRAG를 그 자체로 대규모 운영에 쓰지 않는다. 파일 시스템(parquet) 기반이라 방대한 양을 버틸 수 없다. 각 문서에 GraphRAG를 돌려 산출물을 만들고, 그것을 전용 페이징 구조를 갖춘 Neo4j 같은 전문 그래프 DB에 계속 적재한다. 즉 GraphRAG는 "그래프 DB에 넣기 좋은 데이터를 만들어 주는 문서 파서"다.


4. 실습·구현 가이드 (Step 1·2·3·4)

Step 1 — 환경 설정 (practice5-1)

  1. 설치: !pip install -q graphrag
  2. working_directory 생성 — MS GraphRAG가 동작하는 곳. graphrag init으로 기본 설정 파일(settings.yaml·.env)을 만든다. 완성되면 최상위에 cache/ input/ logs/ output/ prompts/ settings.yaml .env가 놓인다.
  3. LM Studio 로컬 엔드포인트에 맞게 상수를 잡는다:
LMSTUDIO_BASE_URL = "http://host.docker.internal:12345/v1"  # /v1 까지 포함
LMSTUDIO_API_KEY  = "lm-studio"   # LM Studio는 키 검증 안 함 (더미)
LLM_MODEL   = "unsloth/Qwen3.6-35B-A3B-MTP-GGUF-nothink"    # 완성 모델: non-thinking
EMBED_MODEL = "qwen3-embedding-8b:mp"                        # 임베딩 모델
DATA_PATH   = "practices/How_to_invest_money.txt"
  1. settings.yaml에 api_base를 주입하고 동시 요청을 직렬화한다:
settings["completion_models"]["default_completion_model"]["api_base"] = LMSTUDIO_BASE_URL
settings["embedding_models"]["default_embedding_model"]["api_base"]   = LMSTUDIO_BASE_URL
settings["concurrent_requests"] = 1   # 단일 모델 서빙 — 직렬화가 훨씬 빠르다
  1. .env에는 더미 키를 쓴다: GRAPHRAG_API_KEY=lm-studio
  2. 입력 문서를 input/에 복사한다. shutil.copy 대신 shutil.copyfile을 쓰면 컨테이너 재빌드로 파일 소유·권한이 바뀌어도 copymode의 chmod 호출로 인한 PermissionError를 피할 수 있다.

⚠️ 주의 — 리즈닝(thinking) 모델 금지: GraphRAG의 커뮤니티 리포트 생성 단계는 LLM에 JSON 스키마를 강제하는 구조화 출력(structured output)을 요청한다. 추론 모델을 LM Studio에 연결하면 실제 JSON 응답 전체가 reasoning_content에 담기고 content는 빈 문자열로 반환돼 스키마 검증이 매번 실패한다(litellm.JSONSchemaValidationError). 순수 텍스트 질의응답에서는 정상 분리되지만 구조화 출력과 결합될 때만 터지는 문제다. 리즈닝을 끄는 옵션이 있는 모델은 끄고, 없으면 nothink 모델을 구해 써라. GGUF 모델의 chat template을 스캔해 리즈닝 제어 필드를 심어 주는 패처 도구도 강의 커뮤니티(디스코드)에 공개돼 있다.

💡 실무 노하우 — 토큰 출력 속도부터 확인하라: 로컬 LLM이 초당 15~20토큰 수준이면 인덱싱에 몇 시간씩 걸린다. 초당 50~60토큰은 나와야 이 실습 규모가 20분 정도로 끝난다. 임베딩 모델도 동시에 쓰므로 함께 빨라야 한다.

Step 2 — 인덱스 빌드 (practice5-2)

!graphrag index --root ./practices/working_directory

10개 워크플로우가 순차 실행된다 (책이 설명하는 7단계와 이름은 다르지만 역할은 동일): load_input_documents → create_base_text_units → create_final_documents → extract_graph → finalize_graph → extract_covariates → create_communities → create_final_text_units → create_community_reports → generate_text_embeddings

산출물(output/, parquet)과 이번 실습의 실측치:

파일 내용 실습 결과
entities.parquet title·type·description·degree 엔티티 169개
relationships.parquet source·target·weight·combined_degree·description 관계 184개
communities.parquet level·parent·children·entity_ids (Leiden 계층) 커뮤니티 30개
community_reports.parquet title·summary·rating(중요도)·findings 리포트 30개
text_units.parquet 청크 텍스트·n_tokens·document_id

✅ 확인: pd.read_parquet(output_dir / "entities.parquet")로 엔티티 수를 세고 title·type·description·degree 컬럼이 채워졌는지 확인하라. 예: PROJECT GUTENBERG=ORGANIZATION, GEORGE GARR HENRY=PERSON, HOW TO INVEST MONEY=EVENT. 커뮤니티 리포트도 열어 title·summary가 문장으로 생성됐는지 본다.

Step 3 — GraphRAG 질의 (practice5-3)

!graphrag query --root ./practices/working_directory --method global "이 책 전반에서 다루는 투자 대상(증권)의 종류와 저자가 강조하는 투자 원칙은?"
!graphrag query --root ./practices/working_directory --method local "조지 게어 헨리(George Garr Henry)는 어떤 인물이며, 어느 회사에서 어떤 직책을 맡았나?"
  • 답변에는 [Data: Reports (5, 25, +more)] 형식의 근거 인용이 붙는다.
  • 실습 정리: 포괄적인 질문(투자 대상의 종류·원칙)에는 문서 전체 구조를 훑는 글로벌 검색이 더 균형 잡힌 답변을 주고, 세부적인 질문(특정 인물의 경력)에는 관련 엔티티에서 바로 출발하는 로컬 검색이 더 구체적이고 정확하다.

Step 4 — Neo4j 적재와 직접 검색 구현 (practice5-4 · 5-5)

1) Neo4j 준비 (Docker Compose) — Browser 7474, Bolt 7687:

services:
  neo4j:
    image: neo4j:5.12.0
    environment:
      - NEO4J_AUTH=neo4j/password
      - NEO4J_PLUGINS=["apoc", "graph-data-science"]
    ports: ["7474:7474", "7687:7687"]

2) 재실행 안전(멱등) 정리 — 공유 인스턴스이므로 전체 DB를 비우지 않고 이 노트북이 만드는 라벨만 지운 뒤 다시 적재한다:

GRAPHRAG_LABELS = ["Document", "Chunk", "Entity", "Community", "Finding"]
for label in GRAPHRAG_LABELS:
    driver.execute_query(
        f"MATCH (n:{label}) DETACH DELETE n RETURN count(n) AS deleted",
        database_=NEO4J_DATABASE)

3) 유일성 제약 — 중복 적재 방지: create constraint chunk_id if not exists for (c:Chunk) require c.id is unique (라벨별 반복).

4) parquet → Cypher 적재batched_import()가 DataFrame을 배치로 나눠 UNWIND로 밀어 넣는다:

  • Document: MERGE (d:Document {id:value.id}) SET d += value {.title} — 1건
  • Chunk: MERGE (c:Chunk {id:value.id})MATCH (d:Document {id:value.document_id}) MERGE (c)-[:PART_OF]->(d). 책은 이 컬럼이 리스트(document_ids)라 UNWIND가 필요하지만, 현재 버전은 청크당 문서 하나(document_id 단수)라 바로 MATCH하면 된다.
  • Entity: MERGE 후 apoc.create.addLabels로 type(PERSON·ORGANIZATION 등)을 노드 라벨로 부여하고, text_unit_ids를 UNWIND해 (c)-[:HAS_ENTITY]->(e) 연결 — 노드 169·관계 226 생성.
  • Relationship: MERGE (source)-[rel:RELATED {id:value.id}]->(target) (combined_degree는 rank로 rename해 속성 저장) — 관계 184 생성.
  • Community: MERGE (c:Community {community:value.community}) 후 entity_ids를 UNWIND해 (e)-[:IN_COMMUNITY]->(c) — 30건. 책은 별도 파일(create_final_nodes.parquet)로 연결하지만 현재 버전은 communities.parquet의 entity_ids에서 바로 연결한다.
  • Community report: 커뮤니티 노드에 요약 속성을 추가하고 findings를 개별 Finding 노드로 반영(HAS_FINDING).

5) Neo4j Browser 확인MATCH (n:Person) RETURN n LIMIT 25 등으로 라벨·관계(RELATED, PART_OF, HAS_ENTITY, IN_COMMUNITY)가 그래프로 보이는지 확인한다.

6) 벡터 인덱스 구축 (practice5-5):

PROJ_DIM = 1024   # 구버전 프로시저 상한 2048보다 충분히 작게 (MRL truncation)
  • 랭체인 Neo4jVector.from_existing_graph()를 쓰지 않는 이유: 이 클래스는 내부적으로 Neo4j 5.15+에서 도입된 CREATE VECTOR INDEX Cypher 문법을 쓰는데, 실습 환경의 Neo4j는 5.12라 이 문법이 아예 파싱되지 않는다(CypherSyntaxError). 대신 5.12에서도 동작하는 예전 프로시저 방식 db.index.vector.createNodeIndex / db.index.vector.queryNodes로 직접 만들고 조회한다.
  • 이 프로시저는 인덱스 차원을 최대 2048로 제한하므로, 4096차원 임베딩을 앞 주차와 동일한 MRL truncation 방식으로 1024차원으로 잘라 쓴다.
  • Entity 노드의 description을 임베딩해 embedding 속성으로 저장(169건)한 뒤 인덱스를 만든다. 재실행 안전을 위해 인덱스를 먼저 지우고 다시 만든다.

7) 로컬 검색 구현 — 쿼리를 임베딩 벡터로 바꾸고 벡터 인덱스로 관련 엔티티를 검색한 뒤, 연결된 청크·관계·커뮤니티 정보를 구조화해 LLM 프롬프트로 보낸다.

8) 글로벌 검색 구현 — 맵 단계(각 리포트에서 답변+중요도 점수를 {"Answer": "답변", "score": 점수} JSON으로)와 리듀스 단계(중요도를 고려해 핵심 위주로 마크다운 종합)를 프롬프트 2개로 나눠 구현한다:

def global_search(query, level, response_type="multiple paragraphs"):
    community_data = driver.execute_query(
        "MATCH (c:Community) WHERE c.level = $level AND c.full_content IS NOT NULL "
        "RETURN c.full_content AS output", level=level).records
    intermediate = [map_step(query, c["output"]) for c in community_data]
    return reduce_step(intermediate, query, response_type)

✅ 확인: global_search("이 책 전반에서 다루는 투자 대상(증권)의 종류와 저자가 강조하는 투자 원칙은 무엇인가요?", level=0) 결과가 Step 3의 GraphRAG CLI 글로벌 검색과 거의 같은 범위의 종합 답변을 내는지 비교하라. 같게 나오면 Neo4j만으로 Graph RAG 질의가 재현된 것이다.


5. 사례·적용

  • 실습 데이터 전체 흐름: 『How to Invest Money』 인덱싱 → 엔티티 169 · 관계 184 · 커뮤니티 30 · 리포트 30 → Neo4j 적재 → 벡터 인덱스(1024차원) → 로컬/글로벌 검색 재현.
  • 글로벌 질의 사례: "이 책 전반에서 다루는 투자 대상(증권)의 종류와 투자 원칙" → 채권(철도·지방자치단체·정부 채권), 주식, 부동산 담보권·보장 모기지 등을 계층적으로 종합한 답변. 임베딩 유사도만으로는 이렇게 문서 전체를 아우르는 답이 나오지 않는다.
  • 로컬 질의 사례: "조지 게어 헨리는 어떤 인물인가" → Guaranty Trust Company of New York의 부사장(Vice-President), 출판사 Funk & Wagnalls Company, 초출 System Magazine 등 엔티티-관계에서 바로 출발한 정밀 답변 + [Data: Reports (...)] 인용.
  • 적용처 판단: 포괄적·인사이트 질문은 주로 경영진용 전문가 시스템, 인사이트가 필요한 통계·마케팅 팀에서 나온다. 그런 시스템을 만들 때 그래프 DB를 넣으면 유리하다. 반면 일반 지식 질문·Q&A 서비스에서는 이런 질문이 드물어 좋은 디코더 기반 임베딩 모델만으로 거의 해결된다.

💡 실무 노하우 — 답변에서 그래프 DB 냄새 맡기: 답변이 "엔티티–릴레이션–엔티티" 패턴으로 구성돼 나오면 그래프 DB가 중간에 끼어 있다고 감지할 수 있다. 많이 써 보면 이 느낌이 온다 — 상용 서비스 분석에도 쓸 수 있는 감각이다.


6. 핵심 원리

  • 지식의 명시적 구조화: LLM이 매번 어휘 관계를 유추하게 하지 않고, 관계를 미리 그래프로 저장해 두면 논리적 탐색(삼단논법식 연결 추적)으로 정확하게 추론할 수 있다.
  • 계산과 생성의 분업: 커뮤니티 그룹핑은 수학적 계산(Louvain·Leiden), 커뮤니티 요약은 LLM. 각자 잘하는 일에 배치하는 것이 Graph RAG 파이프라인의 설계 원리다.
  • GraphRAG = 파서, Neo4j = 본체: GraphRAG 산출물은 parquet 파일 시스템이라 대규모 운영을 버틸 수 없다. 전용 페이징 구조를 갖춘 그래프 DB에 적재해야 방대한 양을 밀어 넣을 수 있다. GraphRAG의 가치는 "그래프 DB에 넣을 데이터를 만드는 막대한 수작업"을 파이프라인으로 대신해 주는 것이다.
  • 4주차와 같은 패턴의 반복: 4주차에서 인메모리 리트리버를 버리고 pgvector에 넣기 위해 코퍼스를 가공했듯, 이번 주도 결국 Neo4j에 넣기 위한 가공 파이프라인이 본질이다. "일반 코퍼스는 그래프 DB에 예쁘게 들어가지 않는다 → 가공 단계 전체를 시스템이 해 준다"는 실무 흐름을 책이 완전한 코드로 보여 준다.

7. 한계·트레이드오프

  • 모델 성능 의존: 엔티티·관계 추출 품질이 LLM 성능에 달렸다. 8B·13B급으로는 안 되고 30B 이상 권장 — 로컬 실습의 진입 장벽이다.
  • 인덱싱 비용: 로컬 35B급 모델로 요청당 평균 40~70초, 150KB 문서 전체 인덱싱에 수십 분 이상. LLM과 임베딩 모델을 동시에 부리므로 하드웨어 요구가 크다.
  • 리즈닝 모델 비호환: 구조화 출력과 결합 시 JSON이 reasoning_content로 새는 문제로 nothink 모델이 강제된다 (4장 Step 1 주의 박스).
  • 버전 제약: Neo4j 5.15+의 CREATE VECTOR INDEX 문법 vs 5.12의 구버전 프로시저(차원 상한 2048) — 배포 환경의 DB 버전이 구현 방식을 바꾼다.
  • 수요 자체의 희소성: 문서 전체를 관통하는 포괄적 질문은 일반 사용자가 잘 하지 않는다. 전문가 시스템·인사이트 조직이 아니라면 그래프 DB는 과잉 설계일 수 있다.
  • 책 시점의 낡은 기법: 글리닝 등 일부 기법은 약한 모델 시절(책 출간 2024년 초반)의 보완책으로, 강의는 고성능 현대 모델에서는 상당수 무력화됐다고 평가한다 — 기법을 접할 때 "언제 왜 나온 기법인가"를 함께 봐야 한다.

⚠️ 주의: settings.yaml의 기본값(snapshots.embeddings: false 등)에 따라 책이 설명하는 산출물(그래프 임베딩 2D 좌표 등)이 생성되지 않을 수 있다. 버전 간 워크플로우 이름·산출물 스키마 차이를 항상 실물 parquet으로 확인하라.


8. 다른 접근과 비교

접근 특징 Graph RAG 대비
순수 임베딩 RAG(+리랭킹) 단편 지식 질문에 강함, 구축 간단 여러 청크 관통 질문·관계 추론 불가
Agentic AI 모델이 여러 턴 도구 호출로 스스로 수집·병합 같은 질문을 풀 수 있으나 시스템 스스로 해결하는 RAG가 아님 — Graph RAG는 미리 구조화해 단일 질의로 응답
BM25·앙상블(4주차) 키워드 정확 일치 보완 검색 정밀도 문제의 해법이지 관계·인사이트 질문의 해법이 아님
그래프 DB 수동 구축 스키마 통제력 최대 GraphRAG가 자동화해 주는 전 단계(추출~요약)를 수작업으로 해야 함
Prolog 계열 논리 언어 그래프·논리 자체를 언어화한 고전 접근 개념적 선조 격 — 현재는 그래프 DB + LLM 조합이 실용 노선

📚 참고: GraphRAG의 프롬프트·워크플로우 구성은 Microsoft GraphRAG 공식 저장소(https://github.com/microsoft/graphrag) 문서에서, Cypher와 벡터 인덱스 프로시저는 Neo4j 공식 문서(https://neo4j.com/docs/)에서 확인하라. Cypher는 세 페이지만 익혀도 이번 실습의 적재 구문을 전부 읽을 수 있다.


9. 메타인지 자기평가

  1. 기존 RAG가 답하지 못하는 질문 유형 두 가지를 예시와 함께 말할 수 있는가?
  2. MS GraphRAG 파이프라인 8단계(청킹~커뮤니티 요약)에서 LLM이 하는 일과 수학적 계산이 하는 일을 구분할 수 있는가?
  3. 커뮤니티 탐지에 쓰이는 두 알고리즘 이름과, 커뮤니티가 검색에 왜 필요한지 설명할 수 있는가?
  4. 리즈닝 모델을 GraphRAG에 연결하면 어떤 단계가 왜 실패하는지 재현 없이 설명할 수 있는가?
  5. graphrag query--method global--method local을 질문 유형에 따라 골라 쓸 수 있는가?
  6. "GraphRAG는 문서 파서다"라는 문장을 parquet·Neo4j·페이징 구조라는 단어를 써서 남에게 설명할 수 있는가?
  7. Neo4j 5.12 환경에서 벡터 인덱스를 만들 때 부딪히는 두 가지 제약(문법·차원)과 우회법을 말할 수 있는가?
  8. 지금 다니는 조직의 서비스 중 그래프 DB 도입이 정당한 곳과 과잉인 곳을 각각 하나씩 판단해 근거를 댈 수 있는가?
난이도
에피소드
질문
카드를 로딩 중...
답변

클릭하거나 Space를 눌러 뒤집기

0 / 0
학습 진도 0%
이동   Space 뒤집기   R 셔플   P 음성 버전 2026-07-29