# 项目快速上手指南 (面向新开发者) 欢迎加入项目!本指南旨在帮助你快速理解项目的核心功能、技术架构和开发流程,特别是为你(一位Java背景的开发者)提供清晰的切入点。 ## 1. 项目是做什么的?(实现了什么功能) 这是一个基于历史销售数据的 **智能销售预测系统**。 核心功能有三个,全部通过Web界面操作: 1. **模型训练**: 用户可以选择某个**药品**、某个**店铺**或**全局**数据,然后选择一种机器学习算法(如Transformer、mLSTM等)进行训练,最终生成一个预测模型。 2. **销售预测**: 使用已经训练好的模型,对未来的销量进行预测。 3. **结果可视化**: 将历史销量和预测销量在同一个图表中展示出来,方便用户直观地看到趋势。 简单来说,它就是一个 **"数据 -> 训练 -> 模型 -> 预测 -> 可视化"** 的完整闭环应用。 ## 2. 用了什么技术?(技术栈) 你可以将这个项目的技术栈与Java世界进行类比: | 层面 | 本项目技术 | Java世界类比 | 说明 | | :--- | :--- | :--- | :--- | | **后端框架** | **Flask** | Spring Boot | 一个轻量级的Web框架,用于提供API接口。 | | **前端框架** | **Vue.js** | React / Angular | 用于构建用户交互界面的现代化JavaScript框架。 | | **核心算法库** | **PyTorch** | (无直接对应) | 类似于Java的Deeplearning4j,是实现深度学习算法的核心。 | | **数据处理** | **Pandas** | (无直接对应) | Python中用于数据分析和处理的“瑞士军刀”,可以看作是内存中的强大数据表格。 | | **构建/打包** | **Vite** (前端) | Maven / Gradle | 前端项目的构建和依赖管理工具。 | | **数据库** | **SQLite** | H2 / MySQL | 一个轻量级的本地文件数据库,用于记录预测历史等。 | | **实时通信** | **Socket.IO** | WebSocket / STOMP | 用于后端在训练时向前端实时推送进度。 | ## 3. 系统架构是怎样的?(架构层级和设计) 本项目是经典的前后端分离架构,可以分为四个主要层次: ``` +------------------------------------------------------+ | 用户 (Browser) | +------------------------------------------------------+ | +------------------------------------------------------+ | 1. 前端层 (Frontend - Vue.js) | | - Views (页面组件, e.g., ProductPredictionView.vue) | | - API Calls (使用axios与后端通信) | | - Charting (使用Chart.js进行图表渲染) | +------------------------------------------------------+ | (HTTP/S, WebSocket) +------------------------------------------------------+ | 2. 后端API层 (Backend API - Flask) | | - api.py (类似Controller, 定义RESTful接口) | | - 接收请求, 验证参数, 调用业务逻辑层 | +------------------------------------------------------+ | +------------------------------------------------------+ | 3. 业务逻辑层 (Business Logic - Python) | | - core/predictor.py (类似Service层) | | - 封装核心业务, 如“根据参数选择合适的训练器” | +------------------------------------------------------+ | +------------------------------------------------------+ | 4. 数据与模型层 (Data & Model - PyTorch/Pandas) | | - trainers/*.py (具体的算法实现和训练逻辑) | | - predictors/model_predictor.py (模型加载与预测逻辑) | | - saved_models/ (存放训练好的.pth模型文件) | | - data/ (存放原始数据.parquet文件) | +------------------------------------------------------+ ``` ## 4. 关键执行流程 以最常见的“按药品预测”为例: 1. **前端**: 用户在页面上选择药品和模型,点击“预测”按钮。Vue组件通过`axios`向后端发送一个POST请求到 `/api/prediction`。 2. **API层**: `api.py` 接收到请求,像一个Controller一样,解析出药品ID、模型类型等参数。 3. **业务逻辑层**: `api.py` 调用 `core/predictor.py` 中的 `predict` 方法,将参数传递下去。这一层是业务的“调度中心”。 4. **模型层**: `core/predictor.py` 最终调用 `predictors/model_predictor.py` 中的 `load_model_and_predict` 函数。 5. **模型加载与执行**: * 根据参数在 `saved_models/` 目录下找到对应的模型文件(例如 `transformer_store_01010023_best.pth` 或 `mlstm_product_17002608_v3.pth`)。 * 加载文件,从中恢复出 **模型结构**、**模型权重** 和 **数据缩放器**。 * 准备最新的历史数据作为输入,执行预测。 * 将预测结果返回。 6. **返回与渲染**: 结果逐层返回到`api.py`,在这里被格式化为JSON,然后发送给前端。前端接收到JSON后,使用`Chart.js`将历史和预测数据画在图表上。 ## 5. 如何添加一个新的算法?(开发者指南) 这是你最可能接触到的新功能开发。假设你要添加一个名为 `NewNet` 的新算法,你需要按以下步骤操作: **目标**: 让 `NewNet` 出现在前端的“模型类型”下拉框中,并能成功训练和预测。 1. **创建训练器文件**: * 在 `server/trainers/` 目录下,复制一份现有的训练器文件(例如 `tcn_trainer.py`)并重命名为 `newnet_trainer.py`。 * 在 `newnet_trainer.py` 中: * 定义你的 `NewNet` 模型类(继承自 `torch.nn.Module`)。 * 修改 `train_..._with_tcn` 函数,将其重命名为 `train_..._with_newnet`。 * 在这个新函数里,确保实例化的是你的 `NewNet` 模型。 * **最关键的一步**: 在保存checkpoint时,确保 `config` 字典里包含了重建 `NewNet` 所需的所有超参数(比如层数、节点数等)。 * **重要开发规范:参数命名规则** 为了防止在模型加载时出现参数不匹配的错误(例如 `KeyError: 'num_layers'`),我们制定了以下命名规范: > **规则:** 对于特定于某个算法的超参数,其在 `config` 字典中的键名(key)必须以该算法的名称作为前缀或唯一标识。 **示例:** * 对于 `mLSTM` 模型的层数,键名应为 `mlstm_layers`。 * 对于 `TCN` 模型的通道数,键名可以是 `tcn_channels`。 * 对于 `Transformer` 模型的编码器层数,键名可以是 `num_encoder_layers` (因为这在Transformer语境下是明确的)。 在 **加载模型时** ([`server/predictors/model_predictor.py`](server/predictors/model_predictor.py:1)),必须使用与保存时完全一致的键名来读取这些参数。遵循此规则可以从根本上杜绝因参数名不一致导致的模型加载失败问题。 2. **注册新模型**: * 打开 `server/core/config.py` 文件。 * 找到 `SUPPORTED_MODELS` 列表。 * 在列表中添加你的新模型标识符 `'newnet'`。 3. **接入业务逻辑层 (训练)**: * 打开 `server/core/predictor.py` 文件。 * 在 `train_model` 方法中,找到 `if/elif` 模型选择逻辑。 * 添加一个新的 `elif model_type == 'newnet':` 分支,让它调用你在第一步中创建的 `train_..._with_newnet` 函数。 4. **接入模型层 (预测)**: * 打开 `server/predictors/model_predictor.py` 文件。 * 在 `load_model_and_predict` 函数中,找到 `if/elif` 模型实例化逻辑。 * 添加一个新的 `elif model_type == 'newnet':` 分支,确保它能根据 `config` 正确地创建 `NewNet` 模型实例。 5. **更新前端界面**: * 打开 `UI/src/views/training/` 和 `UI/src/views/prediction/` 目录下的相关Vue文件(如 `ProductTrainingView.vue`)。 * 找到定义模型选项的地方(通常是一个数组或对象)。 * 添加 `{ label: '新网络模型 (NewNet)', value: 'newnet' }` 这样的新选项。 完成以上步骤后,重启服务,你就可以在界面上选择并使用你的新算法了。