atharvadevne123/Energy-Oracle

GitHub: atharvadevne123/Energy-Oracle

基于 LightGBM 集成模型的实时区域能耗预测 API,集成特征工程、漂移检测与自动重训练,提供生产级部署能力。

Stars: 0 | Forks: 0

# Energy-Oracle [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/39/39faa54be350a1dab8afd3b2fb8c1c83e4d9cff84abfef2374d19a18053687c4.svg)](https://github.com/atharvadevne123/Energy-Oracle/actions/workflows/ci.yml) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://python.org) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![FastAPI](https://img.shields.io/badge/FastAPI-0.115-009688.svg)](https://fastapi.tiangolo.com) [![LightGBM](https://img.shields.io/badge/LightGBM-4.5-orange.svg)](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 日志 | ## 架构 ![Architecture](https://static.pigsec.cn/wp-content/uploads/repos/cas/06/063851304e3981107d74d1074786d0bb466159b8261ea32770a249e0a46b52d9.png) ## 快速开始 ### 本地运行 (不使用 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, 数据漂移检测, 时间序列预测, 机器学习, 测试用例, 能耗预测, 请求拦截, 逆向工具