chore: add working multi agent langraph limerick writer yaml and end to end test file
This commit is contained in:
@@ -0,0 +1,345 @@
|
||||
# Multi-Agent Limerick Writer - LangGraph with Conditional Routing
|
||||
# True multi-agent system with dynamic workflow and conditional routing
|
||||
#
|
||||
# AGENTS:
|
||||
# - Coordinator: Routes workflow and manages topic
|
||||
# - Writer: Creates the initial limerick
|
||||
# - Rhymer: Improves rhyme scheme (AABBA)
|
||||
# - Meter: Improves syllable meter
|
||||
# - Topic Checker: Ensures limerick matches the topic
|
||||
#
|
||||
# USAGE:
|
||||
# cleveragents interactive -c examples/limerick_writer_multi_agent_langgraph.yaml
|
||||
#
|
||||
# EXAMPLE:
|
||||
# /graph limerick_workflow write me a limerick about quantum physics
|
||||
#
|
||||
# HOW IT WORKS:
|
||||
# - LangGraph manages stateful workflow with conditional routing
|
||||
# - Coordinator decides which specialist agent to invoke next
|
||||
# - Each agent actually executes (not simulation)
|
||||
# - Dynamic routing based on workflow stage
|
||||
|
||||
agents:
|
||||
# Coordinator agent - manages workflow and routes to specialists
|
||||
coordinator:
|
||||
type: llm
|
||||
config:
|
||||
provider: openai
|
||||
model: gpt-4o
|
||||
temperature: 0.3
|
||||
memory_enabled: true
|
||||
max_history: 20
|
||||
max_tokens: 2000
|
||||
system_prompt: |
|
||||
You are the COORDINATOR agent in a multi-agent limerick writing system.
|
||||
|
||||
YOUR ROLE: Route workflow to appropriate specialist agents.
|
||||
|
||||
WORKFLOW STAGES:
|
||||
1. Get topic from user
|
||||
2. Route to WRITER for initial limerick creation
|
||||
3. Route to RHYMER for rhyme scheme improvement
|
||||
4. Route to METER for syllable meter refinement
|
||||
5. Route to TOPIC_CHECKER for final topic alignment
|
||||
6. End workflow
|
||||
|
||||
ROUTING DECISIONS:
|
||||
Output ONE of these routing tags based on workflow stage:
|
||||
|
||||
[ROUTE:WRITER] - When user provides topic, route to writer
|
||||
[ROUTE:RHYMER] - After writer creates limerick, route to rhymer
|
||||
[ROUTE:METER] - After rhymer improves rhymes, route to meter
|
||||
[ROUTE:TOPIC_CHECKER] - After meter refines syllables, route to topic checker
|
||||
[ROUTE:END] - When limerick is complete
|
||||
|
||||
OUTPUT FORMAT:
|
||||
For initial topic:
|
||||
"Great! I'll create a limerick about [topic].
|
||||
[ROUTE:WRITER]"
|
||||
|
||||
For routing between agents:
|
||||
"Proceeding to next stage.
|
||||
[ROUTE:NEXT_AGENT]"
|
||||
|
||||
Always include the [ROUTE:X] tag!
|
||||
|
||||
# Writer agent - creates the initial limerick
|
||||
writer:
|
||||
type: llm
|
||||
config:
|
||||
provider: openai
|
||||
model: gpt-4
|
||||
temperature: 1.0
|
||||
memory_enabled: true
|
||||
max_history: 30
|
||||
max_tokens: 1500
|
||||
system_prompt: |
|
||||
You are the WRITER agent in a multi-agent limerick writing system.
|
||||
|
||||
YOUR ROLE: Create limericks based on a topic from conversation history.
|
||||
|
||||
LIMERICK STRUCTURE:
|
||||
- Five lines total
|
||||
- Lines 1, 2, 5: Three feet (2-3 syllables each), rhyme scheme A
|
||||
- Lines 3, 4: Two feet (2-3 syllables each), rhyme scheme B
|
||||
- Overall rhyme scheme: AABBA
|
||||
- Line 1 traditionally introduces a person and place
|
||||
|
||||
EXAMPLE LIMERICK:
|
||||
The limerick is furtive and mean
|
||||
You must keep her in close quarantine
|
||||
Or she sneaks to the slums
|
||||
And promptly becomes
|
||||
Disorderly, drunk, and obscene.
|
||||
|
||||
TASK:
|
||||
- Review conversation history for the topic
|
||||
- Create a creative limerick about that topic
|
||||
- Follow proper limerick structure
|
||||
|
||||
COMPLETION SIGNAL:
|
||||
End your response with: "[LIMERICK_CREATED]"
|
||||
|
||||
OUTPUT FORMAT:
|
||||
"[WRITER SPEAKING]
|
||||
Creating limerick about [topic]...
|
||||
|
||||
[Your limerick here - 5 lines]
|
||||
|
||||
[LIMERICK_CREATED]"
|
||||
|
||||
# Rhymer agent - improves rhyme scheme
|
||||
rhymer:
|
||||
type: llm
|
||||
config:
|
||||
provider: openai
|
||||
model: gpt-4
|
||||
temperature: 0.5
|
||||
memory_enabled: true
|
||||
max_history: 30
|
||||
max_tokens: 1500
|
||||
system_prompt: |
|
||||
You are the RHYMER agent in a multi-agent limerick writing system.
|
||||
|
||||
YOUR ROLE: Improve the rhyme scheme of limericks.
|
||||
|
||||
RHYME SCHEME RULES:
|
||||
- Limerick rhyme scheme: AABBA
|
||||
- Lines 1, 2, 5 must rhyme (A rhyme)
|
||||
- Lines 3, 4 must rhyme (B rhyme)
|
||||
- Near-rhymes are acceptable
|
||||
- Last word of line 1 is usually a place or person name
|
||||
|
||||
EXAMPLE:
|
||||
There was a young rustic named Mallory, (A)
|
||||
who drew but a very small salary. (A)
|
||||
When he went to the show, (B)
|
||||
His purse made him go (B)
|
||||
To a seat in the uppermost gallery. (A)
|
||||
|
||||
TASK:
|
||||
- Review conversation history to find the limerick from WRITER
|
||||
- Look for "[WRITER SPEAKING]" to find the limerick
|
||||
- Improve the rhyme scheme if needed
|
||||
- Maintain the topic and meaning
|
||||
|
||||
COMPLETION SIGNAL:
|
||||
End your response with: "[RHYMES_IMPROVED]"
|
||||
|
||||
OUTPUT FORMAT:
|
||||
"[RHYMER SPEAKING]
|
||||
Reviewing rhyme scheme...
|
||||
|
||||
[Improved limerick with better rhymes]
|
||||
|
||||
[RHYMES_IMPROVED]"
|
||||
|
||||
# Meter agent - improves syllable meter
|
||||
meter:
|
||||
type: llm
|
||||
config:
|
||||
provider: openai
|
||||
model: gpt-4
|
||||
temperature: 0.5
|
||||
memory_enabled: true
|
||||
max_history: 30
|
||||
max_tokens: 1500
|
||||
system_prompt: |
|
||||
You are the METER agent in a multi-agent limerick writing system.
|
||||
|
||||
YOUR ROLE: Improve the syllable meter of limericks.
|
||||
|
||||
METER RULES:
|
||||
- Lines 1, 2, 5: Three feet of 2-3 syllables each (6-9 syllables total)
|
||||
- Lines 3, 4: Two feet of 2-3 syllables each (4-6 syllables total)
|
||||
- Maintain natural rhythm and flow
|
||||
|
||||
EXAMPLE:
|
||||
A dozen, a gross, and a score (9 syllables)
|
||||
Plus three times the square root of four (9 syllables)
|
||||
Divided by seven (6 syllables)
|
||||
Plus five times eleven (6 syllables)
|
||||
Is nine squared and not a bit more. (8 syllables)
|
||||
|
||||
TASK:
|
||||
- Review conversation history to find the limerick from RHYMER
|
||||
- Look for "[RHYMER SPEAKING]" to find the improved limerick
|
||||
- Improve the syllable meter if needed
|
||||
- Maintain rhyme scheme and topic
|
||||
|
||||
COMPLETION SIGNAL:
|
||||
End your response with: "[METER_REFINED]"
|
||||
|
||||
OUTPUT FORMAT:
|
||||
"[METER SPEAKING]
|
||||
Refining syllable meter...
|
||||
|
||||
[Improved limerick with better meter]
|
||||
|
||||
[METER_REFINED]"
|
||||
|
||||
# Topic checker agent - ensures limerick matches the topic
|
||||
topic_checker:
|
||||
type: llm
|
||||
config:
|
||||
provider: openai
|
||||
model: gpt-4
|
||||
temperature: 0.5
|
||||
memory_enabled: true
|
||||
max_history: 30
|
||||
max_tokens: 1500
|
||||
system_prompt: |
|
||||
You are the TOPIC_CHECKER agent in a multi-agent limerick writing system.
|
||||
|
||||
YOUR ROLE: Ensure the limerick closely matches the requested topic.
|
||||
|
||||
TASK:
|
||||
- Review conversation history to find the original topic
|
||||
- Review the limerick from METER agent
|
||||
- Look for "[METER SPEAKING]" to find the refined limerick
|
||||
- Adjust the limerick to better match the topic if needed
|
||||
- Maintain rhyme scheme and meter
|
||||
|
||||
COMPLETION SIGNAL:
|
||||
End your response with: "[LIMERICK_COMPLETE]"
|
||||
|
||||
OUTPUT FORMAT:
|
||||
"[TOPIC_CHECKER SPEAKING]
|
||||
Verifying topic alignment...
|
||||
|
||||
[Final limerick aligned with topic]
|
||||
|
||||
Limerick complete!
|
||||
[LIMERICK_COMPLETE]"
|
||||
|
||||
routes:
|
||||
# LangGraph workflow with conditional routing
|
||||
limerick_workflow:
|
||||
type: graph
|
||||
entry_point: start
|
||||
checkpointing: true
|
||||
|
||||
nodes:
|
||||
# Coordinator routes workflow
|
||||
coordinate:
|
||||
type: agent
|
||||
agent: coordinator
|
||||
|
||||
# Writer creates initial limerick
|
||||
write:
|
||||
type: agent
|
||||
agent: writer
|
||||
|
||||
# Rhymer improves rhyme scheme
|
||||
improve_rhymes:
|
||||
type: agent
|
||||
agent: rhymer
|
||||
|
||||
# Meter improves syllable meter
|
||||
refine_meter:
|
||||
type: agent
|
||||
agent: meter
|
||||
|
||||
# Topic checker ensures alignment
|
||||
check_topic:
|
||||
type: agent
|
||||
agent: topic_checker
|
||||
|
||||
edges:
|
||||
# Always start with coordinator
|
||||
- source: start
|
||||
target: coordinate
|
||||
|
||||
# Coordinator routes to writer
|
||||
- source: coordinate
|
||||
target: write
|
||||
condition:
|
||||
type: content_contains
|
||||
text: "[ROUTE:WRITER]"
|
||||
|
||||
# Coordinator routes to rhymer
|
||||
- source: coordinate
|
||||
target: improve_rhymes
|
||||
condition:
|
||||
type: content_contains
|
||||
text: "[ROUTE:RHYMER]"
|
||||
|
||||
# Coordinator routes to meter
|
||||
- source: coordinate
|
||||
target: refine_meter
|
||||
condition:
|
||||
type: content_contains
|
||||
text: "[ROUTE:METER]"
|
||||
|
||||
# Coordinator routes to topic checker
|
||||
- source: coordinate
|
||||
target: check_topic
|
||||
condition:
|
||||
type: content_contains
|
||||
text: "[ROUTE:TOPIC_CHECKER]"
|
||||
|
||||
# Coordinator ends workflow
|
||||
- source: coordinate
|
||||
target: end
|
||||
condition:
|
||||
type: content_contains
|
||||
text: "[ROUTE:END]"
|
||||
|
||||
# After writer, go back to coordinator to route to rhymer
|
||||
- source: write
|
||||
target: coordinate
|
||||
|
||||
# After rhymer, go back to coordinator to route to meter
|
||||
- source: improve_rhymes
|
||||
target: coordinate
|
||||
|
||||
# After meter, go back to coordinator to route to topic checker
|
||||
- source: refine_meter
|
||||
target: coordinate
|
||||
|
||||
# After topic checker, go to end
|
||||
- source: check_topic
|
||||
target: end
|
||||
|
||||
# Stream that executes the graph
|
||||
graph_executor:
|
||||
type: stream
|
||||
stream_type: cold
|
||||
operators:
|
||||
- type: graph_execute
|
||||
params:
|
||||
graph: limerick_workflow
|
||||
publications:
|
||||
- __output__
|
||||
|
||||
merges:
|
||||
- sources: [__input__]
|
||||
target: graph_executor
|
||||
|
||||
context:
|
||||
global:
|
||||
app_name: "Multi-Agent Limerick Writer (LangGraph)"
|
||||
version: "2.0-langgraph"
|
||||
log_level: "INFO"
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
#!/bin/bash
|
||||
# End-to-End Test: Multi-Agent Limerick Writer (LangGraph)
|
||||
# Tests the complete limerick writing workflow
|
||||
|
||||
# Change to project root
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
# Check for API key
|
||||
if [ -z "$OPENAI_API_KEY" ]; then
|
||||
echo "Error: OPENAI_API_KEY environment variable not set"
|
||||
echo "Usage: export OPENAI_API_KEY='your-key-here'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=========================================="
|
||||
echo "Limerick Writer Test (LangGraph)"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
echo "Testing complete workflow:"
|
||||
echo " 1. Coordinator gets topic"
|
||||
echo " 2. Writer creates initial limerick"
|
||||
echo " 3. Rhymer improves rhyme scheme"
|
||||
echo " 4. Meter refines syllable meter"
|
||||
echo " 5. Topic Checker ensures alignment"
|
||||
echo ""
|
||||
|
||||
echo "Starting test..."
|
||||
echo ""
|
||||
|
||||
# Run the interactive session with incremental commands
|
||||
cat << 'EOF' | timeout 240 python -m cleveragents interactive -c examples/limerick_writer_multi_agent_langgraph.yaml 2>&1 | tee /tmp/limerick_writer_test.log
|
||||
/graph limerick_workflow hello, what can you do?
|
||||
/graph limerick_workflow write me a limerick about quantum computing
|
||||
/graph limerick_workflow continue to improve the rhymes
|
||||
/graph limerick_workflow now refine the meter
|
||||
/graph limerick_workflow check if it matches the topic well
|
||||
/graph limerick_workflow thank you, that's perfect!
|
||||
exit
|
||||
EOF
|
||||
|
||||
EXIT_CODE=$?
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Test Results"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Check exit code
|
||||
if [ $EXIT_CODE -eq 124 ]; then
|
||||
echo "⚠ WARNING: Test timed out after 240 seconds"
|
||||
elif [ $EXIT_CODE -ne 0 ]; then
|
||||
echo "✗ FAILED: Test exited with code $EXIT_CODE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check log for agent participation
|
||||
echo "Agent Participation Check:"
|
||||
echo "----------------------------------------"
|
||||
agents_found=0
|
||||
|
||||
if grep -q "COORDINATOR" /tmp/limerick_writer_test.log || grep -q "coordinate" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ COORDINATOR agent participated"
|
||||
agents_found=$((agents_found + 1))
|
||||
fi
|
||||
|
||||
if grep -q "WRITER" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ WRITER agent participated"
|
||||
agents_found=$((agents_found + 1))
|
||||
fi
|
||||
|
||||
if grep -q "RHYMER" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ RHYMER agent participated"
|
||||
agents_found=$((agents_found + 1))
|
||||
fi
|
||||
|
||||
if grep -q "METER" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ METER agent participated"
|
||||
agents_found=$((agents_found + 1))
|
||||
fi
|
||||
|
||||
if grep -q "TOPIC_CHECKER\|TOPIC CHECKER" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ TOPIC_CHECKER agent participated"
|
||||
agents_found=$((agents_found + 1))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ $agents_found -ge 4 ]; then
|
||||
echo "✓ Multi-agent collaboration verified ($agents_found/5 agents active)"
|
||||
else
|
||||
echo "⚠ WARNING: Limited agent participation detected ($agents_found/5 agents)"
|
||||
fi
|
||||
|
||||
# Check for limerick structure
|
||||
echo ""
|
||||
echo "Limerick Structure Check:"
|
||||
echo "----------------------------------------"
|
||||
structure_checks=0
|
||||
|
||||
# Check for 5-line structure (multiple occurrences as limerick gets refined)
|
||||
limerick_lines=$(grep -E "^[A-Z].*[a-z\.\!\?]$" /tmp/limerick_writer_test.log | wc -l)
|
||||
if [ $limerick_lines -ge 5 ]; then
|
||||
echo "✓ Limerick contains multiple lines (found $limerick_lines lines)"
|
||||
structure_checks=$((structure_checks + 1))
|
||||
else
|
||||
echo "⚠ WARNING: Limerick may not have proper structure (found $limerick_lines lines)"
|
||||
fi
|
||||
|
||||
# Check for topic mention (quantum computing)
|
||||
if grep -qi "quantum" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ Topic (quantum) referenced in output"
|
||||
structure_checks=$((structure_checks + 1))
|
||||
else
|
||||
echo "⚠ WARNING: Topic may not be properly addressed"
|
||||
fi
|
||||
|
||||
# Check for rhyme-related activity
|
||||
if grep -qi "rhyme\|rhymes\|rhyming" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ Rhyme improvement detected"
|
||||
structure_checks=$((structure_checks + 1))
|
||||
else
|
||||
echo "⚠ WARNING: No rhyme improvement detected"
|
||||
fi
|
||||
|
||||
# Check for meter-related activity
|
||||
if grep -qi "meter\|syllable" /tmp/limerick_writer_test.log; then
|
||||
echo "✓ Meter refinement detected"
|
||||
structure_checks=$((structure_checks + 1))
|
||||
else
|
||||
echo "⚠ WARNING: No meter refinement detected"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ $structure_checks -ge 3 ]; then
|
||||
echo "✓ Limerick workflow: SUCCESSFUL ($structure_checks/4 checks passed)"
|
||||
elif [ $structure_checks -ge 2 ]; then
|
||||
echo "⚠ Limerick workflow: MOSTLY SUCCESSFUL ($structure_checks/4 checks passed)"
|
||||
else
|
||||
echo "✗ Limerick workflow: INCOMPLETE ($structure_checks/4 checks passed)"
|
||||
fi
|
||||
|
||||
# Extract and display final limerick
|
||||
echo ""
|
||||
echo "Final Limerick Extract:"
|
||||
echo "----------------------------------------"
|
||||
# Try to find the last occurrence of what looks like a limerick
|
||||
if grep -A 10 "TOPIC_CHECKER\|TOPIC CHECKER\|Limerick complete" /tmp/limerick_writer_test.log | tail -20 | head -15; then
|
||||
echo "----------------------------------------"
|
||||
else
|
||||
echo "Could not extract final limerick"
|
||||
echo "Check full log at: /tmp/limerick_writer_test.log"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Test Complete!"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# Final summary
|
||||
if [ $agents_found -ge 4 ] && [ $structure_checks -ge 3 ]; then
|
||||
echo "✓ SUCCESS: All tests passed!"
|
||||
echo ""
|
||||
echo "Summary:"
|
||||
echo " • Multi-agent workflow: ✓"
|
||||
echo " • Limerick creation: ✓"
|
||||
echo " • Rhyme improvement: ✓"
|
||||
echo " • Meter refinement: ✓"
|
||||
echo " • Topic alignment: ✓"
|
||||
exit_status=0
|
||||
else
|
||||
echo "⚠ PARTIAL SUCCESS: Some tests failed"
|
||||
echo ""
|
||||
echo "Summary:"
|
||||
echo " • Multi-agent workflow: $([ $agents_found -ge 4 ] && echo '✓' || echo '✗')"
|
||||
echo " • Limerick workflow: $([ $structure_checks -ge 3 ] && echo '✓' || echo '✗')"
|
||||
exit_status=1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Full log saved to: /tmp/limerick_writer_test.log"
|
||||
|
||||
exit $exit_status
|
||||
|
||||
Reference in New Issue
Block a user