项目

一般

简介

0006-推理收口 » 历史记录 » 版本 3

Huarui Lin, 2026-04-13 11:24

1 1 Huarui Lin
## 推理收口
2
3
作为项目收官之周,Step 6 的重心不再是算法攻坚,而是**工程闭环、接口防穿透与双轨制收尾**。
4
5
| 周次 | Story ID | Story 描述 | 规约硬性映射 | 验收标准 | 工时 |
6
|:---:|:---|:---|:---|:---|:---:|
7
| **W8** | **S6-01** | **单基金查询推理引擎(含 SHAP 全链路)**<br>实现从 CSV 到决策文本的单基金端到端推理。 | 规约 6.1/6.2;规约 6.3 (文案拼接);CR-002 (复用Step3原始特征);CR-005 (加载全局参数) | ① 输入 ≥52 周的净值 CSV,输出严格包含 4 个字段:`score`(0-100整数), `top5_positive_features`(List), `top5_negative_features`(List), `recommendation_text`(String);<br>② `score` 必须由 `round(概率 × 100)` 生成,严禁出现小数;<br>③ 文案模板严格对齐规约 6.3 四个得分区间,且必须拼接 Top 贡献特征名;<br>④ 加载 MLflow 模型时,必须显式指定过滤条件 `tags.production = "True"`。 | 2天 |
8
| **W8** | **S6-02** | **批量推荐引擎(性能隔离与降级)**<br>实现基于 DataFrame 的批量打分与排序。 | 规约 6.1 (批量输出);CR-006 (严禁SHAP/性能降级) | ① 输入包含多只基金最新净值的 DataFrame,输出按 `score` 降序排列的 DataFrame;<br>② **CI 红线拦截**:通过 AST 扫描或人工 Review 确保 `inference.py` 的批量分支中**无任何 `shap` 关键字**;<br>③ 返回的 `top_features` 列所有行必须为空字符串 `""`;<br>④ 批量 1000 只基金的端到端耗时(含特征计算+预测)应 < 3 秒。 | 1天 |
9
| **W8** | **S6-03** | **流水线端到端闭环与双轨制文档收尾**<br>验证 Docker 环境下一键运行,更新技术真相源与 Redmine 状态。 | 章程 M5 Done标准;章程成功标准(流水线闭环);架构基线 3 (双轨制) | ① 在 Ubuntu 24 Docker 环境下,通过一条主指令成功执行“全量刷盘重训 → 自动评估 → 自动归档模型”全流程,**零人工干预**;<br>② `docs/inference_api.md` 沉淀单基金/批量接口的输入输出 Schema 及 CR-006 的调用约束;<br>③ Gitea `/docs` 与 Redmine M1-M5 全部任务状态实现 100% 同步闭合。 | 2天 |
10
11
---
12
## 可优化与可复用逻辑提示
13
14
### 1. 特征计算“精简版”的接口复用(防笨重化)
15
16
Step 3 的 `calculate_raw_features` 是针对按年分区大表设计的,内部包含了 `segment_id` 的复杂隔离逻辑与按年循环。
17
但在 Step 6 推理时,输入的永远是**单只基金的小 DataFrame(通常 < 500 行)**,且 `segment_id` 必然只有 `0` 这一个值。
18
**建议实现**:在 `feature_engineering.py` 中暴露一个轻量级包装器 `calculate_raw_features_inference(df_single_fund: pl.DataFrame)`,内部直接调用核心滚动逻辑,但**跳过按年循环与 segment 隔离的开销**。这能将单基金特征计算耗时从秒级压榨到毫秒级。
19
20
### 2. MLflow 模型加载的“防穿透”硬编码
21
22
规约 5.5 提到“新模型打 Production 标签后直接替换”。
23
**防坑点**:MLflow 的 `mlflow.lightgbm.load_model("models:/model_name/latest")` 中的 `latest` 指的是**最后运行的一次 Experiment**,而不是打了 Production 标签的版本。如果在一次失败的训练后没有打标,`latest` 会指向垃圾模型。
24
**强制要求**:`inference.py` 加载模型必须使用如下严格语法:
25
```python
26
model_uri = "models:/fund_dca_model/production"
27
# 禁止使用 "latest"
28
model = mlflow.lightgbm.load_model(model_uri)
29
```
30
31
### 3. “得分区间文案”的逻辑外置
32
33
规约 6.3 的四段文案极易在后续业务迭代中被修改。建议将这四个模板(包含占位符 `{top_feature}`)统一定义在 `config/config.yaml` 的 `inference.recommendation_templates` 节点下,`inference.py` 仅负责读取配置并 `format()`,严禁在代码中硬编码大段中文文案。
34
35
---
36 2 Huarui Lin
37 1 Huarui Lin
## 新增/修改文件清单
38
39
| 操作 | 文件路径 | 简介与企业级约束 |
40
|:---:|:---|:---|
41
| **新增** | `src/inference.py` | **收官核心模块**。包含 `predict_single_fund(csv_path: str) -> dict` 与 `predict_batch(df: pl.DataFrame) -> pl.DataFrame` 两个公开接口。**全局严禁显式 import pandas**。 |
42
| **新增** | `docs/inference_api.md` | **技术真相源**。定义推理服务的契约,包含:单基金输入 CSV 格式示例、输出 JSON Schema、批量接口 DataFrame Schema,以及醒目标注 CR-006 的调用约束。 |
43
| **修改** | `src/feature_engineering.py` | 新增 `calculate_raw_features_inference()` 轻量级公开函数,专为 Step 6 单基金小数据量优化,剥离大表循环逻辑。 |
44
| **修改** | `config/config.yaml` | 在 `inference:` 节点下新增 `recommendation_templates` 字典,包含 80-100、60-79、40-59、0-39 四个区间的文案模板。 |
45
| **修改** | `docs/architecture_baseline.md` | 更新最终版数据流图,补充 Step 6 推理服务从 MLflow 拉取 Production 模型与全局参数的虚线指向。 |
46
| **修改** | `src/utils/config.py` | 对应新增 `inference.recommendation_templates` 的强类型属性。 |
47
48
---
49 3 Huarui Lin
## 下级目录
50 2 Huarui Lin
51
[[CR-006-批量推荐接口_SHAP_归因性能降级策略]]