File size: 9,409 Bytes
e5e36db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1e8d43
5ff0156
 
f1e8d43
5ff0156
 
f1e8d43
5ff0156
e5e36db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# ============================================================================
# openenv.yaml  v1.1.0
# OpenEnv environment specification β€” passes `openenv validate`
# ============================================================================

name: information-integrity-env
version: "1.1.0"
author: openenv-content-moderation
description: >
  A deterministic, benchmarkable content moderation environment where agents
  verify claims, reason over pre-built evidence sources, and make explainable
  moderation decisions (allow / flag / remove).

  Evaluation runs fully offline β€” no external API calls during episodes.
  Three difficulty tiers (easy / medium / hard) with static scenario datasets
  ensure reproducible, comparable benchmarks across agent runs.

license: Apache-2.0

# ---------------------------------------------------------------------------
# Server
# ---------------------------------------------------------------------------
server:
  type: http
  reset_endpoint:    POST /reset
  step_endpoint:     POST /step
  health_endpoint:   GET  /health
  tasks_endpoint:    GET  /tasks
  grade_endpoint:    POST /grade
  collect_endpoint:  POST /collect   # dataset creation only; not used during eval
  state_endpoint:    GET  /state/{session_id}

# ---------------------------------------------------------------------------
# Observation space
# ---------------------------------------------------------------------------
observation:
  type: object
  description: >
    The agent observes the content under review, extracted claims (with live
    verification status), a pre-built evidence pool, and a running interaction
    history. Ground truth is never exposed.
  properties:
    content:
      type: string
      description: The piece of content under moderation review.
    claims:
      type: array
      description: Verifiable claims extracted from the content.
      items:
        type: object
        properties:
          id:                  { type: string }
          text:                { type: string }
          verification_status: { type: string, enum: [unverified, true, false, partially_true, unknown] }
          confidence:          { type: number, minimum: 0.0, maximum: 1.0 }
          verified_by_sources: { type: array, items: { type: string } }
    available_sources:
      type: array
      description: Pre-built evidence pool β€” fully deterministic, no live fetching.
      items:
        type: object
        properties:
          id:          { type: string }
          title:       { type: string }
          text:        { type: string }
          url:         { type: string }
          stance:      { type: string, enum: [supporting, contradicting, neutral] }
          reliability: { type: number, minimum: 0.0, maximum: 1.0 }
          source_type: { type: string }
    interaction_history:
      type: array
      description: Log of all previous actions and their results this episode.
    status_flags:
      type: object
      properties:
        decision_made:       { type: boolean }
        sufficient_evidence: { type: boolean }
        premature_decision:  { type: boolean }
        redundant_actions:   { type: integer }
        max_steps_reached:   { type: boolean }
    step_count:       { type: integer }
    episode_id:       { type: string }
    task_difficulty:  { type: string, enum: [easy, medium, hard] }

# ---------------------------------------------------------------------------
# Action space
# ---------------------------------------------------------------------------
actions:
  verify_claim:
    description: Investigate a specific claim and receive its verification status.
    required_fields: [claim_id]
    optional_fields: [reasoning]
    example:
      type: verify_claim
      claim_id: claim_001
      reasoning: "This is the central assertion β€” verify first."

  check_source:
    description: Read a source and receive its full text, stance, and reliability.
    required_fields: [source_id]
    optional_fields: [reasoning]
    example:
      type: check_source
      source_id: src_003
      reasoning: "WHO source β€” likely authoritative."

  decide:
    description: >
      Make the final moderation decision, ending the episode.
      Must verify >= 1 claim and check >= 2 sources first (or incur premature penalty).
    required_fields: [decision]
    optional_fields: [reasoning]
    example:
      type: decide
      decision: remove
      reasoning: "All claims false per three high-reliability sources."

# ---------------------------------------------------------------------------
# Reward
# ---------------------------------------------------------------------------
reward:
  type: float
  range: [-2.0, 2.0]
  description: >
    Dense step-level reward. Non-sparse by design β€” agents receive positive
    signals for every unique claim verified and source checked.
    See reward_config.yaml for configurable magnitudes.
  components:
    verify_claim_reward:  "+0.20 per unique claim verified"
    check_source_reward:  "+0.20 per unique source checked"
    multi_source_bonus:   "+0.20 when >= 3 unique sources checked"
    decision_correct:     "+1.00 exact match with ground truth"
    decision_partial:     "+0.50 one step away (flag<->remove, flag<->allow)"
    decision_wrong:       "0.00"
    premature_decision:   "-0.50 deciding before sufficient evidence"
    redundant_action:     "-0.10 re-verifying / re-checking same id"
    step_inefficiency:    "-0.05 per step beyond efficient threshold"
    over_aggression:      "-0.30 choosing remove when ground truth is allow/flag"

# ---------------------------------------------------------------------------
# Tasks  (deterministic datasets β€” no live API calls)
# ---------------------------------------------------------------------------
tasks:
  - name: easy
    grader: tasks.easy.grader.grade_episode
 
  - name: medium
    grader: tasks.medium.grader.grade_episode
 
  - name: hard
    grader: tasks.hard.grader.grade_episode

# ---------------------------------------------------------------------------
# Grader
# ---------------------------------------------------------------------------
grader:
  output_range: [0.0, 1.0]
  dimensions:
    decision_score:
      description: Correctness of the final moderation call (partial credit for adjacent decisions)
    evidence_score:
      description: Fraction of available sources consulted
    reasoning_score:
      description: Fraction of claims fully verified before deciding
    efficiency_score:
      description: Steps used relative to difficulty-specific ideal maximum

# ---------------------------------------------------------------------------
# Evaluation protocol
# ---------------------------------------------------------------------------
evaluation:
  description: >
    Run inference.py in benchmark mode to evaluate an agent across all 15 scenarios.
    No external API calls are made during evaluation episodes.
  command: python inference.py --benchmark --out results.json
  expected_output_format: |
    difficulty=easy   avg_score=X.XXXX  avg_reward=X.XXXX  n=5
    difficulty=medium avg_score=X.XXXX  avg_reward=X.XXXX  n=5
    difficulty=hard   avg_score=X.XXXX  avg_reward=X.XXXX  n=5
  tier_validation: easy_avg > medium_avg > hard_avg
  runtime_budget: "< 20 minutes on 2 vCPU / 8 GB RAM"
  logging_protocol: "[START] / [STEP] / [END]"

# ---------------------------------------------------------------------------
# Data pipeline  (dataset creation only β€” not used during eval)
# ---------------------------------------------------------------------------
data_pipeline:
  description: >
    DataCollector is used ONLY to build the static scenario datasets in
    tasks/{difficulty}/scenarios.json.  It is NOT called during evaluation episodes.
  backends:
    - { name: serpapi,          env_key: SERPAPI_KEY }
    - { name: newsapi,          env_key: NEWSAPI_KEY }
    - { name: brave_search,     env_key: BRAVE_SEARCH_KEY }
    - { name: google_factcheck, env_key: GOOGLE_FACTCHECK_KEY }
    - { name: duckduckgo,       env_key: null, note: "No key required; rate-limited fallback" }
  cache:
    backend: redis
    env_key: REDIS_URL
    default: redis://localhost:6379
    ttl_seconds: 86400

# ---------------------------------------------------------------------------
# Constraints
# ---------------------------------------------------------------------------
constraints:
  - Ground truth is never exposed in the Observation
  - No external API calls occur during env.step() or env.reset()
  - All reward computations are deterministic
  - Agents must gather evidence before deciding (premature decision penalty applies)
  - Redundant actions (re-checking same id) are penalised
  - Scenario datasets are static JSON β€” reproducible across runs

# ---------------------------------------------------------------------------
# Baseline
# ---------------------------------------------------------------------------
baseline:
  script: inference.py
  mode: --benchmark
  agent_type: ReAct (LLM-driven)
  logging_protocol: "[START] / [STEP] / [END]"
  model_env_var: MODEL_NAME
  api_base_env_var: API_BASE_URL
  token_env_var: HF_TOKEN
  expected_scores:
    easy:   { avg_score: "~0.78", avg_reward: "~1.20" }
    medium: { avg_score: "~0.63", avg_reward: "~0.90" }
    hard:   { avg_score: "~0.52", avg_reward: "~0.65" }