Tutorial GraphRAG: Retrieval Augmented Generation Berbasis Graph Knowledge
Pendahuluan
Retrieval Augmented Generation (RAG) telah menjadi pendekatan standar untuk menghubungkan Large Language Model (LLM) dengan data eksternal. Namun, RAG tradisional memiliki keterbatasan signifikan: ia hanya melakukan pencarian berbasis kesamaan vektor (similarity search) tanpa memahami hubungan antar entitas dalam dokumen. Di sinilah GraphRAG hadir sebagai solusi.
GraphRAG, yang dikembangkan oleh Microsoft Research, menggabungkan kekuatan knowledge graph dengan RAG untuk menghasilkan jawaban yang lebih komprehensif dan kontekstual. Alih-alih hanya mencari potongan teks yang mirip dengan query, GraphRAG membangun graph pengetahuan dari dokumen, mengidentifikasi entitas dan hubungan antar entitas, lalu menggunakan struktur graph tersebut untuk menjawab pertanyaan yang membutuhkan pemahaman holistik.
Dalam tutorial ini, kita akan mempelajari cara menggunakan library graphrag dari Microsoft untuk membangun sistem RAG berbasis knowledge graph dari awal hingga siap digunakan.
Mengapa GraphRAG?
RAG tradisional bekerja dengan baik untuk pertanyaan yang jawabannya terdapat dalam satu atau beberapa potongan teks. Namun, RAG tradisional kesulitan menjawab pertanyaan yang membutuhkan sintesis informasi dari banyak sumber, seperti:
- "Apa tema utama yang dibahas dalam seluruh dokumen ini?"
- "Bagaimana hubungan antara departemen A dan departemen B dalam organisasi?"
- "Sebutkan semua proyek yang melibatkan teknologi X dan orang Y"
GraphRAG mengatasi keterbatasan ini dengan dua pendekatan query:
Instalasi
Prasyarat
- Python 3.10 atau lebih baru
- API key dari OpenAI atau Azure OpenAI (untuk LLM dan embedding)
- Minimal 8GB RAM (proses indexing membutuhkan memori yang cukup besar)
Instalasi Library
pip install graphrag
Untuk versi terbaru dari repository:
pip install git+https://github.com/microsoft/graphrag.git
Verifikasi instalasi:
import graphrag
print(graphrag.version)
Menyiapkan API Key
GraphRAG membutuhkan LLM untuk proses ekstraksi entitas dan pembuatan ringkasan. Siapkan API key OpenAI:
export GRAPHRAGAPIKEY="sk-your-openai-api-key"
Atau untuk Azure OpenAI:
export GRAPHRAGAPIKEY="your-azure-api-key"
export GRAPHRAGAPIBASE="https://your-resource.openai.azure.com"
export GRAPHRAGAPIVERSION="2024-06-01"
Inisialisasi Proyek
Membuat Struktur Proyek
mkdir graphrag-demo
cd graphrag-demo
python -m graphrag init --root .
Perintah ini akan menghasilkan struktur direktori:
graphrag-demo/
├── settings.yaml # Konfigurasi utama
├── .env # Environment variables
└── input/ # Folder untuk dokumen sumber
Menyiapkan Dokumen Input
Letakkan dokumen teks yang ingin diindeks ke dalam folder input/. GraphRAG mendukung file .txt dan .csv.
mkdir -p input
Sebagai contoh, kita akan membuat beberapa dokumen sampel tentang sebuah perusahaan teknologi fiktif:
# createsampledata.py
import os
documents = {
"companyoverview.txt": """
PT Teknologi Nusantara adalah perusahaan teknologi yang didirikan pada tahun 2020
di Jakarta. Perusahaan ini fokus pada pengembangan solusi kecerdasan buatan untuk
sektor perbankan dan kesehatan. CEO perusahaan adalah Budi Santoso yang sebelumnya
bekerja di Google selama 10 tahun.
Perusahaan memiliki tiga divisi utama: Divisi AI Research yang dipimpin oleh
Dr. Siti Rahayu, Divisi Product Development yang dipimpin oleh Ahmad Wijaya,
dan Divisi Business Development yang dipimpin oleh Maya Kusuma.
PT Teknologi Nusantara telah mendapatkan pendanaan Series B sebesar 50 juta USD
dari Sequoia Capital dan East Ventures pada tahun 2023. Perusahaan saat ini
memiliki 200 karyawan yang tersebar di Jakarta, Bandung, dan Surabaya.
""",
"projects.txt": """
Proyek utama PT Teknologi Nusantara meliputi:
MedAI - Platform diagnostik berbasis AI untuk rumah sakit. Proyek ini dipimpin
oleh Dr. Siti Rahayu dan timnya di Divisi AI Research. MedAI menggunakan model
computer vision untuk analisis citra medis dan telah digunakan oleh 15 rumah sakit
di Indonesia.
FinGuard - Sistem deteksi fraud untuk bank menggunakan machine learning.
Dikembangkan oleh Ahmad Wijaya bersama tim Product Development. FinGuard mampu
mendeteksi transaksi mencurigakan dengan akurasi 99.2% dan telah diadopsi oleh
5 bank nasional.
DataBridge - Platform integrasi data yang menghubungkan berbagai sumber data
enterprise. Proyek kolaborasi antara Divisi Product Development dan Divisi AI
Research. DataBridge mendukung 50+ konektor data dan digunakan oleh 30 perusahaan.
""",
"partnerships.txt": """
PT Teknologi Nusantara menjalin kemitraan strategis dengan beberapa institusi:
- Universitas Indonesia: Kolaborasi riset di bidang NLP Bahasa Indonesia.
Dr. Siti Rahayu menjadi adjunct professor dan membimbing 5 mahasiswa S3.
- Bank Mandiri: Implementasi FinGuard untuk deteksi fraud real-time.
Maya Kusuma memimpin negosiasi kontrak senilai 10 juta USD selama 3 tahun.
- RS Cipto Mangunkusumo: Pilot project MedAI untuk diagnostik radiologi.
Tim AI Research bekerja langsung dengan dokter spesialis radiologi.
- AWS: Partnership untuk cloud infrastructure. PT Teknologi Nusantara
mendapatkan status AWS Advanced Technology Partner dan kredit cloud
sebesar 500 ribu USD.
- Telkom Indonesia: Joint venture untuk pengembangan AI solution bagi
UMKM Indonesia. Budi Santoso dan CEO Telkom menandatangani MoU pada
Januari 2024.
"""
}
os.makedirs("input", existok=True)
for filename, content in documents.items():
with open(f"input/{filename}", "w") as f:
f.write(content)
print("Sample documents created successfully!")
python createsampledata.py
Konfigurasi
File settings.yaml
Edit file settings.yaml untuk menyesuaikan konfigurasi:
llm:
apikey: ${GRAPHRAGAPIKEY}
type: openaichat
model: gpt-4o-mini
maxtokens: 4096
temperature: 0
parallelization:
stagger: 0.3
asyncmode: threaded
embeddings:
asyncmode: threaded
llm:
apikey: ${GRAPHRAGAPIKEY}
type: openaiembedding
model: text-embedding-3-small
chunks:
size: 1200
overlap: 100
entityextraction:
maxgleanings: 1
communityreports:
maxlength: 2000
claimextraction:
enabled: false
storage:
type: file
basedir: "output"
reporting:
type: file
basedir: "logs"
Penjelasan Konfigurasi Penting
| Parameter | Fungsi | Rekomendasi |
|-----------|--------|-------------|
| llm.model | Model LLM untuk ekstraksi | gpt-4o-mini untuk hemat biaya, gpt-4o untuk kualitas |
| chunks.size | Ukuran potongan teks | 1200-1500 karakter optimal |
| chunks.overlap | Overlap antar chunk | 100-200 karakter |
| entityextraction.maxgleanings | Iterasi tambahan ekstraksi | 0-2, lebih tinggi = lebih lengkap tapi lebih mahal |
| claimextraction.enabled | Ekstraksi klaim/fakta | false untuk menghemat token |
Indexing (Membangun Knowledge Graph)
Proses indexing adalah tahap terpenting di mana GraphRAG akan:
python -m graphrag index --root .
Proses ini membutuhkan waktu beberapa menit hingga jam tergantung volume dokumen dan model yang digunakan. Output akan disimpan di folder output/.
Memahami Hasil Indexing
Setelah indexing selesai, periksa folder output/:
import pandas as pd
import os
outputdir = "output"
Melihat entitas yang diekstrak
entities = pd.readparquet(f"{outputdir}/entities.parquet")
print(f"Total entitas: {len(entities)}")
print(entities[["title", "type", "description"]].head(10))
# Melihat hubungan antar entitas
relationships = pd.readparquet(f"{outputdir}/relationships.parquet")
print(f"\nTotal hubungan: {len(relationships)}")
print(relationships[["source", "target", "description"]].head(10))
# Melihat komunitas yang terdeteksi
communities = pd.readparquet(f"{outputdir}/communities.parquet")
print(f"\nTotal komunitas: {len(communities)}")
print(communities[["title", "summary"]].head())
Output yang diharapkan:
Total entitas: 25
title type description
0 PT TEKNOLOGI NUSANTARA ORGANIZATION Perusahaan teknologi di Jakarta...
1 BUDI SANTOSO PERSON CEO PT Teknologi Nusantara...
2 DR. SITI RAHAYU PERSON Kepala Divisi AI Research...
3 AHMAD WIJAYA PERSON Kepala Divisi Product Development...
4 MAYA KUSUMA PERSON Kepala Divisi Business Development...
Total hubungan: 30
source target description
0 BUDI SANTOSO PT TEKNOLOGI NUSANTARA CEO perusahaan...
1 DR. SITI RAHAYU DIVISI AI RESEARCH Memimpin divisi...
2 MEDAI DR. SITI RAHAYU Proyek dipimpin oleh...
Melakukan Query
Local Search
Local Search cocok untuk pertanyaan spesifik tentang entitas tertentu:
python -m graphrag query \
--root . \
--method local \
--query "Apa saja proyek yang dipimpin oleh Dr. Siti Rahayu?"
Untuk menggunakan Local Search secara programatik:
import asyncio
from graphrag.query.indexeradapters import (
readindexerentities,
readindexerrelationships,
readindexertextunits,
readindexerreports,
)
from graphrag.query.llm.oai.chatopenai import ChatOpenAI
from graphrag.query.llm.oai.embedding import OpenAIEmbedding
from graphrag.query.structuredsearch.localsearch.mixedcontext import LocalSearchMixedContext
from graphrag.query.structuredsearch.localsearch.search import LocalSearch
from graphrag.vectorstores.lancedb import LanceDBVectorStore
async def runlocalsearch(query: str):
outputdir = "output"
# Load data
entities = readindexerentities(outputdir)
relationships = readindexerrelationships(outputdir)
textunits = readindexertextunits(outputdir)
reports = readindexerreports(outputdir, "community")
# Setup LLM
llm = ChatOpenAI(
model="gpt-4o-mini",
apikey=os.environ["GRAPHRAGAPIKEY"],
)
embedding = OpenAIEmbedding(
model="text-embedding-3-small",
apikey=os.environ["GRAPHRAGAPIKEY"],
)
# Setup vector store
descriptionembeddingstore = LanceDBVectorStore(
collectionname="entitydescriptionembeddings"
)
descriptionembeddingstore.connect(dburi="output/lancedb")
# Build context
contextbuilder = LocalSearchMixedContext(
entities=entities,
entitytextembeddings=descriptionembeddingstore,
relationships=relationships,
textunits=textunits,
communityreports=reports,
embedding=embedding,
tokenencoder=None,
)
# Create search engine
searchengine = LocalSearch(
llm=llm,
contextbuilder=contextbuilder,
tokenencoder=None,
responsetype="multiple paragraphs",
)
result = await searchengine.asearch(query)
print(result.response)
return result
Jalankan query
asyncio.run(runlocalsearch(
"Apa saja proyek yang dipimpin oleh Dr. Siti Rahayu?"
))
Global Search
Global Search cocok untuk pertanyaan yang membutuhkan pemahaman menyeluruh dari seluruh dokumen:
python -m graphrag query \
--root . \
--method global \
--query "Apa tema dan fokus utama PT Teknologi Nusantara?"
Untuk menggunakan Global Search secara programatik:
from graphrag.query.structuredsearch.globalsearch.search import GlobalSearch
from graphrag.query.structured
search.globalsearch.communitycontext import GlobalCommunityContext
async def runglobalsearch(query: str):
outputdir = "output"
reports = readindexerreports(outputdir, "community")
entities = readindexerentities(outputdir)
llm = ChatOpenAI(
model="gpt-4o-mini",
apikey=os.environ["GRAPHRAGAPIKEY"],
)
contextbuilder = GlobalCommunityContext(
communityreports=reports,
entities=entities,
tokenencoder=None,
)
searchengine = GlobalSearch(
llm=llm,
contextbuilder=contextbuilder,
tokenencoder=None,
responsetype="multiple paragraphs",
maxdatatokens=12000,
)
result = await searchengine.asearch(query)
print(result.response)
return result
asyncio.run(runglobalsearch(
"Apa tema dan fokus utama PT Teknologi Nusantara?"
))
Perbandingan Local vs Global Search
| Aspek | Local Search | Global Search |
|-------|-------------|---------------|
| Cocok untuk | Pertanyaan spesifik tentang entitas | Pertanyaan tematik/holistik |
| Konteks | Entitas relevan + tetangga di graph | Ringkasan semua komunitas |
| Kecepatan | Lebih cepat | Lebih lambat |
| Biaya token | Lebih rendah | Lebih tinggi |
| Contoh | "Siapa CEO perusahaan X?" | "Apa tren utama di industri ini?" |
Advanced Usage
Custom Entity Types
Secara default, GraphRAG mengekstrak entitas bertipe PERSON, ORGANIZATION, LOCATION, dan EVENT. Anda bisa menambahkan tipe kustom:
# settings.yaml
entityextraction:
entitytypes:
- PERSON
- ORGANIZATION
- LOCATION
- EVENT
- TECHNOLOGY
- PRODUCT
- PROJECT
maxgleanings: 1
Menggunakan Model Lokal dengan Ollama
GraphRAG mendukung model lokal melalui API yang kompatibel dengan OpenAI:
# settings.yaml
llm:
apikey: ollama
type: openaichat
model: llama3.1
apibase: http://localhost:11434/v1
maxtokens: 4096
embeddings:
llm:
apikey: ollama
type: openaiembedding
model: nomic-embed-text
apibase: http://localhost:11434/v1
Pastikan Ollama sudah berjalan dan model sudah di-pull:
ollama pull llama3.1
ollama pull nomic-embed-text
Visualisasi Knowledge Graph
Anda bisa memvisualisasikan graph yang dihasilkan menggunakan NetworkX dan matplotlib:
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
Load data
entities = pd.readparquet("output/entities.parquet")
relationships = pd.readparquet("output/relationships.parquet")
Buat graph
G = nx.Graph()
Tambahkan node
for , entity in entities.iterrows():
G.addnode(entity["title"], type=entity["type"])
Tambahkan edge
for , rel in relationships.iterrows():
G.addedge(rel["source"], rel["target"], description=rel["description"])
Warna berdasarkan tipe entitas
colormap = {
"PERSON": "#FF6B6B",
"ORGANIZATION": "#4ECDC4",
"LOCATION": "#45B7D1",
"EVENT": "#96CEB4",
"PROJECT": "#FFEAA7",
}
colors = [colormap.get(G.nodes[node].get("type", ""), "#DDA0DD") for node in G.nodes()]
Visualisasi
plt.figure(figsize=(16, 12))
pos = nx.springlayout(G, k=2, iterations=50, seed=42)
nx.draw(
G, pos,
nodecolor=colors,
nodesize=2000,
fontsize=8,
fontweight="bold",
withlabels=True,
edgecolor="#cccccc",
width=1.5,
alpha=0.9,
)
plt.title("Knowledge Graph - PT Teknologi Nusantara", fontsize=16)
plt.tightlayout()
plt.savefig("knowledgegraph.png", dpi=150)
plt.show()
print("Graph saved to knowledgegraph.png")
Incremental Indexing
Untuk menambahkan dokumen baru tanpa membangun ulang seluruh graph:
# Tambahkan dokumen baru ke folder input
cp newdocument.txt input/
Jalankan indexing dengan mode update
python -m graphrag update --root .
Integrasi dengan LangChain
GraphRAG bisa diintegrasikan dengan LangChain untuk membangun aplikasi yang lebih kompleks:
from langchain.retrievers import BaseRetriever
from langchain.schema import Document
from typing import List
import asyncio
class GraphRAGRetriever(BaseRetriever):
"""Custom retriever yang menggunakan GraphRAG untuk pencarian."""
searchengine: object = None
searchtype: str = "local"
class Config:
arbitrarytypesallowed = True
def getrelevantdocuments(self, query: str) -> List[Document]:
result = asyncio.run(self.searchengine.asearch(query))
return [Document(
pagecontent=result.response,
metadata={"contextdata": str(result.contextdata)}
)]
Penggunaan dengan LangChain
from langchain.chains import RetrievalQA
from langchainopenai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
retriever = GraphRAGRetriever(searchengine=searchengine)
qachain = RetrievalQA.fromchaintype(
llm=llm,
retriever=retriever,
chaintype="stuff",
)
answer = qachain.invoke("Jelaskan partnership PT Teknologi Nusantara")
print(answer["result"])
Best Practices
1. Persiapan Dokumen
- Bersihkan data: Hapus header/footer yang berulang, nomor halaman, dan artefak lainnya
- Format konsisten: Gunakan format teks biasa (.txt) untuk hasil terbaik
- Granularitas tepat: Satu file per topik/bagian lebih baik daripada satu file monolitik besar
- Bahasa konsisten: Hindari mencampur bahasa dalam satu dokumen jika memungkinkan
2. Optimasi Biaya
- Gunakan
gpt-4o-miniuntuk indexing (hemat 10-20x dibanding gpt-4o) - Set
claimextraction.enabled: falsejika tidak diperlukan - Kurangi
maxgleaningsmenjadi 0 untuk dokumen yang sudah terstruktur dengan baik - Monitor penggunaan token melalui log di folder
logs/
# Estimasi biaya indexing
import tiktoken
def estimatecost(inputdir: str, model: str = "gpt-4o-mini"):
enc = tiktoken.encodingformodel(model)
totaltokens = 0
for filename in os.listdir(inputdir):
if filename.endswith(".txt"):
with open(f"{inputdir}/{filename}") as f:
text = f.read()
totaltokens += len(enc.encode(text))
multiplier = 5
estimatedtokens = totaltokens multiplier
costper1m = 0.15 # gpt-4o-mini input
estimatedcost = (estimatedtokens / 1000000) costper1m
print(f"Total input tokens: {totaltokens:,}")
print(f"Estimated processing tokens: {estimatedtokens:,}")
print(f"Estimated cost: ${estimatedcost:.4f}")
estimatecost("input")
3. Tuning Kualitas Graph
- Chunk size: Chunk terlalu kecil kehilangan konteks, terlalu besar mengaburkan entitas. 1200-1500 karakter adalah titik awal yang baik
- Entity types: Tambahkan tipe entitas kustom yang relevan dengan domain Anda
- Gleanings: Tingkatkan
maxgleaningsmenjadi 2-3 untuk dokumen kompleks dengan banyak entitas yang saling terkait - Community detection: Algoritma Leiden otomatis mengelompokkan entitas terkait, hasilnya bisa diperiksa di
communities.parquet
4. Skalabilitas
# Untuk dataset besar, gunakan async mode dan paralelisasi
settings.yaml
"""
parallelization:
stagger: 0.5
numthreads: 4
asyncmode: threaded
snapshots:
graphml: true # Simpan graph dalam format GraphML untuk analisis lanjutan
"""
5. Evaluasi Kualitas
# Script sederhana untuk mengevaluasi kualitas graph
import pandas as pd
def evaluategraphquality(outputdir: str):
entities = pd.readparquet(f"{outputdir}/entities.parquet")
relationships = pd.readparquet(f"{outputdir}/relationships.parquet")
communities = pd.readparquet(f"{outputdir}/communities.parquet")
print("=== Graph Quality Report ===")
print(f"Entities: {len(entities)}")
print(f"Relationships: {len(relationships)}")
print(f"Communities: {len(communities)}")
print(f"Avg relationships per entity: {len(relationships)/len(entities):.1f}")
# Entitas tanpa hubungan (orphans)
connected = set(relationships["source"].tolist() + relationships["target"].tolist())
orphans = entities[~entities["title"].isin(connected)]
print(f"Orphan entities: {len(orphans)}")
if len(orphans) > 0:
print(f" -> {orphans['title'].tolist()}")
# Distribusi tipe entitas
print("\nEntity type distribution:")
print(entities["type"].valuecounts().tostring())
evaluategraphquality("output")
Troubleshooting
Error Umum dan Solusi
1. Rate Limit Erroropenai.RateLimitError: Rate limit reached
Solusi: Tingkatkan parallelization.stagger di settings.yaml menjadi 1.0 atau lebih.
Token limit exceeded for entity extraction
Solusi: Kurangi chunks.size atau gunakan model dengan context window lebih besar.
Jika graph yang dihasilkan kosong atau sangat sedikit entitas:
- Pastikan dokumen input tidak terlalu pendek (minimal beberapa paragraf)
- Periksa bahasa dokumen sesuai dengan prompt yang digunakan
- Coba tingkatkan
maxgleanings
# Gunakan batching untuk dataset besar
python -m graphrag index --root . --limit 100
Kesimpulan
GraphRAG menawarkan pendekatan yang jauh lebih canggih dibandingkan RAG tradisional untuk kasus-kasus yang membutuhkan pemahaman kontekstual dan hubungan antar entitas. Berikut ringkasan key takeaways:
GraphRAG sangat cocok untuk use case seperti analisis dokumen hukum, riset akademis, intelligence reporting, dan knowledge management enterprise di mana hubungan antar entitas sangat penting untuk menghasilkan jawaban yang akurat dan komprehensif.
Untuk eksplorasi lebih lanjut, kunjungi repository resmi Microsoft GraphRAG dan dokumentasinya untuk melihat fitur-fitur terbaru dan contoh penggunaan yang lebih kompleks.