PropertyGraph Index 활용하기

PropertyGraph Index 활용하기 (Mistral AI + LlamaIndex)

LlamaIndex의 PropertyGraphIndex 기본 사용법을 보여주는 노트북이에요. 비정형 문서를 처리해 property graph를 추출하고, 이 그래프를 다양한 방법으로 질의합니다. 저장·로드, 벡터 스토어 조합까지 함께 다룹니다.

출처: 문서

본문

설정 (Setup)

필요한 패키지를 설치하고 API 키를 설정합니다.

%pip install llama-index-core
%pip install llama-index-llms-mistralai
%pip install llama-index-embeddings-mistralai
import nest_asyncio
nest_asyncio.apply()
from IPython.display import Markdown, display
import os
os.environ['MISTRAL_API_KEY'] = 'YOUR MISTRAL API KEY'

Mistral LLM과 임베딩 모델을 설정합니다.

from llama_index.embeddings.mistralai import MistralAIEmbedding
from llama_index.llms.mistralai import MistralAI

llm = MistralAI(model='mistral-large-latest')
embed_model = MistralAIEmbedding()

데이터 다운로드·로드

!mkdir -p 'data/paul_graham/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data/paul_graham/").load_data()

PropertyGraphIndex 만들기

PropertyGraph 생성 과정에서 일어나는 일은 다음과 같아요.

  1. PropertyGraphIndex.from_documents(): 문서를 인덱스로 로드합니다.
  2. 노드 파싱(Parsing Nodes): 인덱스가 문서를 노드로 파싱합니다.
  3. 텍스트에서 경로 추출(Extracting Paths from Text): 노드를 LLM에 넘겨 지식 그래프 트리플(즉, 경로)을 생성하도록 프롬프트합니다.
  4. 암시적 경로 추출(Extracting Implicit Paths): node.relationships 속성으로 암시적 경로를 추론합니다.
  5. 임베딩 생성(Generating Embeddings): 각 텍스트 노드와 그래프 노드의 임베딩을 생성하며, 이 과정 중 두 번 발생합니다.
from llama_index.core import PropertyGraphIndex

index = PropertyGraphIndex.from_documents(
    documents,
    llm=llm,
    embed_model=embed_model,
    show_progress=True,
)

디버깅을 위해 기본 SimplePropertyGraphStore는 그래프의 networkx 표현을 html 파일로 저장하는 헬퍼를 제공합니다.

index.property_graph_store.save_networkx_graph(name="./kg.html")
from llama_index.core import Settings
Settings.llm = llm
Settings.embed_model = embed_model

질의하기 (Querying)

PropertyGraph 인덱스 질의는 일반적으로 하나 이상의 하위 검색기(sub-retriever)를 사용하고 그 결과를 결합합니다. 그래프 검색 과정은 다음을 포함해요.

  • 노드 선택(Selecting Nodes): 그래프에서 관심의 시작점이 되는 노드를 식별합니다.
  • 탐색(Traversing): 선택된 노드에서 연결된 요소들을 탐색합니다.

기본적으로 다음 두 가지 유형의 검색을 동시에 사용합니다.

  • 동의어/키워드 확장(Synonym/Keyword Expansion): LLM으로 질의에서 파생된 동의어와 키워드를 생성합니다.
  • 벡터 검색(Vector Retrieval): 임베딩으로 그래프 안의 노드를 찾습니다.

노드가 식별되면 다음을 선택할 수 있어요.

  • 경로 반환(Return Paths): 선택된 노드에 인접한 경로를 제공하며, 보통 트리플 형태입니다.
  • 경로와 원본 텍스트 반환(Return Paths and Source Text): 경로와 청크의 원본 소스 텍스트(가능하면)를 모두 제공합니다.
retriever = index.as_retriever(
    include_text=False,  # include source text, default True
)

nodes = retriever.retrieve("What happened at Interleaf and Viaweb?")
for node in nodes:
    print(node.text)
query_engine = index.as_query_engine(
    include_text=True
)
response = query_engine.query("What happened at Interleaf and Viaweb?")
display(Markdown(f"{response.response}"))

저장 (Storage)

기본적으로 저장은 단순한 인메모리 추상화로 관리돼요. 임베딩은 SimpleVectorStore, property graph는 SimplePropertyGraphStore가 담당합니다. 이 구조물들을 디스크에 저장·로드할 수 있습니다.

index.storage_context.persist(persist_dir="./storage")
from llama_index.core import StorageContext, load_index_from_storage

index = load_index_from_storage(
    StorageContext.from_defaults(persist_dir="./storage")
)

query_engine = index.as_query_engine(
    include_text=True
)
response = query_engine.query("What happened at Interleaf and Viaweb?")
display(Markdown(f"{response.response}"))

벡터 스토어 (Vector Stores)

Neo4j 같은 일부 그래프 DB는 벡터를 지원하지만, 벡터를 지원하지 않는 경우나 기본 설정을 덮어쓰고 싶을 때 그래프와 함께 사용할 벡터 스토어를 지정할 수 있어요. 아래에서는 ChromaVectorStore를 기본 SimplePropertyGraphStore와 조합해 봅니다.

%pip install llama-index-vector-stores-chroma
from llama_index.core.graph_stores import SimplePropertyGraphStore
from llama_index.vector_stores.chroma import ChromaVectorStore
import chromadb

client = chromadb.PersistentClient("./chroma_db")
collection = client.get_or_create_collection("my_graph_vector_db")

index = PropertyGraphIndex.from_documents(
    documents,
    llm=llm,
    embed_model=embed_model,
    property_graph_store=SimplePropertyGraphStore(),
    vector_store=ChromaVectorStore(chroma_collection=collection),
    show_progress=True,
)

index.storage_context.persist(persist_dir="./storage")

저장된 인덱스를 다시 로드해 쿼리 엔진으로 사용합니다.

index = PropertyGraphIndex.from_existing(
    SimplePropertyGraphStore.from_persist_dir("./storage"),
    vector_store=ChromaVectorStore(chroma_collection=collection),
    llm=llm,
)

query_engine = index.as_query_engine(
    include_text=True
)
response = query_engine.query("why did author do at YC?")
display(Markdown(f"{response.response}"))

더 알아보기 (Learn more)

  • LlamaIndex PropertyGraphIndex 문서 — 지식 그래프 기반 인덱스 가이드
  • SimplePropertyGraphStore / SimpleVectorStore — 기본 인메모리 그래프·벡터 스토어
  • PropertyGraphIndex.from_existing() — 저장된 그래프로 인덱스 복원
  • ChromaVectorStore — Chroma 기반 벡터 스토어 어댑터