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