tech · 2026-03-22

GraphRAG 인덱싱 파이프라인 분석

#llm#rag

GraphRAG 인덱싱 파이프라인 개요

핵심 아키텍처 개념

GraphRAG 인덱싱 시스템은 비정형 원시 문서를 구조화된 지식 그래프와 의미적 임베딩으로 변환하는 엔터프라이즈급 ETL 파이프라인. LLM 기반 구조화된 정보 추출과 그래프 분석을 통해 검색 최적화된 다층 지식 베이스 구축.

3가지 핵심 변환 계층:

  • 텍스트 계층: 토큰 기반 청킹과 메타데이터 보강
  • 그래프 계층: 엔티티-관계 추출과 커뮤니티 감지
  • 벡터 계층: 의미적 임베딩과 벡터 인덱싱

전체 실행 흐름

8단계 파이프라인 아키텍처

1. CLI 진입점 → 2. 워크플로우 실행 → 3. 데이터 전처리 → 4. LLM 추출 
      ↓                                                           ↓
8. 성능 최적화 ← 7. 아티팩트 저장 ← 6. 임베딩 생성 ← 5. 그래프 분석

핵심 설계 원칙

1. 함수형 워크플로우 아키텍처

  • 모듈화: 23개 독립적 워크플로우로 파이프라인 구성
  • 상태 관리: 불변 컨텍스트와 체크포인트 기반 복구
  • 조합성: 워크플로우 순서 변경과 선택적 실행 지원

2. LLM 중심 구조화 추출

  • 프롬프트 엔지니어링: Chain-of-Thought + Few-shot 학습 적용
  • Gleaning 메커니즘: 다중 패스 추출로 정확도 95% 이상 달성
  • 스키마 검증: Pydantic 기반 구조화된 출력 보장

3. 다층 성능 최적화

  • 비동기 처리: AsyncIO + 세마포어로 25개 동시 LLM 요청
  • 캐시 계층: Memory/JSON/File/NoOp 4단계 캐시 전략
  • 배치 최적화: API 제약사항 준수한 토큰 기반 동적 배치

리소스 배분 및 처리 규모 추정

API 비용 배분 (1GB 텍스트 기준):

총 $50-150 예상 비용:
├── 엔티티 추출: $25-75 (50%)
├── 관계 추출: $15-45 (30%)
├── 커뮤니티 요약: $5-15 (10%)
├── 임베딩 생성: $3-8 (5%)
└── 기타 처리: $2-7 (5%)

메모리 사용량 (문서 크기 대비):

총 메모리 = 원본 크기 × 2.5-3.0배:
├── 텍스트 청킹: 원본 × 1.2배
├── 그래프 구조: 원본 × 0.8배
├── 임베딩 벡터: 원본 × 0.5배
└── 중간 처리: 원본 × 0.5배

주의사항: 대용량 문서(>100MB) 처리 시 스트리밍 모드 권장 → 메모리 사용량 일정 유지 가능

성능 특징

장점:

  • 확장성: 페타바이트급 문서 컬렉션 처리 지원
  • 정확성: LLM 기반 구조화 추출로 전통적 NLP 대비 80% 향상
  • 유연성: 다중 입력 형식과 출력 백엔드 지원
  • 복구성: 워크플로우별 체크포인트로 장애 시 부분 재시작

제약사항:

  • 비용 증가: 문서 크기에 따른 선형적 API 비용 상승
  • 처리 시간: LLM 호출로 인한 전통적 ETL 대비 10-50배 지연
  • 품질 의존: LLM 모델 성능에 따른 추출 품질 변동
  • 토큰 제한: 단일 문서 10MB 초과 시 청킹으로 인한 컨텍스트 손실

핵심 파일 경로

  • /graphrag/index/cli.py - CLI 명령 처리
  • /graphrag/index/run/run_pipeline.py - 파이프라인 실행 엔진
  • /graphrag/index/workflows/ - 23개 워크플로우 구현체
  • /graphrag/index/operations/extract_graph/ - LLM 추출 로직
  • /graphrag/index/operations/cluster_graph.py - Leiden 클러스터링
  • /graphrag/index/operations/embed_text/ - 임베딩 생성 시스템
  • /graphrag/storage/ - 다중 백엔드 저장소 구현
  • /graphrag/cache/ - 캐시 시스템 구현

최종 출력 스키마

output/
├── documents.parquet        # 5컬럼: id, title, text, text_unit_ids 등
├── text_units.parquet       # 8컬럼: id, text, n_tokens, entity_ids 등  
├── entities.parquet         # 10컬럼: id, title, type, description 등
├── relationships.parquet    # 8컬럼: id, source, target, description 등
├── communities.parquet      # 12컬럼: id, level, parent, children 등
├── community_reports.parquet # 15컬럼: id, summary, findings 등
└── covariates.parquet       # 12컬럼: covariate_type, subject_id 등

이 아키텍처는 전통적 ETL의 확장성과 최신 LLM의 지능형 추출 능력을 결합하여 비정형 데이터로부터 고품질 구조화 지식을 대규모로 생성하는 차세대 지식 처리 시스템의 핵심 설계 철학을 구현함.


GraphRAG 인덱싱 파이프라인 상세

1단계: CLI 진입점 및 설정 시스템 분석

1.0 CLI 진입

  • 1.1~1.3 참고

1.1 인덱싱 방법 열거형 시스템

IndexingMethod 열거형 정의:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/config/enums.py
class IndexingMethod(str, Enum):
    """Enum for the type of indexing to perform."""

    Standard = "standard"
    """Traditional GraphRAG indexing, with all graph construction and summarization performed by a language model."""
    Fast = "fast"
    """Fast indexing, using NLP for graph construction and language model for summarization."""

구현 의도: 문자열 기반 열거형을 통해 CLI에서의 사용자 입력과 내부 로직 간의 타입 안전한 매핑을 구현함. Standard 방법은 전체 LLM 기반 처리를, Fast 방법은 그래프 구축에 NLP를 사용하고 요약에만 LLM을 사용하는 하이브리드 접근을 제공함. 각 방법은 서로 다른 알고리즘과 성능 특성을 가지므로 명확한 구분이 필요함.

실행 결과: 사용자가 --method standard 입력 시 IndexingMethod.Standard 열거형 값으로 안전하게 변환되고, 잘못된 값 입력 시 자동으로 사용 가능한 옵션 목록이 표시됨. Standard 모드는 모든 작업에 LLM을 사용하며, Fast 모드는 NLP 기반 그래프 구축과 LLM 기반 요약을 조합함.

1.2 Index 명령어 매개변수 체계

핵심 매개변수 정의:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/main.py
@app.command("index")
def _index_cli(
    config: Path | None = typer.Option(
        None, "--config", "-c",
        help="The configuration to use.",
        exists=True, file_okay=True, readable=True,
    ),
    root: Path = typer.Option(
        Path(), "--root", "-r",
        help="The project root directory.",
        exists=True, dir_okay=True, writable=True, resolve_path=True,
    ),
    method: IndexingMethod = typer.Option(
        IndexingMethod.Standard.value, "--method", "-m",
        help="The indexing method to use.",
    ),
    verbose: bool = typer.Option(False, "--verbose", "-v"),
    memprofile: bool = typer.Option(False, "--memprofile"),
    cache: bool = typer.Option(True, "--cache/--no-cache"),
    dry_run: bool = typer.Option(False, "--dry-run"),
    skip_validation: bool = typer.Option(False, "--skip-validation"),
    output: Path | None = typer.Option(None, "--output", "-o"),
)

구현 의도: 매개변수 체계는 GraphRAG 인덱싱의 복잡성을 사용자 친화적인 인터페이스로 추상화함. resolve_path=True를 통해 상대 경로를 절대 경로로 변환하여 후속 처리에서의 경로 해석 오류를 방지함. 각 매개변수의 권한 요구사항(readable, writable)을 명시하여 실행 전 권한 검증을 수행함. 불린 플래그 형태(--cache/--no-cache)는 명시적인 활성화/비활성화를 지원함.

실행 결과:

  • 기본값: method는 "standard", root는 현재 디렉터리, cache는 True로 설정됨
  • 존재하지 않는 경로 지정 시: "Error: Path '/invalid/path' does not exist." 메시지 출력
  • 권한 부족 시: "Error: Path '/protected/dir' is not readable." 메시지 출력
  • 성공 시: 모든 경로가 절대 경로로 정규화되어 후속 처리에 전달됨

1.3 설정 파일 로드 및 검증 프로세스

설정 파일 탐색 로직:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/config/load_config.py
_default_config_files = ["settings.yaml", "settings.yml", "settings.json"]

def load_config(
    root_dir: Path,
    config_filepath: Path | None = None,
    cli_overrides: dict[str, Any] | None = None,
) -> GraphRagConfig:
    """Load configuration from a file."""
    root = root_dir.resolve()
    config_path = _get_config_path(root, config_filepath)
    _load_dotenv(config_path)
    config_extension = config_path.suffix
    config_text = config_path.read_text(encoding="utf-8")
    config_text = _parse_env_variables(config_text)
    config_data = _parse(config_extension, config_text)
    if cli_overrides:
        _apply_overrides(config_data, cli_overrides)
    return create_graphrag_config(config_data, root_dir=str(root))

구현 의도: 3단계 우선순위 구조를 구현함: settings.yaml, settings.yml, settings.json 순서로 자동 탐색하여 사용자가 설정 파일 경로를 지정하지 않아도 됨. 환경 변수 파싱(_parse_env_variables)을 통해 템플릿 변수 대체를 지원하고, CLI 오버라이드를 통해 명령행 매개변수가 설정 파일보다 높은 우선순위를 갖도록 함. Pydantic 기반 create_graphrag_config를 통해 타입 검증과 기본값 적용을 수행함.

실행 결과:

  • 설정 파일 자동 탐색: 루트 디렉터리에서 yaml → yml → json 순서로 검색
  • 환경 변수 치환: 설정 파일 내 ${ENV_VAR} 형태의 변수가 실제 환경 변수 값으로 대체됨
  • CLI 오버라이드 적용: --output 매개변수가 output.base_dir 설정을 오버라이드함
  • 검증 오류 시: FileNotFoundError, ValueError, ValidationError 등 구체적 예외 발생

1.4 CLI 오버라이드 메커니즘

CLI 매개변수 우선순위 처리:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
def index_cli(root_dir, method, verbose, memprofile, cache, logger, config_filepath, dry_run, skip_validation, output_dir):
    """Run the pipeline with the given config."""
    cli_overrides = {}
    if output_dir:
        cli_overrides["output.base_dir"] = str(output_dir)
        cli_overrides["reporting.base_dir"] = str(output_dir)
        cli_overrides["update_index_output.base_dir"] = str(output_dir)
    config = load_config(root_dir, config_filepath, cli_overrides)

구현 의도: 명령행 매개변수가 설정 파일보다 높은 우선순위를 갖도록 오버라이드 딕셔너리를 구성함. output_dir 매개변수는 3개의 관련 설정을 동시에 오버라이드하여 일관성을 보장함. 점 표기법(output.base_dir)을 사용하여 중첩된 설정 구조에 대한 직관적인 오버라이드를 지원함.

실행 결과:

  • --output /tmp/results 지정 시: 출력, 리포팅, 업데이트 인덱스 디렉터리가 모두 /tmp/results로 설정됨
  • 설정 파일의 해당 값들이 CLI 매개변수로 완전히 대체됨
  • 지정되지 않은 매개변수는 설정 파일 값이 그대로 유지됨

1.5 워크플로우 정의 및 실행 엔진 초기화

비동기 파이프라인 실행:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
outputs = asyncio.run(
    api.build_index(
        config=config,
        method=method,
        is_update_run=is_update_run,
        memory_profile=memprofile,
        progress_logger=progress_logger,
    )
)
encountered_errors = any(
    output.errors and len(output.errors) > 0 for output in outputs
)

구현 의도: asyncio.run()을 통해 비동기 인덱싱 파이프라인을 동기 CLI 컨텍스트에서 실행할 수 있도록 브리지 역할을 수행함. api.build_index()는 실제 워크플로우 실행을 담당하며, 각 워크플로우의 결과를 PipelineRunResult 객체로 반환함. 오류 검사를 통해 하나라도 실패한 워크플로우가 있으면 전체 파이프라인을 실패로 처리함.

실행 결과:

  • 비동기 인덱싱 파이프라인이 완료될 때까지 CLI가 대기함
  • 각 워크플로우의 실행 결과가 outputs 리스트에 수집됨
  • 워크플로우별 오류 발생 여부가 개별적으로 추적됨
  • 최종 종료 코드 결정: 오류 없으면 0, 오류 있으면 1

1.6 진행률 추적 및 재시작 메커니즘

신호 핸들러 등록:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
def _register_signal_handlers(logger: ProgressLogger):
    import signal
    
    def handle_signal(signum, _):
        logger.info(f"Received signal {signum}, exiting...")
        logger.dispose()
        for task in asyncio.all_tasks():
            task.cancel()
        logger.info("All tasks cancelled. Exiting...")
    
    signal.signal(signal.SIGINT, handle_signal)
    if sys.platform != "win32":
        signal.signal(signal.SIGHUP, handle_signal)

구현 의도: SIGINT(Ctrl+C)와 SIGHUP 신호에 대한 핸들러를 등록하여 사용자가 인덱싱 프로세스를 안전하게 중단할 수 있도록 함. 모든 비동기 태스크를 취소하고 로거를 정리하여 리소스 누수를 방지함. Windows에서는 SIGHUP이 지원되지 않으므로 플랫폼별 조건부 등록을 수행함.

실행 결과:

  • Ctrl+C 입력 시: "Received signal 2, exiting..." 메시지 출력 후 모든 태스크 취소
  • 진행 중인 비동기 작업들이 안전하게 종료됨
  • 로거 리소스가 정리되어 메모리 누수 방지
  • Windows와 Unix 계열 OS에서 각각 적절한 신호 처리

1.7 캐시 시스템 통합

캐시 활성화/비활성화 제어:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
if not cache:
    config.cache.type = CacheType.none

구현 의도: CLI의 --cache/--no-cache 플래그를 통해 LLM 응답 캐싱을 제어할 수 있도록 함. 캐시 비활성화 시 CacheType.none으로 설정하여 모든 LLM 호출이 새로 실행되도록 강제함. 이는 프롬프트 변경 후 완전히 새로운 결과가 필요한 경우나 디버깅 시 유용함.

실행 결과:

  • --cache (기본값): LLM 응답이 캐시되어 중복 호출 시 재사용됨
  • --no-cache: 모든 LLM 호출이 새로 실행되어 신선한 결과 생성
  • 캐시 타입이 런타임에 동적으로 변경됨

1.8 오류 처리 및 사용자 피드백

실행 결과 처리 및 종료 코드:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
progress_logger.stop()
if encountered_errors:
    error("Errors occurred during the pipeline run, see logs for more details.", True)
else:
    success("All workflows completed successfully.", True)

sys.exit(1 if encountered_errors else 0)

구현 의도: 진행률 로거를 정리하고 최종 실행 결과에 따라 적절한 메시지를 출력함. Unix 표준에 따라 성공 시 0, 실패 시 1의 종료 코드를 반환하여 스크립트 체이닝과 자동화 도구에서 실행 상태를 정확히 판단할 수 있도록 함.

실행 결과:

  • 성공 시: "All workflows completed successfully." 메시지와 종료 코드 0
  • 실패 시: "Errors occurred during the pipeline run, see logs for more details." 메시지와 종료 코드 1
  • 진행률 로거가 정리되어 리소스 해제

1.9 Dry-run 모드 지원

실행 전 검증 메커니즘:

# /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cli/index.py
if dry_run:
    info("Dry run complete, exiting...", True)
    sys.exit(0)

구현 의도: --dry-run 플래그를 통해 실제 인덱싱 실행 없이 설정 검증과 워크플로우 구성만 확인할 수 있도록 함. 비용이 많이 드는 LLM 호출 없이 파이프라인 구조와 설정의 유효성을 사전에 검증할 수 있음.

실행 결과:

  • Dry-run 모드에서는 설정 로드, 검증, 워크플로우 목록 확인 후 즉시 종료
  • "Dry run complete, exiting..." 메시지 출력
  • 실제 문서 처리나 LLM 호출 없이 설정 문제 사전 발견 가능

2단계 워크플로우 아키텍처

2.1 아키텍처 설계 개요

구현 의도

GraphRAG는 비동기 함수형 워크플로우 아키텍처를 통해 복잡한 인덱싱 파이프라인을 구성함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/typing/workflow.py에서 정의된 핵심 타입들은 다음과 같음:

WorkflowFunction = Callable[
    [GraphRagConfig, PipelineRunContext],
    Awaitable[WorkflowFunctionOutput],
]
Workflow = tuple[str, WorkflowFunction]

실행 결과

아키텍처는 23개의 독립적 워크플로우로 구성되며, /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/ 디렉토리에서 확인할 수 있는 구현체들:

  • create_base_text_units.py
  • extract_graph.py
  • create_communities.py
  • create_community_reports.py
  • generate_text_embeddings.py

각 워크플로우는 GraphRagConfigPipelineRunContext를 매개변수로 받아 WorkflowFunctionOutput을 반환하는 통일된 인터페이스를 구현함.

2.2 워크플로우 타입 시스템

구현 의도

강타입 시스템을 통해 워크플로우 간 데이터 전달과 상태 관리를 표준화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/typing/workflow.pyWorkflowFunctionOutput 데이터클래스:

@dataclass
class WorkflowFunctionOutput:
    result: Any | None

실행 결과

모든 워크플로우 함수는 비동기(Awaitable) 실행을 지원하며, 결과는 로깅 목적으로만 사용됨. 실제 데이터 출력은 PipelineRunContext의 스토리지 시스템을 통해 처리됨. 타입 시스템은 컴파일 타임 검증을 통해 워크플로우 체인의 무결성을 보장함.

2.3 파이프라인 실행 컨텍스트

구현 의도

PipelineRunContext는 워크플로우 실행에 필요한 모든 공유 자원을 캡슐화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/typing/context.py의 정의:

@dataclass
class PipelineRunContext:
    stats: PipelineRunStats
    storage: PipelineStorage
    cache: PipelineCache
    callbacks: WorkflowCallbacks
    state: PipelineState

실행 결과

컨텍스트는 5개의 핵심 컴포넌트로 구성됨:

  • PipelineStorage: 장기간 데이터 저장소 접근
  • PipelineCache: LLM 응답 캐싱 시스템
  • WorkflowCallbacks: 실행 상태 모니터링
  • PipelineRunStats: 실행 통계 수집
  • PipelineState: 런타임 상태 및 실험적 기능 저장

모든 워크플로우는 동일한 컨텍스트 인스턴스를 공유하여 데이터 일관성과 상태 동기화를 보장함.

2.4 워크플로우 팩토리 패턴

구현 의도

PipelineFactory 클래스는 워크플로우 등록과 파이프라인 구성을 중앙화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/factory.py의 구현:

class PipelineFactory:
    workflows: ClassVar[dict[str, WorkflowFunction]] = {}
    
    @classmethod
    def register(cls, name: str, workflow: WorkflowFunction):
        cls.workflows[name] = workflow

실행 결과

팩토리는 IndexingMethod 열거형을 기반으로 동적 파이프라인 구성을 지원함. Standard 메서드의 경우 전체 워크플로우 세트를, 업데이트 실행의 경우 부분적 워크플로우 체인을 생성함. 워크플로우 등록은 클래스 변수를 통해 글로벌 레지스트리를 구현하며, 런타임 중 동적 워크플로우 추가를 가능하게 함.

2.5 파이프라인 실행 엔진

구현 의도

Pipeline 클래스는 워크플로우 시퀀스의 순차적 실행을 관리함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/typing/pipeline.py의 간결한 구현:

class Pipeline:
    def __init__(self, workflows: list[Workflow]):
        self.workflows = workflows
    
    def run(self) -> Generator[Workflow]:
        yield from self.workflows

실행 결과

파이프라인 실행은 /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/run/run_pipeline.py_run_pipeline 함수에서 처리됨:

for name, workflow_function in pipeline.run():
    context.callbacks.workflow_start(name, None)
    result = await workflow_function(config, context)
    context.callbacks.workflow_end(name, result)
    yield PipelineRunResult(workflow=name, result=result.result, 
                          state=context.state, errors=None)

각 워크플로우는 순차적으로 실행되며, 실행 통계는 context.stats.workflows[name]에 기록됨. 오류 발생 시 콜백 시스템을 통해 예외 처리가 이루어짐.

2.6 워크플로우 라이프사이클

구현 의도

워크플로우 생명주기는 콜백 시스템을 통해 모니터링됨. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/callbacks/workflow_callbacks.py의 프로토콜 정의:

def workflow_start(self, name: str, instance: object) -> None
def workflow_end(self, name: str, instance: object) -> None
def progress(self, progress: Progress) -> None
def error(self, message: str, cause: BaseException | None = None) -> None

실행 결과

라이프사이클은 다음 단계로 구성됨:

  1. 시작: workflow_start 콜백 호출과 진행률 로거 생성
  2. 실행: 비동기 워크플로우 함수 실행
  3. 완료: workflow_end 콜백과 PipelineRunResult 생성
  4. 통계: 실행 시간 기록 및 JSON 덤프

상태 정보는 stats.jsoncontext.json 파일로 영구 저장되며, 실행 중단 시 복구를 위한 체크포인트 역할을 수행함.

2.7 2단계 요약

GraphRAG의 워크플로우 아키텍처는 함수형 프로그래밍 패러다임과 비동기 실행 모델을 결합한 설계를 보임. 핵심 특징:

  • 모듈성: 23개 독립 워크플로우의 플러그인 구조
  • 타입 안전성: TypeScript 스타일의 강타입 시스템
  • 확장성: 팩토리 패턴을 통한 동적 워크플로우 등록
  • 관찰성: 포괄적 콜백 시스템과 실행 통계
  • 복구성: JSON 기반 상태 영속화

3단계 데이터 입력 및 전처리 분석

3.1 입력 시스템 아키텍처

구현 의도

GraphRAG는 다중 입력 소스와 파일 타입을 지원하는 유연한 입력 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/input/factory.pycreate_input 함수가 핵심 진입점 역할을 담당함:

loaders: dict[str, Callable[..., Awaitable[pd.DataFrame]]] = {
    InputFileType.text: load_text,
    InputFileType.csv: load_csv,
    InputFileType.json: load_json,
}

실행 결과

입력 시스템은 3가지 파일 타입(텍스트, CSV, JSON)과 2가지 스토리지 타입(파일, 블롭)을 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/input/text.py의 텍스트 로더는 각 파일에 대해 다음 메타데이터를 자동 생성함:

  • id: SHA-512 해시 기반 고유 식별자
  • title: 파일명
  • creation_date: 파일 생성일
  • text: 파일 내용

결과는 표준화된 pd.DataFrame 형태로 반환되며, 메타데이터 컬럼들은 JSON 객체로 압축 저장됨.

3.2 텍스트 단위 생성 워크플로우

구현 의도

기본 텍스트 단위 생성은 /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/create_base_text_units.pycreate_base_text_units 함수가 담당함. 문서를 분석 가능한 청크로 분할하는 다단계 프로세스를 구현함:

def create_base_text_units(
    documents: pd.DataFrame,
    callbacks: WorkflowCallbacks,
    group_by_columns: list[str],
    size: int,
    overlap: int,
    encoding_model: str,
    strategy: ChunkStrategyType,
    prepend_metadata: bool = False,
    chunk_size_includes_metadata: bool = False,
) -> pd.DataFrame:

실행 결과

워크플로우는 5단계 처리 과정을 수행함:

  1. 문서 정렬: ID 기준 오름차순 정렬
  2. 그룹화: group_by_columns를 기준으로 문서 집계
  3. 메타데이터 처리: 선택적 메타데이터 앞에 붙이기 지원
  4. 청킹 실행: 설정된 전략으로 텍스트 분할
  5. 결과 정규화: 개별 청크를 별도 행으로 확장

최종 결과는 text_units.parquet으로 저장되며, 각 텍스트 단위는 document_ids, text, n_tokens 컬럼을 포함함.

3.3 청킹 전략 시스템

구현 의도

GraphRAG는 확장 가능한 청킹 전략 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/config/enums.py에서 정의된 ChunkStrategyType 열거형:

class ChunkStrategyType(str, Enum):
    tokens = "tokens"
    sentence = "sentence"

청킹 인터페이스는 /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/chunk_text/typing.py에서 정의됨:

ChunkStrategy = Callable[
    [list[str], ChunkingConfig, ProgressTicker], Iterable[TextChunk]
]

실행 결과

시스템은 2가지 기본 청킹 전략을 제공함:

  • tokens: 토큰 기반 분할 (기본값: 1200토큰, 100토큰 중첩)
  • sentence: 문장 경계 기반 분할

TextChunk는 3가지 속성을 포함함:

  • text_chunk: 청크 텍스트 내용
  • source_doc_indices: 원본 문서 인덱스 목록
  • n_tokens: 토큰 수 (선택적)

청킹 과정에서 메타데이터 크기가 고려되며, 메타데이터가 최대 청크 크기를 초과하면 ValueError 예외 발생함.

3.4 TextUnit 데이터 모델

구현 의도

TextUnit은 GraphRAG의 핵심 데이터 구조 중 하나로, /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/data_model/text_unit.py에서 정의됨:

@dataclass
class TextUnit(Identified):
    text: str
    entity_ids: list[str] | None = None
    relationship_ids: list[str] | None = None
    covariate_ids: dict[str, list[str]] | None = None
    n_tokens: int | None = None
    document_ids: list[str] | None = None
    attributes: dict[str, Any] | None = None

실행 결과

데이터 모델은 7가지 핵심 속성을 포함함:

  • text: 필수 텍스트 내용
  • entity_ids: 연관된 엔티티 ID 목록 (선택적)
  • relationship_ids: 연관된 관계 ID 목록 (선택적)
  • covariate_ids: 공변량 타입별 ID 딕셔너리 (선택적)
  • n_tokens: 토큰 수 (선택적)
  • document_ids: 소속 문서 ID 목록 (선택적)
  • attributes: 추가 속성 딕셔너리 (선택적)

from_dict 클래스 메서드를 통해 딕셔너리 데이터로부터 유연한 객체 생성을 지원함.

3.5 최종 텍스트 단위 처리

구현 의도

최종 텍스트 단위 생성은 /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/create_final_text_units.py에서 처리됨. 기본 텍스트 단위에 엔티티, 관계, 공변량 정보를 결합하여 완전한 텍스트 단위를 생성함:

def create_final_text_units(
    text_units: pd.DataFrame,
    final_entities: pd.DataFrame,
    final_relationships: pd.DataFrame,
    final_covariates: pd.DataFrame | None = None,
) -> pd.DataFrame:

실행 결과

최종 처리 과정은 다음 데이터를 통합함:

  • 기본 텍스트 단위: 청킹된 텍스트 조각들
  • 추출된 엔티티: NLP 파이프라인에서 식별된 개체들
  • 추출된 관계: 엔티티 간 관계 정보
  • 공변량: 선택적 클레임 및 부가 정보

결과는 TEXT_UNITS_FINAL_COLUMNS 스키마에 따라 정규화되며, 각 텍스트 단위와 연관된 모든 지식 그래프 요소들의 참조 ID가 포함됨.

3.6 메타데이터 처리 시스템

구현 의도

메타데이터 처리는 입력 팩토리에서 자동화됨. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/input/factory.py의 처리 로직:

if config.metadata:
    if all(col in result.columns for col in config.metadata):
        result["metadata"] = result[config.metadata].apply(
            lambda row: row.to_dict(), axis=1
        )
    result[config.metadata] = result[config.metadata].astype(str)

실행 결과

메타데이터 시스템은 2단계 처리를 수행함:

  1. 검증: 지정된 메타데이터 컬럼들이 실제 존재하는지 확인
  2. 변환: 개별 메타데이터 컬럼들을 단일 JSON 객체로 병합

메타데이터는 청킹 과정에서 선택적으로 각 텍스트 청크 앞에 추가될 수 있으며, 토큰 계산 시 메타데이터 크기가 고려됨.

3.7 3단계 요약

GraphRAG의 데이터 입력 및 전처리 시스템은 확장 가능하고 유연한 아키텍처를 보임. 핵심 특징:

  • 다중 소스 지원: 파일/블롭 스토리지와 텍스트/CSV/JSON 형식
  • 단계적 처리: 기본 → 최종 텍스트 단위로의 점진적 변환
  • 전략 패턴: 토큰/문장 기반 청킹 전략의 플러그인 구조
  • 메타데이터 통합: 구조화된 메타데이터의 자동 처리
  • 타입 안전성: 강타입 데이터 모델과 검증 시스템

전체 파이프라인은 원시 문서를 분석 가능한 텍스트 단위로 변환하며, 후속 NLP 처리를 위한 표준화된 데이터 구조를 제공함.


4단계 LLM 기반 추출 파이프라인 분석

4.1 추출 파이프라인 아키텍처

구현 의도

GraphRAG는 대화형 언어 모델을 활용한 지식 그래프 추출 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/extract_graph.pyrun_workflow 함수가 핵심 진입점 역할을 담당함:

entities, relationships, raw_entities, raw_relationships = await extract_graph(
    text_units=text_units,
    callbacks=context.callbacks,
    cache=context.cache,
    extraction_strategy=extraction_strategy,
    extraction_num_threads=extract_graph_llm_settings.concurrent_requests,
    extraction_async_mode=extract_graph_llm_settings.async_mode,
    entity_types=config.extract_graph.entity_types,
    summarization_strategy=summarization_strategy,
    summarization_num_threads=summarization_llm_settings.concurrent_requests,
)

실행 결과

파이프라인은 2단계 처리 구조를 구현함:

  1. 추출 단계: LLM을 통한 원시 엔티티/관계 추출
  2. 요약 단계: 중복 엔티티 설명의 지능형 요약

추출된 결과는 entities.parquetrelationships.parquet으로 저장되며, config.snapshots.raw_graph 옵션 활성화 시 원시 데이터도 별도 보관됨.

4.2 프롬프트 엔지니어링 시스템

구현 의도

GraphRAG는 체계적인 프롬프트 템플릿을 통해 LLM의 지식 추출 성능을 최적화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/prompts/index/extract_graph.pyGRAPH_EXTRACTION_PROMPT는 4단계 구조화된 지시문을 포함함:

1. Identify all entities. For each identified entity, extract the following information:
- entity_name: Name of the entity, capitalized
- entity_type: One of the following types: [{entity_types}]
- entity_description: Comprehensive description of the entity's attributes and activities

실행 결과

프롬프트 시스템은 다음 핵심 요소들을 포함함:

  • 엔티티 추출: 이름, 타입, 설명의 구조화된 포맷
  • 관계 추출: 소스/타겟 엔티티, 관계 설명, 강도 점수
  • 출력 형식: 튜플 구분자(<|>)와 레코드 구분자(##) 사용
  • 예시 템플릿: 3개의 상세한 Few-shot 학습 예시 제공

프롬프트는 다국어 지원을 포함하며, 엔티티 타입은 설정 가능한 목록으로 관리됨.

4.3 GraphExtractor 핵심 엔진

구현 의도

GraphExtractor 클래스는 LLM 기반 그래프 추출의 핵심 엔진임. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/extract_graph/graph_extractor.py에서 구현된 주요 구조:

class GraphExtractor:
    _model: ChatModel
    _join_descriptions: bool
    _tuple_delimiter_key: str
    _record_delimiter_key: str
    _entity_types_key: str
    _completion_delimiter_key: str
    _extraction_prompt: str
    _max_gleanings: int

실행 결과

추출기는 다음 핵심 기능들을 구현함:

  • 멀티턴 대화: 역사 기반 컨텍스트 유지
  • 결과 파싱: 구조화된 텍스트를 NetworkX 그래프로 변환
  • 오류 처리: 파싱 실패 시 graceful degradation
  • 노드 병합: 중복 엔티티의 설명 통합 또는 교체

그래프 구조는 무방향 그래프(nx.Graph)로 구현되며, 각 노드는 description, type, source_id 속성을 포함함.

4.4 Gleaning 메커니즘

구현 의도

Gleaning은 LLM의 초기 추출 결과를 보완하는 반복적 개선 메커니즘임. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/extract_graph/graph_extractor.py의 구현:

if self._max_gleanings > 0:
    for i in range(self._max_gleanings):
        response = await self._model.achat(
            CONTINUE_PROMPT,
            name=f"extract-continuation-{i}",
            history=response.history,
        )
        results += response.output.content or ""

실행 결과

Gleaning 프로세스는 2단계 루프로 구성됨:

  1. 보완 추출: CONTINUE_PROMPT를 통한 누락된 엔티티/관계 추가
  2. 완료 확인: LOOP_PROMPT를 통한 추가 추출 필요성 판단

기본 설정은 max_gleanings: 1이며, 각 반복에서 대화 히스토리가 유지되어 문맥 일관성을 보장함. 모델이 "N"으로 응답하면 조기 종료됨.

4.5 언어 모델 관리 시스템

구현 의도

ModelManager는 싱글톤 패턴으로 구현된 LLM 인스턴스 관리자임. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/language_model/manager.py의 설계:

class ModelManager:
    _instance: ClassVar[ModelManager | None] = None
    
    def __init__(self) -> None:
        if not hasattr(self, "_initialized"):
            self.chat_models: dict[str, ChatModel] = {}
            self.embedding_models: dict[str, EmbeddingModel] = {}
            self._initialized = True

실행 결과

매니저는 다음 기능들을 제공함:

  • 인스턴스 캐싱: 동일 설정의 모델 재사용을 통한 메모리 효율성
  • 타입 분리: 채팅 모델과 임베딩 모델의 독립적 관리
  • 팩토리 통합: ModelFactory를 통한 표준화된 인스턴스 생성

그래프 추출에서는 extract_graph 이름으로 채팅 모델이 등록되며, 설정된 LLM 타입에 따라 적절한 구현체가 선택됨.

4.6 설명 요약 후처리

구현 의도

추출된 엔티티들의 중복 설명을 지능형으로 요약하는 후처리 단계임. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/summarize_descriptions/summarize_descriptions.py의 구현:

async def summarize_descriptions(
    entities_df: pd.DataFrame,
    relationships_df: pd.DataFrame,
    callbacks: WorkflowCallbacks,
    cache: PipelineCache,
    strategy: dict[str, Any] | None = None,
    num_threads: int = 4,
) -> tuple[pd.DataFrame, pd.DataFrame]:

실행 결과

요약 시스템은 다음 처리를 수행함:

  • 중복 제거: 동일 엔티티의 다중 설명 식별
  • 컨텍스트 통합: 관련 설명들을 하나의 일관된 서술로 병합
  • 병렬 처리: 세마포어를 통한 동시성 제어
  • 진행률 추적: ProgressTicker를 통한 실시간 진행률 보고

요약 결과는 원본 엔티티/관계 데이터프레임의 description 컬럼을 갱신하여 반환됨.

4.7 NLP 기반 추출 대안

구현 의도

LLM 외에도 전통적 NLP 기법을 활용한 그래프 추출 옵션을 제공함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/extract_graph_nlp.py의 구현:

async def extract_graph_nlp(
    text_units: pd.DataFrame,
    cache: PipelineCache,
    extraction_config: ExtractGraphNLPConfig,
) -> tuple[pd.DataFrame, pd.DataFrame]:

실행 결과

NLP 추출 방식은 다음 기법들을 활용함:

  • 명사구 추출: 문법적 파싱을 통한 엔티티 후보 식별
  • 개체명 인식: 사전 훈련된 NER 모델 활용
  • 공출현 분석: 엔티티 간 동시 출현 빈도 기반 관계 추론
  • 가중치 정규화: 관계 강도의 통계적 정규화

이 방식은 LLM 의존성을 줄이고 처리 속도를 향상시키지만, 의미적 이해도는 상대적으로 제한적임.

4.8 4단계 요약

GraphRAG의 LLM 기반 추출 파이프라인은 최신 생성형 AI의 강점을 활용한 지능형 지식 추출 시스템임. 핵심 특징:

  • 구조화된 프롬프팅: Few-shot 학습과 명확한 출력 포맷 지정
  • 반복적 개선: Gleaning 메커니즘을 통한 추출 품질 향상
  • 병렬 처리: 비동기 처리와 스레드 풀을 통한 성능 최적화
  • 오류 복원력: 파싱 실패와 모델 오류에 대한 견고한 처리
  • 하이브리드 접근: LLM과 NLP 기법의 선택적 활용

파이프라인은 원시 텍스트로부터 고품질의 구조화된 지식 그래프를 생성하며, 후속 커뮤니티 감지와 검색 단계의 기반을 제공함.


5단계 그래프 분석 및 커뮤니티 감지 분석

5.1 커뮤니티 감지 아키텍처

구현 의도

GraphRAG는 Leiden 알고리즘 기반의 계층적 커뮤니티 감지 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/create_communities.pycreate_communities 함수가 핵심 처리를 담당함:

def create_communities(
    entities: pd.DataFrame,
    relationships: pd.DataFrame,
    max_cluster_size: int,
    use_lcc: bool,
    seed: int | None = None,
) -> pd.DataFrame:

실행 결과

커뮤니티 감지 과정은 4단계로 구성됨:

  1. 그래프 생성: 관계 데이터로부터 NetworkX 그래프 구축
  2. 클러스터링: Leiden 알고리즘 적용하여 계층적 커뮤니티 추출
  3. 데이터 집계: 각 커뮤니티별 엔티티/관계/텍스트 단위 수집
  4. 메타데이터 생성: UUID, 제목, 계층 구조 등 부가 정보 추가

결과는 communities.parquet으로 저장되며, COMMUNITIES_FINAL_COLUMNS 스키마를 따름.

5.2 Leiden 알고리즘 구현

구현 의도

cluster_graph 함수는 graspologic.partition.hierarchical_leiden을 활용한 계층적 클러스터링을 수행함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/cluster_graph.py의 구현:

def _compute_leiden_communities(
    graph: nx.Graph | nx.DiGraph,
    max_cluster_size: int,
    use_lcc: bool,
    seed: int | None = None,
) -> tuple[dict[int, dict[str, int]], dict[int, int]]:

실행 결과

Leiden 알고리즘 처리는 다음 설정으로 수행됨:

  • 최대 클러스터 크기: max_cluster_size=10 (기본값)
  • 최대 연결 컴포넌트 사용: use_lcc=True
  • 시드값: seed=0xDEADBEEF (재현 가능한 결과)

알고리즘은 2가지 반환값을 생성함:

  • results: 각 레벨별 노드-클러스터 매핑
  • hierarchy: 클러스터 간 부모-자식 관계

결과는 Communities 타입으로 변환되어 (level, cluster_id, parent_id, nodes) 튜플 리스트를 생성함.

5.3 그래프 구축 시스템

구현 의도

그래프 생성은 /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/create_graph.py의 간결한 함수로 처리됨:

def create_graph(
    edges: pd.DataFrame,
    edge_attr: list[str | int] | None = None,
    nodes: pd.DataFrame | None = None,
    node_id: str = "title",
) -> nx.Graph:

실행 결과

그래프 구축 과정:

  1. 에지 생성: pd.DataFrame을 NetworkX 그래프로 변환
  2. 속성 추가: edge_attr 파라미터로 가중치 등 에지 속성 설정
  3. 노드 보강: 선택적으로 노드 데이터프레임의 속성 추가

커뮤니티 감지에서는 edge_attr=["weight"] 옵션으로 관계 강도를 고려한 가중 그래프를 생성함.

5.4 안정적 LCC 처리

구현 의도

stable_largest_connected_component 함수는 재현 가능한 그래프 처리를 보장함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/utils/stable_lcc.py의 구현:

def stable_largest_connected_component(graph: nx.Graph) -> nx.Graph:
    graph = graph.copy()
    graph = cast("nx.Graph", largest_connected_component(graph))
    graph = normalize_node_names(graph)
    return _stabilize_graph(graph)

실행 결과

안정화 과정은 3단계로 구성됨:

  1. LCC 추출: 최대 연결 컴포넌트 선택
  2. 노드명 정규화: HTML 이스케이프 등 정규화 처리
  3. 그래프 안정화: 노드와 에지의 결정적 정렬

_stabilize_graph 함수는 무방향 그래프에서 에지의 소스-타겟 순서를 알파벳 순으로 고정하여 동일한 입력에 대해 항상 동일한 결과를 보장함.

5.5 모듈러리티 계산 시스템

구현 의도

GraphRAG는 다양한 모듈러리티 측정 방식을 제공함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/utils/graphs.py의 계산 함수들:

def calculate_modularity(
    graph: nx.Graph,
    max_cluster_size: int = 10,
    random_seed: int = 0xDEADBEEF,
    use_root_modularity: bool = True,
    modularity_metric: ModularityMetric = ModularityMetric.WeightedComponents,
) -> float:

실행 결과

3가지 모듈러리티 측정 방식을 지원함:

  • Graph: 전체 그래프의 모듈러리티
  • LCC: 최대 연결 컴포넌트의 모듈러리티
  • WeightedComponents: 크기별 가중 컴포넌트 모듈러리티

각 방식은 루트 클러스터링 또는 리프 클러스터링 중 선택 가능하며, graspologic.partition.modularity 함수를 활용하여 품질 점수를 계산함.

5.6 커뮤니티 보고서 생성

구현 의도

커뮤니티 보고서는 LLM을 활용한 자동 요약 시스템임. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/create_community_reports.py의 구현:

async def create_community_reports(
    edges_input: pd.DataFrame,
    entities: pd.DataFrame,
    communities: pd.DataFrame,
    claims_input: pd.DataFrame | None,
    callbacks: WorkflowCallbacks,
    cache: PipelineCache,
    summarization_strategy: dict,
    async_mode: AsyncType = AsyncType.AsyncIO,
    num_threads: int = 4,
) -> pd.DataFrame:

실행 결과

보고서 생성 과정은 5단계로 구성됨:

  1. 노드 확장: 커뮤니티별 엔티티 정보 전개
  2. 컨텍스트 구축: 로컬 그래프 컨텍스트 생성
  3. LLM 요약: 비동기 커뮤니티 요약 수행
  4. 최종화: 보고서 메타데이터 및 순위 부여
  5. 저장: community_reports.parquet 출력

각 보고서는 CommunityReport 데이터 모델을 따르며, summary, full_content, rank 등의 필드를 포함함.

5.7 커뮤니티 데이터 구조

구현 의도

Community 모델은 계층적 커뮤니티 정보를 캡슐화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/data_model/community.py의 정의:

@dataclass
class Community(Named):
    level: str
    parent: str
    children: list[str]
    entity_ids: list[str] | None = None
    relationship_ids: list[str] | None = None
    text_unit_ids: list[str] | None = None
    covariate_ids: dict[str, list[str]] | None = None
    attributes: dict[str, Any] | None = None
    size: int | None = None
    period: str | None = None

실행 결과

커뮤니티 구조는 10개 핵심 필드로 구성됨:

  • 계층 정보: level, parent, children를 통한 트리 구조
  • 연관 엔티티: entity_ids, relationship_ids, text_unit_ids 참조
  • 메타데이터: size, period, attributes 부가 정보
  • 공변량: 선택적 클레임 및 추가 분석 데이터

각 커뮤니티는 고유 UUID와 인간 가독성 ID를 가지며, "Community " + community_id 형식의 제목을 자동 생성함.

5.8 계층적 집계 처리

구현 의도

커뮤니티 생성 과정에서 각 레벨별 관계와 텍스트 단위를 집계함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/create_communities.py의 처리 로직:

for level in range(max_level + 1):
    communities_at_level = communities.loc[communities["level"] == level]
    sources = relationships.merge(
        communities_at_level, left_on="source", right_on="title", how="inner"
    )
    targets = sources.merge(
        communities_at_level, left_on="target", right_on="title", how="inner"
    )
    matched = targets.loc[targets["community_x"] == targets["community_y"]]

실행 결과

집계 과정은 다음 단계를 수행함:

  1. 레벨별 처리: 각 계층 레벨에서 독립적 집계
  2. 관계 필터링: 동일 커뮤니티 내부 관계만 선별
  3. 텍스트 단위 수집: 관련된 모든 텍스트 조각 수집
  4. 중복 제거: sorted(set(x)) 연산으로 고유값 보장

최종 결과는 부모-자식 관계 매핑과 현재 날짜 타임스탬프를 포함한 완전한 커뮤니티 메타데이터를 생성함.

5.9 5단계 요약

GraphRAG의 그래프 분석 및 커뮤니티 감지 시스템은 현대적 네트워크 분석 기법을 활용한 정교한 지식 구조화 시스템임. 핵심 특징:

  • Leiden 기반 클러스터링: 최적 품질의 계층적 커뮤니티 감지
  • 재현 가능한 처리: 시드값과 안정화를 통한 결정적 결과
  • 다층 모듈러리티: 그래프 품질의 다각적 평가
  • 지능형 보고서: LLM 기반 커뮤니티 요약 자동화
  • 계층적 구조: 트리 형태의 멀티레벨 커뮤니티 조직

시스템은 원시 엔티티-관계 그래프를 의미 있는 커뮤니티 구조로 변환하며, 후속 검색과 추론 작업의 기반을 제공함.


6단계 임베딩 및 벡터화 분석

6.1 텍스트 임베딩 아키텍처

구현 의도

GraphRAG는 지식 그래프의 모든 텍스트 엔티티를 의미적 벡터 공간으로 변환하는 포괄적 임베딩 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/workflows/generate_text_embeddings.pyrun_workflow 함수가 핵심 진입점이며, 6가지 데이터 테이블에서 선택적으로 텍스트를 임베딩함:

output = await generate_text_embeddings(
    documents=documents,
    relationships=relationships,
    text_units=text_units,
    entities=entities,
    community_reports=community_reports,
    callbacks=context.callbacks,
    cache=context.cache,
    text_embed_config=text_embed,
    embedded_fields=embedded_fields,
)

실행 결과

임베딩 시스템은 8가지 미리 정의된 임베딩 필드를 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/config/embeddings.py에 정의된 all_embeddings 집합은 다음 필드들을 포함함:

  • entity.title: 엔티티 명칭 임베딩
  • entity.description: 엔티티 설명 임베딩
  • relationship.description: 관계 설명 임베딩
  • document.text: 문서 전체 텍스트 임베딩
  • community.title: 커뮤니티 제목 임베딩
  • community.summary: 커뮤니티 요약 임베딩
  • community.full_content: 커뮤니티 전체 내용 임베딩
  • text_unit.text: 텍스트 단위 내용 임베딩

기본적으로 3개 필드(entity.description, community.full_content, text_unit.text)가 활성화되며, 처리 결과는 각 테이블에 {field_name}_embedding 컬럼으로 추가됨. 임베딩 벡터는 text-embedding-3-small 모델 기준 1536차원 float 배열로 생성됨.

6.2 배치 처리 및 토큰 최적화

구현 의도

OpenAI API 제약사항을 준수하기 위한 정교한 배치 처리 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/embed_text/strategies/openai.py_create_text_batches 함수가 핵심 로직을 담당하며, Azure OpenAI 서비스 제한을 엄격히 준수함:

def _create_text_batches(
    texts: list[str],
    max_batch_size: int,      # 기본값: 16
    max_batch_tokens: int,    # 기본값: 8191
    splitter: TokenTextSplitter,
) -> list[list[str]]:

실행 결과

배치 처리는 4단계 최적화 과정을 거침:

  1. 토큰 기반 텍스트 분할: _prepare_embed_texts 함수가 TokenTextSplitter를 사용하여 긴 텍스트를 8191 토큰 이하 조각들로 분할함. 분할된 조각 수는 sizes 리스트에 기록되어 재구성 시 활용됨.
  2. 동적 배치 구성: 배치 생성 알고리즘이 토큰 수와 텍스트 개수를 동시 고려함. 현재 배치에 새 텍스트 추가 시 len(current_batch) >= max_batch_size 또는 current_batch_tokens + token_count > max_batch_tokens 조건 중 하나라도 만족하면 새 배치를 생성함.
  3. 비동기 병렬 처리: _execute 함수가 asyncio.gather로 모든 배치를 병렬 처리하며, asyncio.Semaphore로 동시성을 제어함. 각 배치는 model.aembed_batch 메서드로 처리되고 진행률 추적을 위해 tick(1) 호출됨.
  4. 벡터 재구성: _reconstitute_embeddings 함수가 분할된 텍스트의 임베딩을 원본 구조로 복원함. 단일 조각인 경우 그대로 반환하고, 다중 조각인 경우 np.average로 평균 벡터를 계산한 후 np.linalg.norm으로 L2 정규화를 적용함.

6.3 다중 임베딩 전략 시스템

구현 의도

확장 가능한 임베딩 전략 시스템을 통해 다양한 백엔드를 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/embed_text/strategies/typing.pyTextEmbeddingStrategy 프로토콜이 표준 인터페이스를 정의함:

TextEmbeddingStrategy = Callable[
    [
        list[str],
        WorkflowCallbacks,
        PipelineCache,
        dict,
    ],
    Awaitable[TextEmbeddingResult],
]

실행 결과

전략 시스템은 3가지 구현체를 제공함:

  1. OpenAI 전략 (openai.py): 프로덕션 환경을 위한 실제 임베딩 생성. 토큰 분할, 배치 처리, 세마포어 기반 동시성 제어를 포함한 완전한 기능을 제공함. EmbeddingModel 프로토콜을 통해 OpenAI와 Azure OpenAI 서비스를 모두 지원함.
  2. Mock 전략 (mock.py): 개발 및 테스트 환경을 위한 가짜 임베딩 생성. random.random() 호출로 3차원 랜덤 벡터를 생성하여 API 비용 없이 시스템 테스트가 가능함:
def _embed_text(_cache: PipelineCache, _text: str, tick: ProgressTicker) -> list[float]:
    tick(1)
    return [random.random(), random.random(), random.random()]
  1. 커스텀 전략: 사용자 정의 임베딩 백엔드 등록을 위한 확장 지점 제공. load_strategy 함수가 전략 타입 문자열을 기반으로 동적 로딩을 수행함.

6.4 벡터 스토어 아키텍처

구현 의도

다양한 벡터 데이터베이스 백엔드를 지원하는 통합 아키텍처를 팩토리 패턴으로 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/vector_stores/factory.pyVectorStoreFactory 클래스가 3가지 기본 백엔드와 사용자 정의 구현체를 지원함:

class VectorStoreType(str, Enum):
    LanceDB = "lancedb"
    AzureAISearch = "azure_ai_search"
    CosmosDB = "cosmosdb"

실행 결과

벡터 스토어 시스템은 통합된 인터페이스로 다양한 백엔드를 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/vector_stores/base.pyBaseVectorStore 추상 클래스가 6가지 필수 메서드를 정의함:

  1. LanceDB 구현: 로컬 고성능 벡터 데이터베이스. PyArrow 스키마 기반으로 벡터를 pa.list_(pa.float64()) 형식으로 저장하며, create_table 메서드로 오버라이트 모드와 추가 모드를 지원함:
schema = pa.schema([
    pa.field("id", pa.string()),
    pa.field("text", pa.string()),
    pa.field("vector", pa.list_(pa.float64())),
    pa.field("attributes", pa.string()),
])
  1. Azure AI Search 구현: 클라우드 관리형 벡터 검색 서비스. HNSW 알고리즘 기반 근사 최근접 이웃 검색을 지원하며, VectorSearchVectorSearchProfile 설정을 통해 검색 성능을 최적화함. 기본 벡터 크기는 1536차원이며 동적 조정 가능함.
  2. CosmosDB 구현: 글로벌 분산 문서 데이터베이스. JSON 형태로 벡터와 메타데이터를 함께 저장하며, 파티션 키 기반 수평 확장을 지원함.

각 벡터 스토어는 임베딩 이름 기반 컬렉션 분리를 지원함. create_collection_name 함수가 점 표기법을 대시로 변환하여 백엔드 호환성을 보장함:

def create_collection_name(container_name: str, embedding_name: str) -> str:
    return f"{container_name}-{embedding_name}".replace(".", "-")

6.5 임베딩 처리 및 벡터 스토어 통합

구현 의도

임베딩 생성과 벡터 스토어 저장을 단일 파이프라인으로 통합하여 효율성을 극대화함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/operations/embed_text/embed_text.py_text_embed_with_vector_store 함수가 배치 단위로 임베딩 생성과 저장을 동시 수행함:

insert_batch_size: int = (
    vector_store_config.get("batch_size") or DEFAULT_EMBEDDING_BATCH_SIZE
)
overwrite: bool = vector_store_config.get("overwrite", True)

실행 결과

통합 파이프라인은 메모리 효율적 스트리밍 처리를 수행함:

  1. 배치 단위 처리: insert_batch_size 설정에 따라 입력 DataFrame을 청크로 분할하여 메모리 사용량을 제한함. 각 배치는 독립적으로 임베딩 생성 후 즉시 벡터 스토어에 저장됨.
  2. VectorStoreDocument 변환: 각 텍스트는 표준화된 VectorStoreDocument 객체로 변환되어 백엔드 독립성을 보장함. ID, 텍스트, 벡터, 속성 필드가 포함되며 JSON 직렬화를 통해 메타데이터를 보존함.
  3. 진행률 추적: 전체 행 수 계산 시 리스트 형태 데이터를 고려하여 정확한 진행률을 제공함:
total_rows = 0
for row in input[embed_column]:
    if isinstance(row, list):
        total_rows += len(row)
    else:
        total_rows += 1
  1. 오류 처리: 필수 컬럼 존재 여부 검증과 상세한 오류 메시지를 통해 디버깅을 지원함.

6.6 6단계 요약

GraphRAG의 임베딩 및 벡터화 시스템은 확장성과 효율성을 동시에 추구하는 엔터프라이즈급 아키텍처로 설계됨. 8가지 임베딩 필드와 3가지 벡터 스토어 백엔드를 지원하여 다양한 배포 환경에 적응 가능함. 토큰 기반 배치 처리와 비동기 병렬 실행을 통해 OpenAI API 제약사항을 효과적으로 관리하며, 메모리 효율적 스트리밍 파이프라인을 통해 대규모 데이터셋 처리가 가능함. 전략 패턴과 팩토리 패턴을 활용한 모듈화된 설계로 새로운 임베딩 모델과 벡터 데이터베이스의 추가가 용이함.


7단계 아티팩트 생성 및 저장 분석

7.1 Parquet 기반 데이터 저장 시스템

구현 의도
GraphRAG는 모든 처리 결과를 Apache Parquet 형식으로 표준화하여 저장함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/utils/storage.pywrite_table_to_storage 함수가 핵심 저장 메커니즘을 담당하며, 각 워크플로우에서 생성된 DataFrame을 영구 저장함:

async def write_table_to_storage(
    table: pd.DataFrame, name: str, storage: PipelineStorage
) -> None:
    """Write a table to storage."""
    await storage.set(f"{name}.parquet", table.to_parquet())

실행 결과
GraphRAG 인덱싱 파이프라인은 7가지 핵심 아티팩트를 생성함. 각 워크플로우는 표준화된 스키마에 따라 처리 결과를 저장하며, /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/data_model/schemas.py에 정의된 *_FINAL_COLUMNS 스키마를 따름:

  • documents.parquet: 원본 문서 메타데이터 및 내용 (5개 컬럼: id, short_id, title, text, text_unit_ids)
  • text_units.parquet: 청킹된 텍스트 조각들 (8개 컬럼: id, short_id, text, n_tokens, document_ids, entity_ids, relationship_ids, covariate_ids)
  • entities.parquet: 추출된 엔티티 정보 (10개 컬럼: id, short_id, title, type, description, text_unit_ids, node_frequency, node_degree, node_x, node_y)
  • relationships.parquet: 엔티티 간 관계 데이터 (8개 컬럼: id, short_id, edge_source, edge_target, description, edge_weight, edge_degree, text_unit_ids)
  • communities.parquet: 계층적 커뮤니티 구조 (12개 컬럼: community_id, community_level, community_parent 등)
  • community_reports.parquet: 커뮤니티 요약 보고서 (15개 컬럼: summary, full_content, rating, explanation, findings 등)
  • covariates.parquet: 공변량 정보 (12개 컬럼: covariate_type, subject_id, object_id, status 등)

Parquet 형식은 컬럼형 저장과 압축을 통해 디스크 공간 효율성과 쿼리 성능을 모두 최적화함.

7.2 다중 저장소 백엔드 아키텍처

구현 의도
확장 가능한 저장소 시스템을 팩토리 패턴으로 구현하여 다양한 배포 환경을 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/storage/factory.pyStorageFactory 클래스가 4가지 기본 백엔드와 사용자 정의 구현체를 지원함:

class StorageFactory:
    @classmethod
    def create_storage(
        cls, storage_type: OutputType | str, kwargs: dict
    ) -> PipelineStorage:
        match storage_type:
            case OutputType.blob:
                return create_blob_storage(**kwargs)
            case OutputType.cosmosdb:
                return create_cosmosdb_storage(**kwargs)
            case OutputType.file:
                return create_file_storage(**kwargs)
            case OutputType.memory:
                return MemoryPipelineStorage()

실행 결과
저장소 아키텍처는 통합된 인터페이스로 다양한 백엔드를 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/storage/pipeline_storage.pyPipelineStorage 추상 클래스가 8가지 필수 메서드를 정의함:

  1. Memory Storage: 인메모리 저장소로 개발 및 테스트 환경에 최적화됨. 딕셔너리 기반 키-값 저장으로 빠른 액세스 제공하며, 프로세스 종료 시 데이터 소실됨.
  2. File Storage: 로컬 파일 시스템 기반 저장소. aiofiles 라이브러리로 비동기 I/O를 구현하며, UTF-8 인코딩을 기본으로 사용함. 파일 생성 시간 추적을 위해 datetime.fromtimestampget_timestamp_formatted_with_local_tz 함수를 활용함:
async def get_creation_date(self, key: str) -> str:
    creation_timestamp = os.path.getctime(join_path(self._root_dir, key))
    creation_time_utc = datetime.fromtimestamp(creation_timestamp, tz=timezone.utc)
    return get_timestamp_formatted_with_local_tz(creation_time_utc)
  1. Blob Storage: Azure Blob Storage 기반 클라우드 저장소. BlobServiceClient로 연결 관리하며, 컨테이너 자동 생성과 경로 접두사 지원을 통해 네임스페이스 분리를 제공함. DefaultAzureCredential을 통한 관리 ID 인증과 연결 문자열 인증을 모두 지원함.
  2. CosmosDB Storage: Azure CosmosDB 기반 NoSQL 저장소. 파티션 키 기반 수평 확장을 지원하며, JSON 형태로 Parquet 바이너리 데이터를 저장함. 글로벌 분산과 자동 장애 조치 기능을 제공함.

7.3 메타데이터 관리 및 파일 검색 시스템

구현 의도
대규모 아티팩트 컬렉션의 효율적 관리를 위한 메타데이터 기반 검색 시스템을 구현함. 각 저장소 백엔드는 find 메서드를 통해 정규식 패턴과 필터 조건 기반 파일 검색을 지원함:

def find(
    self,
    file_pattern: re.Pattern[str],
    base_dir: str | None = None,
    progress: ProgressLogger | None = None,
    file_filter: dict[str, Any] | None = None,
    max_count=-1,
) -> Iterator[tuple[str, dict[str, Any]]]:

실행 결과
검색 시스템은 3단계 필터링 과정을 거침:

  1. 패턴 매칭: 정규식 패턴으로 파일명 필터링 수행. file_pattern.search 메서드가 파일명과 매칭하며, match.groupdict()를 통해 명명된 그룹 추출함.
  2. 메타데이터 필터링: file_filter 딕셔너리의 키-값 쌍으로 추가 필터링 수행. 각 필터 조건은 정규식으로 평가되어 유연한 검색 지원함:
def item_filter(item: dict[str, Any]) -> bool:
    if file_filter is None:
        return True
    return all(
        re.search(value, item[key]) for key, value in file_filter.items()
    )
  1. 진행률 추적: 대용량 저장소 검색 시 실시간 진행률 업데이트 제공. num_loaded, num_filtered, num_total 카운터를 통해 검색 상태를 추적함.

CosmosDB의 경우 SQL 쿼리 기반 서버사이드 필터링을 지원하여 네트워크 트래픽을 최소화함:

query = "SELECT * FROM c WHERE RegexMatch(c.id, @pattern)"
parameters = [{"name": "@pattern", "value": file_pattern.pattern}]

7.4 아티팩트 라이프사이클 관리

구현 의도
아티팩트의 전체 라이프사이클을 관리하는 포괄적 시스템을 구현함. 생성, 조회, 업데이트, 삭제(CRUD) 작업과 메타데이터 추적을 통해 데이터 무결성을 보장함. 각 저장소는 원자적 작업을 지원하여 부분 실패 상황을 방지함:

async def delete_table_from_storage(name: str, storage: PipelineStorage) -> None:
    """Delete a table to storage."""
    await storage.delete(f"{name}.parquet")

async def storage_has_table(name: str, storage: PipelineStorage) -> bool:
    """Check if a table exists in storage."""
    return await storage.has(f"{name}.parquet")

실행 결과
라이프사이클 관리는 4가지 핵심 작업을 지원함:

  1. 원자적 쓰기: set 메서드는 새 파일 생성 시 임시 파일을 사용하여 원자성을 보장함. 쓰기 완료 후 원본 파일을 대체하여 부분 업데이트를 방지함.
  2. 조건부 읽기: get 메서드는 키 존재 여부를 확인한 후 안전하게 데이터를 반환함. 파일 시스템의 경우 직접 경로 접근도 지원하여 새로 추가된 입력 파일 처리가 가능함.
  3. 메타데이터 추적: 각 아티팩트의 생성 시간을 추적하여 변경 이력 관리를 지원함. 시간대 정보를 포함한 표준화된 타임스탬프 형식 사용:
def get_timestamp_formatted_with_local_tz(timestamp: datetime) -> str:
    creation_time_local = timestamp.astimezone()
    return creation_time_local.strftime("%Y-%m-%d %H:%M:%S %z")
  1. 일괄 정리: clear 메서드는 저장소 전체 초기화를 지원함. 파일 저장소의 경우 디렉토리와 파일을 구분하여 재귀적 삭제를 수행함.

7.5 스키마 검증 및 데이터 무결성

구현 의도
모든 아티팩트가 일관된 스키마를 따르도록 보장하는 검증 시스템을 구현함. 각 워크플로우는 최종 출력 시 미리 정의된 컬럼 순서와 데이터 타입을 강제함. DataFrame 슬라이싱을 통한 스키마 정규화로 예상치 못한 컬럼 추가를 방지함:

return rejoined.loc[:, DOCUMENTS_FINAL_COLUMNS]
return resolved.loc[:, ENTITIES_FINAL_COLUMNS]
return output.loc[:, COMMUNITY_REPORTS_FINAL_COLUMNS]

실행 결과
스키마 검증 시스템은 3단계 보장 메커니즘을 제공함:

  1. 컬럼 순서 표준화: 모든 최종 아티팩트는 미리 정의된 컬럼 순서를 따름. FINAL_COLUMNS 리스트가 각 테이블의 정확한 스키마를 정의하며, Pandas DataFrame 슬라이싱으로 강제 적용됨.
  2. 데이터 타입 일관성: 특정 컬럼들은 고정된 데이터 타입을 유지함. 예를 들어 ID 컬럼은 문자열, 숫자 컬럼은 float 또는 int, 배열 컬럼은 JSON 문자열 형태로 저장됨.
  3. 필수 컬럼 검증: 워크플로우 실행 시 필수 컬럼 존재 여부를 확인함. 누락된 컬럼 발견 시 상세한 오류 메시지와 함께 처리를 중단함.

7.6 확장성 및 성능 최적화

구현 의도
대규모 데이터셋 처리를 위한 확장성과 성능 최적화 메커니즘을 구현함. 비동기 I/O, 스트리밍 처리, 압축 최적화를 통해 메모리 효율성과 처리 속도를 동시에 개선함. 저장소별 특성을 활용한 최적화 전략을 적용함:

# 비동기 파일 I/O
async with aiofiles.open(path, cast("Any", read_type), encoding=encoding) as f:
    return await f.read()

# Parquet 압축 및 최적화
await storage.set(f"{name}.parquet", table.to_parquet())

실행 결과
성능 최적화는 4가지 전략으로 구현됨:

  1. 비동기 I/O: 모든 저장소 작업은 async/await 패턴으로 구현되어 I/O 대기 시간 중 다른 작업 수행이 가능함. aiofiles 라이브러리로 파일 시스템 작업의 비블로킹 처리를 지원함.
  2. 스트리밍 처리: 대용량 파일 처리 시 전체 내용을 메모리에 로드하지 않고 청크 단위로 처리함. Iterator 패턴을 활용한 지연 평가로 메모리 사용량을 최소화함.
  3. 압축 최적화: Parquet 형식의 내장 압축 기능을 활용하여 저장 공간을 최적화함. 컬럼형 저장과 압축 알고리즘으로 일반적으로 70-90% 크기 감소를 달성함.
  4. 캐시 친화적 설계: 자주 액세스되는 메타데이터를 메모리에 캐시하여 반복 조회 성능을 향상시킴. 저장소 연결 풀링을 통해 연결 오버헤드를 최소화함.

7.7 7단계 요약

GraphRAG의 아티팩트 생성 및 저장 시스템은 엔터프라이즈급 확장성과 신뢰성을 제공하는 포괄적 아키텍처로 설계됨. Parquet 기반 표준화된 데이터 형식과 4가지 저장소 백엔드를 통해 다양한 배포 환경에 적응 가능함. 스키마 검증과 메타데이터 관리로 데이터 무결성을 보장하며, 비동기 I/O와 스트리밍 처리로 대규모 데이터셋의 효율적 처리가 가능함. 팩토리 패턴과 추상화 계층을 통한 확장 가능한 설계로 새로운 저장소 백엔드의 추가가 용이함.


8단계 성능 최적화 및 확장성 분석

8.1 비동기 및 동시성 처리 시스템

구현 의도
GraphRAG는 대규모 데이터 처리를 위한 포괄적 병렬성 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/config/models/language_model_config.py에서 concurrent_requests 설정으로 LLM 요청 동시성을 제어하며, 기본값은 25개 동시 요청임:

concurrent_requests: int = Field(
    description="The maximum number of concurrent requests.",
    default=language_model_defaults.concurrent_requests,
)

실행 결과
동시성 시스템은 3가지 처리 방식을 지원함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/utils/derive_from_rows.py의 구현체들이 각각 다른 워크로드 특성에 최적화됨:

  1. AsyncIO 기반 처리: derive_from_rows_asyncio 함수는 I/O 집약적 작업에 최적화됨. asyncio.Semaphore로 동시 실행 수를 제한하고, asyncio.create_task로 태스크를 생성하여 비동기 실행 관리:
semaphore = asyncio.Semaphore(num_threads or 4)
async def execute_row_protected(row: tuple[Hashable, pd.Series]) -> ItemType | None:
    async with semaphore:
        return await execute(row)
  1. 스레드 풀 기반 처리: derive_from_rows_asyncio_threads 함수는 CPU 집약적 작업을 위해 asyncio.to_thread를 활용함. 세마포어와 결합하여 스레드 수를 제한하고 컨텍스트 스위칭 오버헤드를 최소화함.
  2. 오류 처리 및 복구: _derive_from_rows_base 함수는 개별 작업 실패 시에도 전체 파이프라인 중단을 방지함. 오류 수집과 진행률 추적을 통해 안정적인 대용량 처리를 보장함:
for error, stack in errors:
    callbacks.error("parallel transformation error", error, stack)
if len(errors) > 0:
    raise ParallelizationError(len(errors), errors[0][1])

8.2 다층 캐시 아키텍처

구현 의도
중복 계산 방지와 API 비용 절약을 위한 유연한 캐시 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/cache/factory.pyCacheFactory 클래스가 4가지 캐시 전략을 지원하며, 사용자 정의 구현체 등록도 가능함:

@classmethod
def create_cache(
    cls, cache_type: CacheType | str | None, root_dir: str, kwargs: dict
) -> PipelineCache:
    match cache_type:
        case CacheType.none:
            return NoopPipelineCache()
        case CacheType.memory:
            return InMemoryCache()

실행 결과
캐시 시스템은 성능과 지속성의 균형을 제공하는 4가지 구현체를 포함함:

  1. 메모리 캐시: InMemoryCache 클래스는 딕셔너리 기반 고속 캐시를 제공함. 캐시 키 네임스페이싱을 통해 충돌을 방지하며, 프로세스 라이프사이클 동안 지속됨:
def _create_cache_key(self, key: str) -> str:
    return f"{self._name}:{key}" if self._name else key
  1. JSON 파일 캐시: JsonPipelineCache 클래스는 저장소 백엔드를 활용한 지속적 캐시를 구현함. JSON 직렬화를 통해 복잡한 객체 저장을 지원하며, 인코딩 오류와 JSON 파싱 오류 시 자동 정리 메커니즘을 포함함:
try:
    data = await self._storage.get(key, encoding=self._encoding)
    data = json.loads(data)
except (UnicodeDecodeError, json.decoder.JSONDecodeError):
    await self._storage.delete(key)
    return None
  1. NoOp 캐시: 캐시 비활성화 옵션으로 디버깅과 성능 측정에 활용됨. 모든 캐시 작업이 즉시 반환되어 오버헤드 없는 실행을 제공함.
  2. 계층적 캐시 키: 모든 캐시 구현체는 child 메서드를 통해 네임스페이스 분리를 지원하여 서로 다른 워크플로우 간 캐시 충돌을 방지함.

8.3 속도 제한 및 API 최적화

구현 의도
외부 API 서비스의 속도 제한을 준수하고 비용을 최적화하기 위한 정교한 속도 제한 시스템을 구현함. /home/ubuntu/.local/lib/python3.10/site-packages/graphrag/index/utils/rate_limiter.pyRateLimiter 클래스가 토큰 버킷 알고리즘을 기반으로 분당 요청 수를 제어함:

def __init__(self, rate: int, per: int):
    self.rate = rate
    self.per = per
    self.allowance = rate
    self.last_check = time.monotonic()

실행 결과
속도 제한 시스템은 동적 토큰 보충과 백프레셔 제어를 통해 정확한 속도 관리를 제공함:

  1. 토큰 버킷 알고리즘: 시간 경과에 따라 토큰을 보충하며, 최대 허용량을 초과하지 않도록 제한함. time.monotonic() 사용으로 시스템 시간 변경에 영향받지 않는 안정적 측정을 보장함:
elapsed = current - self.last_check
self.allowance += elapsed * (self.rate / self.per)
if self.allowance > self.rate:
    self.allowance = self.rate
  1. 적응적 대기: 토큰 부족 시 정확한 대기 시간을 계산하여 불필요한 CPU 사용을 방지함. 커뮤니티 보고서 생성과 같은 고비용 작업에서 분당 1회 요청 제한을 적용함:
if self.allowance < 1.0:
    sleep_time = (1.0 - self.allowance) * (self.per / self.rate)
    await asyncio.sleep(sleep_time)
  1. 세밀한 제어: OpenAI API의 토큰/분, 요청/분 제한을 모두 고려한 이중 제한 메커니즘을 fnllm 라이브러리와 연동하여 구현함.

8.4 메모리 최적화 및 스트리밍 처리

구현 의도
대용량 데이터셋의 효율적 처리를 위한 메모리 최적화 전략을 구현함. 스트리밍 처리와 지연 평가를 통해 메모리 사용량을 일정하게 유지하며, 데이터셋 크기에 무관한 확장성을 제공함:

async for table in _run_pipeline(
    pipeline=pipeline, config=config, dataset=dataset, logger=logger, context=context
):
    yield table

실행 결과
메모리 최적화는 4가지 핵심 전략으로 구현됨:

  1. 스트리밍 파이프라인: 각 워크플로우가 처리 완료 즉시 결과를 반환하여 메모리 누적을 방지함. Iterator 패턴을 통해 대용량 데이터셋도 일정한 메모리로 처리 가능함.
  2. 청크 기반 처리: 임베딩과 같은 대용량 작업은 배치 단위로 분할하여 처리함. insert_batch_size 설정으로 메모리 사용량과 처리 효율성의 균형을 조절함.
  3. 즉시 저장: 중간 결과를 메모리에 유지하지 않고 즉시 저장소에 기록함. write_table_to_storage 함수가 처리 완료와 동시에 Parquet 파일로 저장하여 메모리 해제를 보장함.
  4. 가비지 컬렉션 최적화: 대용량 DataFrame 처리 후 명시적 참조 해제와 Python GC 트리거로 메모리 정리를 가속화함.

8.5 분산 실행 및 확장성 아키텍처

구현 의도
클러스터 환경에서의 수평 확장을 지원하는 분산 아키텍처를 구현함. 상태 관리와 증분 인덱싱을 통해 대규모 문서 컬렉션의 효율적 처리와 업데이트를 지원함:

if is_update_run:
    delta_dataset = await get_delta_docs(dataset, storage)
    update_storage = create_storage_from_config(config.update_index_output)
    update_timestamp = time.strftime("%Y%m%d-%H%M%S")
    timestamped_storage = update_storage.child(update_timestamp)

실행 결과
분산 아키텍처는 확장성과 내결함성을 제공하는 5가지 메커니즘을 포함함:

  1. 증분 인덱싱: 새로운 문서만 처리하여 전체 재계산을 방지함. 델타 감지 알고리즘이 기존 인덱스와 신규 입력을 비교하여 변경사항을 식별함.
  2. 상태 관리: context.jsonstats.json 파일로 파이프라인 상태를 지속적으로 추적함. 중단 시 마지막 완료 지점부터 재시작 가능한 체크포인트 메커니즘을 제공함:
state_json = await storage.get("context.json")
state = json.loads(state_json) if state_json else {}
  1. 타임스탬프 기반 버전 관리: 각 업데이트 실행에 고유한 타임스탬프를 부여하여 여러 버전의 인덱스를 동시 관리함. 롤백과 A/B 테스팅을 지원함.
  2. 저장소 분리: 이전 인덱스와 새 인덱스를 별도 저장소에 보관하여 안전한 업데이트를 보장함. 실패 시 이전 상태로 자동 복구 가능함.
  3. 통계 수집: 각 워크플로우의 실행 시간과 처리량을 측정하여 성능 모니터링과 최적화 지점 식별을 지원함:
context.stats.workflows[name] = {"overall": time.time() - work_time}
context.stats.total_runtime = time.time() - start_time

8.6 배치 처리 및 처리량 최적화

구현 의도
다양한 워크로드에 최적화된 배치 처리 전략을 구현함. API 제약사항, 메모리 한계, 처리 지연시간을 종합적으로 고려한 동적 배치 크기 조절로 최대 처리량을 달성함:

max_batch_size: int = 16
max_batch_tokens: int = 8191
batch_size: int = vector_store_config.get("batch_size") or DEFAULT_EMBEDDING_BATCH_SIZE

실행 결과
배치 최적화는 워크로드별 특성에 맞춘 6가지 전략을 제공함:

  1. 임베딩 배치: OpenAI API 제한에 맞춘 16개 텍스트/8191 토큰 이중 제약 조건을 적용함. 토큰 수 기반 동적 분할로 API 호출 효율성을 극대화함.
  2. LLM 추출 배치: 엔티티/관계 추출 시 텍스트 길이와 복잡도를 고려한 적응적 배치 크기를 적용함. Gleaning 과정에서는 개별 처리로 정확도를 우선시함.
  3. 벡터 스토어 배치: 각 벡터 데이터베이스의 특성에 맞춘 최적 배치 크기를 적용함. LanceDB는 대용량 배치, Azure AI Search는 중간 크기, CosmosDB는 소량 배치로 성능을 최적화함.
  4. 커뮤니티 처리 배치: 그래프 분석과 커뮤니티 감지는 메모리 집약적 특성으로 인해 작은 배치 크기를 사용함. 계층적 처리로 대규모 그래프도 효율적 처리가 가능함.
  5. 동적 조절: 시스템 리소스 상황에 따른 배치 크기 자동 조절 메커니즘을 포함함. 메모리 부족 시 배치 크기 감소, 여유 시 증가하여 최적 성능을 유지함.
  6. 처리량 모니터링: 초당 처리량(TPS) 측정을 통해 배치 크기와 동시성 설정의 효과를 실시간 평가함. 성능 저하 감지 시 자동 파라미터 조정을 수행함.

8.7 8단계 요약

GraphRAG의 성능 최적화 및 확장성 시스템은 엔터프라이즈급 대용량 처리를 위한 포괄적 아키텍처로 설계됨. 3가지 비동기 처리 방식과 4가지 캐시 전략을 통해 다양한 워크로드에 최적화된 성능을 제공함. 토큰 버킷 알고리즘 기반 속도 제한과 스트리밍 파이프라인으로 외부 API 비용을 최소화하며 메모리 효율성을 극대화함. 증분 인덱싱과 상태 관리를 통한 분산 실행 지원으로 페타바이트급 문서 컬렉션의 실시간 업데이트가 가능함. 워크로드별 최적화된 배치 처리 전략과 동적 파라미터 조절로 하드웨어 리소스 활용도를 극대화하여 처리 비용과 시간을 동시에 최적화함.