Multi-Hop Relationship Traversal¶
Overview¶
The Graffold now supports multi-hop relationship traversal, allowing queries to discover indirect connections between entities through intermediate nodes. This enables answering questions like "What pathways connect BRCA1 to breast cancer?" by traversing protein → pathway → disease relationships.
Features¶
- Configurable Hop Depth: Traverse 1-3 relationship hops (default: 1)
- Path Context: Results include the full relationship path (e.g., "BRCA1 → DNA Repair → Breast Cancer")
- Mode-Aware: Works with all query modes (local, global, hybrid, mix)
- Streaming Support: Compatible with SSE streaming responses
API Usage¶
REST API¶
Add the hop_depth parameter to your query request:
curl -X POST "http://localhost:8000/v1/sessions/{session_id}/query" \
-H "Authorization: Bearer $API_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"question": "What pathways connect BRCA1 to breast cancer?",
"mode": "local",
"hop_depth": 2
}'
Python Client¶
import requests
BASE = "http://localhost:8000"
HEADERS = {"Authorization": "Bearer your_token", "Content-Type": "application/json"}
# Create session
session_data = {
"llm_service": "llama3-instruct",
"database_name": "neo4j",
"database_type": "neo4j",
"agent_type": "graph_rag_agent",
"connection_details": {
"uri": "bolt://localhost:7687",
"user": "neo4j",
"password": "your_password"
}
}
response = requests.post(f"{BASE}/v1/sessions", headers=HEADERS, json=session_data)
session_id = response.json()["session_id"]
# Query with multi-hop traversal
query_data = {
"question": "What pathways connect BRCA1 to breast cancer?",
"mode": "local",
"hop_depth": 2 # Traverse up to 2 hops
}
response = requests.post(
f"{BASE}/v1/sessions/{session_id}/query",
headers=HEADERS,
json=query_data
)
result = response.json()
print(result["answer"])
Streaming Queries¶
Multi-hop traversal works with SSE streaming:
response = requests.post(
f"{BASE}/v1/sessions/{session_id}/query",
headers=HEADERS,
json={
"question": "What pathways connect BRCA1 to breast cancer?",
"stream": True,
"mode": "local",
"hop_depth": 3
},
stream=True
)
for line in response.iter_lines(decode_unicode=True):
if line.startswith("data: "):
print(line[6:])
Response Format¶
Multi-hop results include path context for each relationship:
{
"answer": "BRCA1 connects to breast cancer through DNA repair pathways...",
"sources": [...],
"detailed_results": [
{
"name": "BRCA1",
"id": "P38398",
"labels": ["Protein"],
"neighbors": [
{
"target": "Breast Cancer",
"target_id": "MONDO:0007254",
"target_labels": ["Disease"],
"path_length": 1,
"path_context": ["BRCA1 → ASSOCIATES_WITH → Breast Cancer"]
},
{
"target": "DNA Repair",
"target_id": "GO:0006281",
"target_labels": ["Pathway"],
"path_length": 2,
"path_context": [
"BRCA1 → PARTICIPATES_IN → DNA Repair Pathway",
"DNA Repair Pathway → REGULATES → DNA Repair"
]
}
]
}
]
}
Hop Depth Guidelines¶
- hop_depth=1 (default): Direct relationships only (fastest, most precise)
- hop_depth=2: Includes one intermediate node (e.g., protein → pathway → disease)
- hop_depth=3: Includes two intermediate nodes (slower, broader context)
Recommendation: Start with hop_depth=1 for specific queries, increase to 2-3 for exploratory questions about indirect connections.
Query Mode Compatibility¶
Multi-hop traversal is supported in the following modes:
- local: Entity neighborhood search with multi-hop expansion
- hybrid: Combines local multi-hop with global community summaries
- mix: Weighted blend of vector and graph retrieval with multi-hop support
- global: Uses community summaries (hop_depth not applicable)
- naive: Direct LLM answer (hop_depth not applicable)
Implementation Details¶
Cypher Query Pattern¶
The system uses variable-length path patterns (Cypher is supported by both Neo4j and Memgraph):
MATCH path = (n)-[*1..{hop_depth}]-(m:Entity)
WHERE m.id <> n.id
WITH path, m,
[rel in relationships(path) | type(rel)] as rel_types,
[node in nodes(path) | {name: node.name, labels: labels(node)}] as path_nodes,
length(path) as path_length
Path Context Generation¶
For each multi-hop relationship, the system constructs a human-readable path:
This provides full provenance for indirect connections.
Performance Considerations¶
- Query Time: Increases with hop depth (1-hop: ~100ms, 2-hop: ~300ms, 3-hop: ~1s)
- Result Size: More hops = more neighbors (limited to 30 per seed entity)
- Recommendation: Use
hop_depth=1for production queries, higher values for exploration
Example Use Cases¶
1. Pathway Discovery¶
2. Indirect Protein Associations¶
{
"question": "Which proteins are indirectly associated with Alzheimer's disease?",
"hop_depth": 3
}
3. Disease Mechanism Exploration¶
Validation¶
The implementation includes:
- ✅ Hop depth parameter validation (1-3 range)
- ✅ Path context generation for all multi-hop relationships
- ✅ Integration with all query modes
- ✅ Streaming support via SSE
- ✅ Backward compatibility (defaults to 1-hop)
Future Enhancements¶
Potential improvements for future iterations:
- Weighted path scoring based on relationship types
- Path filtering by relationship type (e.g., only "ASSOCIATES_WITH" paths)
- Shortest path prioritization
- Path visualization in the frontend