atharvadevne123/Energy-Oracle
GitHub: atharvadevne123/Energy-Oracle
基于 LightGBM 集成模型的实时区域能耗预测 API,集成特征工程、漂移检测与自动重训练,提供生产级部署能力。
Stars: 0 | Forks: 0
# Energy-Oracle
[](https://github.com/atharvadevne123/Energy-Oracle/actions/workflows/ci.yml)
[](https://python.org)
[](LICENSE)
[](https://fastapi.tiangolo.com)
[](https://lightgbm.readthedocs.io)
## 概述
Energy-Oracle 使用天气数据和时间上下文,预测四种区域类型的每小时能耗 (kWh) —— **住宅区** (residential)、**商业区** (commercial)、**工业区** (industrial) 和 **混合区** (mixed)。
**核心功能:**
| 特性 | 详情 |
|---|---|
| ML ensemble | LightGBM (70%) + RandomForest (30%) 混合 |
| Feature engineering | 26 项特征:lag, rolling, cyclical, ratio |
| Cross-validation | 5 折 CV 并进行 RMSE 跟踪 |
| Drift detection | 对 temperature, humidity, predicted_kwh 进行 KS-test |
| API | FastAPI `/predict` · `/batch` · `/health` · `/health/deep` · `/metrics` · `/drift` · `/version` |
| 存储 | 通过 SQLAlchemy 实现 SQLite (开发环境) → PostgreSQL (生产环境) |
| Retraining | Airflow DAG (每周) 并带有 RMSE 阈值守护 |
| 可观测性 | Correlation ID 追踪 · 速率限制 · 结构化 JSON 日志 |
## 架构

## 快速开始
### 本地运行 (不使用 Docker)
```
git clone https://github.com/atharvadevne123/Energy-Oracle.git
cd Energy-Oracle
pip install -r requirements.txt
cp .env.example .env
# 在合成数据上训练初始模型
make train
# 启动 API server
make run
# → http://localhost:8000/api/v1/docs
```
### Docker Compose
```
docker-compose up -d
# API: http://localhost:8000
# DB: localhost:5432 (oracle / oracle_pass)
```
## API 参考
### `POST /api/v1/predict`
预测单个区域的能耗。
**请求体:**
```
{
"zone": "residential",
"hour": 18,
"day_of_week": 1,
"temperature": 28.5,
"humidity": 62.0
}
```
**响应:**
```
{
"predicted_kwh": 31.4872,
"zone": "residential",
"hour": 18,
"day_of_week": 1,
"model_version": "1.1.0",
"correlation_id": "f4a3b2c1-..."
}
```
| 字段 | 类型 | 约束 |
|---|---|---|
| `zone` | string | `residential` \| `commercial` \| `industrial` \| `mixed` |
| `hour` | int | 0–23 |
| `day_of_week` | int | 0 (周一) – 6 (周日) |
| `temperature` | float | −20 到 50 °C |
| `humidity` | float | 0–100 % |
### `POST /api/v1/batch`
向量化批量预测,单次请求最多支持 **1 000 条记录**。所有有效记录在一次模型调用中完成评分 —— 没有逐行计算的开销。
**请求体:**
```
{
"records": [
{"zone": "residential", "hour": 8, "day_of_week": 1, "temperature": 20.0, "humidity": 55.0},
{"zone": "commercial", "hour": 12, "day_of_week": 3, "temperature": 25.0, "humidity": 60.0}
]
}
```
**响应:**
```
{
"results": [
{"zone": "residential", "predicted_kwh": 22.4, "error": null},
{"zone": "commercial", "predicted_kwh": 78.1, "error": null}
],
"total": 2,
"successful": 2
}
```
无效记录将返回 `"predicted_kwh": null` 以及非空的 `"error"` 字符串 —— 批次中的其余记录仍会成功处理。
### `GET /api/v1/health`
```
{ "status": "ok", "version": "1.1.0", "uptime_seconds": 142.3 }
```
### `GET /api/v1/health/deep`
逐组件状态检查(数据库连通性 + 模型文件是否存在)。
```
{
"status": "ok",
"uptime_seconds": 142.3,
"version": "1.0.0",
"components": {
"database": {"status": "ok"},
"model": {"status": "ok", "size_kb": 3700}
}
}
```
### `GET /api/v1/version`
```
{ "name": "Energy-Oracle", "version": "1.1.0", "model_version": "1.1.0" }
```
### `GET /api/v1/metrics`
返回模型训练指标以及近期预测的滚动摘要,包括 `kwh_p50`、`kwh_p95` 和各区域计数。
### `GET /api/v1/drift`
运行 KS-test 漂移检测。需要 ≥ 60 条已记录的预测。
## 性能
- **单次预测**:每个进程仅加载一次模型(模块级 cache)—— 后续调用会跳过 `joblib.load`。
- **批量预测**:所有记录在一次向量化的 `DataFrame` 调用中完成 —— 没有逐行的特征工程循环。
- **预测 cache**:LRU cache(512 个条目,`collections.OrderedDict`)—— 重复的相同请求零开销。
- **Zone 编码**:`LabelEncoder` 在导入时拟合一次;`encode_zone()` 仅调用 `transform()`。
- **数据库**:在 `(zone, created_at)` 上建立复合索引,以实现高效的监控查询。
## 安全
有关漏洞报告的指南,请参阅 [SECURITY.md](SECURITY.md)。
关键控制措施:
- **速率限制**:每个 IP 每分钟滑动窗口 60 次请求(可通过 `RATE_LIMIT_PER_MINUTE` 配置)
- **输入验证**:Pydantic schema + 自定义验证器会在数据到达模型之前拒绝超出范围和未知 zone 的输入
- **Correlation ID**:每个请求都带有可追踪的 `X-Correlation-ID` 标头
- **CORS**:可通过 `CORS_ORIGINS` 环境变量配置(默认:`*`)
## 特征工程
流水线从 5 个原始输入中构建 26 项特征:
```
Raw: zone · hour · day_of_week · temperature · humidity
↓
Cyclical: hour_sin/cos · dow_sin/cos
Binary: is_weekend · is_peak_hour · is_off_peak
Lag: temp_lag_1/2/3 · humidity_lag_1/2/3
Rolling: temp_rolling_mean/std (3h, 6h, 12h)
Ratio: heat_index · temp_humidity_ratio · temp_squared · temp_per_baseline
Encoded: zone_encoded (ordinal)
```
## 模型监控与漂移检测
每次预测都会记录到 `prediction_logs` 中。`/api/v1/drift` 端点会运行 KS-tests,将**参考窗口**(最近的 200 条记录减去 50 条)与**当前窗口**(最后 50 条)进行对比:
```
from scipy.stats import ks_2samp
stat, p = ks_2samp(reference, current)
drift_detected = p < 0.05
```
漂移事件会持久化存储在 `drift_events` 表中。
## 自动化重训练
```
# 运行独立重训练
python pipelines/retrain_dag.py
# 或部署为 Airflow DAG(每周计划)
airflow dags trigger energy_oracle_retrain
```
DAG 会验证重训练后的 RMSE 是否低于 `RMSE_THRESHOLD`(默认为 20.0),然后才会接受新模型。
## 开发
```
make install # install dependencies
make test # run pytest suite
make coverage # pytest with --cov and html report
make lint # ruff check + fix
make format # ruff format
make type-check # mypy static analysis
make diagram # regenerate architecture diagram
```
### 环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
| `DATABASE_URL` | `sqlite:///./energy_oracle.db` | 数据库连接字符串 |
| `MODEL_PATH` | `model.joblib` | 持久化 ensemble 的路径 |
| `METRICS_PATH` | `metrics.json` | 训练指标路径 |
| `LOG_LEVEL` | `INFO` | 日志详细级别 |
| `RATE_LIMIT_PER_MINUTE` | `60` | 每个 IP 每分钟的请求速率限制 |
| `RMSE_THRESHOLD` | `20.0` | 重训练时可接受的最大 RMSE |
| `CORS_ORIGINS` | `*` | 逗号分隔的允许 CORS 来源 |
| `MAX_BATCH_SIZE` | `1000` | 每个 `/batch` 请求的最大记录数 |
| `BLEND_ALPHA` | `0.7` | ensemble 混合中 LightGBM 的权重 |
| `ENABLE_JSON_LOGS` | `false` | 输出结构化的 JSON 日志行 |
| `DRIFT_WINDOW_SIZE` | `100` | 漂移检测中使用的最近预测记录数 |
## 许可证
MIT © Reflective Lantern
标签:Airflow, Apex, AV绕过, FastAPI, LightGBM, 数据漂移检测, 时间序列预测, 机器学习, 测试用例, 能耗预测, 请求拦截, 逆向工具