Spaces:
Sleeping
EcoGrid-OpenEnv β Technical Specification
1. Overview
EcoGrid-OpenEnv is a production-grade Reinforcement Learning environment for the OpenEnv framework that simulates sustainable energy grid management. An agent controls energy distribution across renewable sources (solar + wind), fossil fuels, and battery storage to meet variable demand while minimising cost and carbon emissions.
Author: Team DD
Hackathon: Scaler School of Technology Γ Meta PyTorch Finale
Theme: #3 β World Modeling (Professional Tasks) + Mercor Sub-theme
2. File Tree
eco-grid-openenv/
βββ env/
β βββ __init__.py # Package init, re-exports EcoGridEnv
β βββ environment.py # Core EcoGridEnv class (reset/step/state)
β βββ dynamics.py # Deterministic physics helpers (solar/wind/demand/battery)
β βββ reward.py # Multi-objective reward function
β βββ tasks.py # 3 task graders (easy/medium/hard)
βββ models/
β βββ __init__.py # Package init, re-exports all schemas
β βββ schemas.py # Pydantic v2 typed models
βββ tests/
β βββ test_environment.py # Environment unit tests
β βββ test_reward.py # Reward function tests
β βββ test_graders.py # Grader determinism tests
βββ docs/
β βββ SPEC.md # This file
βββ logs/ # Runtime logs (gitignored)
βββ lora_adapter/ # Trained LoRA weights (gitignored)
βββ openenv.yaml # OpenEnv specification file
βββ baseline.py # Heuristic + LLM inference script
βββ train_unsloth.py # Unsloth GRPO training script
βββ app.py # Streamlit dashboard for HF Spaces
βββ Dockerfile # Multi-stage production Dockerfile
βββ docker-compose.yml # Local dev compose config
βββ requirements.txt # Pinned Python dependencies
βββ README.md # Full hackathon README
βββ BLOG.md # HuggingFace blog post (β€400 words)
βββ .gitignore # Ignore logs/, lora_adapter/, __pycache__
3. State Space
| Field | Type | Range | Unit | Description |
|---|---|---|---|---|
| demand | float | [0, 200] | MWh | Energy demand this timestep |
| solar_capacity | float | [0, 1] | ratio | Available solar generation capacity |
| wind_capacity | float | [0, 1] | ratio | Available wind generation capacity |
| battery_level | float | [0, 1] | ratio | Battery state of charge |
| grid_stability | float | [0, 1] | ratio | Grid frequency stability indicator |
| carbon_budget_remaining | float | [0, 1000] | kgCOβ | Remaining carbon emission budget |
| price_signal | float | [0, 300] | $/MWh | Current spot electricity price |
| time_step | int | [0, 96] | step | Current simulation timestep |
4. Action Space
| Field | Type | Range | Constraint | Description |
|---|---|---|---|---|
| renewable_ratio | float | [0, 1] | sum β€ 1.0 | Fraction of demand met by renewables |
| fossil_ratio | float | [0, 1] | sum β€ 1.0 | Fraction of demand met by fossil fuels |
| battery_action | float | [-1, 1] | β | Charge (+1) or discharge (-1) battery |
Constraint: renewable_ratio + fossil_ratio β€ 1.0
The remaining fraction 1 - renewable_ratio - fossil_ratio is unmet demand (blackout risk).
5. Reward Function
Terms (summing to [0, 1])
| Term | Weight | Formula |
|---|---|---|
| cost_savings | 0.30 | 1 - normalised(fossil_cost + grid_cost) |
| carbon_score | 0.30 | 1 - normalised(carbon_emission) |
| stability_score | 0.25 | 1 - blackout_risk |
| renewable_bonus | 0.15 | renewable_ratio Γ (1 - blackout_risk) |
Penalties (subtracted before clip)
| Penalty | Trigger | Value |
|---|---|---|
| blackout_penalty | demand unmet > 20% | -0.5 |
| carbon_overrun | carbon_budget < 0 (hard only) | -0.8 |
Final: clip(weighted_sum - penalties, 0, 1)
6. Task Specifications
Easy: BasicGridBalance
- Episode length: 48 steps
- Conditions: Predictable solar (low noise), stable demand, no battery
- Objective: Minimise cost
- Grader criteria: avg_cost_reduction > 30%, no blackouts, avg_renewable_ratio > 0.5
- Score: total_reward / max_possible_reward
Medium: RenewableVariability
- Episode length: 96 steps
- Conditions: Noisy solar+wind, demand spikes, small battery (capacity=0.3)
- Objective: Avoid blackouts while maintaining renewable usage
- Grader criteria: blackout_episodes < 3, avg_renewable_ratio > 0.6
- Score: 0.4Γ(renewable) + 0.4Γ(stability) + 0.2Γ(cost)
Hard: CarbonConstrained
- Episode length: 96 steps
- Conditions: Strict carbon cap (500 kgCOβ), high volatility (2Γ noise), limited storage
- Objective: Never exceed carbon cap, maintain stability > 0.7
- Grader criteria: carbon_budget β₯ 0 at all steps, grid_stability > 0.7
- Score: 0 if any carbon overrun; else 0.5Γ(carbon) + 0.3Γ(cost) + 0.2Γ(stability)
7. Physics Model
All functions are deterministic given a seed (use np.random.default_rng(seed)).
Solar Output
solar = 0.5 + 0.5 Γ sin(2Ο Γ time_step / 24) + noise Γ N(0, noise_level)
clamped to [0, 1]
Wind Output
wind = random_walk(previous_wind, step_size=0.05) + noise Γ N(0, noise_level)
clamped to [0, 1]
Demand Curve
base = 80 MWh
morning_peak = 30 Γ exp(-((t - 8)Β² / 8))
evening_peak = 40 Γ exp(-((t - 18)Β² / 8))
spike = random_spike_probability Γ spike_magnitude
demand = base + morning_peak + evening_peak + spike
Battery
new_level = clamp(level + action Γ charge_rate, 0, 1)
Carbon Emission
emission = fossil_ratio Γ demand Γ emission_factor (kg COβ/MWh)
8. Mercor Sub-theme
The reward function is designed so that more tokens of agent reasoning correspond to better reward scaling. Specifically:
- Actions that consider multiple objectives (cost + carbon + stability) score higher
- Chain-of-thought prompts in baseline.py encourage structured reasoning
- GRPO training rewards longer, more considered outputs with higher task scores
9. Performance Targets
| Metric | Target |
|---|---|
| Episodes/second (numpy sim) | > 10,000 |
| Random baseline score (easy) | 0.15β0.25 |
| Heuristic baseline score (easy) | 0.68β0.74 |
| Trained agent score (easy) | 0.75β0.85 |
| Seed determinism | 100% reproducible |