EcoGrid / docs /SPEC.md
Loosebag's picture
Initial commit for EcoGrid-OpenEnv hackathon
479b6b0
|
Raw
History Blame Contribute Delete
6.7 kB
# 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 |