Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Run a deterministic no-LLM campaign demo and write a summary artifact.""" | |
| import argparse | |
| import json | |
| import time | |
| from pathlib import Path | |
| from typing import Any, Dict, List | |
| import requests | |
| ROLES = [ | |
| "expense_specialist", | |
| "invoice_specialist", | |
| "gst_specialist", | |
| "fraud_specialist", | |
| ] | |
| def _headers(api_key: str) -> Dict[str, str]: | |
| headers = {"Content-Type": "application/json", "User-Agent": "hackathon-demo-runner/1.0"} | |
| if api_key: | |
| headers["X-API-Key"] = api_key | |
| return headers | |
| def _post(session: requests.Session, url: str, payload: Dict[str, Any], headers: Dict[str, str]) -> Dict[str, Any]: | |
| resp = session.post(url, json=payload, headers=headers, timeout=60) | |
| resp.raise_for_status() | |
| return resp.json() | |
| def run_demo(env_url: str, seed: int, total_periods: int, api_key: str) -> Dict[str, Any]: | |
| started_at = time.time() | |
| session = requests.Session() | |
| headers = _headers(api_key) | |
| start_payload = {"seed": seed, "total_periods": total_periods} | |
| start_data = _post(session, f"{env_url}/campaign/start", start_payload, headers) | |
| campaign_id = start_data["campaign_id"] | |
| periods: List[Dict[str, Any]] = [] | |
| for period in range(1, total_periods + 1): | |
| period_row: Dict[str, Any] = { | |
| "period": period, | |
| "roles": {}, | |
| "overseer_decisions": 0, | |
| "regulatory_shocks_seen": 0, | |
| "schema_version": None, | |
| "policy_version": None, | |
| } | |
| for role in ROLES: | |
| task_start = _post( | |
| session, | |
| f"{env_url}/campaign/task/start", | |
| {"campaign_id": campaign_id, "role": role}, | |
| headers, | |
| ) | |
| observation = task_start.get("observation", {}) | |
| world_state = task_start.get("world_state", {}) | |
| period_row["schema_version"] = world_state.get("schema_version") | |
| period_row["policy_version"] = world_state.get("policy_version") | |
| submit = _post( | |
| session, | |
| f"{env_url}/campaign/task/submit", | |
| { | |
| "campaign_id": campaign_id, | |
| "role": role, | |
| "action": {"findings": [], "submit_final": True}, | |
| }, | |
| headers, | |
| ) | |
| submit_obs = submit.get("observation", {}) | |
| shocks = submit_obs.get("pending_regulatory_shocks", []) | |
| feedback = (submit_obs.get("period_observation") or {}).get("feedback", "") | |
| period_row["roles"][role] = { | |
| "task_id": observation.get("period_observation", {}).get("task_id"), | |
| "reward": observation.get("period_observation", {}).get("reward"), | |
| "shock_count": len(shocks), | |
| "final_deferred": "Final submission was deferred" in feedback, | |
| } | |
| period_row["regulatory_shocks_seen"] += len(shocks) | |
| review = _post( | |
| session, | |
| f"{env_url}/overseer/review", | |
| { | |
| "campaign_id": campaign_id, | |
| "action": { | |
| "audit_trail_id": f"demo-{campaign_id}-p{period}", | |
| "decisions": [], | |
| "conflicts_resolved": [], | |
| "task_reassignments": {}, | |
| }, | |
| }, | |
| headers, | |
| ) | |
| period_row["overseer_decisions"] = len(review.get("result", {}).get("decisions", [])) | |
| if period < total_periods: | |
| _post( | |
| session, | |
| f"{env_url}/campaign/period/advance", | |
| {"campaign_id": campaign_id}, | |
| headers, | |
| ) | |
| periods.append(period_row) | |
| state_resp = session.get( | |
| f"{env_url}/campaign/state", | |
| params={"campaign_id": campaign_id}, | |
| headers=headers, | |
| timeout=60, | |
| ) | |
| state_resp.raise_for_status() | |
| final_state = state_resp.json() | |
| improve = _post( | |
| session, | |
| f"{env_url}/self-improve", | |
| { | |
| "campaign_id": campaign_id, | |
| "train_seeds": [42, 43, 44, 45, 46], | |
| "held_out_seeds": [100, 101, 102], | |
| }, | |
| headers, | |
| ) | |
| ended_at = time.time() | |
| return { | |
| "campaign_id": campaign_id, | |
| "seed": seed, | |
| "total_periods": total_periods, | |
| "duration_seconds": round(ended_at - started_at, 3), | |
| "periods": periods, | |
| "final_state": final_state, | |
| "self_improve": improve, | |
| } | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Run deterministic hackathon campaign demo") | |
| parser.add_argument("--env-url", default="http://localhost:8000", help="API base URL") | |
| parser.add_argument("--seed", type=int, default=42, help="Campaign seed") | |
| parser.add_argument("--periods", type=int, default=5, help="Campaign periods") | |
| parser.add_argument("--api-key", default="", help="Optional X-API-Key") | |
| parser.add_argument( | |
| "--output", | |
| default="artifacts/hackathon_demo_summary.json", | |
| help="Output artifact path", | |
| ) | |
| args = parser.parse_args() | |
| summary = run_demo(args.env_url, args.seed, args.periods, args.api_key) | |
| output_path = Path(args.output) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| output_path.write_text(json.dumps(summary, indent=2), encoding="utf-8") | |
| print(json.dumps({ | |
| "status": "ok", | |
| "campaign_id": summary["campaign_id"], | |
| "output": str(output_path), | |
| "duration_seconds": summary["duration_seconds"], | |
| }, indent=2)) | |
| if __name__ == "__main__": | |
| main() | |