项目

一般

简介

02-全局可复用模块清单 » 历史记录 » 版本 3

Huarui Lin, 2026-04-24 13:14

1 1 Huarui Lin
# 全局清单
2
3
### 一、 全局可复用模块清单 (DRY 原则绝对落地)
4
为了防止几千行代码中出现逻辑分叉导致静默 Bug,以下 4 个模块必须在工程中作为**单一真实来源** 被各阶段强依赖调用。
5
6
| 模块契约名 | 物理路径映射 |
7
| :--- | :--- |
8
| `core.physical_storage_contract` | `src/core/storage/contract.py` |
9
| `core.stream_engine` | `src/core/stream/engine.py` |
10
| `core.standardization_math` | `src/core/math/zscore.py` |
11
| `core.duckdb_time_aligner` | `src/core/sql/aligner.py` |
12 3 Huarui Lin
| `core.telemetry` | `src/core/telemetry.py` |
13 1 Huarui Lin
14
#### 1. `core.physical_storage_contract` (物理存储死锁契约)
15
**被依赖方**:S2, S3, S4, S5.1 参数落盘。
16
**核心职责**:封装所有 Polars 的 `sink_parquet` 动作。
17
*   **强制入参**:`df`, `target_path`, `partition_cols=None` (可选按年拆分)。
18
*   **内部死锁逻辑**:无论传入什么,最终执行前必定被强制注入 `.sort(by=["net_value_date", "fund_id"], maintain_order=False)`,必定注入 `row_group_size=100000`, `compression="zstd"`, `compression_level=7`。任何业务侧企图绕过此模块直接调用 `.write_parquet()` 的代码,必须在 Code Review 中被一票否决。
19
#### 2. `core.stream_engine` (按年流式安全池引擎)
20
**被依赖方**:S2 长缺失切断、S3 特征计算、S5 Spearman 共线性。
21
**核心职责**:封装“年份外层循环 + 内存安全断言 + 释放”的拓扑。
22
*   **核心方法**:`stream_by_year(file_pattern, process_year_func)`
23
*   **内部死锁逻辑**:内部执行年份循环,读取单年数据后,**强制断言内存峰值 < 3GB**(通过 `psutil` 轮询采样),执行业务传入的 `process_year_func`,执行完毕后强制 `del` 释放,进入下一年。彻底杜绝业务侧忘记释放内存导致的 cgroup 击穿。
24
#### 3. `core.standardization_math` (标准化纯数学内核)
25
**被依赖方**:S5 训练前标准化、S6 推理服务。
26
**核心职责**:提供与语言/框架无关的绝对一致的 Z-Score 转换逻辑。
27
*   **核心方法**:`apply_zscore(feature_matrix, param_matrix)` -`standardized_matrix`
28
*   **内部死锁逻辑**:
29
    *   接收的输入形状被抽象为 `(N, 38)`(S5 N=3000万,S6 N=1000)。
30
    *   内部强制执行 **IEEE 754 除零拦截**(`std == 0 -None`)。
31
    *   内部强制执行 **MAD 裁剪**(`clip(lower, upper)`)。
32
    *   **复用意义**:S5 训练和 S6 推理绝对共用这一段底层 NumPy 广播逻辑,从数学根源上抹除“训练分布与推理分布不一致”的终极灾难。
33
#### 4. `core.duckdb_time_aligner` (DuckDB 无状态对齐器)
34
**被依赖方**:S2 粗筛阶段。
35
**核心职责**:生成唯一合法的 SQL 片段。
36
*   **核心方法**:`get_week_alignment_sql(date_col)`
37
*   **内部死锁逻辑**:返回硬编码的纯数学整数除法 SQL 实体:`DATE '1970-01-05' + ((CAST(col AS BIGINT) - CAST(DATE '1970-01-05' AS BIGINT)) / 7) * 7`。彻底封杀任何地方手写字符串拼接日期函数的可能。
38 3 Huarui Lin
39
#### 5. `core.telemetry` (结构化性能遥测内核)
40
**被依赖方**:`scripts/run_offline_pipeline.py` 统筹调用的所有业务 Step 入口函数。
41
**核心职责**:提供零侵入的性能打点装饰器。
42
* **核心方法**:`profile_step(step_name: str)` 装饰器工厂。
43
* **内部死锁逻辑**:
44
  * 强制捕获函数执行前后的 `time.perf_counter` 绝对耗时。
45
  * 强制通过 `psutil.Process().memory_info().rss` 采样首尾内存,计算峰值。
46
  * 强制将结果序列化为 JSON 并输出至 `stderr`,严禁污染业务数据 `stdout`。
47
  * **绝对封杀**:严禁在此模块内引入任何高频 CPU 采样逻辑(防 GIL 抢锁悖论),严禁调用 `gc.collect()`(防 mimalloc STW)。
48
49 1 Huarui Lin
---
50 3 Huarui Lin
51 1 Huarui Lin
### 二、 企业级 CI/CD 强制红线清单 (阻断交付)
52
以下检查项必须作为 Git Pre-commit Hook 或 GitHub Actions 流水线的绝对门禁。任何一条不通过,严禁合并入主分支。
53
#### 红线 1:Pandas 零容忍扫描 (AST 静态分析)
54
*   **实施手段**:在 CI 中引入 Python 的 `ast` 模块扫描所有 `.py` 文件的抽象语法树。
55
*   **拦截逻辑**:如果发现 `import pandas` 或 `from pandas` 的节点,直接报错 `FATAL: Pandas dependency detected. Pipeline corrupted.`。
56
*   **防御目标**:防止研发在局部图方便引入 Pandas,破坏 Polars 全局 Lazy 优化图。
57
#### 红线 2:Schema 对称差拦截 (Pydantic 运行时单测)
58
*   **实施手段**:在 `tests/test_schema_symmetry.py` 中,硬编码 38 维特征名字符串集合,以及 S2(5列)、S3(42列)、S4(4列) 的长度要求。
59
*   **拦截逻辑**:在 CI 中拉起一个极小的 Mock 数据流,跑完 S2->S3->S4 的主流程骨架,在产出节点使用 Pydantic 强校验 `df.columns` 与硬编码集合的**对称差集**。差集如果不为空,直接 `pytest.exit("Schema Drift Detected!")`。
60
#### 红线 3:EWM / OLS 金色单测 (精度基线死锁)
61
*   **实施手段**:使用 NumPy 预生成一组包含精确已知输出的基准时序数据(如纯线性递增序列、已知频率的正弦波),保存在 `.npy` 文件中。
62
*   **拦截逻辑**:CI 单测中调用我们手写的 `scipy.signal.lfilter` (EWM) 与纯标量展开式 (OLS),比对输出结果与 `.npy` 基线。允许的浮点误差死锁为 `1e-7`。一旦底层库升级导致精度漂移越过此阈值,直接阻断流水线。
63
#### 红线 4:工程治理正则扫描 (魔法数字猎手)
64
*   **实施手段**:使用 `grep -En "(1\.4826|0\.90|maintain_order=True|gc\.collect|partition_by\(as_dict=True\))" src/`。
65
*   **拦截逻辑**:
66
    *   `1.4826` 必须来自 `config.yaml`。
67
    *   `maintain_order=True` 违反 Radix Sort 红线。
68
    *   `gc.collect()` 违反 mimalloc 红线。
69
    *   `partition_by(as_dict=True)` 在非安全池内触发 OOM 红线。
70
    *   命中任何一条,CI 直接失败。
71
---
72 2 Huarui Lin
73 1 Huarui Lin
### 三、 系统最终交付物理清单
74
当你完成所有开发后,产出的工程目录中必须严格包含以下物理文件,缺一不可:
75 2 Huarui Lin
76 1 Huarui Lin
**【数据湖层】**
77 2 Huarui Lin
78 1 Huarui Lin
*   `s2_{year}.parquet` (按年拆分,Zstd7,Row Group=10万,严格5列)
79
*   `s3_{year}.parquet` (按年拆分,Zstd7,严格42列)
80
*   `s4_{year}.parquet` (按年拆分,Zstd7,严格4列)
81 2 Huarui Lin
82 1 Huarui Lin
**【模型与参数层】**
83 2 Huarui Lin
84 1 Huarui Lin
*   `standardization_params_wide.parquet` (S5 训练专用,宽表形态,已 shift(1))
85
*   `standardization_params.parquet` (S6 推理专用,长表形态,已自然日 Ffill,已按 `["feature_name", "date"]` 物理排序)
86
*   `model.txt` (LightGBM LambdaRank 最终重训模型实体)
87 2 Huarui Lin
88 1 Huarui Lin
**【微服务层】**
89 2 Huarui Lin
90 1 Huarui Lin
*   `s6_inference/` (独立 FastAPI 仓库或目录,内含 `main.py`,启动即加载全局变量,接收 `(N, 38)` 矩阵,吐出 `N` 维得分)
91 2 Huarui Lin
92 1 Huarui Lin
**【配置与红线层】**
93 2 Huarui Lin
94 1 Huarui Lin
*   `config.yaml` (业务可配:MAD系数、共线性阈值、Spearman模式)
95
*   `core/constants.py` (物理死锁:52周、1970基准日、Parquet压缩级别)
96
*   `.github/workflows/ci.yml` (集成上述四大红线拦截器)
97
*   `configs/config.yaml` (业务超参唯一真实来源,含 D-1 白名单与 MAD 系数)。
98 2 Huarui Lin
99 1 Huarui Lin
---
100
**全链路拆解完毕。** 
101 2 Huarui Lin
102 1 Huarui Lin
从 S0 脚手架到 S6 矩阵推理,从 DuckDB 纯数学偏移到 50GB cgroup 下的微线程 GIL 防线,这套拓扑没有留下任何“自作聪明”的余地。你可以直接将这 5 个阶段的拆解发给研发团队作为**史诗级需求的最细粒度 Task 拆解**开始排期。