项目

一般

简介

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

Huarui Lin, 2026-04-24 19:00

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