## The Problem with Standard RAG
If you've played with RAG (Retrieval-Augmented Generation), you know it's great at finding *similar* text.
If you ask, "Tell me about apples," it finds documents containing "apple", "fruit", "red", etc.
But what happens when you ask a question that requires **reasoning across multiple steps**?
> "What is the weather like in the city where the CEO of SpaceX lives?"
A standard Vector Search struggles here. It sees "weather", "city", "CEO", "SpaceX". It might find a wiki page about SpaceX, or a weather report for a random city. **It lacks the structural understanding to connect the dots:**
1. Find "SpaceX"
2. Find "CEO" (Elon Musk)
3. Find "Lives In" (Boca Chica/Austin/SF)
4. Find "Weather" for that location.
This chain of logic is called **Multi-Hop Reasoning**. And to solve it, we need a **Graph**.
## The Solution: Hybrid RAG (Vector + Graph)
Today, we are building a **Hybrid Agent** using **Mem0**.
Mem0 is fantastic because it auto-routes your memories into two stores:
1. Qdrant (Vector): For fuzzy, semantic search ("Apple" ≈ "Fruit").
2. Neo4j (Graph): For precise, structural relationships ((Elon)-[:FOUNDED]->(SpaceX)).
By querying *both* and synthesizing the results, our agent gets a "Glass Brain"—it can see the hidden connections.
## The Code
### 1. Configuration
We configure Mem0 to use both OpenAI for embeddings/LLM and Neo4j for the graph.
config = {
"version": "v1.1",
"embedder": {
"provider": "openai",
"config": {
"api_key": OPENAI_API_KEY,
"model": "text-embedding-3-small"
}
},
"llm": {
"provider": "openai",
"config": {
"api_key": OPENAI_API_KEY,
"model": "gpt-4o-mini"
}
},
"graph_store": {
"provider": "neo4j",
"config": {
"url": NEO_URI,
"username": NEO_USERNAME,
"password": NEO_PASSWORD
}
},
"vector_store": {
"provider": "qdrant",
"config": {
"host": "localhost",
"port": 6333,
}
}
}
### 2. Hybrid Search Logic
This is where the magic happens. We perform a vector search for context, but we *also* extract entities and run a graph traversal.
def multi_hop_search(query, user_id):
# 1. Vector Search (The standard part)
vector_results = mem_client.search(query, user_id=user_id)
# 2. Graph Search (The "Hop" part)
# Extract entities (e.g., "SpaceX")
entities = extract_entities(query)
# Traverse 2 hops in the graph to find connections
# (SpaceX) --[FOUNDED_BY]--> (Elon) --[LIVES_IN]--> (Texas)
graph_context = get_graph_context(entities, depth=2)
return f"""
=== Vector Context ===
{vector_results}
=== Graph Connections ===
{graph_context}
"""
### 3. The Reasoning Prompt
We feed this rich, hybrid context to the LLM and tell it to explain its reasoning
system_prompt = """
You are a Multi-Hop Reasoning Agent.
Use the provided CONTEXT to answer.
If you use the Graph paths to connect A to C via B, explain that reasoning chain explicitly.
"""
## The Result
When we ask: **"Who is the leader of the project that Dr. Vance runs?"**
**Without Graph:** "I found information about Dr. Vance and a project, but I'm not sure which one she leads."
**With Graph:** "Dr. Vance leads the **Apollo Project**. I can see the connection: (Dr. Vance)-[:LEADS]->(Apollo Project)."
## Conclusion
Combining Vector and Graph databases gives your AI the best of both worlds: the flexibility of natural language and the precision of structured logic.