426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
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) Has been cancelled
281 lines
11 KiB
Python
281 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""ADHDBench CLI -- run attention & context scaling benchmarks.
|
|
|
|
Usage:
|
|
python -m scripts.run_benchmark run --model gpt-4o --levels 0 1 2
|
|
python -m scripts.run_benchmark run --quick
|
|
python -m scripts.run_benchmark run --full
|
|
python -m scripts.run_benchmark baselines
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import asyncio
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
# Ensure the parent directory is importable
|
|
_BENCHMARK_DIR = __import__("pathlib").Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(_BENCHMARK_DIR))
|
|
_ELIZA_ADAPTER_DIR = _BENCHMARK_DIR.parent / "eliza-adapter"
|
|
if _ELIZA_ADAPTER_DIR.is_dir():
|
|
sys.path.insert(0, str(_ELIZA_ADAPTER_DIR))
|
|
|
|
from elizaos_adhdbench.baselines import (
|
|
BOOTSTRAP_ACTION_NAMES,
|
|
compute_always_reply_baseline,
|
|
compute_random_baseline,
|
|
)
|
|
from elizaos_adhdbench.config import ADHDBenchConfig
|
|
from elizaos_adhdbench.scenarios import count_scenarios, get_scenarios, validate_scenarios
|
|
from elizaos_adhdbench.types import ScalePoint
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
prog="adhdbench",
|
|
description="ADHDBench -- Attention & Context Scaling Benchmark for ElizaOS",
|
|
)
|
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
|
|
# -- run --
|
|
run_parser = sub.add_parser("run", help="Run the benchmark")
|
|
run_parser.add_argument(
|
|
"--model",
|
|
default="openai/gpt-oss-120b",
|
|
help="Model name (default: openai/gpt-oss-120b)",
|
|
)
|
|
run_parser.add_argument(
|
|
"--provider",
|
|
default="eliza",
|
|
choices=("mock-passthrough", "eliza", "openai", "cerebras", "groq", "openrouter", "vllm"),
|
|
help=(
|
|
"Model provider (default: eliza — routes through the Eliza "
|
|
"TypeScript benchmark bridge against the real AgentRuntime, #9475). "
|
|
"'mock-passthrough' is the deterministic local runner — smoke "
|
|
"tests only, always scores ~100%% by construction — and must be "
|
|
"requested explicitly. The remaining choices hit an "
|
|
"OpenAI-compatible chat completions endpoint directly."
|
|
),
|
|
)
|
|
run_parser.add_argument("--levels", nargs="+", type=int, default=[0, 1, 2], help="Levels to run (0, 1, 2)")
|
|
run_parser.add_argument("--tags", nargs="+", default=[], help="Filter by scenario tags")
|
|
run_parser.add_argument("--ids", nargs="+", default=[], help="Filter by scenario IDs")
|
|
run_parser.add_argument("--expand-scenarios", action="store_true", help="Include generated edge scenarios")
|
|
run_parser.add_argument("--count-scenarios", action="store_true", help="Print authored, added, and total scenario counts")
|
|
run_parser.add_argument("--validate-scenarios", action="store_true", help="Validate expanded scenario corpus")
|
|
run_parser.add_argument("--output", default="./adhdbench_results", help="Output directory")
|
|
run_parser.add_argument("--quick", action="store_true", help="Quick mode: L0 only, 2 scale points, basic only")
|
|
run_parser.add_argument("--full", action="store_true", help="Full mode: all levels, all scales, both configs")
|
|
run_parser.add_argument("--basic-only", action="store_true", help="Only run basic config")
|
|
run_parser.add_argument("--full-only", action="store_true", help="Only run full config")
|
|
run_parser.add_argument("--verbose", "-v", action="store_true", help="Verbose logging")
|
|
|
|
# -- baselines --
|
|
base_parser = sub.add_parser("baselines", help="Compute baseline scores")
|
|
base_parser.add_argument("--levels", nargs="+", type=int, default=[0, 1, 2])
|
|
|
|
# -- list --
|
|
list_parser = sub.add_parser("list", help="List all scenarios")
|
|
list_parser.add_argument("--levels", nargs="+", type=int, default=[0, 1, 2])
|
|
list_parser.add_argument("--tags", nargs="+", default=[])
|
|
list_parser.add_argument("--expand-scenarios", action="store_true", help="Include generated edge scenarios")
|
|
list_parser.add_argument("--count-scenarios", action="store_true", help="Print authored, added, and total scenario counts")
|
|
list_parser.add_argument("--validate-scenarios", action="store_true", help="Validate expanded scenario corpus")
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def _configure_bridge_model_env(model_name: str | None) -> None:
|
|
provider = os.environ.get("BENCHMARK_MODEL_PROVIDER", "").strip().lower()
|
|
if not provider:
|
|
if os.environ.get("GROQ_API_KEY"):
|
|
provider = "groq"
|
|
elif os.environ.get("OPENROUTER_API_KEY"):
|
|
provider = "openrouter"
|
|
elif os.environ.get("CEREBRAS_API_KEY"):
|
|
provider = "cerebras"
|
|
elif os.environ.get("OPENAI_API_KEY"):
|
|
provider = "openai"
|
|
|
|
model = (model_name or os.environ.get("BENCHMARK_MODEL_NAME", "")).strip()
|
|
if not model:
|
|
model = "openai/gpt-oss-120b"
|
|
|
|
if provider:
|
|
os.environ["BENCHMARK_MODEL_PROVIDER"] = provider
|
|
os.environ["BENCHMARK_MODEL_NAME"] = model
|
|
os.environ["OPENAI_LARGE_MODEL"] = model
|
|
os.environ["OPENAI_SMALL_MODEL"] = model
|
|
os.environ["GROQ_LARGE_MODEL"] = model
|
|
os.environ["GROQ_SMALL_MODEL"] = model
|
|
os.environ["OPENROUTER_LARGE_MODEL"] = model
|
|
os.environ["OPENROUTER_SMALL_MODEL"] = model
|
|
|
|
|
|
def cmd_run(args: argparse.Namespace) -> None:
|
|
"""Run the benchmark."""
|
|
logging.basicConfig(
|
|
level=logging.DEBUG if args.verbose else logging.INFO,
|
|
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
|
|
)
|
|
|
|
if args.count_scenarios:
|
|
print(count_scenarios())
|
|
return
|
|
if args.validate_scenarios:
|
|
print(validate_scenarios())
|
|
return
|
|
|
|
if args.provider is None:
|
|
raise SystemExit(
|
|
"ERROR: --provider is required. Choices: mock-passthrough (smoke "
|
|
"tests only, always ~100%), eliza, openai, cerebras, groq, "
|
|
"openrouter, vllm. Refusing to silently default to mock."
|
|
)
|
|
|
|
# Build config from args
|
|
if args.quick:
|
|
config = ADHDBenchConfig(
|
|
scale_points=(
|
|
ScalePoint(action_count=10, provider_count=8, conversation_prefill=0),
|
|
ScalePoint(action_count=50, provider_count=18, conversation_prefill=30),
|
|
),
|
|
run_basic=True,
|
|
run_full=False,
|
|
levels=(0,),
|
|
tags=tuple(args.tags),
|
|
scenario_ids=tuple(args.ids),
|
|
include_edge_scenarios=args.expand_scenarios,
|
|
model_name=args.model,
|
|
model_provider=args.provider,
|
|
output_dir=args.output,
|
|
)
|
|
elif args.full:
|
|
config = ADHDBenchConfig(
|
|
model_name=args.model,
|
|
model_provider=args.provider,
|
|
output_dir=args.output,
|
|
levels=tuple(args.levels),
|
|
tags=tuple(args.tags),
|
|
scenario_ids=tuple(args.ids),
|
|
include_edge_scenarios=args.expand_scenarios,
|
|
)
|
|
else:
|
|
config = ADHDBenchConfig(
|
|
model_name=args.model,
|
|
model_provider=args.provider,
|
|
output_dir=args.output,
|
|
levels=tuple(args.levels),
|
|
tags=tuple(args.tags),
|
|
scenario_ids=tuple(args.ids),
|
|
include_edge_scenarios=args.expand_scenarios,
|
|
run_basic=not args.full_only,
|
|
run_full=not args.basic_only,
|
|
)
|
|
|
|
def progress(config_name: str, scale: str, current: int, total: int) -> None:
|
|
print(f" [{config_name}/{scale}] {current}/{total}", end="\r", flush=True)
|
|
|
|
provider_lc = (config.model_provider or "").strip().lower()
|
|
if provider_lc == "eliza":
|
|
# Route through the elizaOS TypeScript benchmark bridge instead of
|
|
# the removed in-process Python AgentRuntime.
|
|
from eliza_adapter.adhdbench import ElizaADHDBenchRunner
|
|
from eliza_adapter.server_manager import ElizaServerManager
|
|
|
|
_configure_bridge_model_env(config.model_name)
|
|
manager = ElizaServerManager()
|
|
manager.start()
|
|
try:
|
|
runner = ElizaADHDBenchRunner(config, client=manager.client)
|
|
results = asyncio.run(runner.run(progress_callback=progress))
|
|
finally:
|
|
manager.stop()
|
|
elif provider_lc in {"mock", "mock-passthrough"}:
|
|
# Deterministic Python runner — only useful for smoke tests because
|
|
# it always scores ~100% by construction. Explicit opt-in only.
|
|
from elizaos_adhdbench.runner import ADHDBenchRunner
|
|
runner = ADHDBenchRunner(config)
|
|
results = asyncio.run(runner.run(progress_callback=progress))
|
|
else:
|
|
from elizaos_adhdbench.openai_runner import (
|
|
OpenAICompatibleADHDBenchRunner,
|
|
is_openai_compatible_provider,
|
|
)
|
|
if not is_openai_compatible_provider(provider_lc):
|
|
raise SystemExit(
|
|
f"Unknown --provider {config.model_provider!r}. "
|
|
f"Use 'mock', 'eliza', or one of: openai, cerebras, groq, openrouter, vllm."
|
|
)
|
|
runner = OpenAICompatibleADHDBenchRunner(config)
|
|
results = asyncio.run(runner.run(progress_callback=progress))
|
|
|
|
print(f"\nBenchmark complete. {len(results.results)} scenario results.")
|
|
print(f"Results saved to: {config.output_dir}/")
|
|
|
|
|
|
def cmd_baselines(args: argparse.Namespace) -> None:
|
|
"""Compute and display baseline scores."""
|
|
levels = tuple(args.levels)
|
|
scenarios = get_scenarios(levels=levels)
|
|
|
|
from elizaos_adhdbench.distractor_plugin import get_distractor_plugin_actions_for_scale
|
|
action_pool = BOOTSTRAP_ACTION_NAMES + [
|
|
a.name for a in get_distractor_plugin_actions_for_scale(50, len(BOOTSTRAP_ACTION_NAMES))
|
|
]
|
|
|
|
print(f"Computing baselines for {len(scenarios)} scenarios (levels {levels})...")
|
|
print()
|
|
|
|
random_score = compute_random_baseline(scenarios, action_pool)
|
|
reply_score = compute_always_reply_baseline(scenarios)
|
|
|
|
print(f" Random baseline: {random_score:.1%}")
|
|
print(f" Always-REPLY baseline: {reply_score:.1%}")
|
|
print()
|
|
print("Any real agent should score significantly above both baselines.")
|
|
|
|
|
|
def cmd_list(args: argparse.Namespace) -> None:
|
|
"""List all scenarios matching filters."""
|
|
if args.count_scenarios:
|
|
print(count_scenarios())
|
|
return
|
|
if args.validate_scenarios:
|
|
print(validate_scenarios())
|
|
return
|
|
levels = tuple(args.levels)
|
|
tags = tuple(args.tags)
|
|
scenarios = get_scenarios(levels=levels, tags=tags, include_edge_scenarios=args.expand_scenarios)
|
|
|
|
print(f"{'ID':<10} {'Level':<10} {'Name':<40} {'Tags'}")
|
|
print("-" * 100)
|
|
for s in scenarios:
|
|
tags_str = ", ".join(s.tags)
|
|
level_str = f"L{s.level.value}"
|
|
features = []
|
|
if s.requires_advanced_memory:
|
|
features.append("mem")
|
|
if s.requires_advanced_planning:
|
|
features.append("plan")
|
|
feat_str = f" [{','.join(features)}]" if features else ""
|
|
print(f"{s.id:<10} {level_str:<10} {s.name:<40} {tags_str}{feat_str}")
|
|
print(f"\nTotal: {len(scenarios)} scenarios")
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
if args.command == "run":
|
|
cmd_run(args)
|
|
elif args.command == "baselines":
|
|
cmd_baselines(args)
|
|
elif args.command == "list":
|
|
cmd_list(args)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|