项目

一般

简介

行为

02-全局可复用模块清单 » 历史记录 » 修订 2

« 上一页 | 修订 2/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 个月 之前 · 2 修订