All posts
May 18, 2026

GraphMemory: Building Deep Knowledge Graphs with DuckDB

Learn how to build and query embedded GraphRAG knowledge graphs with GraphMemory and DuckDB. Hybrid search, fuzzy deduping, and easy extraction.

Why GraphMemory is the Missing Piece for RAG

Standard Retrieval-Augmented Generation (RAG) often suffers from a lack of context. If you only use vector search, you are retrieving isolated snippets of text that happen to share semantic similarity. But real-world data is connected. If you want your AI to understand that 'Alice' works for 'Company B' which is a subsidiary of 'Enterprise C,' simple flat vector search isn't enough. You need a graph.

Enter graphmemory. Built by bradAGI, this skill provides an embedded GraphRAG database powered by DuckDB. It allows you to store entities and relations, run multi-hop traversals, and perform hybrid searches—all without the overhead of maintaining a standalone Neo4j or Neptune instance.

What It Does

GraphMemory is a single Python package that turns DuckDB into a high-performance graph store. It ships with built-in HNSW vector search, BM25 full-text search, and a fluent query builder. Key features include:

  • Hybrid Search: Combine vector similarity with keyword relevance to find exactly what you need.
  • DSPy Extraction: Automatically extract entities and relations from raw text and merge them into the graph.
  • Fuzzy Deduplication: Resolve duplicate nodes based on property similarity, ensuring your graph stays clean.
  • Graph Algorithms: Run PageRank, centrality, and community detection using NetworkX integrations.
  • Interactive Visualization: Use the zero-dependency D3.js visualizer to inspect your graph directly in the browser.

When to Use GraphMemory

You should reach for graphmemory when your RAG application requires more than just similarity scores. It is ideal for:

  1. Semantic Knowledge Bases: Storing complex relationships where traversal is part of the retrieval process.
  2. Prototyping: You need a file-backed or in-memory graph database without setting up external services.
  3. Knowledge Extraction: Using LLMs to build structured graphs from unstructured documents using the extraction module.

Do not use it if you are operating at the scale of hundreds of millions of nodes or if your infrastructure already relies on a managed graph service like Neo4j or ArangoDB.

How to Install

Installation is modular. You can install the base package or include extras for extraction and specialized algorithms.

lovable add graphmemory
# Or via pip for specific features
pip install graphmemory[extraction]   # For DSPy extraction
pip install graphmemory[algorithms]   # For NetworkX support

Getting Started with GraphMemory

Initializing a persistent graph database is straightforward. You define your vector length and distance metric at the start.

from graphmemory import GraphMemory, Node, Edge

# Initialize a file-backed graph
graph = GraphMemory(
    database="knowledge_base.db",
    vector_length=1536, 
    distance_metric="cosine",
    auto_index=True
)

# Adding entities
alice = Node(type="Person", properties={"name": "Alice"}, vector=[...])
bob = Node(type="Person", properties={"name": "Bob"}, vector=[...])

graph.insert_node(alice)
graph.insert_node(bob)

# Defining relationships
graph.insert_edge(Edge(source_id=alice.id, target_id=bob.id, relation="colleague"))

Hybrid Search and GraphRAG

The real power comes from combining graph traversal with search. Instead of just asking for 'nodes similar to this vector,' you can assemble a full context window based on graph hops.

# Perform a hybrid search for relevant entities
results = graph.hybrid_search(
    query="Who does Alice work with?", 
    query_vector=[...], 
    text_weight=0.5, 
    vector_weight=0.5
)

# Retrieve multi-hop context for a RAG prompt
context = graph.retrieve(
    query="Alice's network", 
    query_vector=[...], 
    max_hops=2, 
    max_tokens=2000
)

Decision Table for Common Operations

If you want to...Use this method...
Prevent duplicate nodesgraph.merge_node(node, match_keys=["name"])
Deep cleaning of datagraph.resolve_duplicates(similarity_threshold=0.9)
Multi-hop traversalgraph.query().traverse(source_id=id, depth=2).execute()
End-to-end Q&Agraph.ask(query, query_vector, llm_callable=my_llm)
Visualise in Browsergraph.visualize()

Expert Developer Tips

  1. Use Transactions: Wrap bulk updates in with graph.transaction(): to ensure atomicity and significant performance gains during ingestion.
  2. Fuzzy Merging: When extracting entities from clinical or technical text, set a similarity_threshold in merge_node to handle minor spelling variations automatically.
  3. HNSW Tuning: If search speed is a bottleneck, adjust hnsw_ef_search during initialization. Higher values increase accuracy; lower values increase speed.

GraphMemory provides the structure that pure vector databases lack, giving your AI agents a logical map of the world to navigate.

Learn more and see the full source at /skill/graphmemory.

Related posts