added server, reward meterics,openenv.yaml,tasks.py, grpo_train.py script
Browse files- .dockerignore +17 -0
- .gitignore +2 -0
- .python-version +1 -0
- Dockerfile +14 -0
- README.md +2 -73
- create_env/debate_env.py +0 -30
- server/environment.py → environment.py +36 -2
- ep.txt +361 -0
- grpo_train.py +213 -0
- inference.py +113 -0
- openenv.yaml +29 -0
- prompter/system_prompt.py +43 -0
- pyproject.toml +18 -0
- requirements.txt +395 -0
- reward_metrics/reward_metrics.py +111 -0
- server/app.py +11 -0
- tasks.py +99 -0
- training_results.json +431 -0
- uv.lock +0 -0
- worflow.md +101 -0
.dockerignore
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Virtual environments
|
| 2 |
+
.venv
|
| 3 |
+
venv
|
| 4 |
+
env
|
| 5 |
+
|
| 6 |
+
# Python cache
|
| 7 |
+
__pycache__
|
| 8 |
+
*.pyc
|
| 9 |
+
*.pyo
|
| 10 |
+
*.pyd
|
| 11 |
+
|
| 12 |
+
# Git and OS files
|
| 13 |
+
.git
|
| 14 |
+
.DS_Store
|
| 15 |
+
|
| 16 |
+
# Hugging Face / Model Caches
|
| 17 |
+
.cache
|
.gitignore
CHANGED
|
@@ -3,6 +3,8 @@ __pycache__/
|
|
| 3 |
*.py[codz]
|
| 4 |
*$py.class
|
| 5 |
|
|
|
|
|
|
|
| 6 |
# C extensions
|
| 7 |
*.so
|
| 8 |
|
|
|
|
| 3 |
*.py[codz]
|
| 4 |
*$py.class
|
| 5 |
|
| 6 |
+
|
| 7 |
+
ignore
|
| 8 |
# C extensions
|
| 9 |
*.so
|
| 10 |
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.11
|
Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
COPY requirements.txt .
|
| 5 |
+
|
| 6 |
+
RUN pip install torch --index-url https://download.pytorch.org/whl/cpu
|
| 7 |
+
|
| 8 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 9 |
+
|
| 10 |
+
COPY . .
|
| 11 |
+
|
| 12 |
+
ENV PYTHONPATH=/app
|
| 13 |
+
EXPOSE 7860
|
| 14 |
+
CMD ["uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,73 +1,2 @@
|
|
| 1 |
-
#
|
| 2 |
-
|
| 3 |
-
**An OpenEnv RL Benchmark for Multi-Turn Adversarial Reasoning and Policy Defense**
|
| 4 |
-
|
| 5 |
-
## 📖 Overview & Real-World Utility (30% Rubric Focus)
|
| 6 |
-
As Large Language Models are increasingly deployed in enterprise environments for drafting corporate policies, legal summaries, and public relations statements, they must be capable of surviving hostile review processes.
|
| 7 |
-
|
| 8 |
-
This environment simulates a strategic **"Red-Teaming"** scenario. The agent acts as the defender of a claim and must successfully navigate a 5-phase adversarial debate against a dynamically generated, skeptical LLM opponent.
|
| 9 |
-
|
| 10 |
-
This is not a toy game; it is a direct simulation of **RLAIF (Reinforcement Learning from AI Feedback)** workflows used at frontier labs to align models against sycophancy (backing down too easily) while training them to maintain logical consistency, deliver strong refutations, and synthesize opposing viewpoints.
|
| 11 |
-
|
| 12 |
-
---
|
| 13 |
-
|
| 14 |
-
## ⚙️ Environment Mechanics
|
| 15 |
-
|
| 16 |
-
### The State Machine (5 Phases)
|
| 17 |
-
The environment enforces strict episode boundaries through a 5-turn state machine. The agent must adapt its strategy based on the current phase:
|
| 18 |
-
1. **OPENING:** Formulate a strong, initial logical claim.
|
| 19 |
-
2. **CHALLENGE:** The opponent attacks the core claim to expose logical gaps.
|
| 20 |
-
3. **REBUTTAL:** The agent must directly and forcefully address the opponent's challenge.
|
| 21 |
-
4. **CONSOLIDATION:** The opponent questions the underlying evidence of the rebuttal.
|
| 22 |
-
5. **CLOSING:** The agent must semantically synthesize the entire conversation into a concluding statement.
|
| 23 |
-
|
| 24 |
-
### Action & Observation Spaces
|
| 25 |
-
* **Action (`DebateAction`)**:
|
| 26 |
-
* `argument` (str): The raw text of the agent's move.
|
| 27 |
-
* `phase_tag` (str): The agent's awareness of the current environment phase.
|
| 28 |
-
* **Observation (`DebateObservation`)**:
|
| 29 |
-
* `topic` (str): The debate topic.
|
| 30 |
-
* `opponent_challenge` (str): The dynamically generated counter-argument from the Groq-powered adversary.
|
| 31 |
-
* `phase` (str): The current phase of the debate.
|
| 32 |
-
* `reward` (float): The step-by-step reward signal `[-1.0, 1.0]`.
|
| 33 |
-
* `done` (bool): Episode termination flag.
|
| 34 |
-
|
| 35 |
-
---
|
| 36 |
-
|
| 37 |
-
## 🧠 Meaningful Reward Function & Semantic Shaping
|
| 38 |
-
To provide dense, partial progress signals for GRPO training, the reward function uses **SentenceTransformers (`all-MiniLM-L6-v2`)** rather than simple keyword matching.
|
| 39 |
-
|
| 40 |
-
* **Semantic Coverage Scoring:** In the `CLOSING` phase, the environment computes vectorized Cosine Similarities between the agent's final statement and the history of both the agent's and opponent's previous arguments. High overlap yields high rewards, teaching the model to actively *synthesize* rather than ignore the opponent.
|
| 41 |
-
* **Anti-Reward Hacking (Repetition Penalty):** The environment tracks the agent's embedded history. If the agent repeats its own previous argument (Cosine Similarity > 0.8), it receives a harsh `-1.0` penalty, forcing novel generation.
|
| 42 |
-
* **Bounded Vector Caching:** To ensure the environment runs blazingly fast during RL training loops, embeddings are cached in a FIFO bounded dictionary, preventing memory leaks (OOM) over thousands of episodes.
|
| 43 |
-
|
| 44 |
-
---
|
| 45 |
-
|
| 46 |
-
## 🎯 Evaluation Tasks & Graders
|
| 47 |
-
The environment includes three deterministic graders. **Crucially, the graders evaluate the raw text of the agent's metadata, completely decoupled from the environment's internal training reward.** This prevents the agent from simply "gaming the training math" during evaluation.
|
| 48 |
-
|
| 49 |
-
| Task | Difficulty | Objective & Grading Criteria |
|
| 50 |
-
| :--- | :--- | :--- |
|
| 51 |
-
| **Task 1: Single Claim** | **Easy** | Evaluates the formulation of the opening statement. Graded heavily on length thresholds and the presence of logical structuring keywords (e.g., "therefore", "consequently"). |
|
| 52 |
-
| **Task 2: Claim & Rebuttal** | **Medium** | Evaluates 3-turn survival. Graded on the textual strength of the rebuttal (use of refutation patterns) and whether the agent successfully generated novel text without triggering the environment's repetition penalty. |
|
| 53 |
-
| **Task 3: Full Debate Synthesis** | **Hard** | Evaluates full 5-turn survival. Graded strictly on the inclusion of semantic synthesis phrases and impactful concluding statements. |
|
| 54 |
-
|
| 55 |
-
---
|
| 56 |
-
|
| 57 |
-
## 📊 Baseline Inference Scores
|
| 58 |
-
A baseline script (`baseline.py`) is provided. It uses the **OpenAI API Client** (routed to Groq's `llama-3.1-8b-instant` for high-speed evaluation) to prove the environment provides a perfect learning gradient with substantial headroom for RL fine-tuning.
|
| 59 |
-
|
| 60 |
-
* **Task 1 (Easy):** `1.00 / 1.00` (The base model easily formulates initial claims).
|
| 61 |
-
* **Task 2 (Medium):** `0.71 / 1.00` (The model survives but struggles to deliver mathematically perfect refutations).
|
| 62 |
-
* **Task 3 (Hard):** `0.50 / 1.00` (The model survives 5 turns but completely fails to synthesize the opponent's arguments, proving significant headroom for GRPO training).
|
| 63 |
-
|
| 64 |
-
---
|
| 65 |
-
|
| 66 |
-
## 🚀 Setup & Installation
|
| 67 |
-
|
| 68 |
-
### Prerequisites
|
| 69 |
-
1. Install dependencies:
|
| 70 |
-
```bash
|
| 71 |
-
pip install -r requirements.txt
|
| 72 |
-
```
|
| 73 |
-
|
|
|
|
| 1 |
+
# -Debate-Coach-Environment
|
| 2 |
+
An RL environment where an agent learns to construct, defend, and rebut arguments on any topic — scored by both rule-based logic checkers and an LLM judge.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create_env/debate_env.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
| 1 |
-
from schema.schemas import DebateState,DebateObservation
|
| 2 |
-
from uuid import uuid4
|
| 3 |
-
|
| 4 |
-
class DebateEnvironment:
|
| 5 |
-
|
| 6 |
-
def __init__(self):
|
| 7 |
-
self._state = DebateState()
|
| 8 |
-
self.picked_topic = ""
|
| 9 |
-
|
| 10 |
-
def reset(self,topic:str,opponent_challenge:str) -> DebateObservation:
|
| 11 |
-
|
| 12 |
-
attempt_count = 0
|
| 13 |
-
|
| 14 |
-
self.picked_topic = topic
|
| 15 |
-
self._state = DebateState(
|
| 16 |
-
episode_id=str(uuid4()),
|
| 17 |
-
step_count=0,
|
| 18 |
-
current_phase="opening",
|
| 19 |
-
)
|
| 20 |
-
|
| 21 |
-
return DebateObservation(
|
| 22 |
-
topic=self.picked_topic,
|
| 23 |
-
opponent_challenge=opponent_challenge,
|
| 24 |
-
attempt_count=attempt_count,
|
| 25 |
-
phase=self._state.current_phase
|
| 26 |
-
)
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
server/environment.py → environment.py
RENAMED
|
@@ -43,7 +43,7 @@ class DebateEnvironment:
|
|
| 43 |
self._state = DebateState(
|
| 44 |
episode_id=str(uuid4()),
|
| 45 |
step_count=0,
|
| 46 |
-
current_phase="
|
| 47 |
)
|
| 48 |
|
| 49 |
return DebateObservation(
|
|
@@ -63,6 +63,7 @@ class DebateEnvironment:
|
|
| 63 |
|
| 64 |
phases = ["OPENING", "CHALLENGE", "REBUTTAL", "CONSOLIDATION", "CLOSING"]
|
| 65 |
|
|
|
|
| 66 |
if self._state.step_count < 5:
|
| 67 |
self._state.current_phase = phases[self._state.step_count]
|
| 68 |
|
|
@@ -74,6 +75,7 @@ class DebateEnvironment:
|
|
| 74 |
self._state.step_count += 1
|
| 75 |
is_done = self._state.step_count >= 5
|
| 76 |
|
|
|
|
| 77 |
|
| 78 |
return DebateObservation(
|
| 79 |
topic=self.picked_topic,
|
|
@@ -81,7 +83,7 @@ class DebateEnvironment:
|
|
| 81 |
done=is_done,
|
| 82 |
reward=reward,
|
| 83 |
attempt_count=self._state.step_count,
|
| 84 |
-
phase=
|
| 85 |
metadata=self._state.history[-1] if self._state.history else {}
|
| 86 |
)
|
| 87 |
|
|
@@ -97,6 +99,11 @@ class DebateEnvironment:
|
|
| 97 |
opp_refutation = self.reward_metrics.opponent_coverage(opponent_history,text)
|
| 98 |
synthesis = self.reward_metrics.synthesis_score(text)
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
if action.phase_tag != self._state.current_phase:
|
| 102 |
reward -= 1.0
|
|
@@ -205,3 +212,30 @@ class DebateEnvironment:
|
|
| 205 |
print(f"Groq API Error: {e}")
|
| 206 |
return "Error: Could not generate response."
|
| 207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
self._state = DebateState(
|
| 44 |
episode_id=str(uuid4()),
|
| 45 |
step_count=0,
|
| 46 |
+
current_phase="OPENING",
|
| 47 |
)
|
| 48 |
|
| 49 |
return DebateObservation(
|
|
|
|
| 63 |
|
| 64 |
phases = ["OPENING", "CHALLENGE", "REBUTTAL", "CONSOLIDATION", "CLOSING"]
|
| 65 |
|
| 66 |
+
|
| 67 |
if self._state.step_count < 5:
|
| 68 |
self._state.current_phase = phases[self._state.step_count]
|
| 69 |
|
|
|
|
| 75 |
self._state.step_count += 1
|
| 76 |
is_done = self._state.step_count >= 5
|
| 77 |
|
| 78 |
+
next_phase = phases[self._state.step_count] if self._state.step_count < 5 else "CLOSING"
|
| 79 |
|
| 80 |
return DebateObservation(
|
| 81 |
topic=self.picked_topic,
|
|
|
|
| 83 |
done=is_done,
|
| 84 |
reward=reward,
|
| 85 |
attempt_count=self._state.step_count,
|
| 86 |
+
phase=next_phase,
|
| 87 |
metadata=self._state.history[-1] if self._state.history else {}
|
| 88 |
)
|
| 89 |
|
|
|
|
| 99 |
opp_refutation = self.reward_metrics.opponent_coverage(opponent_history,text)
|
| 100 |
synthesis = self.reward_metrics.synthesis_score(text)
|
| 101 |
|
| 102 |
+
print(f" DBG current_phase={self._state.current_phase}")
|
| 103 |
+
print(f" DBG action.phase_tag={action.phase_tag}")
|
| 104 |
+
print(f" DBG agent_history count={len(agent_history)}")
|
| 105 |
+
print(f" DBG opponent_history count={len(opponent_history)}")
|
| 106 |
+
print(f" DBG word_count={len(action.argument.split())}")
|
| 107 |
|
| 108 |
if action.phase_tag != self._state.current_phase:
|
| 109 |
reward -= 1.0
|
|
|
|
| 212 |
print(f"Groq API Error: {e}")
|
| 213 |
return "Error: Could not generate response."
|
| 214 |
|
| 215 |
+
|
| 216 |
+
# env = DebateEnvironment()
|
| 217 |
+
# obs = env.reset("AI should be regulated")
|
| 218 |
+
|
| 219 |
+
# for i in range(5):
|
| 220 |
+
# action = DebateAction(
|
| 221 |
+
# argument="therefore this position is correct because evidence strongly supports it and proves the point",
|
| 222 |
+
# phase_tag=obs.phase.upper()
|
| 223 |
+
# )
|
| 224 |
+
# obs = env.step(action)
|
| 225 |
+
# print(f"Step {i+1}: phase={obs.phase} reward={obs.reward}")
|
| 226 |
+
|
| 227 |
+
env = DebateEnvironment()
|
| 228 |
+
obs = env.reset("AI should be regulated")
|
| 229 |
+
|
| 230 |
+
test_args = [
|
| 231 |
+
"therefore AI regulation is necessary because unchecked systems cause harm to society",
|
| 232 |
+
"however critics argue that regulation stifles innovation and economic growth significantly",
|
| 233 |
+
"this fails because evidence shows regulated industries like pharma still innovate effectively",
|
| 234 |
+
"taken together the evidence proves that smart regulation enables rather than blocks progress",
|
| 235 |
+
"in conclusion therefore regulation frameworks protect citizens while preserving innovation capacity",
|
| 236 |
+
]
|
| 237 |
+
|
| 238 |
+
for i, arg in enumerate(test_args):
|
| 239 |
+
action = DebateAction(argument=arg, phase_tag=obs.phase.upper())
|
| 240 |
+
obs = env.step(action)
|
| 241 |
+
print(f"Step {i+1}: phase={obs.phase} reward={obs.reward:.3f}")
|
ep.txt
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
🎯 Topic: Universal Basic Income is necessary
|
| 2 |
+
|
| 3 |
+
--- TURN 1 ---
|
| 4 |
+
|
| 5 |
+
Action Phase: OPENING
|
| 6 |
+
Env Expected Phase: OPENING
|
| 7 |
+
Reward: -0.80
|
| 8 |
+
Opponent: (I stand up, adjust my glasses, and smile slightly, showing a hint of skepticism)
|
| 9 |
+
|
| 10 |
+
Thank you, my opponent, for presenting your opening claim. I appreciate the enthusiasm for exploring the potential benefits of Universal Basic Income (UBI) in the face of rapid AI automation. However, I must respectfully express my doubts about the effectiveness of UBI as a panacea for the challenges posed by AI job displacement.
|
| 11 |
+
|
| 12 |
+
While it's true that AI and automation may revolutionize the job market, I'm not convinced that UBI is the solution to this problem. In fact, I'd like to argue that relying on UBI might even exacerbate the issue rather than address it.
|
| 13 |
+
|
| 14 |
+
Firstly, I'd like to question the assumption that UBI would provide a sufficient safety net for those displaced by AI automation. Would a basic income be enough to sustain individuals and families through a potentially prolonged period of unemployment? Or would it only serve as a Band-Aid solution, masking the underlying problems without addressing the root causes?
|
| 15 |
+
|
| 16 |
+
Furthermore, I'd like to point out that UBI might create unintended consequences, such as reducing the incentive for people to work and innovate, or even discouraging entrepreneurship and economic growth. By providing a basic income without strings attached, might we inadvertently create a culture of dependency rather than self-sufficiency?
|
| 17 |
+
|
| 18 |
+
So, while I acknowledge the potential benefits of UBI, I believe we need to delve deeper into the complexities of this issue and explore alternative solutions that address the root causes of job displacement rather than just treating its symptoms.
|
| 19 |
+
|
| 20 |
+
(leaning forward, with a hint of curiosity) I'd love to hear more about your opponent's response to these concerns. How do you plan to address the challenges and potential drawbacks of implementing UBI in the face of rapid AI automation?
|
| 21 |
+
|
| 22 |
+
--- TURN 2 ---
|
| 23 |
+
|
| 24 |
+
Action Phase: CHALLENGE
|
| 25 |
+
Env Expected Phase: CHALLENGE
|
| 26 |
+
Reward: -0.73
|
| 27 |
+
Opponent: (I stand up, adjusting my glasses and clearing my throat)
|
| 28 |
+
|
| 29 |
+
I appreciate my opponent bringing up the potential concern of inflation as a result of implementing Universal Basic Income (UBI). However, I would like to express some skepticism regarding this claim. While it's true that injecting a large amount of money into the economy can have inflationary effects, it's essential to examine the complexity of this issue more closely.
|
| 30 |
+
|
| 31 |
+
Firstly, the relationship between UBI and inflation is not as straightforward as some critics suggest. Many studies have shown that the inflationary effects of UBI are likely to be minimal, especially if implemented in conjunction with other policies aimed at stabilizing the economy.
|
| 32 |
+
|
| 33 |
+
For instance, if we were to implement a UBI that's indexed to the cost of living, it would likely offset any potential inflationary pressures. Additionally, the benefits of UBI, such as reducing poverty and increasing economic mobility, could lead to increased economic activity, which would actually help to counterbalance any inflationary effects.
|
| 34 |
+
|
| 35 |
+
Furthermore, it's worth noting that many developed economies have implemented policies that inject significant amounts of money into the economy without triggering runaway inflation. For example, the COVID-19 stimulus packages that were implemented worldwide injected trillions of dollars into the economy, yet inflation remained relatively under control.
|
| 36 |
+
|
| 37 |
+
So, while I acknowledge that inflation is a valid concern, I believe it's essential to consider the nuances of this issue and not rely solely on a simplistic narrative that UBI will inevitably lead to inflation. I'd love to hear my opponent's response to these points.
|
| 38 |
+
|
| 39 |
+
--- TURN 3 ---
|
| 40 |
+
|
| 41 |
+
Action Phase: REBUTTAL
|
| 42 |
+
Env Expected Phase: REBUTTAL
|
| 43 |
+
Reward: -0.71
|
| 44 |
+
Opponent: **Attack on the Core Claim: "That inflation can be mitigated by restructuring current welfare programs and implementing a VAT."**
|
| 45 |
+
|
| 46 |
+
As the adversary, I will identify several logical gaps in this reasoning:
|
| 47 |
+
|
| 48 |
+
**Gap 1: Overly simplified assumption about the relationship between welfare programs and inflation**
|
| 49 |
+
|
| 50 |
+
The core claim assumes that restructuring current welfare programs can mitigate inflation. However, this relationship is more complex. Welfare programs are often designed to address poverty and income inequality, which can have a more significant impact on inflation than the programs themselves. For instance, a welfare program that increases the purchasing power of the poor can actually stimulate demand and lead to higher inflation.
|
| 51 |
+
|
| 52 |
+
**Gap 2: Lack of consideration for the potential impact of VAT on the poor**
|
| 53 |
+
|
| 54 |
+
Implementing a VAT can lead to regressive taxation, where the poor are disproportionately affected. The VAT can increase the cost of essential goods and services, such as food, healthcare, and education, which are often consumed by lower-income households. This can exacerbate poverty and inequality, leading to higher inflation in the long run.
|
| 55 |
+
|
| 56 |
+
**Gap 3: Failure to address the root causes of inflation**
|
| 57 |
+
|
| 58 |
+
The core claim focuses on restructuring welfare programs and implementing a VAT as a solution to mitigate inflation. However, inflation is often the result of underlying economic imbalances, such as:
|
| 59 |
+
|
| 60 |
+
1. **Monetary policy**: Excessive money printing or quantitative easing can lead to inflation.
|
| 61 |
+
2. **Supply and demand imbalance**: Shortages or surpluses in key commodities can drive prices up or down.
|
| 62 |
+
3. **Exchange rates**: Changes in exchange rates can affect the prices of imported goods and services.
|
| 63 |
+
|
| 64 |
+
These underlying causes of inflation are not addressed by restructuring welfare programs or implementing a VAT.
|
| 65 |
+
|
| 66 |
+
**Gap 4: Potential unintended consequences of VAT implementation**
|
| 67 |
+
|
| 68 |
+
Implementing a VAT can lead to various unintended consequences, such as:
|
| 69 |
+
|
| 70 |
+
1. **Tax evasion**: A high VAT rate can lead to widespread tax evasion, reducing government revenue and increasing the burden on honest taxpayers.
|
| 71 |
+
2. **Black market growth**: A VAT can create opportunities for black market activity, as individuals seek to avoid paying the tax.
|
| 72 |
+
3. **Inflationary pressure**: A VAT can lead to higher prices, which can fuel inflation.
|
| 73 |
+
|
| 74 |
+
**Gap 5: Lack of consideration for the impact on economic growth**
|
| 75 |
+
|
| 76 |
+
Restructuring welfare programs and implementing a VAT can have a negative impact on economic growth. A VAT can increase the cost of doing business, reduce consumer spending, and decrease economic activity. This can lead to a decrease in
|
| 77 |
+
|
| 78 |
+
--- TURN 4 ---
|
| 79 |
+
|
| 80 |
+
Action Phase: CONSOLIDATION
|
| 81 |
+
Env Expected Phase: CONSOLIDATION
|
| 82 |
+
Reward: -0.80
|
| 83 |
+
Opponent: I'm not familiar with the previous challenge you're referring to, but let's assume it was a critique of the idea that inflation can be mitigated by restructuring current welfare programs and implementing a Value-Added Tax (VAT).
|
| 84 |
+
|
| 85 |
+
Here's my response as a critical rebutter:
|
| 86 |
+
|
| 87 |
+
"While the agent suggests that restructuring current welfare programs and implementing a VAT can mitigate inflation, this proposal fails to address the root causes of inflation. Implementing a VAT will likely increase the cost of living for low-income households, who often rely on welfare programs for basic necessities. This could exacerbate the very issues that welfare programs aim to address.
|
| 88 |
+
|
| 89 |
+
Furthermore, restructuring welfare programs might not necessarily reduce inflation. If the restructuring involves reducing benefits or imposing stricter eligibility criteria, it could lead to increased poverty and reduced economic activity, which in turn could fuel inflation. Inflation is a complex issue that requires a multifaceted approach, and simply tweaking welfare programs and implementing a VAT might not be enough to address it.
|
| 90 |
+
|
| 91 |
+
Additionally, the agent's proposal does not consider the potential impact of a VAT on the economy's overall competitiveness. A VAT can increase the cost of production and reduce the competitiveness of domestic industries, leading to higher prices and potentially even higher inflation.
|
| 92 |
+
|
| 93 |
+
In conclusion, while the agent's proposal might provide some short-term relief, it fails to address the underlying causes of inflation and could even exacerbate the problem. A more comprehensive and nuanced approach is needed to mitigate inflation effectively."
|
| 94 |
+
|
| 95 |
+
--- TURN 5 ---
|
| 96 |
+
|
| 97 |
+
Action Phase: CLOSING
|
| 98 |
+
Env Expected Phase: CLOSING
|
| 99 |
+
Reward: -0.28
|
| 100 |
+
Opponent:
|
| 101 |
+
|
| 102 |
+
🏁 Episode Done: True
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
----------------------------------------------------------------------------------
|
| 108 |
+
|
| 109 |
+
----------------------------------------------------------------------------------
|
| 110 |
+
|
| 111 |
+
🚀 Starting Baseline Evaluation with llama-3.1-8b-instant
|
| 112 |
+
📋 Topic: Universal Basic Income is necessary for the future economy.
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
----------------------------------------
|
| 116 |
+
Evaluating Task 1: Single Claim (1 Step)
|
| 117 |
+
|
| 118 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 19.60it/s]
|
| 119 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 55.55it/s]
|
| 120 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 18.90it/s]
|
| 121 |
+
Task 1 Score: 1.00
|
| 122 |
+
|
| 123 |
+
----------------------------------------
|
| 124 |
+
Evaluating Task 2: Claim and Rebuttal (3 Steps)
|
| 125 |
+
|
| 126 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 52.65it/s]
|
| 127 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 76.91it/s]
|
| 128 |
+
Batches: 100%|███████████████████��█████████████████████████████████████| 1/1 [00:00<00:00, 29.41it/s]
|
| 129 |
+
|
| 130 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 45.47it/s]
|
| 131 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 99.95it/s]
|
| 132 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 22.99it/s]
|
| 133 |
+
|
| 134 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 50.00it/s]
|
| 135 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 71.39it/s]
|
| 136 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 19.41it/s]
|
| 137 |
+
Task 2 Score: 0.60
|
| 138 |
+
|
| 139 |
+
----------------------------------------
|
| 140 |
+
Evaluating Task 3: Full Debate (5 Steps)
|
| 141 |
+
|
| 142 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 47.43it/s]
|
| 143 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 90.86it/s]
|
| 144 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 31.74it/s]
|
| 145 |
+
|
| 146 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 45.46it/s]
|
| 147 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 66.63it/s]
|
| 148 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 25.64it/s]
|
| 149 |
+
|
| 150 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 43.51it/s]
|
| 151 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 76.91it/s]
|
| 152 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 30.75it/s]
|
| 153 |
+
|
| 154 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 76.89it/s]
|
| 155 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 18.01it/s]
|
| 156 |
+
|
| 157 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 51.25it/s]
|
| 158 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 52.63it/s]
|
| 159 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 33.17it/s]
|
| 160 |
+
Task 3 Score: 0.50
|
| 161 |
+
|
| 162 |
+
========================================
|
| 163 |
+
🏆 BASELINE EVALUATION COMPLETE
|
| 164 |
+
Task 1 (Easy): 1.00 / 1.00
|
| 165 |
+
Task 2 (Medium): 0.60 / 1.00
|
| 166 |
+
Task 3 (Hard): 0.50 / 1.00
|
| 167 |
+
========================================
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
--------------------------------------------------------------------------------------
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
--------------------------------------------------------------------------------------
|
| 175 |
+
|
| 176 |
+
🚀 Starting Baseline Evaluation with llama-3.1-8b-instant
|
| 177 |
+
📋 Topic: Universal Basic Income is necessary for the future economy.
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
----------------------------------------
|
| 181 |
+
Evaluating Task 1: Single Claim (1 Step)
|
| 182 |
+
|
| 183 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 7.97it/s]
|
| 184 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 71.42it/s]
|
| 185 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 20.65it/s]
|
| 186 |
+
Task 1 Score: 1.00
|
| 187 |
+
|
| 188 |
+
----------------------------------------
|
| 189 |
+
Evaluating Task 2: Claim and Rebuttal (3 Steps)
|
| 190 |
+
|
| 191 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 38.79it/s]
|
| 192 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 71.39it/s]
|
| 193 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 22.30it/s]
|
| 194 |
+
|
| 195 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 54.21it/s]
|
| 196 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 62.50it/s]
|
| 197 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 23.33it/s]
|
| 198 |
+
|
| 199 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 40.25it/s]
|
| 200 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 61.55it/s]
|
| 201 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 22.10it/s]
|
| 202 |
+
Task 2 Score: 0.77
|
| 203 |
+
|
| 204 |
+
----------------------------------------
|
| 205 |
+
Evaluating Task 3: Full Debate (5 Steps)
|
| 206 |
+
|
| 207 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 17.63it/s]
|
| 208 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 39.47it/s]
|
| 209 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 14.67it/s]
|
| 210 |
+
|
| 211 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 47.57it/s]
|
| 212 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 64.47it/s]
|
| 213 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 23.96it/s]
|
| 214 |
+
|
| 215 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 32.30it/s]
|
| 216 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 69.68it/s]
|
| 217 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 24.39it/s]
|
| 218 |
+
|
| 219 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 40.00it/s]
|
| 220 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 51.22it/s]
|
| 221 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 20.00it/s]
|
| 222 |
+
|
| 223 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 28.20it/s]
|
| 224 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 24.43it/s]
|
| 225 |
+
Batches: 100%|█████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 17.79it/s]
|
| 226 |
+
Task 3 Score: 0.50
|
| 227 |
+
|
| 228 |
+
========================================
|
| 229 |
+
🏆 BASELINE EVALUATION COMPLETE
|
| 230 |
+
Task 1 (Easy): 1.00 / 1.00
|
| 231 |
+
Task 2 (Medium): 0.77 / 1.00
|
| 232 |
+
Task 3 (Hard): 0.50 / 1.00
|
| 233 |
+
========================================
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
------------------------------------------------------------------------------------
|
| 237 |
+
|
| 238 |
+
------------------------------------------------------------------------------------
|
| 239 |
+
|
| 240 |
+
🚀 Starting Baseline Evaluation with llama-3.1-8b-instant
|
| 241 |
+
📋 Topic: Universal Basic Income is necessary for the future economy.
|
| 242 |
+
|
| 243 |
+
----------------------------------------
|
| 244 |
+
Evaluating Task 1: Single Claim (1 Step)
|
| 245 |
+
|
| 246 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 5.67it/s]
|
| 247 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 55.55it/s]
|
| 248 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 16.36it/s]
|
| 249 |
+
Task 1 Score: 1.00
|
| 250 |
+
|
| 251 |
+
----------------------------------------
|
| 252 |
+
Evaluating Task 2: Claim and Rebuttal (3 Steps)
|
| 253 |
+
|
| 254 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 36.29it/s]
|
| 255 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 43.06it/s]
|
| 256 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 18.82it/s]
|
| 257 |
+
|
| 258 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 19.95it/s]
|
| 259 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 36.70it/s]
|
| 260 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12.33it/s]
|
| 261 |
+
|
| 262 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 32.60it/s]
|
| 263 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 39.28it/s]
|
| 264 |
+
Batches: 100%|█████████████████████████████████████████████��████████████████████████████████| 1/1 [00:00<00:00, 16.25it/s]
|
| 265 |
+
Task 2 Score: 0.71
|
| 266 |
+
|
| 267 |
+
----------------------------------------
|
| 268 |
+
Evaluating Task 3: Full Debate (5 Steps)
|
| 269 |
+
|
| 270 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 19.25it/s]
|
| 271 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 32.47it/s]
|
| 272 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12.61it/s]
|
| 273 |
+
|
| 274 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 34.34it/s]
|
| 275 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 48.01it/s]
|
| 276 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 18.80it/s]
|
| 277 |
+
|
| 278 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 13.95it/s]
|
| 279 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 17.19it/s]
|
| 280 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 13.01it/s]
|
| 281 |
+
|
| 282 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 19.12it/s]
|
| 283 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 29.64it/s]
|
| 284 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11.00it/s]
|
| 285 |
+
|
| 286 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 22.31it/s]
|
| 287 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 44.27it/s]
|
| 288 |
+
Batches: 100%|██████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 21.85it/s]
|
| 289 |
+
Task 3 Score: 0.50
|
| 290 |
+
|
| 291 |
+
========================================
|
| 292 |
+
🏆 BASELINE EVALUATION COMPLETE
|
| 293 |
+
Task 1 (Easy): 1.00 / 1.00
|
| 294 |
+
Task 2 (Medium): 0.71 / 1.00
|
| 295 |
+
Task 3 (Hard): 0.50 / 1.00
|
| 296 |
+
========================================
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
|
| 300 |
+
---------------------------------------------------------------------------------
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
---------------------------------------------------------------------------------
|
| 304 |
+
|
| 305 |
+
Step 1: phase=CHALLENGE reward=0.23333333333333334
|
| 306 |
+
|
| 307 |
+
Step 2: phase=REBUTTAL reward=0.0
|
| 308 |
+
|
| 309 |
+
Step 3: phase=CONSOLIDATION reward=0.0
|
| 310 |
+
|
| 311 |
+
Step 4: phase=CLOSING reward=0.0
|
| 312 |
+
|
| 313 |
+
Step 5: phase=CLOSING reward=0.0
|
| 314 |
+
|
| 315 |
+
-----------------------------------------------------------------------------------
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
-----------------------------------------------------------------------------------
|
| 319 |
+
|
| 320 |
+
DBG current_phase=OPENING
|
| 321 |
+
DBG action.phase_tag=OPENING
|
| 322 |
+
DBG agent_history count=1
|
| 323 |
+
DBG opponent_history count=1
|
| 324 |
+
DBG word_count=14
|
| 325 |
+
Step 1: phase=CHALLENGE reward=0.23333333333333334
|
| 326 |
+
|
| 327 |
+
DBG current_phase=CHALLENGE
|
| 328 |
+
DBG action.phase_tag=CHALLENGE
|
| 329 |
+
DBG agent_history count=2
|
| 330 |
+
DBG opponent_history count=2
|
| 331 |
+
DBG word_count=14
|
| 332 |
+
Step 2: phase=REBUTTAL reward=0.0
|
| 333 |
+
|
| 334 |
+
DBG current_phase=REBUTTAL
|
| 335 |
+
DBG action.phase_tag=REBUTTAL
|
| 336 |
+
DBG agent_history count=3
|
| 337 |
+
DBG opponent_history count=3
|
| 338 |
+
DBG word_count=14
|
| 339 |
+
Step 3: phase=CONSOLIDATION reward=0.0
|
| 340 |
+
|
| 341 |
+
DBG current_phase=CONSOLIDATION
|
| 342 |
+
DBG action.phase_tag=CONSOLIDATION
|
| 343 |
+
DBG agent_history count=4
|
| 344 |
+
DBG opponent_history count=4
|
| 345 |
+
DBG word_count=14
|
| 346 |
+
Step 4: phase=CLOSING reward=0.0
|
| 347 |
+
|
| 348 |
+
DBG current_phase=CLOSING
|
| 349 |
+
DBG action.phase_tag=CLOSING
|
| 350 |
+
DBG agent_history count=5
|
| 351 |
+
DBG opponent_history count=5
|
| 352 |
+
DBG word_count=14
|
| 353 |
+
Step 5: phase=CLOSING reward=0.0
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
-----------------------------------------------------------------------------------
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
-----------------------------------------------------------------------------------
|
| 361 |
+
|
grpo_train.py
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
grpo_train.py
|
| 3 |
+
Simple GRPO-style training loop for the Debate Coach Environment.
|
| 4 |
+
Tracks reward improvement across episodes to demonstrate learning signal.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from dotenv import load_dotenv
|
| 8 |
+
load_dotenv()
|
| 9 |
+
|
| 10 |
+
import os
|
| 11 |
+
import time
|
| 12 |
+
import json
|
| 13 |
+
from collections import defaultdict
|
| 14 |
+
from openai import OpenAI
|
| 15 |
+
|
| 16 |
+
from environment import DebateEnvironment
|
| 17 |
+
from schema.schemas import DebateAction
|
| 18 |
+
from tasks import Task1_SingleClaim, Task2_ClaimAndRebuttal, Task3_FullDebate
|
| 19 |
+
|
| 20 |
+
# ── Config ────────────────────────────────────────────────────────────────────
|
| 21 |
+
API_BASE_URL = os.getenv("API_BASE_URL", "https://api.groq.com/openai/v1")
|
| 22 |
+
HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("GROQ_API_KEY")
|
| 23 |
+
MODEL_NAME = os.getenv("MODEL_NAME", "llama-3.1-8b-instant")
|
| 24 |
+
|
| 25 |
+
NUM_EPISODES = 30 # total training episodes
|
| 26 |
+
GROUP_SIZE = 5 # GRPO: episodes per group for baseline calculation
|
| 27 |
+
SLEEP_BETWEEN_CALLS = 1.0 # seconds — Groq rate limit protection
|
| 28 |
+
|
| 29 |
+
TOPICS = [
|
| 30 |
+
"Universal Basic Income is necessary for the future economy.",
|
| 31 |
+
"Artificial Intelligence should be strictly regulated by governments.",
|
| 32 |
+
"Social media does more harm than good to society.",
|
| 33 |
+
"Climate change requires immediate radical policy action.",
|
| 34 |
+
"Remote work is more productive than office work.",
|
| 35 |
+
]
|
| 36 |
+
|
| 37 |
+
client = OpenAI(base_url=API_BASE_URL, api_key=HF_TOKEN)
|
| 38 |
+
|
| 39 |
+
def generate_argument(topic: str, phase: str, opponent_challenge: str,
|
| 40 |
+
temperature: float = 0.7) -> str:
|
| 41 |
+
"""
|
| 42 |
+
The 'policy' — generates an argument given the current observation.
|
| 43 |
+
Temperature is increased over time to encourage exploration (GRPO-style).
|
| 44 |
+
"""
|
| 45 |
+
prompt = f"You are a skilled debater. Topic: '{topic}'.\n"
|
| 46 |
+
prompt += f"Current debate phase: {phase}.\n"
|
| 47 |
+
|
| 48 |
+
if opponent_challenge:
|
| 49 |
+
prompt += f"Opponent argued: '{opponent_challenge}'\n"
|
| 50 |
+
prompt += ("Respond directly and logically. "
|
| 51 |
+
"Use words like 'therefore', 'because', 'however', "
|
| 52 |
+
"'this fails because', 'the evidence shows'.\n")
|
| 53 |
+
else:
|
| 54 |
+
prompt += ("Make a strong opening claim. "
|
| 55 |
+
"Use 'therefore' or 'because' to show reasoning.\n")
|
| 56 |
+
|
| 57 |
+
prompt += "Be concise: 30-60 words. No filler phrases."
|
| 58 |
+
|
| 59 |
+
try:
|
| 60 |
+
resp = client.chat.completions.create(
|
| 61 |
+
model=MODEL_NAME,
|
| 62 |
+
messages=[{"role": "user", "content": prompt}],
|
| 63 |
+
temperature=temperature,
|
| 64 |
+
max_tokens=200,
|
| 65 |
+
)
|
| 66 |
+
return resp.choices[0].message.content.strip()
|
| 67 |
+
except Exception as e:
|
| 68 |
+
print(f" [Agent API Error] {e}")
|
| 69 |
+
return "therefore this position is correct because the evidence supports it."
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def run_episode(env: DebateEnvironment, topic: str,
|
| 73 |
+
grader, temperature: float = 0.7) -> dict:
|
| 74 |
+
"""
|
| 75 |
+
Runs one full episode and returns a result dict with:
|
| 76 |
+
- per-step rewards from the environment
|
| 77 |
+
- final task score from the grader
|
| 78 |
+
"""
|
| 79 |
+
obs = env.reset(topic)
|
| 80 |
+
step_rewards = []
|
| 81 |
+
|
| 82 |
+
while not obs.done:
|
| 83 |
+
argument = generate_argument(
|
| 84 |
+
topic=obs.topic,
|
| 85 |
+
phase=obs.phase.upper(),
|
| 86 |
+
opponent_challenge=obs.opponent_challenge,
|
| 87 |
+
temperature=temperature,
|
| 88 |
+
)
|
| 89 |
+
action = DebateAction(argument=argument, phase_tag=obs.phase.upper())
|
| 90 |
+
obs = env.step(action)
|
| 91 |
+
step_rewards.append(obs.reward)
|
| 92 |
+
time.sleep(SLEEP_BETWEEN_CALLS)
|
| 93 |
+
|
| 94 |
+
final_score = grader.grade(obs)
|
| 95 |
+
|
| 96 |
+
return {
|
| 97 |
+
"topic": topic,
|
| 98 |
+
"step_rewards": step_rewards,
|
| 99 |
+
"mean_reward": sum(step_rewards) / len(step_rewards) if step_rewards else 0.0,
|
| 100 |
+
"final_score": final_score,
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
# GRPO core
|
| 105 |
+
def compute_grpo_advantage(group_results: list[dict]) -> list[float]:
|
| 106 |
+
"""
|
| 107 |
+
GRPO: advantage = (score - group_mean) / (group_std + epsilon)
|
| 108 |
+
This tells us which episodes in the group were above/below average.
|
| 109 |
+
A positive advantage = this episode's policy was better than the group baseline.
|
| 110 |
+
"""
|
| 111 |
+
scores = [r["final_score"] for r in group_results]
|
| 112 |
+
mean = sum(scores) / len(scores)
|
| 113 |
+
variance = sum((s - mean) ** 2 for s in scores) / len(scores)
|
| 114 |
+
std = variance ** 0.5
|
| 115 |
+
|
| 116 |
+
advantages = [(s - mean) / (std + 1e-8) for s in scores]
|
| 117 |
+
return advantages
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
# Training loop
|
| 121 |
+
def train():
|
| 122 |
+
env = DebateEnvironment()
|
| 123 |
+
grader = Task3_FullDebate()
|
| 124 |
+
|
| 125 |
+
all_results = []
|
| 126 |
+
group_buffer = []
|
| 127 |
+
episode_scores = []
|
| 128 |
+
|
| 129 |
+
# Temperature annealing: start high (explore) → end lower (exploit)
|
| 130 |
+
def get_temperature(episode: int) -> float:
|
| 131 |
+
return max(0.4, 1.0 - (episode / NUM_EPISODES) * 0.6)
|
| 132 |
+
|
| 133 |
+
print("=" * 50)
|
| 134 |
+
print("GRPO Training — Debate Coach Environment")
|
| 135 |
+
print(f"Episodes: {NUM_EPISODES} | Group size: {GROUP_SIZE}")
|
| 136 |
+
print(f"Model: {MODEL_NAME}")
|
| 137 |
+
print("=" * 50)
|
| 138 |
+
|
| 139 |
+
for episode in range(NUM_EPISODES):
|
| 140 |
+
topic = TOPICS[episode % len(TOPICS)]
|
| 141 |
+
temp = get_temperature(episode)
|
| 142 |
+
|
| 143 |
+
print(f"\nEpisode {episode + 1}/{NUM_EPISODES} | "
|
| 144 |
+
f"Topic: {topic[:40]}... | Temp: {temp:.2f}")
|
| 145 |
+
|
| 146 |
+
result = run_episode(env, topic, grader, temperature=temp)
|
| 147 |
+
all_results.append(result)
|
| 148 |
+
group_buffer.append(result)
|
| 149 |
+
episode_scores.append(result["final_score"])
|
| 150 |
+
|
| 151 |
+
print(f" Step rewards: {[f'{r:.2f}' for r in result['step_rewards']]}")
|
| 152 |
+
print(f" Mean reward: {result['mean_reward']:.3f}")
|
| 153 |
+
print(f" Final score: {result['final_score']:.3f}")
|
| 154 |
+
|
| 155 |
+
# Every GROUP_SIZE episodes: compute GRPO advantage for the group
|
| 156 |
+
if len(group_buffer) == GROUP_SIZE:
|
| 157 |
+
advantages = compute_grpo_advantage(group_buffer)
|
| 158 |
+
group_scores = [r["final_score"] for r in group_buffer]
|
| 159 |
+
|
| 160 |
+
print(f"\n --- Group {episode // GROUP_SIZE + 1} Summary ---")
|
| 161 |
+
print(f" Scores: {[f'{s:.2f}' for s in group_scores]}")
|
| 162 |
+
print(f" Advantages: {[f'{a:.2f}' for a in advantages]}")
|
| 163 |
+
print(f" Best episode in group: "
|
| 164 |
+
f"Episode {episode - GROUP_SIZE + 1 + group_scores.index(max(group_scores)) + 1} "
|
| 165 |
+
f"(score={max(group_scores):.2f})")
|
| 166 |
+
|
| 167 |
+
# In real GRPO: you would use advantages to weight your policy gradient update.
|
| 168 |
+
# Here we log them so you can see the signal your environment produces.
|
| 169 |
+
for i, (res, adv) in enumerate(zip(group_buffer, advantages)):
|
| 170 |
+
res["advantage"] = adv
|
| 171 |
+
|
| 172 |
+
group_buffer = []
|
| 173 |
+
|
| 174 |
+
# Final report
|
| 175 |
+
print("\n" + "=" * 50)
|
| 176 |
+
print("TRAINING COMPLETE — Reward Curve")
|
| 177 |
+
print("=" * 50)
|
| 178 |
+
|
| 179 |
+
# Print reward curve in 5-episode windows
|
| 180 |
+
window = 5
|
| 181 |
+
for i in range(0, NUM_EPISODES, window):
|
| 182 |
+
chunk = episode_scores[i:i + window]
|
| 183 |
+
avg = sum(chunk) / len(chunk)
|
| 184 |
+
bar = "█" * int(avg * 20)
|
| 185 |
+
print(f" Episodes {i+1:2d}-{i+len(chunk):2d}: {avg:.3f} {bar}")
|
| 186 |
+
|
| 187 |
+
overall_avg = sum(episode_scores) / len(episode_scores)
|
| 188 |
+
first_half = sum(episode_scores[:NUM_EPISODES//2]) / (NUM_EPISODES // 2)
|
| 189 |
+
second_half = sum(episode_scores[NUM_EPISODES//2:]) / (NUM_EPISODES - NUM_EPISODES // 2)
|
| 190 |
+
|
| 191 |
+
print(f"\n Overall average: {overall_avg:.3f}")
|
| 192 |
+
print(f" First half average: {first_half:.3f}")
|
| 193 |
+
print(f" Second half average: {second_half:.3f}")
|
| 194 |
+
print(f" Trend: {'IMPROVING ↑' if second_half > first_half else 'DECLINING ↓'}")
|
| 195 |
+
|
| 196 |
+
# Save results to JSON for your README / submission
|
| 197 |
+
with open("training_results.json", "w") as f:
|
| 198 |
+
json.dump({
|
| 199 |
+
"model": MODEL_NAME,
|
| 200 |
+
"num_episodes": NUM_EPISODES,
|
| 201 |
+
"episode_scores": episode_scores,
|
| 202 |
+
"overall_avg": overall_avg,
|
| 203 |
+
"first_half_avg": first_half,
|
| 204 |
+
"second_half_avg": second_half,
|
| 205 |
+
"all_results": all_results,
|
| 206 |
+
}, f, indent=2)
|
| 207 |
+
|
| 208 |
+
print("\n Results saved to training_results.json")
|
| 209 |
+
print("=" * 50)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
if __name__ == "__main__":
|
| 213 |
+
train()
|
inference.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dotenv import load_dotenv
|
| 2 |
+
load_dotenv()
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
Inference Script
|
| 6 |
+
===================================
|
| 7 |
+
Compliant with Hackathon Mandatory Variables.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import os
|
| 11 |
+
import time
|
| 12 |
+
from openai import OpenAI
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
from environment import DebateEnvironment
|
| 16 |
+
from schema.schemas import DebateAction
|
| 17 |
+
from tasks import Task1_SingleClaim, Task2_ClaimAndRebuttal, Task3_FullDebate
|
| 18 |
+
|
| 19 |
+
API_BASE_URL = os.getenv("API_BASE_URL")
|
| 20 |
+
HF_TOKEN = os.getenv("HF_TOKEN")
|
| 21 |
+
MODEL_NAME = os.getenv("MODEL_NAME")
|
| 22 |
+
|
| 23 |
+
client = OpenAI(
|
| 24 |
+
base_url=API_BASE_URL,
|
| 25 |
+
api_key=HF_TOKEN
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def generate_agent_argument(topic: str, phase: str, opponent_challenge: str) -> str:
|
| 30 |
+
"""Uses the injected LLM to generate the agent's move based on the observation."""
|
| 31 |
+
prompt = f"You are a skilled debater. The topic is: '{topic}'.\n"
|
| 32 |
+
prompt += f"The current phase of the debate is: {phase}.\n"
|
| 33 |
+
|
| 34 |
+
if opponent_challenge:
|
| 35 |
+
prompt += f"Your opponent just argued: '{opponent_challenge}'\n"
|
| 36 |
+
prompt += "Write a direct, logical response to their challenge. Use reasoning keywords like 'therefore' or 'because'.\n"
|
| 37 |
+
else:
|
| 38 |
+
prompt += "Write a strong, logical opening statement for your side. Use reasoning keywords like 'therefore' or 'because'.\n"
|
| 39 |
+
|
| 40 |
+
prompt += "Keep your response under 50 words and do not include any conversational filler."
|
| 41 |
+
|
| 42 |
+
try:
|
| 43 |
+
response = client.chat.completions.create(
|
| 44 |
+
model=MODEL_NAME,
|
| 45 |
+
messages=[{"role": "user", "content": prompt}],
|
| 46 |
+
temperature=0.7,
|
| 47 |
+
max_tokens=150
|
| 48 |
+
)
|
| 49 |
+
return response.choices[0].message.content.strip()
|
| 50 |
+
except Exception as e:
|
| 51 |
+
print(f"Agent API Error: {e}")
|
| 52 |
+
return "therefore I agree."
|
| 53 |
+
|
| 54 |
+
def evaluate_baseline():
|
| 55 |
+
env = DebateEnvironment()
|
| 56 |
+
topic = "Universal Basic Income is necessary for the future economy."
|
| 57 |
+
|
| 58 |
+
print(f"Starting Baseline Evaluation with {MODEL_NAME}")
|
| 59 |
+
print(f"Topic: {topic}\n")
|
| 60 |
+
print("-" * 40)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
print("Evaluating Task 1: Single Claim (1 Step)")
|
| 64 |
+
obs = env.reset(topic)
|
| 65 |
+
|
| 66 |
+
argument = generate_agent_argument(obs.topic, obs.phase, obs.opponent_challenge)
|
| 67 |
+
action = DebateAction(argument=argument, phase_tag=obs.phase.upper())
|
| 68 |
+
obs = env.step(action)
|
| 69 |
+
|
| 70 |
+
task1 = Task1_SingleClaim()
|
| 71 |
+
score1 = task1.grade(obs)
|
| 72 |
+
print(f"Task 1 Score: {score1:.2f}\n")
|
| 73 |
+
time.sleep(1)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
print("-" * 40)
|
| 77 |
+
print("Evaluating Task 2: Claim and Rebuttal (3 Steps)")
|
| 78 |
+
obs = env.reset(topic)
|
| 79 |
+
|
| 80 |
+
for _ in range(3):
|
| 81 |
+
argument = generate_agent_argument(obs.topic, obs.phase, obs.opponent_challenge)
|
| 82 |
+
action = DebateAction(argument=argument, phase_tag=obs.phase.upper())
|
| 83 |
+
obs = env.step(action)
|
| 84 |
+
time.sleep(1)
|
| 85 |
+
|
| 86 |
+
task2 = Task2_ClaimAndRebuttal()
|
| 87 |
+
score2 = task2.grade(obs)
|
| 88 |
+
print(f"Task 2 Score: {score2:.2f}\n")
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
print("-" * 40)
|
| 92 |
+
print("Evaluating Task 3: Full Debate (5 Steps)")
|
| 93 |
+
obs = env.reset(topic)
|
| 94 |
+
|
| 95 |
+
while not obs.done:
|
| 96 |
+
argument = generate_agent_argument(obs.topic, obs.phase, obs.opponent_challenge)
|
| 97 |
+
action = DebateAction(argument=argument, phase_tag=obs.phase.upper())
|
| 98 |
+
obs = env.step(action)
|
| 99 |
+
time.sleep(1)
|
| 100 |
+
|
| 101 |
+
task3 = Task3_FullDebate()
|
| 102 |
+
score3 = task3.grade(obs)
|
| 103 |
+
print(f"Task 3 Score: {score3:.2f}\n")
|
| 104 |
+
|
| 105 |
+
print("=" * 40)
|
| 106 |
+
print("BASELINE EVALUATION COMPLETE")
|
| 107 |
+
print(f"Task 1 (Easy): {score1:.2f} / 1.00")
|
| 108 |
+
print(f"Task 2 (Medium): {score2:.2f} / 1.00")
|
| 109 |
+
print(f"Task 3 (Hard): {score3:.2f} / 1.00")
|
| 110 |
+
print("=" * 40)
|
| 111 |
+
|
| 112 |
+
if __name__ == "__main__":
|
| 113 |
+
evaluate_baseline()
|
openenv.yaml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: debate-coach-env
|
| 2 |
+
version: "1.0.0"
|
| 3 |
+
description: "Argument quality evaluation environment for training LLM reasoning and persuasion"
|
| 4 |
+
author: your-hf-username
|
| 5 |
+
tasks:
|
| 6 |
+
- name: single_claim
|
| 7 |
+
difficulty: easy
|
| 8 |
+
max_steps: 1
|
| 9 |
+
- name: claim_and_rebuttal
|
| 10 |
+
difficulty: medium
|
| 11 |
+
max_steps: 3
|
| 12 |
+
- name: full_debate
|
| 13 |
+
difficulty: hard
|
| 14 |
+
max_steps: 5
|
| 15 |
+
action_space:
|
| 16 |
+
type: structured
|
| 17 |
+
fields:
|
| 18 |
+
- name: argument
|
| 19 |
+
type: string
|
| 20 |
+
- name: phase_tag
|
| 21 |
+
type: string
|
| 22 |
+
observation_space:
|
| 23 |
+
type: structured
|
| 24 |
+
fields:
|
| 25 |
+
- topic
|
| 26 |
+
- opponent_challenge
|
| 27 |
+
- done
|
| 28 |
+
- reward
|
| 29 |
+
- phase
|
prompter/system_prompt.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class SystemPrompt:
|
| 2 |
+
def __init__(self, topic: str):
|
| 3 |
+
self.topic = topic
|
| 4 |
+
|
| 5 |
+
def get_prompt(self, phase: str, argument: str = "", opponent_challenge: str = "") -> str:
|
| 6 |
+
"""Dynamically generates a prompt based on the current debate phase."""
|
| 7 |
+
|
| 8 |
+
# We use a dictionary to store templates with placeholders
|
| 9 |
+
templates = {
|
| 10 |
+
"OPENING": f"""
|
| 11 |
+
Role: Debate Opponent.
|
| 12 |
+
Topic: {self.topic}.
|
| 13 |
+
Action: Acknowledge the opening claim: "{argument}" and set a skeptical stage.
|
| 14 |
+
""",
|
| 15 |
+
|
| 16 |
+
"CHALLENGE": f"""
|
| 17 |
+
Role: Adversary.
|
| 18 |
+
Topic: {self.topic}.
|
| 19 |
+
Action: Attack the core claim: "{argument}". Identify logical gaps in this specific reasoning.
|
| 20 |
+
""",
|
| 21 |
+
|
| 22 |
+
"REBUTTAL": f"""
|
| 23 |
+
Role: Critical Rebutter.
|
| 24 |
+
The agent argued: "{argument}".
|
| 25 |
+
Your previous challenge was: "{opponent_challenge}".
|
| 26 |
+
Action: Point out why the agent's response fails to address your challenge.
|
| 27 |
+
""",
|
| 28 |
+
|
| 29 |
+
"CONSOLIDATION": f"""
|
| 30 |
+
Role: Fact Checker.
|
| 31 |
+
Topic: {self.topic}.
|
| 32 |
+
Action: Question the evidence provided in: "{argument}". Focus on the weakest point.
|
| 33 |
+
""",
|
| 34 |
+
|
| 35 |
+
"CLOSING": f"""
|
| 36 |
+
Role: Final Judge.
|
| 37 |
+
Topic: {self.topic}.
|
| 38 |
+
Action: Provide a final summary of the conversation. Evaluate if the agent remained consistent.
|
| 39 |
+
"""
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
# Return the specific phase prompt, or a default if not found
|
| 43 |
+
return templates.get(phase.upper(), "Continue the debate logically.")
|
pyproject.toml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "debate-coach-environment"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Strategic Argument Red-Teaming Environment"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
requires-python = ">=3.11"
|
| 7 |
+
dependencies = [
|
| 8 |
+
"openenv-core>=0.2.0",
|
| 9 |
+
"sentence-transformers",
|
| 10 |
+
"torch",
|
| 11 |
+
"openai",
|
| 12 |
+
"fastapi",
|
| 13 |
+
"uvicorn",
|
| 14 |
+
"pydantic"
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
[project.scripts]
|
| 18 |
+
server = "server.app:main"
|
requirements.txt
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file was autogenerated by uv via the following command:
|
| 2 |
+
# uv pip compile pyproject.toml -o requirements.txt
|
| 3 |
+
aiofile==3.9.0
|
| 4 |
+
# via py-key-value-aio
|
| 5 |
+
aiofiles==24.1.0
|
| 6 |
+
# via gradio
|
| 7 |
+
annotated-doc==0.0.4
|
| 8 |
+
# via
|
| 9 |
+
# fastapi
|
| 10 |
+
# typer
|
| 11 |
+
annotated-types==0.7.0
|
| 12 |
+
# via pydantic
|
| 13 |
+
anyio==4.12.1
|
| 14 |
+
# via
|
| 15 |
+
# gradio
|
| 16 |
+
# httpx
|
| 17 |
+
# mcp
|
| 18 |
+
# openai
|
| 19 |
+
# py-key-value-aio
|
| 20 |
+
# sse-starlette
|
| 21 |
+
# starlette
|
| 22 |
+
# watchfiles
|
| 23 |
+
attrs==26.1.0
|
| 24 |
+
# via
|
| 25 |
+
# cyclopts
|
| 26 |
+
# jsonschema
|
| 27 |
+
# referencing
|
| 28 |
+
authlib==1.6.9
|
| 29 |
+
# via fastmcp
|
| 30 |
+
backports-tarfile==1.2.0
|
| 31 |
+
# via jaraco-context
|
| 32 |
+
beartype==0.22.9
|
| 33 |
+
# via py-key-value-aio
|
| 34 |
+
brotli==1.2.0
|
| 35 |
+
# via gradio
|
| 36 |
+
cachetools==7.0.5
|
| 37 |
+
# via py-key-value-aio
|
| 38 |
+
caio==0.9.25
|
| 39 |
+
# via aiofile
|
| 40 |
+
certifi==2026.2.25
|
| 41 |
+
# via
|
| 42 |
+
# httpcore
|
| 43 |
+
# httpx
|
| 44 |
+
# requests
|
| 45 |
+
cffi==2.0.0
|
| 46 |
+
# via cryptography
|
| 47 |
+
charset-normalizer==3.4.6
|
| 48 |
+
# via requests
|
| 49 |
+
click==8.3.1
|
| 50 |
+
# via
|
| 51 |
+
# typer
|
| 52 |
+
# uvicorn
|
| 53 |
+
colorama==0.4.6
|
| 54 |
+
# via
|
| 55 |
+
# click
|
| 56 |
+
# tqdm
|
| 57 |
+
cryptography==46.0.6
|
| 58 |
+
# via
|
| 59 |
+
# authlib
|
| 60 |
+
# pyjwt
|
| 61 |
+
cyclopts==4.10.1
|
| 62 |
+
# via fastmcp
|
| 63 |
+
distro==1.9.0
|
| 64 |
+
# via openai
|
| 65 |
+
dnspython==2.8.0
|
| 66 |
+
# via email-validator
|
| 67 |
+
docstring-parser==0.17.0
|
| 68 |
+
# via cyclopts
|
| 69 |
+
docutils==0.22.4
|
| 70 |
+
# via rich-rst
|
| 71 |
+
email-validator==2.3.0
|
| 72 |
+
# via pydantic
|
| 73 |
+
exceptiongroup==1.3.1
|
| 74 |
+
# via fastmcp
|
| 75 |
+
fastapi==0.135.2
|
| 76 |
+
# via
|
| 77 |
+
# debate-coach-environment (pyproject.toml)
|
| 78 |
+
# gradio
|
| 79 |
+
# openenv-core
|
| 80 |
+
fastmcp==3.1.1
|
| 81 |
+
# via openenv-core
|
| 82 |
+
ffmpy==1.0.0
|
| 83 |
+
# via gradio
|
| 84 |
+
filelock==3.25.2
|
| 85 |
+
# via
|
| 86 |
+
# huggingface-hub
|
| 87 |
+
# torch
|
| 88 |
+
fsspec==2026.2.0
|
| 89 |
+
# via
|
| 90 |
+
# gradio-client
|
| 91 |
+
# huggingface-hub
|
| 92 |
+
# torch
|
| 93 |
+
gradio==6.10.0
|
| 94 |
+
# via openenv-core
|
| 95 |
+
gradio-client==2.4.0
|
| 96 |
+
# via
|
| 97 |
+
# gradio
|
| 98 |
+
# hf-gradio
|
| 99 |
+
groovy==0.1.2
|
| 100 |
+
# via gradio
|
| 101 |
+
h11==0.16.0
|
| 102 |
+
# via
|
| 103 |
+
# httpcore
|
| 104 |
+
# uvicorn
|
| 105 |
+
hf-gradio==0.3.0
|
| 106 |
+
# via gradio
|
| 107 |
+
hf-xet==1.4.2
|
| 108 |
+
# via huggingface-hub
|
| 109 |
+
httpcore==1.0.9
|
| 110 |
+
# via httpx
|
| 111 |
+
httpx==0.28.1
|
| 112 |
+
# via
|
| 113 |
+
# fastmcp
|
| 114 |
+
# gradio
|
| 115 |
+
# gradio-client
|
| 116 |
+
# huggingface-hub
|
| 117 |
+
# mcp
|
| 118 |
+
# openai
|
| 119 |
+
# openenv-core
|
| 120 |
+
# safehttpx
|
| 121 |
+
httpx-sse==0.4.3
|
| 122 |
+
# via mcp
|
| 123 |
+
huggingface-hub==1.7.2
|
| 124 |
+
# via
|
| 125 |
+
# gradio
|
| 126 |
+
# gradio-client
|
| 127 |
+
# openenv-core
|
| 128 |
+
# sentence-transformers
|
| 129 |
+
# tokenizers
|
| 130 |
+
# transformers
|
| 131 |
+
idna==3.11
|
| 132 |
+
# via
|
| 133 |
+
# anyio
|
| 134 |
+
# email-validator
|
| 135 |
+
# httpx
|
| 136 |
+
# requests
|
| 137 |
+
importlib-metadata==8.7.1
|
| 138 |
+
# via
|
| 139 |
+
# keyring
|
| 140 |
+
# opentelemetry-api
|
| 141 |
+
jaraco-classes==3.4.0
|
| 142 |
+
# via keyring
|
| 143 |
+
jaraco-context==6.1.2
|
| 144 |
+
# via keyring
|
| 145 |
+
jaraco-functools==4.4.0
|
| 146 |
+
# via keyring
|
| 147 |
+
jinja2==3.1.6
|
| 148 |
+
# via
|
| 149 |
+
# gradio
|
| 150 |
+
# torch
|
| 151 |
+
jiter==0.13.0
|
| 152 |
+
# via openai
|
| 153 |
+
joblib==1.5.3
|
| 154 |
+
# via scikit-learn
|
| 155 |
+
jsonref==1.1.0
|
| 156 |
+
# via fastmcp
|
| 157 |
+
jsonschema==4.26.0
|
| 158 |
+
# via mcp
|
| 159 |
+
jsonschema-path==0.4.5
|
| 160 |
+
# via fastmcp
|
| 161 |
+
jsonschema-specifications==2025.9.1
|
| 162 |
+
# via jsonschema
|
| 163 |
+
keyring==25.7.0
|
| 164 |
+
# via py-key-value-aio
|
| 165 |
+
markdown-it-py==4.0.0
|
| 166 |
+
# via rich
|
| 167 |
+
markupsafe==3.0.3
|
| 168 |
+
# via
|
| 169 |
+
# gradio
|
| 170 |
+
# jinja2
|
| 171 |
+
mcp==1.26.0
|
| 172 |
+
# via fastmcp
|
| 173 |
+
mdurl==0.1.2
|
| 174 |
+
# via markdown-it-py
|
| 175 |
+
more-itertools==10.8.0
|
| 176 |
+
# via
|
| 177 |
+
# jaraco-classes
|
| 178 |
+
# jaraco-functools
|
| 179 |
+
mpmath==1.3.0
|
| 180 |
+
# via sympy
|
| 181 |
+
networkx==3.6.1
|
| 182 |
+
# via torch
|
| 183 |
+
numpy==2.4.3
|
| 184 |
+
# via
|
| 185 |
+
# gradio
|
| 186 |
+
# pandas
|
| 187 |
+
# scikit-learn
|
| 188 |
+
# scipy
|
| 189 |
+
# sentence-transformers
|
| 190 |
+
# transformers
|
| 191 |
+
openai==2.29.0
|
| 192 |
+
# via
|
| 193 |
+
# debate-coach-environment (pyproject.toml)
|
| 194 |
+
# openenv-core
|
| 195 |
+
openapi-pydantic==0.5.1
|
| 196 |
+
# via fastmcp
|
| 197 |
+
openenv-core==0.2.3
|
| 198 |
+
# via debate-coach-environment (pyproject.toml)
|
| 199 |
+
opentelemetry-api==1.40.0
|
| 200 |
+
# via fastmcp
|
| 201 |
+
orjson==3.11.7
|
| 202 |
+
# via gradio
|
| 203 |
+
packaging==26.0
|
| 204 |
+
# via
|
| 205 |
+
# fastmcp
|
| 206 |
+
# gradio
|
| 207 |
+
# gradio-client
|
| 208 |
+
# huggingface-hub
|
| 209 |
+
# transformers
|
| 210 |
+
pandas==3.0.1
|
| 211 |
+
# via gradio
|
| 212 |
+
pathable==0.5.0
|
| 213 |
+
# via jsonschema-path
|
| 214 |
+
pillow==12.1.1
|
| 215 |
+
# via gradio
|
| 216 |
+
platformdirs==4.9.4
|
| 217 |
+
# via fastmcp
|
| 218 |
+
py-key-value-aio==0.4.4
|
| 219 |
+
# via fastmcp
|
| 220 |
+
pycparser==3.0
|
| 221 |
+
# via cffi
|
| 222 |
+
pydantic==2.12.5
|
| 223 |
+
# via
|
| 224 |
+
# debate-coach-environment (pyproject.toml)
|
| 225 |
+
# fastapi
|
| 226 |
+
# fastmcp
|
| 227 |
+
# gradio
|
| 228 |
+
# mcp
|
| 229 |
+
# openai
|
| 230 |
+
# openapi-pydantic
|
| 231 |
+
# openenv-core
|
| 232 |
+
# pydantic-settings
|
| 233 |
+
pydantic-core==2.41.5
|
| 234 |
+
# via pydantic
|
| 235 |
+
pydantic-settings==2.13.1
|
| 236 |
+
# via mcp
|
| 237 |
+
pydub==0.25.1
|
| 238 |
+
# via gradio
|
| 239 |
+
pygments==2.19.2
|
| 240 |
+
# via rich
|
| 241 |
+
pyjwt==2.12.1
|
| 242 |
+
# via mcp
|
| 243 |
+
pyperclip==1.11.0
|
| 244 |
+
# via fastmcp
|
| 245 |
+
python-dateutil==2.9.0.post0
|
| 246 |
+
# via pandas
|
| 247 |
+
python-dotenv==1.2.2
|
| 248 |
+
# via
|
| 249 |
+
# fastmcp
|
| 250 |
+
# pydantic-settings
|
| 251 |
+
python-multipart==0.0.22
|
| 252 |
+
# via
|
| 253 |
+
# gradio
|
| 254 |
+
# mcp
|
| 255 |
+
pytz==2026.1.post1
|
| 256 |
+
# via gradio
|
| 257 |
+
pywin32==311
|
| 258 |
+
# via mcp
|
| 259 |
+
pywin32-ctypes==0.2.3
|
| 260 |
+
# via keyring
|
| 261 |
+
pyyaml==6.0.3
|
| 262 |
+
# via
|
| 263 |
+
# fastmcp
|
| 264 |
+
# gradio
|
| 265 |
+
# huggingface-hub
|
| 266 |
+
# jsonschema-path
|
| 267 |
+
# openenv-core
|
| 268 |
+
# transformers
|
| 269 |
+
referencing==0.37.0
|
| 270 |
+
# via
|
| 271 |
+
# jsonschema
|
| 272 |
+
# jsonschema-path
|
| 273 |
+
# jsonschema-specifications
|
| 274 |
+
regex==2026.2.28
|
| 275 |
+
# via transformers
|
| 276 |
+
requests==2.33.0
|
| 277 |
+
# via openenv-core
|
| 278 |
+
rich==14.3.3
|
| 279 |
+
# via
|
| 280 |
+
# cyclopts
|
| 281 |
+
# fastmcp
|
| 282 |
+
# openenv-core
|
| 283 |
+
# rich-rst
|
| 284 |
+
# typer
|
| 285 |
+
rich-rst==1.3.2
|
| 286 |
+
# via cyclopts
|
| 287 |
+
rpds-py==0.30.0
|
| 288 |
+
# via
|
| 289 |
+
# jsonschema
|
| 290 |
+
# referencing
|
| 291 |
+
safehttpx==0.1.7
|
| 292 |
+
# via gradio
|
| 293 |
+
safetensors==0.7.0
|
| 294 |
+
# via transformers
|
| 295 |
+
scikit-learn==1.8.0
|
| 296 |
+
# via sentence-transformers
|
| 297 |
+
scipy==1.17.1
|
| 298 |
+
# via
|
| 299 |
+
# scikit-learn
|
| 300 |
+
# sentence-transformers
|
| 301 |
+
semantic-version==2.10.0
|
| 302 |
+
# via gradio
|
| 303 |
+
sentence-transformers==5.3.0
|
| 304 |
+
# via debate-coach-environment (pyproject.toml)
|
| 305 |
+
shellingham==1.5.4
|
| 306 |
+
# via typer
|
| 307 |
+
six==1.17.0
|
| 308 |
+
# via python-dateutil
|
| 309 |
+
sniffio==1.3.1
|
| 310 |
+
# via openai
|
| 311 |
+
sse-starlette==3.3.4
|
| 312 |
+
# via mcp
|
| 313 |
+
starlette==0.52.1
|
| 314 |
+
# via
|
| 315 |
+
# fastapi
|
| 316 |
+
# gradio
|
| 317 |
+
# mcp
|
| 318 |
+
# sse-starlette
|
| 319 |
+
sympy==1.14.0
|
| 320 |
+
# via torch
|
| 321 |
+
threadpoolctl==3.6.0
|
| 322 |
+
# via scikit-learn
|
| 323 |
+
tokenizers==0.22.2
|
| 324 |
+
# via transformers
|
| 325 |
+
tomli==2.4.1
|
| 326 |
+
# via openenv-core
|
| 327 |
+
tomli-w==1.2.0
|
| 328 |
+
# via openenv-core
|
| 329 |
+
tomlkit==0.13.3
|
| 330 |
+
# via gradio
|
| 331 |
+
torch==2.10.0
|
| 332 |
+
# via
|
| 333 |
+
# debate-coach-environment (pyproject.toml)
|
| 334 |
+
# sentence-transformers
|
| 335 |
+
tqdm==4.67.3
|
| 336 |
+
# via
|
| 337 |
+
# huggingface-hub
|
| 338 |
+
# openai
|
| 339 |
+
# sentence-transformers
|
| 340 |
+
# transformers
|
| 341 |
+
transformers==5.3.0
|
| 342 |
+
# via sentence-transformers
|
| 343 |
+
typer==0.24.1
|
| 344 |
+
# via
|
| 345 |
+
# gradio
|
| 346 |
+
# hf-gradio
|
| 347 |
+
# huggingface-hub
|
| 348 |
+
# openenv-core
|
| 349 |
+
# transformers
|
| 350 |
+
typing-extensions==4.15.0
|
| 351 |
+
# via
|
| 352 |
+
# anyio
|
| 353 |
+
# exceptiongroup
|
| 354 |
+
# fastapi
|
| 355 |
+
# gradio
|
| 356 |
+
# gradio-client
|
| 357 |
+
# huggingface-hub
|
| 358 |
+
# mcp
|
| 359 |
+
# openai
|
| 360 |
+
# opentelemetry-api
|
| 361 |
+
# py-key-value-aio
|
| 362 |
+
# pydantic
|
| 363 |
+
# pydantic-core
|
| 364 |
+
# referencing
|
| 365 |
+
# sentence-transformers
|
| 366 |
+
# starlette
|
| 367 |
+
# torch
|
| 368 |
+
# typing-inspection
|
| 369 |
+
typing-inspection==0.4.2
|
| 370 |
+
# via
|
| 371 |
+
# fastapi
|
| 372 |
+
# mcp
|
| 373 |
+
# pydantic
|
| 374 |
+
# pydantic-settings
|
| 375 |
+
tzdata==2025.3
|
| 376 |
+
# via pandas
|
| 377 |
+
uncalled-for==0.2.0
|
| 378 |
+
# via fastmcp
|
| 379 |
+
urllib3==2.6.3
|
| 380 |
+
# via requests
|
| 381 |
+
uvicorn==0.42.0
|
| 382 |
+
# via
|
| 383 |
+
# debate-coach-environment (pyproject.toml)
|
| 384 |
+
# fastmcp
|
| 385 |
+
# gradio
|
| 386 |
+
# mcp
|
| 387 |
+
# openenv-core
|
| 388 |
+
watchfiles==1.1.1
|
| 389 |
+
# via fastmcp
|
| 390 |
+
websockets==16.0
|
| 391 |
+
# via
|
| 392 |
+
# fastmcp
|
| 393 |
+
# openenv-core
|
| 394 |
+
zipp==3.23.0
|
| 395 |
+
# via importlib-metadata
|
reward_metrics/reward_metrics.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#similarity runs a full encode on every call — if called multiple times per step it's slow. This matters for training loops. Consider caching or batching, but not urgent right now.
|
| 2 |
+
|
| 3 |
+
from sentence_transformers import SentenceTransformer, util
|
| 4 |
+
from transformers import logging as transformers_logging
|
| 5 |
+
import logging
|
| 6 |
+
import torch
|
| 7 |
+
|
| 8 |
+
transformers_logging.set_verbosity_error()
|
| 9 |
+
|
| 10 |
+
model = SentenceTransformer('all-MiniLM-L6-v2')
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class RewardMetrics:
|
| 14 |
+
def __init__(self):
|
| 15 |
+
self.LINKING_PHRASES = [
|
| 16 |
+
"taken together", "overall", "this shows",
|
| 17 |
+
"together", "therefore", "thus", "in conclusion"
|
| 18 |
+
]
|
| 19 |
+
self.NEGATION_PATTERNS = [
|
| 20 |
+
"fails", "incorrect", "wrong", "does not",
|
| 21 |
+
"untrue", "contradiction", "weak"
|
| 22 |
+
]
|
| 23 |
+
self.IMPACT_PHRASES = [
|
| 24 |
+
"we win", "therefore", "in conclusion",
|
| 25 |
+
"the key takeaway", "this proves"
|
| 26 |
+
]
|
| 27 |
+
self._embedding_cache = {}
|
| 28 |
+
|
| 29 |
+
def _get_embedding(self,text:str):
|
| 30 |
+
"""Fetches embedding from cache, or computes it if not found."""
|
| 31 |
+
if text not in self._embedding_cache:
|
| 32 |
+
self._embedding_cache[text] = model.encode(text,convert_to_tensor=True)
|
| 33 |
+
|
| 34 |
+
return self._embedding_cache[text]
|
| 35 |
+
|
| 36 |
+
def similarity(self,a,b):
|
| 37 |
+
emb1 = self._get_embedding(a)
|
| 38 |
+
emb2 = self._get_embedding(b)
|
| 39 |
+
return util.cos_sim(emb1, emb2).item()
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def argument_coverage(self,agent_args, closing, threshold=0.5):
|
| 43 |
+
|
| 44 |
+
if not agent_args:
|
| 45 |
+
return 0.0
|
| 46 |
+
|
| 47 |
+
closing_emb = self._get_embedding(closing)
|
| 48 |
+
history_embs = [self._get_embedding(arg) for arg in agent_args]
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# Stacking them into a single 2D PyTorch tensor
|
| 53 |
+
history_matrix = torch.stack(history_embs)
|
| 54 |
+
|
| 55 |
+
similarities = util.cos_sim(closing_emb, history_matrix)
|
| 56 |
+
|
| 57 |
+
# similarities is a tensor of shape [1, num_args]
|
| 58 |
+
covered = (similarities > threshold).sum().item()
|
| 59 |
+
|
| 60 |
+
return covered / len(agent_args)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def synthesis_score(self,text):
|
| 64 |
+
count = sum(1 for phrase in self.LINKING_PHRASES if phrase in text.lower())
|
| 65 |
+
return min(count / len(self.LINKING_PHRASES), 1.0)
|
| 66 |
+
|
| 67 |
+
def opponent_coverage(self,opponent_args, closing, threshold=0.5):
|
| 68 |
+
|
| 69 |
+
if not opponent_args:
|
| 70 |
+
return 0.0
|
| 71 |
+
|
| 72 |
+
closing_emb = self._get_embedding(closing)
|
| 73 |
+
history_embs = [self._get_embedding(arg) for arg in opponent_args]
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
# Stacking them into a single 2D PyTorch tensor
|
| 78 |
+
history_matrix = torch.stack(history_embs)
|
| 79 |
+
|
| 80 |
+
similarities = util.cos_sim(closing_emb, history_matrix)
|
| 81 |
+
|
| 82 |
+
# similarities is a tensor of shape [1, num_args]
|
| 83 |
+
covered = (similarities > threshold).sum().item()
|
| 84 |
+
|
| 85 |
+
return covered / len(opponent_args)
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def refutation_strength(self,text):
|
| 89 |
+
count = sum(1 for word in self.NEGATION_PATTERNS if word in text.lower())
|
| 90 |
+
return min(count / len(self.NEGATION_PATTERNS), 1.0)
|
| 91 |
+
|
| 92 |
+
def cal_refu_score(self,opponent_args,text:str):
|
| 93 |
+
coverage = self.opponent_coverage(opponent_args,text)
|
| 94 |
+
strength = self.refutation_strength(text)
|
| 95 |
+
|
| 96 |
+
refutation_score = (coverage * 0.7) + (strength* 0.3)
|
| 97 |
+
|
| 98 |
+
return refutation_score
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def impact_score(self,text):
|
| 102 |
+
count = 0
|
| 103 |
+
for phrase in self.IMPACT_PHRASES:
|
| 104 |
+
if phrase in text.lower():
|
| 105 |
+
count += 1
|
| 106 |
+
|
| 107 |
+
# bonus if appears near end
|
| 108 |
+
if any(phrase in text.lower()[-100:] for phrase in self.IMPACT_PHRASES):
|
| 109 |
+
count += 1
|
| 110 |
+
|
| 111 |
+
return min(count / (len(self.IMPACT_PHRASES) + 1), 1.0)
|
server/app.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import uvicorn
|
| 2 |
+
from openenv.core.env_server import create_fastapi_app
|
| 3 |
+
from environment import DebateEnvironment
|
| 4 |
+
|
| 5 |
+
app = create_fastapi_app(DebateEnvironment)
|
| 6 |
+
|
| 7 |
+
def main():
|
| 8 |
+
uvicorn.run("server.app:app", host="0.0.0.0", port=8000)
|
| 9 |
+
|
| 10 |
+
if __name__ == "__main__":
|
| 11 |
+
main()
|
tasks.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from schema.schemas import DebateObservation
|
| 2 |
+
from reward_metrics.reward_metrics import RewardMetrics
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
metrics = RewardMetrics()
|
| 6 |
+
|
| 7 |
+
class Task1_SingleClaim:
|
| 8 |
+
"""
|
| 9 |
+
EASY: Can the agent formulate a strong, logical opening statement?
|
| 10 |
+
Evaluated after step 1.
|
| 11 |
+
"""
|
| 12 |
+
name = "single_claim"
|
| 13 |
+
difficulty = "easy"
|
| 14 |
+
|
| 15 |
+
def grade(self, observation: DebateObservation) -> float:
|
| 16 |
+
score = 0.0
|
| 17 |
+
|
| 18 |
+
action_text = observation.metadata.get("action", "")
|
| 19 |
+
|
| 20 |
+
# Check 1: Length threshold (0.4 points)
|
| 21 |
+
if len(action_text.split()) >= 10:
|
| 22 |
+
score += 0.4
|
| 23 |
+
|
| 24 |
+
# Check 2: Reasoning Keyword Presence (0.4 points)
|
| 25 |
+
reasoning_keywords = ["because", "therefore", "however", "consequently", "shows", "proves"]
|
| 26 |
+
if any(kw in action_text.lower() for kw in reasoning_keywords):
|
| 27 |
+
score += 0.4
|
| 28 |
+
|
| 29 |
+
# Check 3: Phase validation (0.2 points)
|
| 30 |
+
if observation.metadata.get("phase") == "OPENING":
|
| 31 |
+
score += 0.2
|
| 32 |
+
|
| 33 |
+
return min(1.0, score)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class Task2_ClaimAndRebuttal:
|
| 37 |
+
"""
|
| 38 |
+
MEDIUM: Can the agent survive a back-and-forth and deliver a strong rebuttal?
|
| 39 |
+
Evaluated after step 3 (Opening -> Challenge -> Rebuttal).
|
| 40 |
+
"""
|
| 41 |
+
name = "claim_and_rebuttal"
|
| 42 |
+
difficulty = "medium"
|
| 43 |
+
|
| 44 |
+
def grade(self, observation: DebateObservation) -> float:
|
| 45 |
+
# Fail immediately if they didn't reach the required depth (crashed or quit early)
|
| 46 |
+
if observation.attempt_count < 3:
|
| 47 |
+
return 0.0
|
| 48 |
+
|
| 49 |
+
score = 0.0
|
| 50 |
+
action_text = observation.metadata.get("action", "")
|
| 51 |
+
|
| 52 |
+
# 1. Base points for reaching the correct phase successfully
|
| 53 |
+
score += 0.3
|
| 54 |
+
|
| 55 |
+
# 2. Direct Evaluation: Is it actually a rebuttal?
|
| 56 |
+
|
| 57 |
+
refutation_strength = metrics.refutation_strength(action_text)
|
| 58 |
+
score += (refutation_strength * 0.4)
|
| 59 |
+
|
| 60 |
+
if len(action_text.split()) > 15:
|
| 61 |
+
score += 0.3
|
| 62 |
+
|
| 63 |
+
return min(1.0, score)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class Task3_FullDebate:
|
| 67 |
+
"""
|
| 68 |
+
HARD: Can the agent complete a 5-turn debate and successfully synthesize
|
| 69 |
+
the arguments into a concluding statement?
|
| 70 |
+
Evaluated at the end of the episode (step 5).
|
| 71 |
+
"""
|
| 72 |
+
name = "full_debate"
|
| 73 |
+
difficulty = "hard"
|
| 74 |
+
|
| 75 |
+
def grade(self, observation: DebateObservation) -> float:
|
| 76 |
+
if not observation.done or observation.attempt_count < 5:
|
| 77 |
+
return 0.0
|
| 78 |
+
|
| 79 |
+
score = 0.0
|
| 80 |
+
action_text = observation.metadata.get("action", "")
|
| 81 |
+
|
| 82 |
+
# 1. Base points for surviving all 5 turns
|
| 83 |
+
score += 0.2
|
| 84 |
+
|
| 85 |
+
# 2. Direct Evaluation: Synthesis
|
| 86 |
+
|
| 87 |
+
synthesis = metrics.synthesis_score(action_text)
|
| 88 |
+
score += (synthesis * 0.4)
|
| 89 |
+
|
| 90 |
+
# 3. Direct Evaluation: Impact
|
| 91 |
+
|
| 92 |
+
impact = metrics.impact_score(action_text)
|
| 93 |
+
score += (min(impact, 2) * 0.1)
|
| 94 |
+
|
| 95 |
+
# 4. Length check: A closing summary must be substantial
|
| 96 |
+
if len(action_text.split()) >= 20:
|
| 97 |
+
score += 0.3
|
| 98 |
+
|
| 99 |
+
return max(0.0, min(1.0, score))
|
training_results.json
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "llama-3.1-8b-instant",
|
| 3 |
+
"num_episodes": 30,
|
| 4 |
+
"episode_scores": [
|
| 5 |
+
0.5,
|
| 6 |
+
0.5,
|
| 7 |
+
0.5,
|
| 8 |
+
0.5,
|
| 9 |
+
0.5571428571428572,
|
| 10 |
+
0.5,
|
| 11 |
+
0.5,
|
| 12 |
+
0.5,
|
| 13 |
+
0.5,
|
| 14 |
+
0.5,
|
| 15 |
+
0.5,
|
| 16 |
+
0.5,
|
| 17 |
+
0.5,
|
| 18 |
+
0.5,
|
| 19 |
+
0.5,
|
| 20 |
+
0.5,
|
| 21 |
+
0.5,
|
| 22 |
+
0.5,
|
| 23 |
+
0.5,
|
| 24 |
+
0.5,
|
| 25 |
+
0.5,
|
| 26 |
+
0.5,
|
| 27 |
+
0.5,
|
| 28 |
+
0.5,
|
| 29 |
+
0.5,
|
| 30 |
+
0.5,
|
| 31 |
+
0.5,
|
| 32 |
+
0.5,
|
| 33 |
+
0.5,
|
| 34 |
+
0.5
|
| 35 |
+
],
|
| 36 |
+
"overall_avg": 0.5019047619047619,
|
| 37 |
+
"first_half_avg": 0.5038095238095238,
|
| 38 |
+
"second_half_avg": 0.5,
|
| 39 |
+
"all_results": [
|
| 40 |
+
{
|
| 41 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 42 |
+
"step_rewards": [
|
| 43 |
+
0.21666666666666667,
|
| 44 |
+
0.0,
|
| 45 |
+
0.0,
|
| 46 |
+
0.0,
|
| 47 |
+
0.0
|
| 48 |
+
],
|
| 49 |
+
"mean_reward": 0.043333333333333335,
|
| 50 |
+
"final_score": 0.5,
|
| 51 |
+
"advantage": -0.4999997812500918
|
| 52 |
+
},
|
| 53 |
+
{
|
| 54 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 55 |
+
"step_rewards": [
|
| 56 |
+
0.21666666666666667,
|
| 57 |
+
0.0,
|
| 58 |
+
0.0,
|
| 59 |
+
0.0,
|
| 60 |
+
0.0
|
| 61 |
+
],
|
| 62 |
+
"mean_reward": 0.043333333333333335,
|
| 63 |
+
"final_score": 0.5,
|
| 64 |
+
"advantage": -0.4999997812500918
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"topic": "Social media does more harm than good to society.",
|
| 68 |
+
"step_rewards": [
|
| 69 |
+
0.23333333333333334,
|
| 70 |
+
0.0,
|
| 71 |
+
0.0,
|
| 72 |
+
0.0,
|
| 73 |
+
0.0
|
| 74 |
+
],
|
| 75 |
+
"mean_reward": 0.04666666666666667,
|
| 76 |
+
"final_score": 0.5,
|
| 77 |
+
"advantage": -0.4999997812500918
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 81 |
+
"step_rewards": [
|
| 82 |
+
0.21666666666666667,
|
| 83 |
+
0.0,
|
| 84 |
+
0.0,
|
| 85 |
+
0.0,
|
| 86 |
+
0.0
|
| 87 |
+
],
|
| 88 |
+
"mean_reward": 0.043333333333333335,
|
| 89 |
+
"final_score": 0.5,
|
| 90 |
+
"advantage": -0.4999997812500918
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"topic": "Remote work is more productive than office work.",
|
| 94 |
+
"step_rewards": [
|
| 95 |
+
0.2,
|
| 96 |
+
0.0,
|
| 97 |
+
0.0,
|
| 98 |
+
0.0,
|
| 99 |
+
0.0
|
| 100 |
+
],
|
| 101 |
+
"mean_reward": 0.04,
|
| 102 |
+
"final_score": 0.5571428571428572,
|
| 103 |
+
"advantage": 1.9999991250003866
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 107 |
+
"step_rewards": [
|
| 108 |
+
0.21666666666666667,
|
| 109 |
+
0.0,
|
| 110 |
+
0.0,
|
| 111 |
+
0.0,
|
| 112 |
+
0.0
|
| 113 |
+
],
|
| 114 |
+
"mean_reward": 0.043333333333333335,
|
| 115 |
+
"final_score": 0.5,
|
| 116 |
+
"advantage": 0.0
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 120 |
+
"step_rewards": [
|
| 121 |
+
0.21666666666666667,
|
| 122 |
+
0.0,
|
| 123 |
+
0.0,
|
| 124 |
+
0.0,
|
| 125 |
+
0.0
|
| 126 |
+
],
|
| 127 |
+
"mean_reward": 0.043333333333333335,
|
| 128 |
+
"final_score": 0.5,
|
| 129 |
+
"advantage": 0.0
|
| 130 |
+
},
|
| 131 |
+
{
|
| 132 |
+
"topic": "Social media does more harm than good to society.",
|
| 133 |
+
"step_rewards": [
|
| 134 |
+
0.2,
|
| 135 |
+
0.0,
|
| 136 |
+
0.0,
|
| 137 |
+
0.0,
|
| 138 |
+
0.0
|
| 139 |
+
],
|
| 140 |
+
"mean_reward": 0.04,
|
| 141 |
+
"final_score": 0.5,
|
| 142 |
+
"advantage": 0.0
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 146 |
+
"step_rewards": [
|
| 147 |
+
0.23333333333333334,
|
| 148 |
+
0.0,
|
| 149 |
+
0.0,
|
| 150 |
+
0.0,
|
| 151 |
+
0.0
|
| 152 |
+
],
|
| 153 |
+
"mean_reward": 0.04666666666666667,
|
| 154 |
+
"final_score": 0.5,
|
| 155 |
+
"advantage": 0.0
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"topic": "Remote work is more productive than office work.",
|
| 159 |
+
"step_rewards": [
|
| 160 |
+
0.2,
|
| 161 |
+
0.0,
|
| 162 |
+
0.0,
|
| 163 |
+
0.0,
|
| 164 |
+
0.0
|
| 165 |
+
],
|
| 166 |
+
"mean_reward": 0.04,
|
| 167 |
+
"final_score": 0.5,
|
| 168 |
+
"advantage": 0.0
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 172 |
+
"step_rewards": [
|
| 173 |
+
0.21666666666666667,
|
| 174 |
+
0.0,
|
| 175 |
+
0.0,
|
| 176 |
+
0.0,
|
| 177 |
+
0.0
|
| 178 |
+
],
|
| 179 |
+
"mean_reward": 0.043333333333333335,
|
| 180 |
+
"final_score": 0.5,
|
| 181 |
+
"advantage": 0.0
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 185 |
+
"step_rewards": [
|
| 186 |
+
0.21666666666666667,
|
| 187 |
+
0.0,
|
| 188 |
+
0.0,
|
| 189 |
+
0.0,
|
| 190 |
+
0.0
|
| 191 |
+
],
|
| 192 |
+
"mean_reward": 0.043333333333333335,
|
| 193 |
+
"final_score": 0.5,
|
| 194 |
+
"advantage": 0.0
|
| 195 |
+
},
|
| 196 |
+
{
|
| 197 |
+
"topic": "Social media does more harm than good to society.",
|
| 198 |
+
"step_rewards": [
|
| 199 |
+
0.23333333333333334,
|
| 200 |
+
0.0,
|
| 201 |
+
0.0,
|
| 202 |
+
0.0,
|
| 203 |
+
0.0
|
| 204 |
+
],
|
| 205 |
+
"mean_reward": 0.04666666666666667,
|
| 206 |
+
"final_score": 0.5,
|
| 207 |
+
"advantage": 0.0
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 211 |
+
"step_rewards": [
|
| 212 |
+
0.21666666666666667,
|
| 213 |
+
0.0,
|
| 214 |
+
0.0,
|
| 215 |
+
0.0,
|
| 216 |
+
0.0
|
| 217 |
+
],
|
| 218 |
+
"mean_reward": 0.043333333333333335,
|
| 219 |
+
"final_score": 0.5,
|
| 220 |
+
"advantage": 0.0
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
"topic": "Remote work is more productive than office work.",
|
| 224 |
+
"step_rewards": [
|
| 225 |
+
0.21666666666666667,
|
| 226 |
+
0.0,
|
| 227 |
+
0.0,
|
| 228 |
+
0.0,
|
| 229 |
+
0.0
|
| 230 |
+
],
|
| 231 |
+
"mean_reward": 0.043333333333333335,
|
| 232 |
+
"final_score": 0.5,
|
| 233 |
+
"advantage": 0.0
|
| 234 |
+
},
|
| 235 |
+
{
|
| 236 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 237 |
+
"step_rewards": [
|
| 238 |
+
0.21666666666666667,
|
| 239 |
+
0.0,
|
| 240 |
+
0.0,
|
| 241 |
+
0.0,
|
| 242 |
+
0.0
|
| 243 |
+
],
|
| 244 |
+
"mean_reward": 0.043333333333333335,
|
| 245 |
+
"final_score": 0.5,
|
| 246 |
+
"advantage": 0.0
|
| 247 |
+
},
|
| 248 |
+
{
|
| 249 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 250 |
+
"step_rewards": [
|
| 251 |
+
0.21666666666666667,
|
| 252 |
+
0.0,
|
| 253 |
+
0.0,
|
| 254 |
+
0.0,
|
| 255 |
+
0.0
|
| 256 |
+
],
|
| 257 |
+
"mean_reward": 0.043333333333333335,
|
| 258 |
+
"final_score": 0.5,
|
| 259 |
+
"advantage": 0.0
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"topic": "Social media does more harm than good to society.",
|
| 263 |
+
"step_rewards": [
|
| 264 |
+
0.23333333333333334,
|
| 265 |
+
0.0,
|
| 266 |
+
0.0,
|
| 267 |
+
0.0,
|
| 268 |
+
0.0
|
| 269 |
+
],
|
| 270 |
+
"mean_reward": 0.04666666666666667,
|
| 271 |
+
"final_score": 0.5,
|
| 272 |
+
"advantage": 0.0
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 276 |
+
"step_rewards": [
|
| 277 |
+
0.21666666666666667,
|
| 278 |
+
0.0,
|
| 279 |
+
0.0,
|
| 280 |
+
0.0,
|
| 281 |
+
0.0
|
| 282 |
+
],
|
| 283 |
+
"mean_reward": 0.043333333333333335,
|
| 284 |
+
"final_score": 0.5,
|
| 285 |
+
"advantage": 0.0
|
| 286 |
+
},
|
| 287 |
+
{
|
| 288 |
+
"topic": "Remote work is more productive than office work.",
|
| 289 |
+
"step_rewards": [
|
| 290 |
+
0.2,
|
| 291 |
+
0.0,
|
| 292 |
+
0.0,
|
| 293 |
+
0.0,
|
| 294 |
+
0.0
|
| 295 |
+
],
|
| 296 |
+
"mean_reward": 0.04,
|
| 297 |
+
"final_score": 0.5,
|
| 298 |
+
"advantage": 0.0
|
| 299 |
+
},
|
| 300 |
+
{
|
| 301 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 302 |
+
"step_rewards": [
|
| 303 |
+
0.21666666666666667,
|
| 304 |
+
0.0,
|
| 305 |
+
0.0,
|
| 306 |
+
0.0,
|
| 307 |
+
0.0
|
| 308 |
+
],
|
| 309 |
+
"mean_reward": 0.043333333333333335,
|
| 310 |
+
"final_score": 0.5,
|
| 311 |
+
"advantage": 0.0
|
| 312 |
+
},
|
| 313 |
+
{
|
| 314 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 315 |
+
"step_rewards": [
|
| 316 |
+
0.21666666666666667,
|
| 317 |
+
0.0,
|
| 318 |
+
0.0,
|
| 319 |
+
0.0,
|
| 320 |
+
0.0
|
| 321 |
+
],
|
| 322 |
+
"mean_reward": 0.043333333333333335,
|
| 323 |
+
"final_score": 0.5,
|
| 324 |
+
"advantage": 0.0
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"topic": "Social media does more harm than good to society.",
|
| 328 |
+
"step_rewards": [
|
| 329 |
+
0.21666666666666667,
|
| 330 |
+
0.0,
|
| 331 |
+
0.0,
|
| 332 |
+
0.0,
|
| 333 |
+
0.0
|
| 334 |
+
],
|
| 335 |
+
"mean_reward": 0.043333333333333335,
|
| 336 |
+
"final_score": 0.5,
|
| 337 |
+
"advantage": 0.0
|
| 338 |
+
},
|
| 339 |
+
{
|
| 340 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 341 |
+
"step_rewards": [
|
| 342 |
+
0.21666666666666667,
|
| 343 |
+
0.0,
|
| 344 |
+
0.0,
|
| 345 |
+
0.0,
|
| 346 |
+
0.0
|
| 347 |
+
],
|
| 348 |
+
"mean_reward": 0.043333333333333335,
|
| 349 |
+
"final_score": 0.5,
|
| 350 |
+
"advantage": 0.0
|
| 351 |
+
},
|
| 352 |
+
{
|
| 353 |
+
"topic": "Remote work is more productive than office work.",
|
| 354 |
+
"step_rewards": [
|
| 355 |
+
0.2,
|
| 356 |
+
0.0,
|
| 357 |
+
0.0,
|
| 358 |
+
0.0,
|
| 359 |
+
0.0
|
| 360 |
+
],
|
| 361 |
+
"mean_reward": 0.04,
|
| 362 |
+
"final_score": 0.5,
|
| 363 |
+
"advantage": 0.0
|
| 364 |
+
},
|
| 365 |
+
{
|
| 366 |
+
"topic": "Universal Basic Income is necessary for the future economy.",
|
| 367 |
+
"step_rewards": [
|
| 368 |
+
0.2,
|
| 369 |
+
0.0,
|
| 370 |
+
0.0,
|
| 371 |
+
0.0,
|
| 372 |
+
0.0
|
| 373 |
+
],
|
| 374 |
+
"mean_reward": 0.04,
|
| 375 |
+
"final_score": 0.5,
|
| 376 |
+
"advantage": 0.0
|
| 377 |
+
},
|
| 378 |
+
{
|
| 379 |
+
"topic": "Artificial Intelligence should be strictly regulated by governments.",
|
| 380 |
+
"step_rewards": [
|
| 381 |
+
0.21666666666666667,
|
| 382 |
+
0.0,
|
| 383 |
+
0.0,
|
| 384 |
+
0.0,
|
| 385 |
+
0.0
|
| 386 |
+
],
|
| 387 |
+
"mean_reward": 0.043333333333333335,
|
| 388 |
+
"final_score": 0.5,
|
| 389 |
+
"advantage": 0.0
|
| 390 |
+
},
|
| 391 |
+
{
|
| 392 |
+
"topic": "Social media does more harm than good to society.",
|
| 393 |
+
"step_rewards": [
|
| 394 |
+
0.21666666666666667,
|
| 395 |
+
0.0,
|
| 396 |
+
0.0,
|
| 397 |
+
0.0,
|
| 398 |
+
0.0
|
| 399 |
+
],
|
| 400 |
+
"mean_reward": 0.043333333333333335,
|
| 401 |
+
"final_score": 0.5,
|
| 402 |
+
"advantage": 0.0
|
| 403 |
+
},
|
| 404 |
+
{
|
| 405 |
+
"topic": "Climate change requires immediate radical policy action.",
|
| 406 |
+
"step_rewards": [
|
| 407 |
+
0.21666666666666667,
|
| 408 |
+
0.0,
|
| 409 |
+
0.0,
|
| 410 |
+
0.0,
|
| 411 |
+
0.0
|
| 412 |
+
],
|
| 413 |
+
"mean_reward": 0.043333333333333335,
|
| 414 |
+
"final_score": 0.5,
|
| 415 |
+
"advantage": 0.0
|
| 416 |
+
},
|
| 417 |
+
{
|
| 418 |
+
"topic": "Remote work is more productive than office work.",
|
| 419 |
+
"step_rewards": [
|
| 420 |
+
0.23333333333333334,
|
| 421 |
+
0.0,
|
| 422 |
+
0.0,
|
| 423 |
+
0.0,
|
| 424 |
+
0.0
|
| 425 |
+
],
|
| 426 |
+
"mean_reward": 0.04666666666666667,
|
| 427 |
+
"final_score": 0.5,
|
| 428 |
+
"advantage": 0.0
|
| 429 |
+
}
|
| 430 |
+
]
|
| 431 |
+
}
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
worflow.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
## WORKFLOW:
|
| 3 |
+
The Workflow: How the Debate Happens
|
| 4 |
+
Here is the step-by-step lifecycle of an episode in your project:
|
| 5 |
+
|
| 6 |
+
1. Reset: The Environment picks a topic (e.g., "AI should be regulated"). It sends the first Observation to the Agent.
|
| 7 |
+
|
| 8 |
+
2. The Agent's Turn (Action): The Agent (your LLM) receives the observation and generates a DebateAction. It sends its argument and a phase_tag (like "claim").
|
| 9 |
+
|
| 10 |
+
3. The Environment's Turn (Step):
|
| 11 |
+
|
| 12 |
+
- The Opponent: The environment has its own logic (or a fixed LLM) that generates an opponent_challenge.
|
| 13 |
+
|
| 14 |
+
- The Grader: The environment evaluates the Agent's argument. Did it use a fallacy? Was it logical? It calculates a Reward.
|
| 15 |
+
|
| 16 |
+
4. Loop: This repeats until the phase reaches "closing" or the step_count hits a limit.
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
## STEP()
|
| 21 |
+
after every step() what we need:
|
| 22 |
+
|
| 23 |
+
What is a "Step"? One step should be one exchange:
|
| 24 |
+
|
| 25 |
+
```bash
|
| 26 |
+
Agent makes a claim -> Environment (Opponent) rebuts -> Grader evaluates.
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
Q) what does the agent need to see after each step?
|
| 30 |
+
ans:
|
| 31 |
+
|
| 32 |
+
A covnersation or debate ends if:
|
| 33 |
+
|
| 34 |
+
- Agent says he dont know
|
| 35 |
+
- Agent repeat same conversation again and again like if convo_repeat > 2 ends loop
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
Problem and Solving it:
|
| 39 |
+
|
| 40 |
+
- In RL, the environment is the authority.
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
|
| 44 |
+
RL loop:
|
| 45 |
+
environment owns: state, phase transitions, reward calculation
|
| 46 |
+
agent owns: only the action content (the argument text)
|
| 47 |
+
|
| 48 |
+
step 1: agent submits claim text → env moves to challenge phase, env generates opponent challenge
|
| 49 |
+
step 2: agent submits rebuttal text → env moves to closing phase
|
| 50 |
+
step 3: agent submits conclusion → env calculates final reward, done=True
|
| 51 |
+
|
| 52 |
+
```
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
| Step | Environment Phase | Agent's Goal | Opponent's Behavior |
|
| 56 |
+
|------|------------------|--------------------------------------------|----------------------------------|
|
| 57 |
+
| 0 | OPENING | Make a core claim; sets the stage | Acknowledges |
|
| 58 |
+
| 1 | CHALLENGE | Defend against a specific counter | Attacks the core claim |
|
| 59 |
+
| 2 | REBUTTAL | Attack the opponent's logic | Offers a counter-theory |
|
| 60 |
+
| 3 | CONSOLIDATION | Connect all evidence together | Questions the evidence |
|
| 61 |
+
| 4 | CLOSING | Final summary / impact statement | Final "Judge" summary |
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
### FRAME IT
|
| 66 |
+
But your framing needs to shift. Right now you're building "a debate game." You need to frame it as "Argument Quality Evaluation Environment" — a tool for training and evaluating LLM reasoning and persuasion capabilities. That framing scores higher on real-world utility (30% of grade).
|
| 67 |
+
|
| 68 |
+
### NEW BUILD TESTING
|
| 69 |
+
|
| 70 |
+
What you need to build, reframed
|
| 71 |
+
The 3 required tasks should be difficulty tiers of the same domain:
|
| 72 |
+
|
| 73 |
+
- Task 1 (Easy) — Single claim grader
|
| 74 |
+
Agent makes one claim on a topic. Grader scores: length ✓, contains reasoning keyword ✓, on-topic ✓. Score 0.0–1.0.
|
| 75 |
+
|
| 76 |
+
- Task 2 (Medium) — Claim + rebuttal grader
|
| 77 |
+
Agent makes a claim, receives an opponent challenge, must rebut. Grader scores rebuttal quality against the challenge. Partial credit for partial engagement.
|
| 78 |
+
|
| 79 |
+
- Task 3 (Hard) — Full 5-phase debate grader
|
| 80 |
+
Your current full episode. Grader scores coverage, synthesis, logical consistency across all phases. This is where your RewardMetrics class shines.
|
| 81 |
+
|
| 82 |
+
## Priority order right now
|
| 83 |
+
|
| 84 |
+
- 3 tasks with clear difficulty progression and deterministic graders ✓
|
| 85 |
+
- Rewards normalized to [0.0, 1.0] ✓
|
| 86 |
+
- Pydantic schemas ✓
|
| 87 |
+
- state() method ✓
|
| 88 |
+
- Embedding cache with batched matrix ops ✓
|
| 89 |
+
- opponent_coverage upgraded to match argument_coverage ✓
|
| 90 |
+
- impact_score normalized ✓
|
| 91 |
+
- Task graders call RewardMetrics directly instead of depending on environment reward ✓
|
| 92 |
+
- Baseline script producing reproducible scores ✓
|
| 93 |
+
- Shared metrics instance at module level — good memory management ✓
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
### Does the "Debate" Topic Align with "Real-World Tasks"?
|
| 97 |
+
|
| 98 |
+
Yes, but it requires careful framing. If you call it a "Philosophical Debate Game," the judges might penalize it as a "toy."
|
| 99 |
+
To maximize that 30% weight, you must frame this environment as "Strategic Argument Red-Teaming" or "PR/Legal Objection Handling." * The Real-World Pitch: "Companies use LLMs to draft policies, PR statements, and legal summaries. This environment simulates a hostile review process. The agent must defend a claim against an adversarial LLM (representing a skeptical public, opposing counsel, or strict compliance reviewer). This is a direct simulation of RLHF/RLAIF reasoning workflows used at Meta and Anthropic."
|
| 100 |
+
|
| 101 |
+
This framing instantly elevates your project from a "game" to an Enterprise Agent Evaluation Tool.
|