Spaces:
Configuration error
Configuration error
Download evaluate.py from saadumar26/decision-debate-agent: direct link, hf CLI and curl.
- Browser
- Download file 5.3 kB
-
https://huggingface.co/spaces/saadumar26/decision-debate-agent/resolve/main/evaluate.py
- Command line
-
hf download hf://spaces/saadumar26/decision-debate-agent/evaluate.py
-
curl -L -o evaluate.py https://huggingface.co/spaces/saadumar26/decision-debate-agent/resolve/main/evaluate.py
5.3 kB
| """ | |
| Evaluation runner. | |
| Runs both the baseline (single prompt) and the full agent (multi-persona | |
| debate graph) on every scenario in eval_data/scenarios.json, and saves | |
| raw outputs + basic run metadata (timing, retry counts) to a results | |
| file. This does NOT auto-score quality -- per the hackathon brief, a | |
| "good final result" is user-defined, and forcing an LLM to grade its own | |
| sibling's outputs would be circular evidence. Instead this script produces | |
| the paired baseline/agent transcripts that a human (you) scores against | |
| the rubric in eval_data/rubric.md, and that go into the submission as | |
| raw evidence. | |
| Usage: | |
| python evaluate.py # run all scenarios | |
| python evaluate.py --limit 2 # quick smoke test on first 2 | |
| """ | |
| import json | |
| import time | |
| import shutil | |
| import argparse | |
| import tempfile | |
| from pathlib import Path | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| from baseline import run_baseline | |
| from graph import run_debate | |
| from memory.vector_store import DecisionMemory | |
| SCENARIOS_PATH = Path("eval_data/scenarios.json") | |
| RESULTS_PATH = Path("eval_data/results.json") | |
| def load_scenarios(): | |
| with open(SCENARIOS_PATH, "r", encoding="utf-8") as f: | |
| return json.load(f) | |
| def run_one_scenario(scenario: dict) -> dict: | |
| """Each scenario gets a FRESH, isolated memory store. | |
| Discovered issue: running all benchmark scenarios against one shared | |
| persistent memory (as this originally did) caused cross-scenario | |
| contamination -- e.g. the 'used_vs_new_car' scenario's agent output | |
| referenced "your upcoming housing goal", which the user never | |
| mentioned in that query. It leaked in because the unrelated | |
| 'rent_vs_buy' scenario, run earlier in the same batch, had been | |
| stored in memory and got retrieved as a "similar past decision" by | |
| TF-IDF's loose similarity matching. | |
| This is a real failure mode, not just a benchmark artifact: in | |
| production, an unrelated prior decision (even the user's own) being | |
| injected as unstated context could distort advice on a fresh | |
| question. The fix here is narrow and honest about its limits: for | |
| evaluation, we isolate memory per scenario so the debate quality is | |
| judged on its own merits, uncontaminated. Memory's actual value | |
| (recalling a user's own genuinely related past decisions) would need | |
| a separate, deliberately-related test case to demonstrate -- it is | |
| not validated by this benchmark run. | |
| """ | |
| query = scenario["query"] | |
| print(f"\n=== Scenario: {scenario['id']} ===") | |
| print(f"Query: {query}") | |
| temp_dir = tempfile.mkdtemp(prefix="eval_memory_") | |
| memory = DecisionMemory(persist_dir=temp_dir) | |
| try: | |
| print("Running baseline...") | |
| t0 = time.time() | |
| baseline_output = run_baseline(query) | |
| baseline_time = time.time() - t0 | |
| print(f" baseline done in {baseline_time:.1f}s") | |
| print("Running agent (multi-persona debate)...") | |
| t0 = time.time() | |
| agent_result = run_debate(query, memory) | |
| agent_time = time.time() - t0 | |
| print(f" agent done in {agent_time:.1f}s (verification retries: {agent_result.get('retry_count', 0) - 1})") | |
| return { | |
| "id": scenario["id"], | |
| "category": scenario.get("category"), | |
| "query": query, | |
| "note": scenario.get("note", ""), | |
| "baseline": { | |
| "output": baseline_output, | |
| "time_seconds": round(baseline_time, 2), | |
| }, | |
| "agent": { | |
| "optimist_view": agent_result["optimist_view"], | |
| "skeptic_view": agent_result["skeptic_view"], | |
| "analyst_view": agent_result["analyst_view"], | |
| "moderator_output": agent_result["moderator_output"], | |
| "verification_retries": agent_result.get("retry_count", 1) - 1, | |
| "time_seconds": round(agent_time, 2), | |
| }, | |
| } | |
| finally: | |
| shutil.rmtree(temp_dir, ignore_errors=True) | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--limit", type=int, default=None, help="Only run the first N scenarios") | |
| args = parser.parse_args() | |
| scenarios = load_scenarios() | |
| if args.limit: | |
| scenarios = scenarios[: args.limit] | |
| results = [] | |
| for scenario in scenarios: | |
| try: | |
| result = run_one_scenario(scenario) | |
| except RuntimeError as e: | |
| if "DAILY quota exhausted" in str(e): | |
| print(f"\n STOPPING: {e}") | |
| print(f" Saving {len(results)} completed results so far before exiting.") | |
| break | |
| print(f" ERROR on {scenario['id']}: {e}") | |
| result = {"id": scenario["id"], "query": scenario["query"], "error": str(e)} | |
| results.append(result) | |
| continue | |
| except Exception as e: | |
| print(f" ERROR on {scenario['id']}: {e}") | |
| result = {"id": scenario["id"], "query": scenario["query"], "error": str(e)} | |
| results.append(result) | |
| RESULTS_PATH.parent.mkdir(exist_ok=True) | |
| with open(RESULTS_PATH, "w", encoding="utf-8") as f: | |
| json.dump(results, f, indent=2, ensure_ascii=False) | |
| print(f"\nSaved {len(results)} results to {RESULTS_PATH}") | |
| if __name__ == "__main__": | |
| main() |