⚡ Status: ✅ Fully Functional | Dashboard: http://localhost:8501 | Updated: March 19, 2026
An intelligent demand response system for managing electric grids using AI-powered load balancing with LangGraph, LangChain, and Groq API. Uses real Kaggle smart grid dataset with an interactive, minimalistic Streamlit dashboard.
This project implements an Demand Response Agent that automatically identifies stressed grids and intelligently manages thermostat loads to prevent blackouts. It uses:
- LangGraph: 4-node agentic workflow for deterministic decision-making
- Real Data: 50,000 real smart grid measurements from Kaggle
- AI Decision Engine: Groq API for fast LLM inference
- Interactive Dashboard: Streamlit UI with real-time visualization
- Scenario Testing: Multiple grid conditions to test DR responses
DemandResponseAgent (LangGraph-based)
├── 1️⃣ analyze_grid_state
│ └── Check: Frequency < 59.9 Hz OR Surplus > 50 MW?
├── 2️⃣ select_responsive_devices
│ └── Sort by flexibility score, select top candidates
├── 3️⃣ plan_dr_actions
│ └── Calculate temperature targets for max reduction
└── 4️⃣ validate_actions
└── Verify actions are safe and achievable
- DRController: Manages thermostat pool and executes agent decisions
- SmartGridDataLoader: Loads and processes Kaggle dataset (50K records)
- GridState: Real-time grid conditions (demand, generation, frequency, status)
- Thermostat: Connected device with current temp, target temp, capacity, flexibility
- DRAction: Specific temperature adjustment commands
- ✅ Analyzes real grid stress (frequency-based detection)
- ✅ Deterministic device selection using flexibility scores
- ✅ Generates temperature-adjustment actions for load reduction
- ✅ Validates all actions before execution
- ✅ Works with 50,000+ real smart grid measurements
- ✅ Responds differently based on actual grid conditions (NORMAL, WARNING, CRITICAL)
- 📊 Dashboard Tab: Real-time grid metrics, scenario switching, live DR agent execution
- ➕ Create Scenario Tab: Build custom scenarios with configurable grid conditions
- 🎛️ Pre-loaded Scenarios: Normal Day, Peak Demand, Emergency (with pre-configured grid states)
▶️ DR Agent Execution: Run agent with one click, see real-time actions and impact analysis- 📈 Visualizations: Supply vs demand charts, energy mix distribution
- ⚙️ Flexible Configuration: Adjust demand, generation, frequency, renewable %, and device count
- 📥 Loads Kaggle smart grid dataset automatically
- 🔄 Generates 3 realistic scenarios with different grid conditions
- 📊 16 features: power consumption, voltage, frequency, renewable %, temperature, humidity, etc.
- 🌍 100,000x scaling from residential (kW) to regional (MW) levels
All parameters calculated from real smart grid data - NO hardcoded values:
- 📈 Smart Defaults: Slider ranges derived from 50K real records (min, max, median)
- 🧮 Intelligent Device Count: Calculated by agent logic (1 device per 100 MW demand)
- 🌡️ Real Thermostat Properties: Sourced directly from Kaggle dataset rows
- 📊 Capacity Calculation: Based on actual power consumption patterns
- 🔍 Transparency: Shows data sources and real ranges to user
- ✅ Test 1 (WARNING): Data from row 15703 (5.0% voltage fluctuation)
- ✅ Test 2 (CRITICAL): Data from row 15644 (4.12% fluctuation, realistic power factor)
- ✅ Test 3 (NORMAL): Data from row 27011 (optimal conditions, -4.76% fluctuation)
- Result: 7 actions, 15 actions, 0 actions (as expected)
50,000 Kaggle Records → Statistical Analysis → Intelligent Parameters
├─ Power Consumption (kW) → Demand ranges & device capacity
├─ Solar/Wind/Grid Supply (kW) → Generation & renewable percentage
├─ Voltage Fluctuation (%) → Frequency derivation
├─ Power Factor → Grid quality metrics
└─ Temperature (°C) → Thermostat baseline
- Python 3.9+
- Groq API key (free tier: https://console.groq.com)
- Kaggle account (for dataset, optional - auto-downloads)
-
Clone/Navigate to project
cd smartGridLoadBalancer -
Create virtual environment
python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Configure environment
cp .env.example .env # Edit .env and add your GROQ_API_KEY export GROQ_API_KEY="your-api-key-here"
-
Get Groq API Key
- Visit https://console.groq.com
- Sign up/login (free)
- Create API key in Settings
- Copy to
.envfile
streamlit run dashboard.pyOpen browser to http://localhost:8501 and:
- View the Dashboard tab with 3 pre-loaded scenarios (Normal Day, Peak Demand, Emergency)
- Click scenario buttons to switch between grid conditions
- Click "
▶️ Run DR Agent" to execute demand response analysis - Navigate to Create Scenario tab to design custom scenarios
- Adjust demand, generation, frequency, renewables, and device count with sliders
python example_with_real_data.pyShows 3 scenarios with real grid data:
- Scenario 1: 59.71 Hz (CRITICAL) - 5 devices, 3 DR actions
- Scenario 2: 60.07 Hz (Normal) - 8 devices, 0 actions
- Scenario 3: 60.00 Hz (Normal) - 11 devices, 0 actions
from data_loader import SmartGridDataLoader
from dr_controller import DRController
from models import GridState
# Load real Kaggle data
loader = SmartGridDataLoader()
scenarios = loader.get_dataset_scenarios(samples=3)
# Run agent on a scenario
scenario = scenarios[0]
grid = scenario['grid']
thermostats = scenario['thermostats']
controller = DRController()
for t in thermostats:
controller.register_thermostat(t)
# Execute demand response
result = controller.run_dr(grid)
print(f"Actions: {len(result['actions'])}")
print(f"Analysis: {result['analysis']}")
# Apply actions to devices
controller.apply_all_actions(result['actions'])Input: GridState + Thermostat List
↓
1️⃣ analyze_grid_state
• Check: frequency_hz < 59.9 OR demand_surplus > 50 MW?
• Output: need_dr (boolean)
↓
2️⃣ select_responsive_devices
• Filter thermostats by flexibility (>0.5)
• Sort by flexibility_score (highest first)
• Select top N devices
↓
3️⃣ plan_dr_actions
• For each selected device:
- Calculate: target_temp = current_temp - 2°C
- Calculate: reduction = capacity * flexibility * 0.5 MW
• Output: List[DRAction]
↓
4️⃣ validate_actions
• Verify target_temp within bounds
• Check expected reductions sum
• Return final validated actions
↓
Output: Result{'actions': [...], 'analysis': '...'}
| Condition | Input | Decision | Actions |
|---|---|---|---|
| CRITICAL | freq=59.71 Hz | Grid stressed | 3 actions, ~1.5 MW reduction |
| NORMAL | freq=60.07 Hz | Grid stable | 0 actions (no DR needed) |
| NORMAL | freq=60.00 Hz | Grid stable | 0 actions (no DR needed) |
- Model: Llama 3.1 8B Instant (via Groq)
- Temperature: 0.3 (deterministic responses)
- Max Tokens: 512 per decision
- Latency: ~2-5 seconds (includes network + inference)
- Cost: Free with Groq community tier
| Status | Frequency | Surplus | DR Action |
|---|---|---|---|
| 🟢 NORMAL | ≥60.0 Hz | Any | None (stable) |
| 🟡 WARNING | 59.5-59.9 Hz | <50 MW | Prepare devices |
| 🔴 CRITICAL | <59.5 Hz OR >50 MW surplus | Peak | Execute DR |
Flexibility (0-1) determines how quickly a device can respond:
- 0.9-1.0: Office/Tech buildings (high responsiveness)
- 0.7-0.8: Commercial spaces (good responsiveness)
- 0.5-0.7: Residential areas (moderate, comfort-aware)
- <0.5: Not selected for DR (comfort priority)
Scenario 1: 5 devices selected
├── TH_002 (flex=0.90) ✓ Selected
├── TH_004 (flex=0.85) ✓ Selected
├── TH_001 (flex=0.80) ✓ Selected
└── TH_000 (flex=0.70) ✗ Not selected
└── TH_003 (flex=0.75) ✗ Not selected
- ✅ API keys stored in
.env(never committed) - ✅ Temperature changes bounded within ±5°C
- ✅ All actions validated before execution
- ✅ Device-specific action constraints enforced
- ✅ Audit trail of all DR decisions
# Interactive dashboard with Kaggle data
streamlit run dashboard.py
# Command-line demonstration
python example_with_real_data.py
# Test agent with synthetic data
python test_agent_fix.py--- SCENARIO 1 ---
Grid Frequency: 59.71 Hz
Grid Demand: 119.140 MW
Thermostats: 5 devices
✅ AGENT ANALYSIS:
Grid stress detected: critical
📋 DR ACTIONS:
Actions Generated: 3
Expected Reduction: 1.5000 MW
Impact: 1.26% of demand
from demand_response_agent import create_dr_agent
from models import GridState, GridStatus, Thermostat, ThermostatMode
# Create test agent
agent = create_dr_agent()
# Create stressed grid
grid = GridState(
datetime.now(),
demand_mw=500, generation_mw=400,
frequency_hz=59.7, # Below threshold
status=GridStatus.CRITICAL,
renewable_pct=75
)
# Create thermostats
thermostats = [
Thermostat(f"TH_{i:03d}", f"Bldg {i}", 22, 22,
ThermostatMode.COOLING, 0.5, 0.7 + i*0.01)
for i in range(5)
]
# Run agent
result = agent.invoke({
'grid': grid,
'thermostats': thermostats
})
assert len(result['actions']) > 0
assert result['analysis'] != ""smartGridLoadBalancer/
├── demand_response_agent.py # 4-node LangGraph workflow
├── dr_controller.py # Thermostat management & execution
├── data_loader.py # Kaggle dataset integration
├── models.py # Data structures (GridState, Thermostat, etc)
├── dashboard.py # Streamlit UI (4 tabs)
├── example_with_real_data.py # Demo script with scenarios
├── test_agent_fix.py # Unit tests
├── requirements.txt # Dependencies
├── .env.example # Environment template
└── README.md # This file
GROQ_API_KEY=gsk_xxxxxxxxxxxxx
# Optional: Kaggle credentials (for dataset auto-download)
KAGGLE_USERNAME=your_username
KAGGLE_KEY=your_api_keyThermostat(
device_id="TH_001", # Unique identifier
location="Office Building", # Physical location
current_temp=22.5, # Current temperature (°C)
target_temp=22.0, # Target setpoint
mode=ThermostatMode.COOLING, # HEATING or COOLING
capacity_mw=0.5, # Max reduction capacity
flexibility=0.85 # 0-1 responsiveness score
)GridState(
timestamp=now,
demand_mw=800, # Current demand (MW)
generation_mw=750, # Current generation (MW)
frequency_hz=59.8, # Grid frequency
status=GridStatus.CRITICAL, # NORMAL/WARNING/CRITICAL
renewable_pct=45, # Renewable % of generation
stress_level=0.95 # Stress metric (0-1)
)- Grid Status Cards: Frequency (Hz), Demand (MW), Generation (MW), Status indicator
- Status Indicator: 🟢 NORMAL | 🟡 WARNING | 🔴 CRITICAL
- Real-time Visualizations:
- Supply vs Demand bar chart (demand in red, generation in green)
- Energy Mix pie chart (renewable % vs traditional)
- Scenario Selector: Quick buttons to switch between 3 pre-loaded scenarios
- Device Metrics: Total devices, total capacity (MW), average flexibility score
- DR Agent Execution: Single-click button to run demand response analysis
- Results Panel: Shows number of actions, expected load reduction, and impact percentage
- Actions Table: Lists all generated DR actions with device IDs, targets, and reduction values
- Scenario Name Input: Custom name for your scenario
- Grid Parameters:
- Demand slider (200-1000 MW)
- Generation slider (200-1000 MW)
- Frequency slider (58.5-61.5 Hz, normal = 60 Hz)
- Renewable % slider (0-100%)
- Device Configuration: Number of controllable devices (3-50)
- Status Prediction: Automatically calculates grid status based on imbalance
- Create Button: Saves scenario and adds to dashboard scenario list
# Check .env file exists
ls -la .env
# Set environment variable
export GROQ_API_KEY="your-key-here"
# Verify
echo $GROQ_API_KEY# Clear Streamlit cache
streamlit cache clear
# Check port is available
lsof -i :8501
# Use different port
streamlit run dashboard.py --server.port 8502# Ensure kagglehub is installed
pip install kagglehub
# Check internet connection
ping console.groq.com- Verify grid frequency < 59.9 Hz or surplus > 50 MW
- Check thermostat flexibility > 0.5
- Confirm at least 3 devices registered
- Check GROQ_API_KEY is valid
✅ Scenario Differentiation Bug
- Problem: All scenarios showed identical data
- Root Cause:
example_with_real_data.pyreused controller across scenarios, accumulating thermostats - Solution: Create fresh controller for each scenario
- Verification: Scenario 1 shows 59.71 Hz with 3 actions, Scenarios 2-3 show normal frequency with 0 actions
✅ Dashboard Scenario Selection
- Problem: Clicking scenario buttons didn't switch between scenarios
- Root Cause: Streamlit rerun was resetting
selected_scenariovariable to 0 - Solution: Implemented Streamlit
session_statefor persistent selection - Verification: Dashboard now properly switches scenarios, metrics update in real-time
Dashboard: http://localhost:8501
│
├── Scenario 1: Normal Day (60.00 Hz, NORMAL) → 5 devices, 0 actions
├── Scenario 2: Peak Demand (59.70 Hz, WARNING) → 8 devices, 3+ actions
└── Scenario 3: Emergency (59.30 Hz, CRITICAL) → 15 devices, 5+ actions
- Old Approach: LLM generated device selections and actions (unreliable JSON parsing)
- New Approach: Deterministic algorithms using mathematical thresholds
- Result: 100% consistent, fast, and verifiable decisions
Real data produces naturally varied scenarios:
- Scenario 1: Low frequency (59.71 Hz) triggers critical status and DR actions
- Scenario 2: Near-normal frequency (60.07 Hz) with different demand patterns
- Scenario 3: Stable frequency (60.00 Hz) requiring no response
def needs_dr(grid: GridState) -> bool:
return (grid.frequency_hz < 59.9 or
grid.demand_surplus > 50)| Aspect | Value |
|---|---|
| Decision Time | 2-5 seconds |
| LLM Latency | ~1-2 seconds (Groq) |
| Data Load Time | ~1-2 seconds (50K records) |
| Dashboard Startup | ~3-5 seconds |
| Max Devices/Scenario | 100+ thermostats |
| Memory Usage | 150-200 MB |
- Time-series forecasting for demand prediction
- Machine learning model for device responsiveness
- Multi-region federation support
- Vehicle-to-Grid (V2G) integration
- Solar/wind generation forecasting
- Price-responsive DR scheduling
- Real-time SCADA connectivity
- Anomaly detection for grid faults
- Advanced visualization dashboards
- API gateway for third-party integrations
Current Status: ✅ Fully functional with real Kaggle data, interactive dashboard, and tested scenarios.
Questions or Issues? Review the troubleshooting section or check the example scripts in the project.