logic-engine / examples /ace /rr_benchmark.py
ghostdrive1's picture
Upload folder using huggingface_hub
116524e verified
Raw
History Blame Contribute Delete
15.8 kB
#!/usr/bin/env python3
"""E2E benchmark: RR (PydanticAI) over 30 traces.
Generates 30 synthetic agent traces with known errors, runs the full
ACE learning pipeline (RRStep -> Tag -> Update -> Apply), and reports:
- Success rate (RR produced valid learnings)
- Skills extracted
- Timing
Usage:
uv run python examples/ace/rr_benchmark.py
ACE_MODEL=bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0 uv run python examples/ace/rr_benchmark.py
"""
import json
import logging
import os
import sys
import time
from pathlib import Path
from dotenv import load_dotenv
_root = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(_root))
load_dotenv(_root / ".env")
from ace.core.skillbook import Skillbook
from ace.implementations import SkillManager
from ace.steps.rr_step import RRConfig, RRStep
from ace.runners.trace_analyser import TraceAnalyser
MODEL = os.getenv("ACE_MODEL", "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0")
logging.basicConfig(level=logging.WARNING, format="%(name)s | %(message)s")
logging.getLogger("ace.steps.rr").setLevel(logging.INFO)
# ---------------------------------------------------------------------------
# Synthetic traces — 30 traces with realistic agent errors
# ---------------------------------------------------------------------------
TRACES = [
# Math errors (5)
{
"question": "What is 17 x 23?",
"ground_truth": "391",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "17x23 = 17x20 + 17x3 = 340 + 51 = 381",
"answer": "381",
"skill_ids": [],
}
],
},
{
"question": "What is 144 / 12?",
"ground_truth": "12",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "144/12 = 14",
"answer": "14",
"skill_ids": [],
}
],
},
{
"question": "What is 25% of 80?",
"ground_truth": "20",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "25% of 80 = 80/25 = 3.2",
"answer": "3.2",
"skill_ids": [],
}
],
},
{
"question": "What is sqrt(169)?",
"ground_truth": "13",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "sqrt(169) is about 14",
"answer": "14",
"skill_ids": [],
}
],
},
{
"question": "What is 2^10?",
"ground_truth": "1024",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "2^10 = 2x10 = 20",
"answer": "20",
"skill_ids": [],
}
],
},
# Geography errors (5)
{
"question": "What is the capital of Australia?",
"ground_truth": "Canberra",
"feedback": "Incorrect. The capital is Canberra, not Sydney.",
"steps": [
{
"role": "agent",
"reasoning": "Sydney is the largest city, so it must be the capital.",
"answer": "Sydney",
"skill_ids": [],
}
],
},
{
"question": "What is the capital of Brazil?",
"ground_truth": "Brasilia",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Sao Paulo is the biggest city.",
"answer": "Sao Paulo",
"skill_ids": [],
}
],
},
{
"question": "What is the capital of Turkey?",
"ground_truth": "Ankara",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Istanbul is the most famous city.",
"answer": "Istanbul",
"skill_ids": [],
}
],
},
{
"question": "What is the capital of Myanmar?",
"ground_truth": "Naypyidaw",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Yangon is the largest city.",
"answer": "Yangon",
"skill_ids": [],
}
],
},
{
"question": "What is the capital of Nigeria?",
"ground_truth": "Abuja",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Lagos is the most well-known city.",
"answer": "Lagos",
"skill_ids": [],
}
],
},
# Science errors (5)
{
"question": "What is the boiling point of water in Fahrenheit?",
"ground_truth": "212",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Water boils at 100 degrees.",
"answer": "100",
"skill_ids": [],
}
],
},
{
"question": "How many chromosomes do humans have?",
"ground_truth": "46",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Humans have 23 chromosomes.",
"answer": "23",
"skill_ids": [],
}
],
},
{
"question": "What is the speed of light in km/s?",
"ground_truth": "299,792",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Speed of light is about 300,000 miles per second.",
"answer": "300,000 miles/s",
"skill_ids": [],
}
],
},
{
"question": "What is the atomic number of gold?",
"ground_truth": "79",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Gold is Au, atomic number around 80.",
"answer": "80",
"skill_ids": [],
}
],
},
{
"question": "What planet is closest to the sun?",
"ground_truth": "Mercury",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Venus is very hot so it must be closest.",
"answer": "Venus",
"skill_ids": [],
}
],
},
# Correct answers (5) — RR should find nothing or minimal learnings
{
"question": "What is 2+2?",
"ground_truth": "4",
"feedback": "Correct.",
"steps": [
{"role": "agent", "reasoning": "2+2=4.", "answer": "4", "skill_ids": []}
],
},
{
"question": "What is the capital of France?",
"ground_truth": "Paris",
"feedback": "Correct.",
"steps": [
{
"role": "agent",
"reasoning": "The capital of France is Paris.",
"answer": "Paris",
"skill_ids": [],
}
],
},
{
"question": "What color is the sky?",
"ground_truth": "Blue",
"feedback": "Correct.",
"steps": [
{
"role": "agent",
"reasoning": "The sky appears blue due to Rayleigh scattering.",
"answer": "Blue",
"skill_ids": [],
}
],
},
{
"question": "How many days in a week?",
"ground_truth": "7",
"feedback": "Correct.",
"steps": [
{
"role": "agent",
"reasoning": "A week has 7 days.",
"answer": "7",
"skill_ids": [],
}
],
},
{
"question": "What is H2O?",
"ground_truth": "Water",
"feedback": "Correct.",
"steps": [
{
"role": "agent",
"reasoning": "H2O is the chemical formula for water.",
"answer": "Water",
"skill_ids": [],
}
],
},
# Reasoning errors (5)
{
"question": "If all roses are flowers and some flowers fade quickly, do all roses fade quickly?",
"ground_truth": "No, not necessarily.",
"feedback": "Incorrect. 'Some flowers fade quickly' doesn't mean all roses do.",
"steps": [
{
"role": "agent",
"reasoning": "Roses are flowers, flowers fade, so roses fade.",
"answer": "Yes",
"skill_ids": [],
}
],
},
{
"question": "A bat and ball cost $1.10 total. The bat costs $1 more than the ball. How much is the ball?",
"ground_truth": "$0.05",
"feedback": "Incorrect. If ball=$0.10, bat=$1.10, total=$1.20.",
"steps": [
{
"role": "agent",
"reasoning": "$1.10 - $1.00 = $0.10.",
"answer": "$0.10",
"skill_ids": [],
}
],
},
{
"question": "Is a whale a fish?",
"ground_truth": "No, a whale is a mammal.",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "Whales live in water, so they are fish.",
"answer": "Yes",
"skill_ids": [],
}
],
},
{
"question": "Can you fold a piece of paper more than 7 times?",
"ground_truth": "Yes, the record is 12 folds.",
"feedback": "Incorrect.",
"steps": [
{
"role": "agent",
"reasoning": "It's physically impossible to fold paper more than 7 times.",
"answer": "No",
"skill_ids": [],
}
],
},
{
"question": "Does hot water freeze faster than cold water?",
"ground_truth": "It can, under certain conditions (Mpemba effect).",
"feedback": "Incorrect — the Mpemba effect is real.",
"steps": [
{
"role": "agent",
"reasoning": "Hot water has more energy so it takes longer to cool.",
"answer": "No, never.",
"skill_ids": [],
}
],
},
# Tool-use errors (5)
{
"question": "Search for 'Python 3.12 release date'",
"ground_truth": "October 2, 2023",
"feedback": "Agent searched for wrong query.",
"steps": [
{
"role": "agent",
"reasoning": "I'll search for 'Python release'.",
"answer": "Python 3.11 was released Oct 2022",
"skill_ids": [],
},
{
"role": "agent",
"reasoning": "Found a result about 3.11.",
"answer": "October 2022",
"skill_ids": [],
},
],
},
{
"question": "Convert 100 USD to EUR",
"ground_truth": "~92 EUR",
"feedback": "Agent used wrong conversion direction.",
"steps": [
{
"role": "agent",
"reasoning": "1 EUR = 1.08 USD, so 100*1.08=108.",
"answer": "108 EUR",
"skill_ids": [],
}
],
},
{
"question": "Get weather in Tokyo",
"ground_truth": "22C, partly cloudy",
"feedback": "Agent misspelled the city name.",
"steps": [
{
"role": "agent",
"reasoning": "I'll call weather API for Tokio.",
"answer": "Error: 404 city not found",
"skill_ids": [],
},
{
"role": "agent",
"reasoning": "API failed, I'll guess.",
"answer": "Probably warm and humid",
"skill_ids": [],
},
],
},
{
"question": "Calculate the area of a circle with radius 5",
"ground_truth": "78.54",
"feedback": "Agent used diameter instead of radius.",
"steps": [
{
"role": "agent",
"reasoning": "Area = pi * r^2 = pi * 10^2 = 314.16",
"answer": "314.16",
"skill_ids": [],
}
],
},
{
"question": "List files in /home/user/docs",
"ground_truth": "report.pdf, notes.txt, budget.xlsx",
"feedback": "Agent listed wrong directory.",
"steps": [
{
"role": "agent",
"reasoning": "I'll list /home/user.",
"answer": "Desktop/, docs/, Downloads/",
"skill_ids": [],
}
],
},
]
assert len(TRACES) == 30, f"Expected 30 traces, got {len(TRACES)}"
# ---------------------------------------------------------------------------
# Run benchmark
# ---------------------------------------------------------------------------
def main():
print(f"Model: {MODEL}")
print(f"Traces: {len(TRACES)}")
print(f"{'=' * 60}")
skillbook = Skillbook()
rr = RRStep(
MODEL,
config=RRConfig(
max_requests=20,
timeout=15.0,
),
)
sm = SkillManager(MODEL)
analyser = TraceAnalyser.from_roles(
reflector=rr,
skill_manager=sm,
skillbook=skillbook,
)
t0 = time.time()
results = analyser.run(TRACES, epochs=1)
elapsed = time.time() - t0
# Report
print(f"\n{'=' * 60}")
print(f" BENCHMARK RESULTS")
print(f"{'=' * 60}")
successes = sum(1 for r in results if r.error is None)
failures = sum(1 for r in results if r.error is not None)
print(f"\n Traces processed: {len(results)}/{len(TRACES)}")
print(f" Successes: {successes}")
print(f" Failures: {failures}")
print(f" Time: {elapsed:.1f}s ({elapsed/len(TRACES):.1f}s/trace)")
if failures > 0:
print(f"\n Errors:")
for r in results:
if r.error is not None:
print(f" - {r.error}")
skills = skillbook.skills()
print(f"\n Skills extracted: {len(skills)}")
for s in skills[:20]:
print(f" [{s.id}] {s.content[:80]}")
if len(skills) > 20:
print(f" ... and {len(skills) - 20} more")
# Save results
out_dir = _root / "examples" / "ace" / "benchmark_output"
out_dir.mkdir(exist_ok=True)
skillbook.save_to_file(str(out_dir / "skillbook.json"))
print(f"\n Skillbook saved to: {out_dir / 'skillbook.json'}")
# Summary
print(f"\n{'=' * 60}")
rate = successes / len(results) * 100 if results else 0
print(f" Success rate: {rate:.0f}%")
print(f" Skills learned: {len(skills)}")
print(f" Total time: {elapsed:.1f}s")
print(f"{'=' * 60}")
return 0 if rate >= 80 else 1
if __name__ == "__main__":
sys.exit(main())