GraphRAG lets you build a knowledge graph from your documents and query it using a large language model (LLM).

Here’s how it works with LlamaIndex, using an example of summarizing community discussions.

Imagine you have a Slack channel or a forum where people are discussing a particular topic, say, "improving LlamaIndex performance." You want to get a concise summary of the key points, common questions, and proposed solutions discussed over several weeks.

First, you need to ingest your data. Let’s say you have a collection of Slack messages.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.graph_stores import NebulaGraphStore
from llama_index.core.indices.knowledge_graph import KnowledgeGraphIndex
from llama_index.core.schema import TextNode
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
import os

# Assuming your Slack messages are saved as text files in a directory named 'slack_data'
# Each file could represent a day or a thread.
reader = SimpleDirectoryReader("./slack_data")
documents = reader.load_data()

# Initialize embedding model and LLM
embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
llm = OpenAI(model="gpt-3.5-turbo")

Now, you’ll create a knowledge graph. LlamaIndex can extract entities and relationships from your text and store them. For this example, we’ll use an in-memory graph for simplicity, but you could connect to external graph databases like NebulaGraph or Neo4j.

# For demonstration, we'll use an in-memory graph.
# For persistent graph storage, you'd configure a graph store like NebulaGraphStore.
# graph_store = NebulaGraphStore(host="localhost", port=9669) # Example for NebulaGraph

# Create nodes from documents
nodes = []
for doc in documents:
    # Simple entity extraction: split by common separators or use NLP techniques
    # For a real-world scenario, you'd use more sophisticated Named Entity Recognition (NER)
    text_chunks = doc.text.split('\n\n') # Assuming double newline separates distinct messages/posts
    for i, chunk in enumerate(text_chunks):
        if chunk.strip(): # Ensure chunk is not empty
            node_id = f"{doc.id_}-{i}"
            nodes.append(TextNode(id_=node_id, text=chunk, metadata={"source": doc.metadata.get("file_name", "unknown")}))

# Build the Knowledge Graph Index
# This step involves the LLM identifying entities and relationships in the text
# and structuring them into a graph.
kg_index = KnowledgeGraphIndex(
    nodes=nodes,
    llm=llm,
    embed_model=embed_model,
    # graph_store=graph_store, # Uncomment to use an external graph store
    show_progress=True
)

The KnowledgeGraphIndex processes your documents. It uses the LLM to identify key entities (like "LlamaIndex," "performance," "indexing," "query engine") and the relationships between them (e.g., "LlamaIndex" improves "performance," "indexing" affects "query engine"). These become nodes and edges in your graph.

Once the graph is built, you can query it. LlamaIndex translates your natural language questions into graph traversals and LLM prompts to retrieve and synthesize answers.

# Create a query engine for the knowledge graph
kg_query_engine = kg_index.as_query_engine()

# Example query: "What are the main challenges discussed regarding LlamaIndex performance?"
response = kg_query_engine.query(
    "What are the main challenges discussed regarding LlamaIndex performance and what solutions were proposed?"
)

print(response)

The query engine will first identify relevant nodes and edges in the graph that match your query terms. It then uses the LLM to synthesize this information into a coherent answer. For instance, if the graph contains nodes like "slow query times" and "memory usage" linked to "LlamaIndex performance" as challenges, and nodes like "vector indexing optimization" and "batch processing" linked as solutions, the LLM will combine these to form a summary.

This approach is powerful for summarizing discussions because it can identify recurring themes and connections that might be buried in a long stream of text. It moves beyond simple keyword matching to understanding the semantic relationships within the conversation.

The real power of GraphRAG lies in its ability to reconstruct context. Instead of just retrieving documents based on keyword similarity, it retrieves structured knowledge derived from those documents. This means an LLM can reason over relationships, understand causality, and provide more nuanced answers. For example, if a discussion mentioned "user A suggested X, which led to Y problem for user B," a graph can represent this sequence and dependency, allowing the LLM to answer questions about the impact of suggestions.

When you’re working with large datasets and complex interactions, the LLM’s context window becomes a bottleneck. GraphRAG circumvents this by pre-processing the information into a structured graph. The LLM then only needs to process relevant subgraphs or specific relationships, making summarization and question-answering much more efficient and effective.

The next step is often exploring advanced graph querying techniques, such as traversing multiple hops or applying graph algorithms to identify central themes or community consensus.

Want structured learning?

Take the full Llamaindex course →