| π Navigation: π Home | π Docs | π Quickstart | π Plugins | π OSINT |
CrawlLama uses LangGraph for complex, multi-stage reasoning processes. This guide explains how the multi-hop reasoning system works and how to use it.
The multi-hop agent uses a StateGraph with the following nodes:
βββββββββββ
β Router ββββ
βββββββββββ β
βΌ
ββββββββββββββββ
βInitial Searchβ
ββββββββββββββββ
β
βΌ
βββββββββββ
β Analyze βββββ
βββββββββββ β
β β
ββββββ΄βββββ β
β β β
Needs Ready β
more? β β
β β β
βΌ βΌ β
ββββββββββ ββββββββββββ
βFollow-Upβ βSynthesizeβ
ββββββββββ ββββββββββββ
β β
ββββββββββββββββ
β
βΌ
βββββββββββ
βCritique β
βββββββββββ
β
βββββ΄ββββ
β β
Good Improve
β β
βΌ β
END ββββΊ (back to Follow-Up)
Purpose: Classifies query complexity
Logic:
Examples:
Purpose: First information search
Process:
Purpose: Evaluation of collected information
Checks:
Decision:
if complete and confidence >= threshold:
β Synthesize
else if steps < max_hops:
β Follow-Up
else:
β Synthesize (with available info)
Purpose: Targeted follow-up searches
Process:
Example:
Purpose: Final answer generation
Process:
Purpose: Self-critique of generated answer
Evaluation:
Decision:
if quality >= threshold:
β END
else if steps < max_hops:
β Follow-Up (for improvement)
else:
β END
from core.langgraph_agent import MultiHopReasoningAgent
import json
# Load config
config = json.load(open("config.json"))
# Initialize agent
agent = MultiHopReasoningAgent(
config=config,
max_hops=3, # Max reasoning steps
confidence_threshold=0.7, # Min confidence to stop
enable_critique=True # Enable self-critique
)
# Query
result = agent.query("Compare Python and JavaScript for web development")
# Result structure
print(result["answer"]) # Final answer
print(result["confidence"]) # Confidence score
print(result["steps"]) # Number of hops taken
print(result["search_queries"]) # Queries performed
print(result["reasoning_path"]) # Step-by-step reasoning
# Enable multi-hop reasoning
python main.py --multihop "Complex question here"
# Custom max hops
python main.py --multihop --max-hops 5 "Your question"
curl -X POST http://localhost:8000/query \
-H "Content-Type: application/json" \
-d '{
"query": "Compare Python and JavaScript",
"use_multihop": true,
"max_hops": 3
}'
{
"llm": {
"model": "qwen3:4b",
"temperature": 0.7,
"max_tokens": 4096
},
"multihop": {
"enabled": true,
"max_hops": 3,
"confidence_threshold": 0.7,
"enable_critique": true
}
}
max_hops:
confidence_threshold:
enable_critique:
true: Better quality, slowerfalse: Faster, no self-checkingβ Suitable for:
β Not suitable for:
# For fast answers
agent = MultiHopReasoningAgent(
config=config,
max_hops=2,
confidence_threshold=0.6,
enable_critique=False
)
# For maximum quality
agent = MultiHopReasoningAgent(
config=config,
max_hops=5,
confidence_threshold=0.8,
enable_critique=True
)
result = agent.query("Your question")
# Log reasoning path
for i, step in enumerate(result["reasoning_path"], 1):
print(f"Step {i}: {step}")
# Check if enough information was gathered
if result["steps"] == max_hops:
print("Warning: Reached max hops, might need more information")
query = "Compare React and Vue.js for building SPAs"
result = agent.query(query)
# Reasoning path:
# 1. Router: Complex query detected
# 2. Initial search: "React vs Vue.js SPA"
# 3. Analyze: Need more details on performance
# 4. Follow-up: "React performance benchmarks"
# 5. Follow-up: "Vue.js modern features"
# 6. Synthesize: Comprehensive comparison
# 7. Critique: Quality check passed
query = "What are the pros and cons of electric vehicles?"
result = agent.query(query)
# Expected hops: 2-3
# - Initial: General EV info
# - Follow-up 1: EV advantages
# - Follow-up 2: EV disadvantages
# - Synthesize: Balanced overview
Solution:
confidence_thresholdmax_hopsSolution:
enable_critiquemax_hopsconfidence_thresholdSolution:
max_hopsenable_critique# In langgraph_agent.py
def _custom_node(self, state: ReasoningState) -> ReasoningState:
"""Custom processing node."""
# Your logic here
return state
# Add to graph
workflow.add_node("custom", self._custom_node)
workflow.add_edge("analyze", "custom")
class CustomReasoningState(ReasoningState):
"""Extended state with custom fields."""
custom_data: List[str]
extra_metadata: Dict[str, Any]