|
Download README.md from TheRubberDuckDebuggers/cascade-containment: direct link, hf CLI and curl.
- Browser
- Download file 14 kB
-
https://huggingface.co/spaces/TheRubberDuckDebuggers/cascade-containment/resolve/main/README.md
- Command line
-
hf download hf://spaces/TheRubberDuckDebuggers/cascade-containment/README.md
-
curl -L -o README.md https://huggingface.co/spaces/TheRubberDuckDebuggers/cascade-containment/resolve/main/README.md
14 kB
| title: Cascade Containment | |
| emoji: π¦ | |
| colorFrom: red | |
| colorTo: blue | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| ## π¦ An RL Benchmark for Sequential Resource Allocation Under Spreading Cascade Dynamics | |
| [](https://github.com/meta-pytorch/OpenEnv) | |
| [](https://python.org) | |
| [](https://hub.docker.com) | |
| [](https://huggingface.co/spaces/TheRubberDuckDebuggers/cascade-containment) | |
| [](LICENSE) | |
| Meta PyTorch OpenEnv Hackathon Γ SST 2026 β [Live Demo](https://therubberduckdebuggers-cascade-containment.hf.space) Β· [GitHub](https://github.com/Rohitchandramouli/cascade-containment) | |
| --- | |
| ## The Problem | |
| Sequential resource allocation under uncertainty is one of the most consequential decision problems in the real world. Whether containing an epidemic, deploying firefighting crews, isolating a cyberattack, or routing aid β the agent faces the same fundamental challenge: | |
| - **Resources are scarce** β you cannot cover every district simultaneously | |
| - **Data is delayed** β by the time a crisis is visible, it has already grown | |
| - **Interventions cascade** β actions in one district affect adjacent ones | |
| - **Acting too late is catastrophic** β hospital collapse ends the episode; proactive containment is rewarded exponentially more than reactive response | |
| No existing OpenEnv benchmark formalises this problem class. Cascade Containment does. | |
| --- | |
| ## Environment Overview | |
| A city health authority must allocate limited medical resources across districts to contain a spreading outbreak. Each step, the agent observes district infection rates (possibly lagged), hospital capacity levels, and growth signals β then decides where to deploy resources, impose restrictions, or gather data. | |
| The environment is **not epidemic-specific**. The underlying mechanics β spreading cascade, delayed observation, resource scarcity, geographic spillover β are structurally identical across multiple real-world domains. | |
| --- | |
| ## Quick Start | |
| ```python | |
| from client import CascadeContainmentEnv | |
| from models import ContainmentAction | |
| with CascadeContainmentEnv( | |
| base_url="https://therubberduckdebuggers-cascade-containment.hf.space" | |
| ).sync() as env: | |
| result = env.reset(task_name="medium") | |
| obs = result.observation | |
| while not result.done: | |
| most_infected = max(obs.districts, key=lambda d: d.reported_infection_rate) | |
| action = ContainmentAction( | |
| action_type="allocate", | |
| district_id=most_infected.district_id | |
| ) | |
| result = env.step(action) | |
| obs = result.observation | |
| print(f"Step {obs.current_step}: reward={result.reward:.3f}") | |
| ``` | |
| ## Running the Full Baseline Evaluation | |
| ```bash | |
| export API_BASE_URL="https://router.huggingface.co/v1" | |
| export MODEL_NAME="meta-llama/Llama-3.1-8B-Instruct" | |
| export HF_TOKEN="hf_your_token_here" | |
| export ENV_BASE_URL="https://therubberduckdebuggers-cascade-containment.hf.space" | |
| # Full LLM+GRPO evaluation (~10 minutes, emits [START][STEP][END] logs) | |
| python inference.py | |
| # Local validation + greedy benchmark | |
| python scripts/test_local.py | |
| ``` | |
| --- | |
| ## Action Space | |
| | Field | Type | Values | | |
| | --- | --- | --- | | |
| | `action_type` | `string` | `"test"` Β· `"restrict"` Β· `"allocate"` | | |
| | `district_id` | `int` | 0-indexed district target | | |
| | Action | Cost | Effect | | |
| | --- | --- | --- | | |
| | **test** | 1 resource | Reveals accurate current infection data for district | | |
| | **restrict** | Free | Imposes movement restrictions; reduces spread rate; penalised if infection < 0.20 | | |
| | **allocate** | 1 resource | Deploys medical resources; reduces existing infection by 5% and slows future spread | | |
| Movement restrictions lift automatically once a district's infection drops below the safe threshold. | |
| --- | |
| ## Observation Space | |
| The agent receives a filtered, potentially lagged view of the world β **never the full ground truth**: | |
| ```python | |
| CityObservation: | |
| districts: List[DistrictObservation] # per-district visible state | |
| available_resources: int # budget remaining this step | |
| current_step: int | |
| max_steps: int | |
| done: bool | |
| reward: float | None | |
| message: str | None | |
| ``` | |
| | Field | Description | Observability | | |
| | --- | --- | --- | | |
| | `reported_infection_rate` | Active infection fraction | Real-time (easy/medium); **3-day lagged** (hard) | | |
| | `growth_rate_hint` | Noisy signal of true spread rate | Always real-time Β± noise | | |
| | `hospital_capacity_remaining` | ICU/ward capacity fraction | Always real-time | | |
| | `population_density` | District's share of city population | Always real-time | | |
| | `restriction_active` | Whether movement restrictions are in place | Always real-time | | |
| | `tested_recently` | Tested within last 2 days | Always real-time | | |
| --- | |
| ## Epidemiological Model | |
| ```text | |
| new_infection = current + (spread_rate β natural_recovery β intervention) + geographic_spillover | |
| ``` | |
| | Parameter | Value | Rationale | | |
| | --- | --- | --- | | |
| | Spread rate | 3β8% per day | Realistic for respiratory outbreaks (seasonal flu: 5β10%) | | |
| | Natural recovery | 1% per day | Background case resolution without medical intervention | | |
| | Treatment effect | β5% existing infection | Medical deployment (antivirals, PPE, rapid response) | | |
| | Spread reduction | β10% per allocation | Resource-driven suppression of transmission | | |
| | Geographic spillover | 1% to adjacent districts | Linear topology β no wrap-around (geographically realistic) | | |
| | Hospital breach threshold | β€10% capacity | Real ICU overflow and triage failure threshold | | |
| --- | |
| ## Three Tasks | |
| | Task | Districts | Steps | Resources | Data Lag | Challenge | | |
| | --- | --- | --- | --- | --- | --- | | |
| | **easy** | 2 | 10 | 10 | None | Single outbreak; D1 starts infected, D0 is clean | | |
| | **medium** | 4 | 15 | 8 | None | Two simultaneous outbreaks; forced triage between competing threats | | |
| | **hard** | 6 | 15 | 7 | **3 days** | Six seeded infections (only D2 and D4 above safe threshold); 3-day data lag; scarce resources | | |
| **Easy** β D1 starts at 0.50 infection, D0 is clean. The agent must observe and target the correct district. A fixed-target agent ignoring observations scores ~43% and breaches hospitals 60% of the time. | |
| **Medium** β D0 starts above the infection threshold (0.42); D2 is in the warning zone (0.38, below the 0.40 threshold). D1 and D3 start low but grow into crisis within 4β6 steps via spillover. With 8 resources across 4 districts over 15 steps, genuine triage is required. | |
| **Hard** β 3-day information lag means the agent sees infection rates from 3 days ago. The `growth_rate_hint` provides a noisy signal to estimate current state. Structural uncertainty β not testable around. | |
| --- | |
| ## Reward Function | |
| | Term | Value | Fires When | | |
| | --- | --- | --- | | |
| | Infection penalty | `β0.50 Γ density` | District infection > 0.40 | | |
| | Hospital breach | `β1.00` | Hospital capacity β€ 10% | | |
| | Early containment | `+0.50 Γ (1 β step/max_steps)` | District infection < 0.20 | | |
| | Correct prioritisation | `+0.30` | Allocate to highest-infected district | | |
| | Unnecessary restriction | `β0.20` | Restrict district below 0.20 | | |
| Key design choices: early containment bonus decays over time (proactive action worth more); infection penalty scales with population density (realistic triage); hospital breach fires at 10% not 0% (real ICU thresholds); restrictions auto-lift when infection drops below safe threshold. | |
| --- | |
| ## Grader | |
| Fully deterministic β no randomness, no LLM calls. Identical trajectories always produce identical scores in `[0.0, 1.0]`. | |
| | Component | Weight | Measures | | |
| | --- | --- | --- | | |
| | **Hospital score** | 45% | Average capacity preserved; Γ0.6 multiplier if any district collapsed | | |
| | **Containment score** | 30% | Fraction of district-days below infection threshold (first 2 steps excluded) | | |
| | **Efficiency score** | 15% | Fraction of resource actions targeting highest-infected district (grader uses pre-action state to avoid penalising successful treatments) | | |
| | **Speed score** | 10% | `1 β (steps / max_steps)` if episode ends early; else 0 | | |
| Hospital is weighted highest because system capacity preservation is the primary operational constraint in real outbreak response β a functioning healthcare system is the prerequisite for everything else. | |
| --- | |
| ## Baseline Agent β GRPO-Style Episodic Memory | |
| No weight updates, no gradient computation. The prompt is the policy; memory updates are the policy improvement. | |
| ### Learning Loop | |
| ```text | |
| Rollout 1: Base prompt, no prior knowledge | |
| compute advantage = R1 - mean([]) | |
| store steps with reward > -0.3 into EpisodicMemory | |
| Rollout 2: Memory-augmented prompt | |
| retrieve top-5 similar past decisions by L1 distance on infection profiles | |
| inject as concrete examples into prompt | |
| compute advantage = R2 - mean([R1]) | |
| reinforce if advantage > -0.5 | |
| ... repeat for N rollouts (easy=2, medium=3, hard=3) | |
| Report best grader score across all rollouts | |
| ``` | |
| ### Benchmark Scores | |
| Results from `baseline/run.py` (Llama 3.1 8B Instant via Groq, runtime ~10 minutes): | |
| | Task | Greedy (D0) | LLM+GRPO | Lift | | |
| | --- | --- | --- | --- | | |
| | Easy | 42.8% (breach 60%) | **90.8%** | +48pp | | |
| | Medium | 39.6% (breach 100%) | **78.0%** | +38pp | | |
| | Hard | 35.3% (breach 100%) | **61.1%** | +26pp | | |
| | **Average** | **39.2%** | **75.9%** | **+37pp** | | |
| The greedy baseline (always allocates to D0) scores 33β43% with 60β100% hospital breach rates β no trivial exploit path. LLM+GRPO reaches 66β91% with zero breaches, demonstrating that genuine triage reasoning is required and rewarded. | |
| --- | |
| ## Generalisation | |
| | Domain | Spreading cascade | Delayed data | Resource scarcity | | |
| | --- | --- | --- | --- | | |
| | π¦ **Epidemic containment** | Infection spreads between districts | Lagged case counts | Medical resources | | |
| | π₯ **Wildfire deployment** | Fire spreads across terrain | Satellite update delay | Firefighting crews | | |
| | π‘οΈ **Cyberattack isolation** | Lateral movement between systems | Detection lag | Security team hours | | |
| | π’ **Misinformation containment** | Narrative spread through networks | Viral detection lag | Correction budget | | |
| | π€ **Poverty intervention** | Deprivation cascades through communities | Census data lag | Aid allocation | | |
| --- | |
| ## Project Structure | |
| ```text | |
| cascade-containment/ | |
| βββ inference.py # Evaluation entry point (mandatory [START][STEP][END] logs) | |
| βββ models.py # Typed data contracts: Action, Observation, State | |
| βββ client.py # OpenEnv client interface | |
| βββ openenv.yaml # Environment manifest for OpenEnv registry | |
| β | |
| βββ server/ | |
| β βββ app.py # FastAPI server + judge dashboard + /grade /info /demo /validate endpoints | |
| β βββ environment.py # Core RL loop (reset/step/state OpenEnv interface) | |
| β βββ grader.py # Deterministic trajectory scorer β no LLM calls | |
| β βββ constants.py # Single source of truth for all numeric configuration | |
| β βββ utils.py # Spread computation, observation builder, helper functions | |
| β βββ Dockerfile # Container definition | |
| β βββ tasks/ | |
| β βββ task_easy.py # 2 districts, 10 steps, real-time data (D1 seeded) | |
| β βββ task_medium.py # 4 districts, 15 steps, forced triage | |
| β βββ task_hard.py # 6 districts, 15 steps, 3-day data lag | |
| β | |
| βββ baseline/ | |
| β βββ policy.py # LLM policy with chain-of-thought prompting | |
| β βββ evaluator.py # GRPO episodic memory loop (easy=2, medium=3, hard=3 rollouts) | |
| β βββ run.py # CLI entry point | |
| β | |
| βββ scripts/ | |
| β βββ test_local.py # Phase 1 spec checks + greedy benchmark + variance analysis | |
| β | |
| βββ core/ | |
| βββ trajectory.py # EpisodicMemory β L1 similarity retrieval, phase-weighted | |
| βββ reward.py # Score normalisation utilities | |
| βββ policy_update.py # Advantage computation, memory gating (threshold -0.3) | |
| ``` | |
| --- | |
| ## OpenEnv Compliance | |
| | Requirement | Status | | |
| | --- | --- | | |
| | `reset()` returns `CityObservation` | β | | |
| | `step(action)` returns `CityObservation` | β | | |
| | `state` property returns `State` | β | | |
| | Typed `Action` subclass | β `ContainmentAction(Action)` | | |
| | Typed `Observation` subclass | β `CityObservation(Observation)` | | |
| | `openenv.yaml` manifest | β | | |
| | Dockerfile builds | β | | |
| | HF Space deploys | β | | |
| | `inference.py` at root | β | | |
| | `[START][STEP][END]` structured logs | β | | |
| | Runtime < 20 minutes | β ~~10 minutes | | |
| | `API_BASE_URL`, `MODEL_NAME`, `HF_TOKEN` env vars | β | | |
| | OpenAI client for all LLM calls | β | | |
| | Grader scores in `[0.0, 1.0]` | β | | |
| | 3+ tasks with difficulty progression | β | | |
| | Phase 1 automated validation | β 10/10 checks pass | | |
| --- | |
| ## Setup and Local Development | |
| ### Local Server | |
| ```bash | |
| pip install -r requirements.txt | |
| uvicorn server.app:app --host 0.0.0.0 --port 7860 | |
| export ENV_BASE_URL=http://localhost:7860 | |
| python baseline/run.py | |
| ``` | |
| ### Docker | |
| ```bash | |
| docker build -t cascade-containment . | |
| docker run -p 7860:7860 cascade-containment | |
| ``` | |
| --- | |
| ## Tags | |
| `reinforcement-learning` Β· `resource-allocation` Β· `sequential-decision-making` Β· `partial-observability` Β· `cascade-dynamics` Β· `epidemic-response` Β· `openenv` Β· `llm-agent` Β· `grpo` Β· `episodic-memory` Β· `triage` Β· `multi-district` Β· `docker` Β· `fastapi` | |