elizaos--eliza
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
192 行
7.5 KiB
Python
192 行
7.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Compute per-benchmark and total run costs for each harness.
|
|
|
|
Reads the checked-in ``benchmark_results/latest/<benchmark>__<harness>.json``
|
|
snapshots, pulls per-benchmark token totals from ``metrics.token_metrics``, and
|
|
applies pricing for:
|
|
|
|
* Cerebras ``gpt-oss-120b`` ($0.35 / $0.75 per 1M in/out)
|
|
* Anthropic ``claude-opus-4-8`` ($15 / $75 per 1M in/out)
|
|
|
|
Output: a markdown cost report (per benchmark x harness, plus per-harness
|
|
totals and averages) for both models.
|
|
|
|
Token counts are benchmark-driven and harness-dependent (tool loops, retries),
|
|
so they are a sound basis for projecting what an Opus run of the *same* work
|
|
would cost on each harness. The ``smithers`` harness has limited real snapshots
|
|
(BFCL measured live); where a smithers snapshot is absent we fall back to the
|
|
hermes token profile (smithers and hermes share the same per-turn
|
|
OpenAI-compatible pattern) and flag the row as projected.
|
|
|
|
Usage:
|
|
python -m scripts.compute_costs # from packages/benchmarks
|
|
python scripts/compute_costs.py --json # machine-readable
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import sys
|
|
|
|
_HERE = Path(__file__).resolve().parent
|
|
_BENCH_ROOT = _HERE.parent
|
|
sys.path.insert(0, str(_BENCH_ROOT.parent)) # packages/ for `benchmarks` ns
|
|
|
|
from benchmarks.lib.pricing import compute_cost_usd # noqa: E402
|
|
|
|
GPT_OSS = {"gpt-oss-120b": {"input_per_million_usd": 0.35, "output_per_million_usd": 0.75}}
|
|
OPUS = {"opus": {"input_per_million_usd": 15.0, "output_per_million_usd": 75.0}}
|
|
|
|
HARNESSES = ("eliza", "hermes", "openclaw", "smithers")
|
|
|
|
|
|
def _tokens(snapshot: dict) -> tuple[int, int] | None:
|
|
metrics = snapshot.get("metrics") or {}
|
|
tm = metrics.get("token_metrics") or snapshot.get("token_metrics") or {}
|
|
pt = tm.get("prompt_tokens")
|
|
ct = tm.get("completion_tokens")
|
|
if not isinstance(pt, (int, float)) or not isinstance(ct, (int, float)):
|
|
return None
|
|
if pt == 0 and ct == 0:
|
|
return None
|
|
return int(pt), int(ct)
|
|
|
|
|
|
def load_snapshots(latest_dir: Path) -> dict[str, dict[str, tuple[int, int]]]:
|
|
"""Return {benchmark_id: {harness: (prompt_tokens, completion_tokens)}}."""
|
|
out: dict[str, dict[str, tuple[int, int]]] = {}
|
|
for path in sorted(latest_dir.glob("*.json")):
|
|
stem = path.stem
|
|
if "__" not in stem:
|
|
continue
|
|
bench, harness = stem.rsplit("__", 1)
|
|
bench = bench.replace("-", "_")
|
|
try:
|
|
snap = json.loads(path.read_text(encoding="utf-8"))
|
|
except (OSError, json.JSONDecodeError):
|
|
continue
|
|
toks = _tokens(snap)
|
|
if toks is None:
|
|
continue
|
|
out.setdefault(bench, {})[harness] = toks
|
|
return out
|
|
|
|
|
|
def project_smithers(per_bench: dict[str, dict[str, tuple[int, int]]]) -> set[str]:
|
|
"""Fill missing smithers rows from the hermes profile. Returns projected set."""
|
|
projected: set[str] = set()
|
|
for bench, by_harness in per_bench.items():
|
|
if "smithers" in by_harness:
|
|
continue
|
|
proxy = by_harness.get("hermes") or by_harness.get("openclaw") or by_harness.get("eliza")
|
|
if proxy is not None:
|
|
by_harness["smithers"] = proxy
|
|
projected.add(bench)
|
|
return projected
|
|
|
|
|
|
def _cost(toks: tuple[int, int], model: str) -> float:
|
|
pt, ct = toks
|
|
if model == "gpt-oss-120b":
|
|
return compute_cost_usd("gpt-oss-120b", pt, ct, pricing=GPT_OSS) or 0.0
|
|
return compute_cost_usd("opus", pt, ct, pricing=OPUS) or 0.0
|
|
|
|
|
|
def build_report(per_bench, projected, smithers_measured) -> str:
|
|
lines: list[str] = []
|
|
lines.append("# Benchmark cost report\n")
|
|
lines.append(
|
|
"Per-benchmark token totals from `benchmark_results/latest`, priced on "
|
|
"Cerebras `gpt-oss-120b` ($0.35/$0.75 per 1M) and Anthropic "
|
|
"`claude-opus-4-8` ($15/$75 per 1M).\n"
|
|
)
|
|
lines.append(
|
|
"`*` = smithers row projected from the hermes token profile "
|
|
"(no smithers snapshot yet). `†` = smithers measured live.\n"
|
|
)
|
|
lines.append(
|
|
"> **Caveat:** these are the token volumes recorded in the checked-in "
|
|
"snapshots, which were captured at the *calibration sample sizes* "
|
|
"(e.g. `max_examples=2`), not full datasets. A full-dataset run scales "
|
|
"roughly by `(full_N / sample_N)` per benchmark. Treat the totals as the "
|
|
"cost of the recorded configuration and a per-token basis for scaling, "
|
|
"not as the cost of a complete leaderboard run.\n"
|
|
)
|
|
|
|
for model_label, model in (("gpt-oss-120b (Cerebras)", "gpt-oss-120b"), ("opus-4.8 (Anthropic)", "opus")):
|
|
lines.append(f"\n## Cost per benchmark — {model_label}\n")
|
|
lines.append("| benchmark | " + " | ".join(HARNESSES) + " |")
|
|
lines.append("|" + "---|" * (len(HARNESSES) + 1))
|
|
totals = {h: 0.0 for h in HARNESSES}
|
|
counts = {h: 0 for h in HARNESSES}
|
|
for bench in sorted(per_bench):
|
|
by_harness = per_bench[bench]
|
|
cells = []
|
|
for h in HARNESSES:
|
|
toks = by_harness.get(h)
|
|
if toks is None:
|
|
cells.append("—")
|
|
continue
|
|
c = _cost(toks, model)
|
|
totals[h] += c
|
|
counts[h] += 1
|
|
mark = ""
|
|
if h == "smithers" and bench in projected:
|
|
mark = "*"
|
|
elif h == "smithers" and bench in smithers_measured:
|
|
mark = "†"
|
|
cells.append(f"${c:,.4f}{mark}")
|
|
lines.append(f"| {bench} | " + " | ".join(cells) + " |")
|
|
lines.append("| **TOTAL** | " + " | ".join(f"**${totals[h]:,.2f}**" for h in HARNESSES) + " |")
|
|
lines.append(
|
|
"| **AVG/bench** | "
|
|
+ " | ".join(
|
|
f"${(totals[h] / counts[h]):,.4f}" if counts[h] else "—" for h in HARNESSES
|
|
)
|
|
+ " |"
|
|
)
|
|
lines.append(f"| benchmarks counted | " + " | ".join(str(counts[h]) for h in HARNESSES) + " |")
|
|
return "\n".join(lines) + "\n"
|
|
|
|
|
|
def main() -> int:
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--latest", default=str(_BENCH_ROOT / "benchmark_results" / "latest"))
|
|
ap.add_argument("--out", default=str(_BENCH_ROOT / "docs" / "COST_REPORT.md"))
|
|
ap.add_argument("--json", action="store_true", help="print machine-readable summary")
|
|
args = ap.parse_args()
|
|
|
|
latest = Path(args.latest)
|
|
per_bench = load_snapshots(latest)
|
|
smithers_measured = {b for b, h in per_bench.items() if "smithers" in h}
|
|
projected = project_smithers(per_bench)
|
|
|
|
report = build_report(per_bench, projected, smithers_measured)
|
|
Path(args.out).write_text(report, encoding="utf-8")
|
|
|
|
# Summary to stdout.
|
|
summary: dict[str, dict[str, float]] = {}
|
|
for model_label, model in (("gpt_oss_120b", "gpt-oss-120b"), ("opus_4_8", "opus")):
|
|
summary[model_label] = {}
|
|
for h in HARNESSES:
|
|
total = sum(_cost(t, model) for by in per_bench.values() if (t := by.get(h)))
|
|
summary[model_label][h] = round(total, 2)
|
|
|
|
if args.json:
|
|
print(json.dumps({"summary": summary, "benchmarks_counted": len(per_bench)}, indent=2))
|
|
else:
|
|
print(f"Wrote {args.out}")
|
|
print(f"Benchmarks with token data: {len(per_bench)}")
|
|
for model_label in summary:
|
|
print(f"\nTotal run cost ({model_label}):")
|
|
for h in HARNESSES:
|
|
print(f" {h:10s} ${summary[model_label][h]:,.2f}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|