FairRecovery-PlusPlus / docs /README_FairRecovery.md
joshua400
๐Ÿ”ง FIX: Standardized project links and renamed docs folder for professional submission
bee85a1
|
Raw
History Blame Contribute Delete
10.6 kB

๐Ÿ™๏ธ FairRecovery++ โ€” Post-Disaster City Recovery RL Environment

OpenEnv Theme Space Tests

Train an LLM to make fair disaster recovery decisions โ€” where helping wealthy zones first systematically abandons the most vulnerable people.


๐ŸŒŠ The Problem

After disasters like the 2022 Bengaluru floods and 2023 Chennai floods, city authorities must allocate scarce resources (medical units, power crews, water tankers) across many damaged neighborhoods simultaneously โ€” under tight budgets and time pressure.

The trap every naive AI falls into: optimising for speed means fixing the easiest zones first, which are almost always the wealthiest. Zone 0 (wealthy district, moderate damage) is faster to restore than Zone 4 (informal settlement, 92% damage, 96% vulnerable population). A greedy agent picks Zone 0 every time โ€” and Zone 4 stays dark for days.

FairRecovery++ is an OpenEnv RL environment that teaches LLM agents to escape this trap: learn to jointly optimize service restoration and equitable distribution across vulnerable populations.

Primary Theme: 3.1 โ€” Real-World Professional Tasks
Secondary Theme: 2 โ€” Long-Horizon Planning & Instruction Following


๐ŸŽฏ The Fairness Trap (Hard Scenario)

Zone Damage Service Vulnerable Pop Priority?
Zone 0 (wealthy) 35% 65% 8% โŒ Easy but low need
Zone 1 50% 50% 40% Medium
Zone 2 60% 40% 55% Medium
Zone 3 (poor) 72% 28% 72% High
Zone 4 (informal) 92% 8% 96% โœ… Must prioritize

A greedy agent always picks Zone 0 (quick ROI, easy reward). A fairness-aware agent learns to prioritize Zone 4 despite lower immediate returns โ€” because that's where 96% of the population is vulnerable.


๐Ÿ—๏ธ Architecture

LLM Agent (GRPO trained)
        โ”‚
        โ–ผ FairRecoveryAction
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Safety Shield (shield.py)    โ”‚  โ† blocks invalid actions before mutation
โ”‚  Stage validator              โ”‚
โ”‚  Budget enforcer              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚ valid action
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  FairRecoveryEnvironment      โ”‚  โ† core OpenEnv Environment class
โ”‚  Multi-step protocol:         โ”‚
โ”‚  analyze โ†’ allocate โ†’         โ”‚
โ”‚  execute โ†’ (ร—MAX_DAYS) โ†’      โ”‚
โ”‚  submit                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚ updated CityState
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Reward Engine (RLVR)         โ”‚  โ† no learned reward model
โ”‚  R_exec  (service improvement)โ”‚
โ”‚  R_fair  (disparity reduction)โ”‚
โ”‚  R_safe  (constraint penalty) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚ per-step reward
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Composable Rubrics (RFC 004) โ”‚  โ† FairnessRubric + UtilityRubric
โ”‚  Terminal episode scoring     โ”‚     + AnalysisRubric
โ”‚  Grader score โˆˆ (0.01, 0.99)  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐ŸŽฎ What the Agent Sees, Does, and Gets Rewarded For

Observation (per step)

{
  "zones": [
    {"zone_id": 4, "damage": 0.92, "service": 0.08, "vulnerable_ratio": 0.96}
  ],
  "day": 2,
  "budget_left": 25.0,
  "step_stage": "allocate",
  "fairness_score": -0.61,
  "cumulative_reward": 0.142
}

Action (multi-step protocol โ€” not just one choice)

// Step 1: analyze
{"action_type": "analyze", "critical_zones": [3, 4], "reasoning": "highest damage ร— vulnerability"}

// Step 2: allocate
{"action_type": "allocate", "allocations": [
  {"zone": 4, "resource": "medical"},
  {"zone": 3, "resource": "power"}
]}

// Step 3: execute (commits allocations, receives dense reward)
{"action_type": "execute"}

// After MAX_DAYS: submit (receives terminal bonus)
{"action_type": "submit"}

Reward System (RLVR โ€” all verifiable, no learned model)

Component Formula Weight What it teaches
R_exec Avg service improvement this step 1.0 Restore services efficiently
R_fair โˆ’(avg_service_normal โˆ’ avg_service_vulnerable) 0.5 Don't leave vulnerable zones behind
R_safe โˆ’0.1 ร— violations 0.5 Respect constraints
R_analysis Overlap(chosen, top-k by damageร—vuln) 0.1 Correctly identify critical zones
Terminal bonus 0.5ร—avg_svc + 0.5ร—(1+R_fair) โ€” Long-horizon outcome

Grader score: 0.6 ร— avg_service + 0.4 ร— (1 + fairness) clamped to (0.01, 0.99)

Anti-Reward-Hacking Measures

  • Stage ordering enforced by shield (can't skip analyze โ†’ go straight to execute)
  • Budget overflow: allocations rejected + penalty, state NOT mutated
  • Persistent ignore penalty: if vulnerable zones receive 0 resources for 2+ consecutive days
  • Early-submit blocked until MIN_STEPS reached
  • Step cap: force-terminate at MAX_STEPS_SAFETY_CAP

๐Ÿ“Š Training Results

Reward: Baseline vs Trained Agent

Training Results

Bar chart: Avg Curriculum Reward, Avg Final Utility, Avg Final Fairness โ€” baseline (grey) vs Sarvam-105B trained (blue) across 32 episodes.

Per-Episode Reward Heatmap

Score Heatmap

Each column is one episode. Trained agent (bottom row) shows consistently warmer (higher) rewards, especially in later episodes.

Reward Curve Over Training

Training Loss

4-episode moving average. Trained agent steadily improves above greedy baseline.

Key Numbers

Metric Greedy Baseline Sarvam-105B Trained ฮ”
Avg Episode Reward 0.549 0.602 +9.8%
Avg Final Fairness 0.537 0.539 +0.4%
Strategy discovered Always Zone 0 Medical-first equity โ€”

The trained agent spontaneously discovered a "medical-first equity" strategy: prioritize Zone 4 with medical resources (highest service impact for most vulnerable) before addressing easier zones.


๐Ÿš€ Quick Start

git clone https://github.com/joshua400/FairRecovery-PlusPlus
cd FairRecovery-PlusPlus
pip install -r requirements.txt
uvicorn server.app:app --reload
# Verify environment
curl http://localhost:8000/health

# Run a full episode
python inference.py --difficulty hard --episodes 3 --policy fairness_aware

Use as OpenEnv client

from client import FairRecoveryEnv

env = FairRecoveryEnv(base_url="https://Joshua1702-FairRecovery-PlusPlus.hf.space")
obs = env.reset(difficulty="hard")

for day in range(5):
    action = your_policy(obs)      # analyze โ†’ allocate โ†’ execute
    obs = env.step(action)
    print(f"Day {obs.day}: reward={obs.reward:+.3f} fair={obs.fairness_score:.3f}")

Run training (Colab)

Open train_COMPLETE.ipynb โ€” runs on free Colab T4 in ~10 minutes.


๐Ÿ“ Project Structure

fairrecovery_env/
โ”œโ”€โ”€ constants.py          # REWARD_WEIGHTS, RESOURCE_COSTS, thresholds
โ”œโ”€โ”€ models.py             # Pydantic v2 Action / Observation / State
โ”œโ”€โ”€ state.py              # CityState + ZoneState (mutable world model)
โ”œโ”€โ”€ tasks.py              # 3 scenarios: easy / medium / hard (fairness trap)
โ”œโ”€โ”€ rewards.py            # 5-component RLVR reward engine (pure functions)
โ”œโ”€โ”€ rubrics.py            # RFC 004 composable rubrics
โ””โ”€โ”€ shield.py             # Safety validator (blocks before mutation)

server/
โ”œโ”€โ”€ fairrecovery_environment.py   # OpenEnv Environment class
โ””โ”€โ”€ app.py                        # FastAPI + OpenEnv integration

client.py                 # Typed HTTP client
inference.py              # Baseline policies (greedy, fairness-aware, random)
train_COMPLETE.ipynb      # GRPO training notebook (TRL + Unsloth)
generate_summary_plots.py # Reproduce all plots from episode_log.csv

๐Ÿ”— Materials

Resource Link
๐Ÿค— Live Environment (HF Space) https://huggingface.co/spaces/Joshua1702/FairRecovery-PlusPlus
๐Ÿ’ป GitHub https://github.com/joshua400/FairRecovery-PlusPlus
๐Ÿ““ Training Notebook train_COMPLETE.ipynb (Colab-ready)
๐Ÿ“ HF Blog Post [ADD LINK AFTER PUBLISHING]
๐ŸŽฅ Demo Video [ADD LINK AFTER RECORDING]

๐ŸŒ Why It Matters

Post-disaster recovery planning is a $200B/year global challenge. AI systems that optimize only for speed or total utility systematically disadvantage the most vulnerable populations โ€” the elderly, disabled, and low-income communities who live in the hardest-hit zones.

FairRecovery++ is the first OpenEnv environment to encode intersectional fairness as a verifiable, first-class RL objective, making it a research-grade benchmark for safe and fair LLM agent training. The environment can be extended to vaccination rollout, hospital resource allocation, or any domain where efficiency vs equity trade-offs matter.


OpenEnv Compliance Checklist

  • โœ… openenv.yaml manifest present
  • โœ… Environment base class used with try/import fallback
  • โœ… reset() / step() / state() standard API
  • โœ… Pydantic v2 typed Action / Observation / State
  • โœ… Hosted on HF Spaces (Docker)
  • โœ… GRPO training with TRL + Unsloth (see train_COMPLETE.ipynb)
  • โœ… Training evidence: plots in assets/ and episode data in episode_log.csv
  • โœ… Composable rubrics (OpenEnv RFC 004)
  • โœ… Anti-reward-hacking: shield + stage gates + persistent ignore penalty

Built for the Meta PyTorch OpenEnv Hackathon India 2026.