Spaces:
Sleeping
Sleeping
Shivappa Sangapur
feat: DebateArenaEnv complete - server/client separation, LLM multi-agent, Docker, OpenEnv compliant
b1eddd6 Download server/tools.py from Shivacode/debatearena: direct link, hf CLI and curl.
- Browser
- Download file 8.16 kB
-
https://huggingface.co/spaces/Shivacode/debatearena/resolve/main/server/tools.py
- Command line
-
hf download hf://spaces/Shivacode/debatearena/server/tools.py
-
curl -L -o tools.py https://huggingface.co/spaces/Shivacode/debatearena/resolve/main/server/tools.py
8.16 kB
| """ | |
| DebateArenaEnv — MCP tool registry. | |
| Each function here is an MCP tool callable via: | |
| dispatch(tool_name, params_dict) → JSON string | |
| Also exported as TOOL_REGISTRY dict for the FastAPI wrapper. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| from typing import Any, Dict, List, Optional | |
| from server.env import get_env | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # Tool implementations | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| def tool_new_episode(topic_id: Optional[str] = None) -> Dict[str, Any]: | |
| """Start a new debate episode.""" | |
| obs = get_env().reset(topic_id) | |
| return {"observation": obs, "result": obs["message"]} | |
| def tool_topic_info() -> Dict[str, Any]: | |
| """Return the current topic details.""" | |
| s = get_env().state() | |
| return {"topic": s.get("topic", {})} | |
| def tool_verify_fact(fact_key: str, role: str = "proposer") -> Dict[str, Any]: | |
| """Check whether a named fact is TRUE or FALSE before citing it.""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole(role), | |
| tool="verify_fact", | |
| params={"fact_key": fact_key, "role": role}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| return {"observation": obs, "reward": reward, "done": done, "result": info["result"]} | |
| def tool_submit_argument(argument: str, facts_cited: list) -> Dict[str, Any]: | |
| """Proposer submits a reasoned argument defending the motion.""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole.PROPOSER, | |
| tool="submit_argument", | |
| params={"argument": argument, "facts_cited": facts_cited}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| return {"observation": obs, "reward": reward, "done": done, "result": info["result"]} | |
| def tool_submit_rebuttal( | |
| rebuttal: str, | |
| facts_cited: list, | |
| expose_fallacy: Optional[str] = None, | |
| ) -> Dict[str, Any]: | |
| """Challenger submits a rebuttal to the proposer's argument.""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole.CHALLENGER, | |
| tool="submit_rebuttal", | |
| params={"rebuttal": rebuttal, "facts_cited": facts_cited, "expose_fallacy": expose_fallacy}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| return {"observation": obs, "reward": reward, "done": done, "result": info["result"]} | |
| def tool_refine_position(refined_claim: str, reason: str) -> Dict[str, Any]: | |
| """Proposer updates their position after hearing the challenger (belief-updating bonus).""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole.PROPOSER, | |
| tool="refine_position", | |
| params={"refined_claim": refined_claim, "reason": reason}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| return {"observation": obs, "reward": reward, "done": done, "result": info["result"]} | |
| def tool_concede_point(sub_point: str, maintain_main: str) -> Dict[str, Any]: | |
| """Proposer concedes a minor sub-point while maintaining the core claim (concession bonus).""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole.PROPOSER, | |
| tool="concede_point", | |
| params={"sub_point": sub_point, "maintain_main": maintain_main}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| return {"observation": obs, "reward": reward, "done": done, "result": info["result"]} | |
| def tool_end_debate(closing_statement: str, role: str = "proposer") -> Dict[str, Any]: | |
| """Close the debate with a final statement. Triggers reward computation.""" | |
| from server.env import AgentAction, AgentRole | |
| env = get_env() | |
| action = AgentAction( | |
| role=AgentRole(role), | |
| tool="end_debate", | |
| params={"closing_statement": closing_statement, "role": role}, | |
| ) | |
| obs, reward, done, info = env.step(action) | |
| # Attach rubric breakdown | |
| s = get_env().state() | |
| state_obj = get_env()._state | |
| if state_obj is not None: | |
| from server.rubric import DebateArenaRubric | |
| topic_dict = get_env()._topic.to_dict() if get_env()._topic else {} | |
| _, results = DebateArenaRubric().score(topic_dict, state_obj.to_dict()) | |
| breakdown = DebateArenaRubric.format_breakdown(results) | |
| else: | |
| breakdown = "" | |
| return { | |
| "observation": obs, | |
| "reward": reward, | |
| "done": done, | |
| "result": info["result"], | |
| "winner": obs.get("winner", "?"), | |
| "breakdown": breakdown, | |
| } | |
| def tool_get_state() -> Dict[str, Any]: | |
| """Return the current environment state.""" | |
| return get_env().state() | |
| def tool_curriculum() -> Dict[str, Any]: | |
| """Return the curriculum win-rate summary.""" | |
| from server.tasks import REGISTRY | |
| return REGISTRY.summary() | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # Registry + dispatch | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| TOOL_REGISTRY: Dict[str, Any] = { | |
| "new_episode": tool_new_episode, | |
| "topic_info": tool_topic_info, | |
| "verify_fact": tool_verify_fact, | |
| "submit_argument": tool_submit_argument, | |
| "submit_rebuttal": tool_submit_rebuttal, | |
| "refine_position": tool_refine_position, | |
| "concede_point": tool_concede_point, | |
| "end_debate": tool_end_debate, | |
| "get_state": tool_get_state, | |
| "curriculum": tool_curriculum, | |
| } | |
| def dispatch(tool_name: str, params: Dict[str, Any]) -> str: | |
| """Call a tool by name with a params dict. Returns JSON string.""" | |
| fn = TOOL_REGISTRY.get(tool_name) | |
| if fn is None: | |
| return json.dumps({"error": f"Unknown tool: {tool_name}"}) | |
| try: | |
| result = fn(**params) | |
| return json.dumps(result) | |
| except Exception as exc: | |
| return json.dumps({"error": str(exc)}) | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| # MCP manifest | |
| # ────────────────────────────────────────────────────────────────────────────── | |
| MCP_MANIFEST = { | |
| "name": "debatearena", | |
| "version": "1.0.0", | |
| "tools": [ | |
| {"name": "new_episode", "description": "Start a new debate episode"}, | |
| {"name": "topic_info", "description": "Get current topic details"}, | |
| {"name": "verify_fact", "description": "Check a fact before citing it"}, | |
| {"name": "submit_argument", "description": "Proposer submits argument"}, | |
| {"name": "submit_rebuttal", "description": "Challenger submits rebuttal"}, | |
| {"name": "refine_position", "description": "Proposer updates position (belief-updating bonus)"}, | |
| {"name": "concede_point", "description": "Proposer concedes sub-point (concession bonus)"}, | |
| {"name": "end_debate", "description": "Close debate and compute reward"}, | |
| {"name": "get_state", "description": "Get current environment state"}, | |
| {"name": "curriculum", "description": "Get curriculum win-rate summary"}, | |
| ], | |
| } | |