GraphRAG 설치 & 인덱싱

JERRY·2025년 11월 20일

Project

목록 보기
3/14

GraphRAG 설치 & 인덱싱 구축 (Local 환경에서 구축한 전체 과정 정리)

감사(Audit) 보고서 기반 고급 검색·질의응답(QA) 시스템 구축을 위한 GraphRAG 실험 정리본
2025.11 — Local 환경에서 GraphRAG 전체 인덱싱 성공 기록

1. GraphRAG란 무엇인가?

기존 RAG(Retrieval-Augmented Generation)는 텍스트 chunk 기반의 단순 검색이라
문서 간 관계·의미·구조적 흐름을 놓치는 문제가 존재함.

GraphRAG는 다음을 제공함:

기능설명
Graph 기반 Semantic Search문서에서 엔티티(조직·부서·사건 등)와 관계를 추출하여 지식그래프 구축
Community Summaries문서들의 핵심 클러스터를 자동 요약
전역(Global) 검색질문과 직접 관련된 문서 뿐 아니라 연관된 개념까지 확장 검색
정밀 감사/규정 문서 검색에 최적화규정 간 연결, 지적사항–원인–영향 구조 분석 가능

1) 일반 RAG vs GraphRAG

구분일반 RAGGraphRAG
검색 방식벡터 유사도 기반지식 그래프 탐색 기반
문맥 이해문장 중심엔티티 및 관계 중심
설명 가능성약함문제–원인–조치 관계에서 근거 제시 가능
활용단순 답변형 챗봇설명형, 구조화된 감사 보고서 보조

2) 감사 보고서 형식과 GraphRAG의 적합성

공공기관 감사보고서는 일반적으로 아래와 같은 구조를 가집니다:
1. 지적사항
2. 원인
3. 관련 규정 위반
4. 조치/처분
5. 동일/유사사례

이런 관계형 텍스트를 GraphRAG가 아래와 같이 효과적으로 처리합니다:

  • 엔티티 추출 → 문제, 원인, 규정, 금액, 처분
  • 관계 연결 → 문제 ↔ 규정 위반 / 문제 ↔ 조치
  • 저장 형태 → 지식그래프 (노드 + 관계)
  • 검색 시 → 유사/관련 노드 중심으로 추론형 답변 생성

2.프로젝트 폴더 구조

graphrag_project/
 ├─ settings.yaml        # GraphRAG 전체 파이프라인 설정 파일
 ├─ .env                 # API Key 저장
 ├─ input/               # PDF 또는 TXT 입력
 ├─ input_txt/           # 변환된 텍스트 임시 저장
 ├─ output/              # 결과물 (지식그래프, 요약, 인덱스 등)
 ├─ scripts/
 │     └─ pdf_to_txt.py  # PDF → TXT 변환
 ├─ run_all.bat          # 전체 자동 실행 스크립트

3. GraphRAG 설치 과정

1) Conda 가상환경 만들기

conda create -n graphrag_env python=3.11 -y
conda activate graphrag_env

2) GraphRAG 설치 (2.2.0 기준)

pip install graphrag==2.2.0

3) Graph 인덱싱 실행

  • 프로젝트 폴더를 생성 : graphrag_project

  • GraphRAG 설정 파일 생성 : graphrag init

  • PDF 파일을 아래 폴더에 복사

    graphrag_project/input/pdfs

4. .env 설정

GRAPHRAG_API_KEY=********************
OPENAI_API_KEY=********************
OPENAI_API_BASE=https://api.openai.com/v1
OPENAI_API_TYPE=openai

5. settings.yaml 수정

  • 엔티티 스키마(기관/부서/문제점/원인/영향/조치사항 등)
  • 관계 스키마(관련됨/위반/원인/영향/법령근거/부적정집행 등)
  • 클러스터링 종류(Louvain)
  • 텍스트 splitter 크기
  • 요약 구조(사실·문제점·원인·영향 등)
version: "1.0"

root: .
encoding: utf-8

models:
  llm:
    type: openai_chat
    model: gpt-4o-mini
    api_key: ${OPENAI_API_KEY}

  embedding:
    type: openai_embedding
    model: text-embedding-3-small
    api_key: ${OPENAI_API_KEY}

  default_chat_model:
    type: openai_chat
    model: gpt-4o-mini
    api_key: ${OPENAI_API_KEY}

  default_embedding_model:
    type: openai_embedding
    model: text-embedding-3-small
    api_key: ${OPENAI_API_KEY}

input:
  type: file
  file_type: text
  base_dir: "input"

output:
  base_dir: "output"

6. prompts 수정

                  ┌───────────────────────────────┐
                  │          PDF / TEXT         │
                  └───────────────────────────────┘
                                 │
                                 ▼
       ┌─────────────────────────────────────────────────────┐
       │                인덱싱 단계 (Indexing)            │
       └─────────────────────────────────────────────────────┘
                                 │
                           extract_graph
                           extract_claims
                       summarize_descriptions
                     question_gen_system_prompt
                                 ↓
                        community detection
                                 ↓
           community_report_graph / community_report_text
                                 ↓
       ┌─────────────────────────────────────────────────────┐
       │                검색 단계 (Query)                 │
       └─────────────────────────────────────────────────────┘
                      basic_search_system_prompt
                      local_search_system_prompt
         global_search_map / reduce / knowledge prompt
                 drift_search / drift_reduce_prompt
프롬프트역할
extract_graph엔티티/관계 추출
extract_claims핵심 주장(Claim) 추출
summarize_descriptions엔티티 설명 요약
community_report_graph그래프 기반 커뮤니티 보고서
community_report_text텍스트 기반 커뮤니티 보고서
question_gen_system_prompt문서 기반 질문 생성
basic_search_system_prompt기본 검색 프롬프트
local_search_system_prompt특정 문서/클러스터 범위 검색
global_search_map_system_prompt전역 검색 MAP 단계
global_search_reduce_system_prompt전역 검색 REDUCE 단계
global_search_knowledge_system_prompt전역 지식 요약
drift_search_system_prompt시계열 변화(드리프트) 검색
drift_reduce_prompt드리프트 요약

7. PDF → TXT 변환 자동화 (pdf_to_txt.py)

감사 보고서는 표·회계항목이 많고 PDF 구조가 복잡하여 PDF 파싱 오류가 발생할 수 있음
이를 자동 필터링/로그 기록하도록 구성

  • TXT가 이미 존재하면 재변환하지 않음
  • 깨진 PDF 오류 무시하고 다음 파일로 계속 진행

pdf_to_txt.py

import os
import sys
import pdfplumber

def convert_pdf_to_txt(pdf_path, txt_path):
    """PDF → TXT 변환 함수"""
    try:
        with pdfplumber.open(pdf_path) as pdf:
            text = ""
            for page in pdf.pages:
                text += page.extract_text() or ""
    except Exception as e:
        print(f"[ERROR] 변환 실패 → {pdf_path} | {e}")
        return False

    # 저장
    with open(txt_path, "w", encoding="utf-8") as f:
        f.write(text)
    return True


def main(pdf_dir, txt_temp_dir, final_txt_dir):
    print(f"[INFO] PDF 폴더: {pdf_dir}")
    print(f"[INFO] TXT 생성 폴더(temp): {txt_temp_dir}")
    print(f"[INFO] TXT 이동 폴더(final): {final_txt_dir}")

    # 폴더 생성
    os.makedirs(txt_temp_dir, exist_ok=True)
    os.makedirs(final_txt_dir, exist_ok=True)

    # PDF 목록 읽어오기
    pdf_files = [f for f in os.listdir(pdf_dir) if f.lower().endswith(".pdf")]
    print(f"[INFO] 변환 대상 PDF 총 {len(pdf_files)}개")

    converted_count = 0
    skipped_count = 0

    for pdf_file in pdf_files:
        pdf_path = os.path.join(pdf_dir, pdf_file)
        txt_filename = os.path.splitext(pdf_file)[0] + ".txt"
        final_txt_path = os.path.join(final_txt_dir, txt_filename)

        # 이미 존재하는 TXT는 건너뛰기 (옵션 B의 핵심)
        if os.path.exists(final_txt_path):
            skipped_count += 1
            print(f"[SKIP] 이미 존재 → {txt_filename}")
            continue

        print(f"[INFO] 변환 중 → {pdf_file}")
        tmp_txt_path = os.path.join(txt_temp_dir, txt_filename)

        if convert_pdf_to_txt(pdf_path, tmp_txt_path):
            # 최종 txt 폴더로 이동
            os.replace(tmp_txt_path, final_txt_path)
            converted_count += 1
        else:
            print(f"[ERROR] 변환 실패: {pdf_file}")

    print("===============================================")
    print(f"[INFO] 새로 변환된 TXT: {converted_count}개")
    print(f"[INFO] 스킵된 PDF (이미 TXT 존재): {skipped_count}개")
    print("===============================================")


if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("사용법: python pdf_to_txt.py <PDF_DIR> <TEMP_TXT_DIR> <FINAL_TXT_DIR>")
        sys.exit(1)

    main(sys.argv[1], sys.argv[2], sys.argv[3])

8. 전체 자동화 실행 코드 (run_all.bat)

아래의 작업이 한번에 수행 됨

  • conda 환경 활성화
  • .env 로드
  • PDF→TXT 변환
  • GraphRAG 인덱싱 실행
  • output 생성

run_all.bat

@echo off
setlocal enabledelayedexpansion
chcp 65001 >nul

echo ===============================================
echo   PDF → TXT 변환 + GraphRAG Indexing 자동화
echo ===============================================
echo 현재 작업 디렉토리: %cd%
echo.

REM ----------------------------------------------------
REM 1. Conda 환경 확인
REM ----------------------------------------------------
echo [1/6] Conda 환경 확인 중...
conda env list | findstr /c:"audit_graphrag" >nul
if %ERRORLEVEL% NEQ 0 (
    echo [ERROR] audit_graphrag 환경이 존재하지 않습니다.
    pause
    exit /b
)
echo [OK] audit_graphrag 환경 발견
echo.

REM ----------------------------------------------------
REM 2. Conda 환경 활성화 (정상 작동 방식)
REM ----------------------------------------------------
echo [2/6] Conda 환경 활성화...
call C:\Users\Administrator\anaconda3\Scripts\activate.bat audit_graphrag

if %ERRORLEVEL% NEQ 0 (
    echo [ERROR] conda activate 실패
    pause
    exit /b
)
echo [OK] conda activate 완료
echo.

REM ----------------------------------------------------
REM 3. .env 파일 로딩
REM ----------------------------------------------------
echo [3/6] .env 파일 로딩 중...
for /f "usebackq tokens=1,* delims==" %%a in (".env") do (
    set %%a=%%b
)
echo [OK] API Key 로딩 완료
echo.

REM ----------------------------------------------------
REM 4. PDF → TXT 변환 수행 (신규/없는 TXT만 처리)
REM ----------------------------------------------------
echo [4/6] PDF → TXT 변환 준비 중...
echo TXT는 없는 파일만 생성됩니다.
echo.

python scripts\pdf_to_txt.py input input_txt input

if %ERRORLEVEL% NEQ 0 (
    echo [ERROR] PDF → TXT 변환 실패
    pause
    exit /b
)
echo [OK] PDF → TXT 변환 완료
echo.

REM ----------------------------------------------------
REM 5. GraphRAG Indexing 실행
REM ----------------------------------------------------
echo [5/6] GraphRAG Indexing 실행...
echo 시작 시간: %date% %time%
echo.

graphrag index --root . --verbose

if %ERRORLEVEL% NEQ 0 (
    echo [ERROR] GraphRAG Indexing 실패
    pause
    exit /b
)

echo [OK] GraphRAG Indexing 완료!
echo.
pause

GraphRAG 인덱싱 단계 (자동 처리 과정)

단계설명output 위치
1️⃣ 텍스트 chunking텍스트를 토큰 단위로 분할output/chunks/
2️⃣ 임베딩 생성embedding 모델로 각 chunk 벡터화output/embeddings/
3️⃣ 그래프 추출엔티티·관계 분석 → 지식그래프 생성output/graph/
4️⃣ community detection문서 클러스터링output/graph/communities
5️⃣ summary 생성각 클러스터별 의미 요약output/community_reports/
6️⃣ 검색 인덱스 구축local·global search용 DBoutput/search_index/

최종 Output 폴더 구조 및 활용

output/
  ├─ entities.json
  ├─ relationships.json
  ├─ graph/
  ├─ summaries/
  ├─ embeddings/
  ├─ community_reports/
  ├─ search_index/
  • 활용 방식

    파일용도
    entities.json문서에서 추출된 엔티티 목록
    relationships.json엔티티 간 연결 (기관–규정, 문제점–원인 등)
    community_reports/그래프 클러스터 별 자동 요약 → QA 답변 구성 근거로 사용
    search_index/Streamlit QA 앱에서 실제로 사용되는 검색 DB
    embeddings/Fast search용 chunk 벡터

9. 다음 작업 : Streamlit QA 앱으로 연결

완성된 output 디렉토리를 기반으로 GraphRAG 기반 지역+전역 검색(Local+Global Search) QA 시스템을 바로 만들 예정

0개의 댓글