$npx -y skills add QFIN-tech/model-evo --skill feature-matching从 Spark 现成宽表拉取样本+特征+标签,生成 spark-submit 提交脚本,用户确认后由本 skill 自动提交集群,落本地 sample.parquet;或在 local_file 模式下从本地 parquet/csv 直接转写+派生 feature-list.csv。当用户要"取数""拉样本""拉宽表""准备建模样本"时使用。
| 1 | # feature-matching |
| 2 | |
| 3 | > 取数 skill:配置一份样本+特征清单 → 生成 spark-submit 提交脚本 → 用户确认后由本 skill 自动提交集群 → 落本地 `sample.parquet`;或在 local_file 模式下从本地 parquet/csv 直接转写为 `sample.parquet` + 派生 `feature-list.csv`。所有产物落到 `<session_dir>/sample-features/feature-matching/`。 |
| 4 | |
| 5 | ## 1. 输入依赖 |
| 6 | |
| 7 | | 输入 | 必选 | 来源 | 说明 | |
| 8 | |---|:---:|---|---| |
| 9 | | `session_dir` | ✅ | CLAUDE.md 会话约定(`runs/<timestamp>-<model_name>`) | 只在 CLI 上拼接,不写进任何 yaml/csv,保持配置可移植 | |
| 10 | | `model_name` | ✅ | 用户输入 / task-spec 文档 | 模型简称,由 task-spec 阶段确认 | |
| 11 | | 样本表 `sample_table` | spark 模式 ✅ | task-spec 文档 > 其他上游 md > 交互询问 | 库.表;拼接模式下为提供 label + 主键的主表 | |
| 12 | | 特征表 `feature_table` | 否 | 同上 | 传时启用样本表⋈特征表拼接模式 | |
| 13 | | 取数窗口 `fetch_dt` | spark 模式 ✅ | 同上 | `[起, 止]` 两元素列表,8 位 `YYYYMMDD` | |
| 14 | | 标签 `label_col` / `label_expr` | ✅(至少一个) | 同上 | `label_expr` 非空时替代 `label_col`(`config_io.validate_common` 校验) | |
| 15 | | HDFS 中间路径 `hdfs_base` | spark 模式 ✅ | task-spec 文档 > 交互询问,**必须回显确认**(见 `references/interaction-conventions.md`) | 留空会把本地路径误当 HDFS 写 → 权限错误 | |
| 16 | | 特征清单 | 否 | 三档来源优先级:yaml `features` > `feature_list_source` 文件 > 按 `model-knowledge/assets/feature-knowledge/feature-knowledge.md` 索引自动识别(feature_table 优先/business_domain 兜底) | 单表模式必须指定 `features`;拼接模式可留空=取特征表全部列 | |
| 17 | | 本地 parquet / csv | local_file 模式 ✅ | 用户提供 / 上游 orchestration 透传 | 预组装好的本地 parquet 或 csv(含 `id_cols + label_col + dt_col + features`);csv 输入会被读后转写为 sample.parquet,输出统一 parquet | |
| 18 | |
| 19 | **入参来源优先级**:`classification-model-task-spec` 规格文档 > 其他上游 markdown(`classification-model-recommend` 的 `reports/{model_id}_*.md`、`classification-model-training` 的 run `report.md` 等)> 交互询问用户。task-spec 规格文档字段契约: |
| 20 | |
| 21 | | 文档字段 | 映射到 | 示例 | |
| 22 | |---|---|---| |
| 23 | | 样本表 | `model.sample_table` | `<db>.<sample_table>` | |
| 24 | | 特征表 | `model.feature_table` | `<db>.<feature_table>` | |
| 25 | | join-key | `model.join_keys` | `user_no, pday` | |
| 26 | | 特征列 | `model.features` / 留空取全列 | 清单 或 "全部" | |
| 27 | | label 列 | `model.label_col` | `label` | |
| 28 | | 取数窗口 | `model.fetch_dt` | `20260312 ~ 20260524` | |
| 29 | | HDFS 中间路径 | `spark_submit.hdfs_base` | `/user/{用户}/feature-matching` | |
| 30 | |
| 31 | 本 skill 支持两种取数模式,由 `--feature-table` 参数决定: |
| 32 | |
| 33 | 1. **单表模式**(默认): 仅传 `--sample-table` 一张宽表,直接取 `features + label`。 |
| 34 | 2. **样本表⋈特征表模式**: 额外传 `--feature-table` 时启用。样本表(`--sample-table`,提供 label + 主键)为主,LEFT JOIN 特征表(`--feature-table`,提供特征)。 |
| 35 | - `--features` 留空 + 无 `--feature-list-source` → 取**特征表全部列**(`b.* EXCEPT (join_keys)`) |
| 36 | - 指定 `--features f0,f1,...` → 只取特征表中这些列 |
| 37 | - 拼接键 `--join-keys`(默认 `user_no,pday`) |
| 38 | |
| 39 | ## 2. 执行命令 |
| 40 | |
| 41 | `<skill_dir>` 指本 skill 所在目录(即本文件所在目录),执行时替换为实际绝对路径,不要依赖当前工作目录。 |
| 42 | |
| 43 | ### 2.0 驾驶模式感知(进入 skill 首要动作) |
| 44 | |
| 45 | 进入本 skill 后,**首要动作是读** `<session_dir>/task-spec/_manifest.json` 的 `driving_mode` 字段,按其取值调整交互约定与默认值。字段定义、关键词检测、`auto`/`manual` 各阶段行为、本 skill 的具体跳过项与默认值(jion-key / 特征清单 / HDFS 路径 / feature_lag_day)详见 [../classification-model-orchestration/references/driving-mode.md](../classification-model-orchestration/references/driving-mode.md) 第 6.3 节。本 skill 是 `driving_mode` 的**消费者**,不改字段。 |
| 46 | |
| 47 | 本 skill 有两条互斥的执行分支:**2.1 spark 提交模式**(从 Spark 宽表取数)与 **2.2 mode=local_file 模式**(本地 parquet/csv 直接转写+派生,跳过 spark-submit)。走哪条分支由 `--mode`(默认 `spark`)决定。 |
| 48 | |
| 49 | ### 2.1 spark 提交模式 |
| 50 | |
| 51 | 两步法:① `fetch_sample.py` 不带 `--submit` 生成 spark-submit wrapper;② 用户确认后加 `--submit` 提交集群。完整两步命令、`--submit` 行为、特征清单三档来源、⚠️ Bash 工具超时提醒详见 `references/spark-workflow.md`。 |
| 52 | |
| 53 | ### 2.2 mode=local_file 模式(本地 parquet/csv,跳过 spark-submit) |
| 54 | |
| 55 | 当用户已有预组装好的本地 parquet 或 csv(含 `id_cols + label_col + dt_col + features`),或上游 `classification-model-orchestration` 在第零步 B 选择"本地样本"透传 `mode=local_file` 标记时,走此分支,**只做"转写为 sample.parquet + 派生 feature-list.csv"两件事,不走 spark-submit**: |
| 56 | |
| 57 | ```bash |
| 58 | python <skill_dir>/scripts/fetch_sample.py \ |
| 59 | --session-dir <session_dir> \ |
| 60 | --model-name <model_name> \ |
| 61 | --mode local_file \ |
| 62 | --local-parquet-path <local_sample.parquet | local_sample.csv> \ |
| 63 | [--features f0,f1,f2 | --no-filter-feas] |
| 64 | ``` |
| 65 | |
| 66 | **脚本行为**: |
| 67 | - 跳过 `gen_fetch_command.build_command`,不生成 spark-submit wrapper 脚本 |
| 68 | - 输入 `.parquet` → `shutil.copyfile` 直接复制为 `sample.parquet`;输入 `.csv` → `pandas.read_csv` 读后 `to_parquet` 转写为 `sample.parquet` |
| 69 | - 调 `derive_feature_list.py` 派生 `feature-list.csv`:`exclude_cols = id_cols + dt_col + label_col + join_keys`;默认按 `feature-knowledge.md` 索引自动识别的清单过滤(`--filter <识别到的csv>`);`--no-filter-feas` 或未识别到时派生全量列 |
| 70 | - 落 yaml 到 `<session_dir>/sample-features/feature-matching/sample_config.<model_name>.yaml`,含 `model.mode="local_file"`、`model.sample_table="local_file"`(占位)、`model.local_parquet_path=<path>`、`spark_submit.hdfs_base=""` |
| 71 | |
| 72 | **local_file 模式下参数语义**(与 spark 模式的差异): |
| 73 | - `--sample-table / --fetch-start / --fetch-end / --feature-table / --join-keys` 均可选(仅记录用,不强制) |
| 74 | - `--submit` 在 local_file 模式下无效(转写+派生已在脚本内同步完成,无需提交集群) |
| 75 | - `--features` 留空时,`feature-list.csv` 派生用 sample 全列减去 exclude_cols |
| 76 | - `--local-parquet-path` 接受 `.parquet` / `.csv`,其他扩展名报错终止 |
| 77 | |
| 78 | **与 spark 模式的产物布局一致**: local_file 模式产出的 `sample.parquet` + `feature-list.csv` 落在 `<sessio |