Spaces:
Sleeping
Sleeping
| """Build the dispatch arena scenario catalog. | |
| Usage: | |
| .venv/bin/python -m dispatch_arena.scripts.build_catalog | |
| .venv/bin/python -m dispatch_arena.scripts.build_catalog --backend llm | |
| .venv/bin/python -m dispatch_arena.scripts.build_catalog --easy 30 --medium 40 --hard 30 --out catalog.json | |
| Backends: | |
| anchor (default): deterministic, no API key needed | |
| llm : uses Claude (anthropic SDK, requires ANTHROPIC_API_KEY). | |
| Falls back per-scenario to anchors if the LLM trips. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import logging | |
| import sys | |
| from pathlib import Path | |
| from dispatch_arena.catalog.builder import ( | |
| AnchorScenarioBuilder, | |
| LLMScenarioBuilder, | |
| save_catalog, | |
| ) | |
| def parse_args(argv=None): | |
| parser = argparse.ArgumentParser(description="Generate the Dispatch Arena scenario catalog.") | |
| parser.add_argument("--backend", choices=["anchor", "llm"], default="anchor") | |
| parser.add_argument("--easy", type=int, default=30) | |
| parser.add_argument("--medium", type=int, default=40) | |
| parser.add_argument("--hard", type=int, default=30) | |
| parser.add_argument("--seed", type=int, default=0, help="master RNG seed for determinism") | |
| parser.add_argument( | |
| "--out", | |
| type=Path, | |
| default=Path(__file__).resolve().parents[1] / "catalog" / "catalog.json", | |
| ) | |
| parser.add_argument("--verbose", action="store_true") | |
| return parser.parse_args(argv) | |
| def main(argv=None) -> int: | |
| args = parse_args(argv) | |
| logging.basicConfig( | |
| level=logging.INFO if args.verbose else logging.WARNING, | |
| format="%(levelname)s %(name)s: %(message)s", | |
| ) | |
| counts = {"easy": args.easy, "medium": args.medium, "hard": args.hard} | |
| total = sum(counts.values()) | |
| if args.backend == "llm": | |
| builder = LLMScenarioBuilder(master_seed=args.seed) | |
| else: | |
| builder = AnchorScenarioBuilder(master_seed=args.seed) | |
| print(f"Building {total} scenarios via {args.backend} backend ({counts}) -> {args.out}") | |
| specs = builder.build_batch(counts) | |
| args.out.parent.mkdir(parents=True, exist_ok=True) | |
| save_catalog(specs, args.out) | |
| # Summary | |
| by_diff = {} | |
| by_skill = {} | |
| for s in specs: | |
| by_diff[s.difficulty] = by_diff.get(s.difficulty, 0) + 1 | |
| for t in s.skill_focus: | |
| by_skill[t] = by_skill.get(t, 0) + 1 | |
| print(f"\n=== CATALOG WRITTEN: {len(specs)} scenarios ===") | |
| print(f"By difficulty: {by_diff}") | |
| print(f"By skill_focus tag: {dict(sorted(by_skill.items(), key=lambda kv: -kv[1]))}") | |
| print(f"Output: {args.out}") | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |