Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 1. Base image
FROM python:3.11-slim

# 2. Set working directory
WORKDIR /app

# 3. Install system dependencies (Fixes the phik/CMake error)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
gcc \
g++ \
cmake \
&& rm -rf /var/lib/apt/lists/*

# 4. Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt

# 5. Copy application code
COPY ./app ./app

# 6. Run the app
#CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,24 @@
# AI-Energy-Sandbox
This is a sandbox repo for energy domain AI model experimentation
This repository provides an implementation of a robustness and reliability evaluation for energy forecasting models, aligned with the requirements of the EU AI Act. The model is evaluated using the Giskard module. A detailed description of the implemented tests and their mapping to relevant EU AI Act requirements can be found in `app/main.py`.

---

# Deployment
To deploy the servie - run the following command; it will be avalible at `http://0.0.0.0:8501`
```bash
docker-compose up --build
```

---

# Using the Dashboard
The Dashboard is orginized by chosing existing submission_id or typying a new one. For now, only xgboost or torch models are avaliable. On the main tab, there is a box to submit checkpoint of a model (xgboost or torch). Examples of models and datasets for these three types can be found in example_xgboost, example_torch folders and in demonstration_preparation.ipynb file . To submit data, choice your dataframe saved as csv file and select target columns. To generate reports of model and data, switch to correspinding tab, configure ieeebus39 if needed and push the button.

---

# Demonstration Data
The repository includes example files demonstrating the full workflow. The sample dataset corresponds to electricity consumption forecasting for a new england zone, based on data from:

> [https://www.iso-ne.com/isoexpress/web/reports/load-and-demand/-/tree/zone-info](https://www.iso-ne.com/isoexpress/web/reports/load-and-demand/-/tree/zone-info)

This example illustrates how the system can be used to assess energy forecasting models under regulatory-oriented robustness and reliability criteria. The data and checkpoints for models are stored in example_xgboost and example_torch folders.
Empty file added app/__init__.py
Empty file.
148 changes: 148 additions & 0 deletions app/ieee_bus_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import giskard
from typing import Any, List, Optional
import pandas as pd
from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum
from giskard.scanner.issues import Issue
import numpy as np

class IssueLevel(str, Enum):
MAJOR = "major"
MEDIUM = "medium"
MINOR = "minor"


@dataclass(frozen=True)
class IssueGroup:
name: str
description: str

class IssueLevel(str, Enum):
MAJOR = "major"
MEDIUM = "medium"
MINOR = "minor"

Non_convergence = IssueGroup(
name = 'Non convergence',
description= 'Iterative Newton method did not converge for some input loads'
)


Line_overload = IssueGroup(
name = 'Line overload',
description= 'Some lines are overloaded'
)


Trans_overload = IssueGroup(
name = 'Transformer overload',
description= 'Some transformers are overloaded'
)

Voltage_viol = IssueGroup(
name = 'Volatge Violations',
description= 'Some buses have too low or too high voltage'
)


def test_ieeebus(model_forecasting, model_ieee, dataset_system_load):
"""This function tests the forecasting model by running power flow simulations on the IEEE 39-bus system for the predicted loads.
It checks for convergence, line overloads, transformer overloads, and voltage violations, and returns a list of issues found.
"""
loads = model_forecasting.predict(dataset_system_load).prediction
print(loads)
model_ieee.predict(loads)
results = model_ieee.results
Issues = []

not_converged_input_loads = []
for i in range(len(results)):
if results[i] is None:
not_converged_input_loads.append(i)
if len(not_converged_input_loads) > 0:
examples_df = pd.DataFrame({'input_loads': loads[not_converged_input_loads].reshape(-1)})
Issues.append(
Issue(
model_forecasting,
dataset_system_load,
Non_convergence,
IssueLevel.MAJOR,
description = f'Newton-raphson method did not converge.',
examples = examples_df)
)

line_overloads = []
for i in range(len(results)):
if results[i] is not None and sum(results[i]['over_line'] > 100):
line_overloads.append(i)

if len(line_overloads) > 0:
examples_df = pd.DataFrame(
{
'input_loads': loads[line_overloads].reshape(-1),
'overloaded_lines': [model_ieee.model.line.index[results[i]['over_line'] > 100].tolist() for i in line_overloads]
}
)
Issues.append(
Issue(
model_forecasting,
dataset_system_load,
Line_overload,
IssueLevel.MAJOR,
description = f'Some lines are overloaded.',
examples = examples_df)
)

trans_overloads = []
for i in range(len(results)):
if results[i] is not None and sum(results[i]['over_trans'] > 100):
trans_overloads.append(i)

if len(line_overloads) > 0:
examples_df = pd.DataFrame(
{
'input_loads': loads[trans_overloads].reshape(-1),
'overloaded_transformers': [model_ieee.model.trafo.index[results[i]['over_trans'] > 100].tolist() for i in trans_overloads]
}
)
Issues.append(
Issue(
model_forecasting,
dataset_system_load,
Trans_overload,
IssueLevel.MAJOR,
description = f'Some transformers are overloaded.',
examples = examples_df)
)

voltage_viloations = []
max_vm = np.array(model_ieee.model.bus["max_vm_pu"].tolist())
min_vm = np.array(model_ieee.model.bus["min_vm_pu"].tolist())

for i in range(len(results)):
if results[i] is not None and (sum(results[i]['vm'] > max_vm) or sum(results[i]['vm'] < min_vm)):
voltage_viloations.append(i)

if len(line_overloads) > 0:
examples_df = pd.DataFrame(
{
'input_loads': loads[voltage_viloations].reshape(-1),
'buses_violated_voltage': [model_ieee.model.bus.index[(results[i]['vm'] > max_vm) | (results[i]['vm'] < min_vm)].tolist() for i in voltage_viloations]
}
)
Issues.append(
Issue(
model_forecasting,
dataset_system_load,
Voltage_viol,
IssueLevel.MAJOR,
description = f'Some buses have too low or too high voltage.',
examples = examples_df)
)


return Issues



Loading