advanced35 min read

GraphRAG

Use knowledge graphs to capture entity relationships for relationship-aware retrieval.

Learning Objectives

  • Understand knowledge graphs and their role in RAG
  • Learn entity and relationship extraction
  • Implement graph-based retrieval with Neo4j
  • Compare GraphRAG with vector search approaches

What is GraphRAG?

GraphRAG uses knowledge graphs — structured representations of entities and their relationships — instead of or alongside vector-based retrieval. While vector search treats documents as isolated chunks, GraphRAG captures how concepts connect to each other, enabling relationship-aware retrieval. Example Scenario: A student asks, "How does Django connect Python code to a database?" In a vector-based system, relevant chunks about Django, Python, and databases might be retrieved separately. In GraphRAG, the system can traverse the knowledge graph: • Python → [HAS_FRAMEWORK] → Django • Django → [INCLUDES] → Django ORM • Django ORM → [CONNECTS_TO] → Database • Django ORM → [USES] → Models This traversal provides structured, relationship-aware context that helps the LLM generate a more coherent answer about how these components connect.

Knowledge Graphs Explained

A knowledge graph consists of: Entities (Nodes): Concepts, objects, or things. Examples: "Python", "Django", "PostgreSQL", "ORM" Relationships (Edges): Connections between entities with labeled types. Examples: "HAS_FRAMEWORK", "CONNECTS_TO", "USED_BY" Properties: Attributes attached to entities or relationships. Examples: Entity "Django" has property "version: 4.2" Why Knowledge Graphs for RAG? • Multi-hop reasoning: Answer questions that require connecting information across multiple documents • Structural understanding: Capture hierarchies, dependencies, and associations • Disambiguation: Distinguish between entities with the same name based on their relationships • Community detection: Identify clusters of related concepts for summarization When GraphRAG is More Useful Than Vector Search: • Questions about relationships between concepts • Multi-hop reasoning (connecting A to C through B) • Queries requiring structural understanding (hierarchies, dependencies) • When the knowledge base has rich entity relationships When Vector Search is Sufficient: • Direct factual questions answerable from a single chunk • Keyword or semantic matching • When the knowledge base is primarily narrative text without strong entity relationships

Entity and Relationship Extraction

Building a knowledge graph from documents requires extracting entities and relationships. This can be done with LLMs or specialized NLP models. LLM-Based Extraction: Use a language model to identify entities and relationships from text. This is flexible and handles diverse text but can be expensive at scale. NER + Relation Extraction: Use dedicated Named Entity Recognition and relation extraction models. More efficient but may require domain-specific training.
entity_extraction.pypython
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0)

def extract_entities_and_relations(text: str) -> dict:
    """Extract entities and relationships from text using LLM."""
    response = llm.invoke(
        f"""Extract all entities and relationships from the following text.
        
        Format each relationship as: (Entity1) -[RELATIONSHIP_TYPE]-> (Entity2)
        
        Also list each unique entity with a brief description.
        
        Text: {text}
        
        Entities:
        Relationships:"""
    )
    return response.content

text = """Django is a high-level Python web framework. It uses an ORM 
(Object-Relational Mapping) to connect Python objects to database tables. 
Django supports PostgreSQL, MySQL, and SQLite databases."""

result = extract_entities_and_relations(text)
print(result)
# Expected output:
# Entities:
# - Django: A high-level Python web framework
# - Python: Programming language
# - ORM: Object-Relational Mapping system
# - PostgreSQL: Relational database
# - MySQL: Relational database  
# - SQLite: Lightweight database
#
# Relationships:
# (Django) -[IS_FRAMEWORK_FOR]-> (Python)
# (Django) -[USES]-> (ORM)
# (ORM) -[MAPS]-> (Python objects) to (database tables)
# (Django) -[SUPPORTS]-> (PostgreSQL)
# (Django) -[SUPPORTS]-> (MySQL)
# (Django) -[SUPPORTS]-> (SQLite)

Graph-Based Retrieval with Neo4j

Neo4j is a popular graph database for implementing GraphRAG. It uses the Cypher query language for graph traversal and pattern matching.
Microsoft GraphRAG
Microsoft's GraphRAG approach specifically focuses on building hierarchical community summaries from knowledge graphs for global query answering. This is different from generic graph-based RAG, which focuses on entity traversal. Both are valid approaches with different strengths.
graphrag_neo4j.pypython
from neo4j import GraphDatabase

driver = GraphDatabase.driver(
    "bolt://localhost:7687", 
    auth=("neo4j", "password")
)

def create_knowledge_graph(session):
    """Build a knowledge graph from extracted entities."""
    session.run("""
        CREATE (python:Technology {name: 'Python', type: 'Language'})
        CREATE (django:Framework {name: 'Django', type: 'Web Framework'})
        CREATE (orm:Component {name: 'Django ORM', type: 'ORM'})
        CREATE (pg:Database {name: 'PostgreSQL', type: 'RDBMS'})
        
        CREATE (django)-[:BUILT_WITH]->(python)
        CREATE (django)-[:INCLUDES]->(orm)
        CREATE (orm)-[:CONNECTS_TO]->(pg)
        CREATE (orm)-[:MAPS {description: 'Python objects to database tables'}]->(pg)
    """)

def graph_retrieval(session, question: str) -> str:
    """Retrieve relevant subgraph for a question."""
    # Extract key entity from question
    entity = extract_key_entity(question)  # e.g., "Django"
    
    # Traverse graph to find related nodes within 2 hops
    result = session.run("""
        MATCH (start {name: $entity})-[r*1..2]-(connected)
        RETURN start.name AS source,
               [rel IN r | type(rel)] AS relationships,
               connected.name AS target,
               connected.type AS target_type
    """, entity=entity)
    
    # Format as context for LLM
    context_parts = []
    for record in result:
        path = f"{record['source']} -> {' -> '.join(record['relationships'])} -> {record['target']} ({record['target_type']})"
        context_parts.append(path)
    
    return "\n".join(context_parts)

with driver.session() as session:
    context = graph_retrieval(session, "How does Django connect to databases?")
    print(context)
    # Django -> INCLUDES -> Django ORM (ORM)
    # Django ORM -> CONNECTS_TO -> PostgreSQL (RDBMS)
    # Django -> BUILT_WITH -> Python (Language)

Key Takeaways

  • ✓GraphRAG captures entity relationships that vector search misses
  • ✓Knowledge graphs consist of entities (nodes) and relationships (edges)
  • ✓Entity extraction can be done with LLMs or specialized NLP models
  • ✓Neo4j with Cypher enables graph traversal for relationship-aware retrieval
  • ✓GraphRAG is most valuable for multi-hop reasoning and relationship queries
  • ✓Microsoft's GraphRAG uses community summaries; generic GraphRAG uses entity traversal