426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
394 lines
13 KiB
Python
394 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Run AgentBench benchmark and generate results report.
|
|
|
|
Usage:
|
|
python run_benchmark.py # Run with mock runtime
|
|
python run_benchmark.py --runtime bridge # Run through the Eliza TS bridge
|
|
python run_benchmark.py --env os db # Run specific environments
|
|
python run_benchmark.py --runtime bridge --trajectories
|
|
"""
|
|
|
|
import argparse
|
|
import asyncio
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add parent directory to path for imports
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from elizaos_agentbench import (
|
|
AgentBenchConfig,
|
|
AgentBenchDataMode,
|
|
AgentBenchEnvironment,
|
|
AgentBenchRunner,
|
|
BenchmarkSplit,
|
|
upstream_loader,
|
|
)
|
|
from elizaos_agentbench.mock_runtime import SmartMockRuntime
|
|
from elizaos_agentbench.trajectory_integration import export_trajectories_from_results
|
|
|
|
|
|
def _load_dotenv() -> None:
|
|
"""
|
|
Best-effort .env loader.
|
|
|
|
We avoid adding a dependency on python-dotenv for benchmarks and keep
|
|
behavior conservative:
|
|
- only set vars that are not already set in the environment
|
|
- ignore comments/blank lines
|
|
- support simple KEY=VALUE lines (optionally quoted)
|
|
"""
|
|
|
|
candidates = [
|
|
Path.cwd() / ".env",
|
|
Path(__file__).resolve().parents[3] / ".env",
|
|
]
|
|
|
|
for path in candidates:
|
|
if not path.is_file():
|
|
continue
|
|
|
|
try:
|
|
for raw_line in path.read_text().splitlines():
|
|
line = raw_line.strip()
|
|
if not line or line.startswith("#") or "=" not in line:
|
|
continue
|
|
key, value = line.split("=", 1)
|
|
k = key.strip()
|
|
if not k or k in os.environ:
|
|
continue
|
|
v = value.strip()
|
|
if (v.startswith('"') and v.endswith('"')) or (v.startswith("'") and v.endswith("'")):
|
|
v = v[1:-1]
|
|
os.environ[k] = v
|
|
except OSError:
|
|
# If .env can't be read, silently ignore.
|
|
pass
|
|
|
|
|
|
async def main() -> int:
|
|
parser = argparse.ArgumentParser(
|
|
description="Run AgentBench benchmark via the eliza TS bridge"
|
|
)
|
|
parser.add_argument(
|
|
"--runtime",
|
|
choices=["mock", "bridge", "elizaos", "eliza", "hermes", "openclaw", "smithers"],
|
|
default="mock",
|
|
help=(
|
|
"Runtime backend: mock for offline smoke tests, bridge/eliza/elizaos "
|
|
"for Eliza TS, or hermes/openclaw for adapter clients"
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
"--elizaos",
|
|
action="store_true",
|
|
help="Deprecated alias for --runtime bridge",
|
|
)
|
|
parser.add_argument(
|
|
"--env",
|
|
nargs="+",
|
|
choices=["os", "db", "kg", "ws", "lt", "cg", "hh", "m2w", "all"],
|
|
default=["all"],
|
|
help="Environments to run",
|
|
)
|
|
parser.add_argument(
|
|
"--split",
|
|
choices=["dev", "test"],
|
|
default="test",
|
|
help="Upstream AgentBench data split (dev = small validation, test = leaderboard)",
|
|
)
|
|
parser.add_argument(
|
|
"--data-mode",
|
|
choices=["auto", "fixture", "full"],
|
|
default="auto",
|
|
help="Task data mode: auto uses full data when present and compact fixtures otherwise",
|
|
)
|
|
parser.add_argument(
|
|
"--fetch-data",
|
|
action="store_true",
|
|
help="Fetch full upstream AgentBench data before running",
|
|
)
|
|
parser.add_argument(
|
|
"--verify-data",
|
|
action="store_true",
|
|
help="Verify full upstream AgentBench data before running",
|
|
)
|
|
parser.add_argument(
|
|
"--allow-empty",
|
|
action="store_true",
|
|
help="Allow enabled environments to load zero tasks",
|
|
)
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
help="Allow empty task sets for setup checks",
|
|
)
|
|
parser.add_argument(
|
|
"--output",
|
|
type=str,
|
|
default="./benchmark_results",
|
|
help="Output directory",
|
|
)
|
|
parser.add_argument(
|
|
"--max-tasks",
|
|
type=int,
|
|
default=None,
|
|
help="Max tasks per environment",
|
|
)
|
|
parser.add_argument(
|
|
"--trajectories",
|
|
action="store_true",
|
|
help="Enable trajectory logging for RL training export",
|
|
)
|
|
parser.add_argument(
|
|
"--trajectory-format",
|
|
choices=["art", "grpo"],
|
|
default="art",
|
|
help="Trajectory export format (art=OpenPipe ART, grpo=GRPO groups)",
|
|
)
|
|
parser.add_argument(
|
|
"--expand-scenarios",
|
|
action="store_true",
|
|
help="Run each selected task with 10 additional edge-condition variants",
|
|
)
|
|
parser.add_argument(
|
|
"--count-scenarios",
|
|
action="store_true",
|
|
help="Print task counts for the selected environments and exit",
|
|
)
|
|
parser.add_argument(
|
|
"--validate-scenarios",
|
|
action="store_true",
|
|
help="Validate selected base/expanded task definitions and exit",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print("=" * 60)
|
|
if args.elizaos:
|
|
args.runtime = "bridge"
|
|
|
|
print("AgentBench Evaluation")
|
|
print("=" * 60)
|
|
|
|
if args.fetch_data:
|
|
upstream_loader.fetch_upstream_data(verify=True)
|
|
elif args.verify_data:
|
|
upstream_loader.verify_upstream_data()
|
|
|
|
# Create configuration
|
|
config = AgentBenchConfig(
|
|
output_dir=args.output,
|
|
save_detailed_logs=True,
|
|
enable_metrics=True,
|
|
enable_memory_tracking=True,
|
|
use_docker=False, # Use local execution for safety
|
|
split=BenchmarkSplit(args.split),
|
|
data_mode=AgentBenchDataMode(args.data_mode),
|
|
allow_empty_tasks=args.allow_empty,
|
|
dry_run=args.dry_run,
|
|
include_edge_scenarios=bool(args.expand_scenarios),
|
|
)
|
|
|
|
# Map environment names
|
|
env_map = {
|
|
"os": AgentBenchEnvironment.OS,
|
|
"db": AgentBenchEnvironment.DATABASE,
|
|
"kg": AgentBenchEnvironment.KNOWLEDGE_GRAPH,
|
|
"ws": AgentBenchEnvironment.WEB_SHOPPING,
|
|
"lt": AgentBenchEnvironment.LATERAL_THINKING,
|
|
"cg": AgentBenchEnvironment.CARD_GAME,
|
|
"hh": AgentBenchEnvironment.HOUSEHOLDING,
|
|
"m2w": AgentBenchEnvironment.WEB_BROWSING,
|
|
}
|
|
|
|
# Envs that run end-to-end without external dependencies. The
|
|
# remaining three (Card Game, Householding, Web Shopping) are
|
|
# wired but need external SDKs/corpora; they're opt-in via --env.
|
|
implemented_envs = [
|
|
AgentBenchEnvironment.OS,
|
|
AgentBenchEnvironment.DATABASE,
|
|
AgentBenchEnvironment.KNOWLEDGE_GRAPH,
|
|
AgentBenchEnvironment.LATERAL_THINKING,
|
|
AgentBenchEnvironment.WEB_BROWSING,
|
|
]
|
|
|
|
for env in AgentBenchEnvironment:
|
|
env_config = config.get_env_config(env)
|
|
|
|
if "all" in args.env:
|
|
env_config.enabled = env in implemented_envs
|
|
else:
|
|
env_key = next((k for k, v in env_map.items() if v == env), None)
|
|
env_config.enabled = env_key in args.env
|
|
|
|
if args.max_tasks:
|
|
env_config.max_tasks = args.max_tasks
|
|
|
|
# OS-specific settings
|
|
if env == AgentBenchEnvironment.OS:
|
|
env_config.additional_settings["use_docker"] = False
|
|
|
|
if args.count_scenarios or args.validate_scenarios:
|
|
summary: list[dict[str, int | str]] = []
|
|
for env in AgentBenchEnvironment:
|
|
env_config = config.get_env_config(env)
|
|
if not env_config.enabled:
|
|
continue
|
|
counts = upstream_loader.count_tasks(
|
|
env,
|
|
split=config.split.value,
|
|
limit=env_config.max_tasks,
|
|
data_mode=config.data_mode,
|
|
include_edge_scenarios=config.include_edge_scenarios,
|
|
)
|
|
summary.append(counts)
|
|
if args.validate_scenarios:
|
|
tasks = upstream_loader.load_tasks(
|
|
env,
|
|
split=config.split.value,
|
|
limit=env_config.max_tasks,
|
|
data_mode=config.data_mode,
|
|
include_edge_scenarios=config.include_edge_scenarios,
|
|
)
|
|
upstream_loader.validate_tasks(tasks)
|
|
print(json.dumps(summary, indent=2, sort_keys=True))
|
|
return 0
|
|
|
|
# Initialize runtime.
|
|
print("\n" + "=" * 60)
|
|
print(
|
|
"Using deterministic mock runtime"
|
|
if args.runtime == "mock"
|
|
else "Using ELIZA TypeScript agent via benchmark server"
|
|
)
|
|
print("=" * 60)
|
|
eliza_server = None
|
|
runtime = SmartMockRuntime()
|
|
runtime_name = str(args.runtime).strip().lower()
|
|
if runtime_name == "eliza":
|
|
runtime_name = "bridge"
|
|
if runtime_name in {"bridge", "elizaos"}:
|
|
from eliza_adapter.agentbench import ElizaAgentHarness
|
|
|
|
_load_dotenv()
|
|
os.environ["BENCHMARK_HARNESS"] = "eliza"
|
|
os.environ["ELIZA_BENCH_HARNESS"] = "eliza"
|
|
if os.environ.get("ELIZA_BENCH_URL"):
|
|
# Reuse an already-running benchmark server instead of cold-booting
|
|
# one per benchmark (matches the mint/tau_bench reuse pattern).
|
|
from eliza_adapter.client import ElizaClient
|
|
|
|
client = ElizaClient()
|
|
client.wait_until_ready(timeout=180)
|
|
eliza_harness = ElizaAgentHarness(client)
|
|
else:
|
|
from eliza_adapter import ElizaServerManager
|
|
|
|
eliza_server = ElizaServerManager()
|
|
eliza_server.start()
|
|
eliza_harness = ElizaAgentHarness(eliza_server.client)
|
|
runtime._app_harness = eliza_harness # type: ignore[attr-defined]
|
|
print("Eliza benchmark server connected")
|
|
elif runtime_name in {"hermes", "openclaw", "smithers"}:
|
|
from elizaos_agentbench.agent_fn_harness import AgentFnHarness
|
|
|
|
_load_dotenv()
|
|
os.environ["BENCHMARK_HARNESS"] = runtime_name
|
|
os.environ["ELIZA_BENCH_HARNESS"] = runtime_name
|
|
model_name = (
|
|
os.environ.get("BENCHMARK_MODEL_NAME")
|
|
or os.environ.get("MODEL_NAME")
|
|
or os.environ.get("CEREBRAS_MODEL")
|
|
or "gemma-4-31b"
|
|
)
|
|
if runtime_name == "hermes":
|
|
from hermes_adapter.agentbench import build_agentbench_agent_fn
|
|
elif runtime_name == "smithers":
|
|
from smithers_adapter.agentbench import build_agentbench_agent_fn
|
|
else:
|
|
from openclaw_adapter.agentbench import build_agentbench_agent_fn
|
|
|
|
runtime._app_harness = AgentFnHarness( # type: ignore[attr-defined]
|
|
build_agentbench_agent_fn(model_name=model_name),
|
|
harness=runtime_name,
|
|
)
|
|
print(f"{runtime_name} AgentBench adapter connected")
|
|
|
|
# Show enabled environments
|
|
enabled = config.get_enabled_environments()
|
|
print(f"\nEnvironments to evaluate: {[e.value for e in enabled]}")
|
|
|
|
# Run benchmark
|
|
print("\nStarting benchmark...")
|
|
runner = AgentBenchRunner(config=config, runtime=runtime)
|
|
try:
|
|
report = await runner.run_benchmarks()
|
|
finally:
|
|
if eliza_server is not None:
|
|
eliza_server.stop()
|
|
|
|
# Print detailed results
|
|
print("\n" + "=" * 60)
|
|
print("BENCHMARK RESULTS")
|
|
print("=" * 60)
|
|
|
|
print("\n📊 Overall Performance:")
|
|
print(f" Success Rate: {report.overall_success_rate * 100:.1f}%")
|
|
print(f" Total Tasks: {report.total_tasks}")
|
|
print(f" Passed: {report.passed_tasks}")
|
|
print(f" Failed: {report.failed_tasks}")
|
|
print(f" Avg Duration: {report.average_duration_ms:.0f}ms")
|
|
|
|
print("\n📋 Per-Environment Breakdown:")
|
|
for env, env_report in report.environment_reports.items():
|
|
icon = "✅" if env_report.success_rate >= 0.5 else "⚠️" if env_report.success_rate >= 0.3 else "❌"
|
|
print(f"\n {icon} {env.value.upper()}")
|
|
print(f" Success Rate: {env_report.success_rate * 100:.1f}%")
|
|
print(f" Tasks: {env_report.passed_tasks}/{env_report.total_tasks}")
|
|
print(f" Avg Steps: {env_report.average_steps:.1f}")
|
|
print(f" Avg Duration: {env_report.average_duration_ms:.0f}ms")
|
|
|
|
# Comparison with baselines
|
|
if config.enable_baseline_comparison:
|
|
print("\n📈 Comparison with GPT-4 Baseline:")
|
|
gpt4_comp = report.comparison_to_baseline.get("gpt4_comparison", {})
|
|
for env_name, data in gpt4_comp.items():
|
|
our_score = data.get("our_score", 0) * 100
|
|
gpt4_score = data.get("gpt4_score", 0) * 100
|
|
diff = data.get("difference", 0) * 100
|
|
icon = "↑" if diff > 0 else "↓" if diff < 0 else "="
|
|
print(f" {env_name}: {our_score:.1f}% vs {gpt4_score:.1f}% ({icon}{abs(diff):.1f}%)")
|
|
|
|
# Key findings
|
|
print("\n💡 Key Findings:")
|
|
for finding in report.summary.get("key_findings", []):
|
|
print(f" • {finding}")
|
|
|
|
# Recommendations
|
|
if report.summary.get("recommendations"):
|
|
print("\n🎯 Recommendations:")
|
|
for rec in report.summary.get("recommendations", []):
|
|
print(f" • {rec}")
|
|
|
|
print(f"\n📁 Results saved to: {args.output}")
|
|
print(" - agentbench-results.json")
|
|
print(" - agentbench-report.md")
|
|
print(" - agentbench-detailed.json")
|
|
|
|
if args.trajectories:
|
|
export_path = export_trajectories_from_results(args.output, args.trajectory_format)
|
|
print(f"\nTrajectory export saved to: {export_path}")
|
|
|
|
print("\n" + "=" * 60)
|
|
|
|
# Return exit code based on performance
|
|
return 0 if report.overall_success_rate >= 0.3 else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
exit_code = asyncio.run(main())
|
|
sys.exit(exit_code)
|