update by wensicheng on 0629

This commit is contained in:
tao.chen
2026-07-01 17:46:08 +08:00
parent 0fc1c702d9
commit 2f406bd64d
12 changed files with 1012 additions and 1574 deletions
+73 -140
View File
@@ -1,165 +1,98 @@
---
name: metadata-validator
description: 当需要校验某个数据需求中候选表、字段、join 关联和时间字段是否真实存在于工作区元数据中时使用。触发词包括"validate metadata"、"check if table exists"、"field mapping"、"join key validation"、"确认表/字段"、"校验 schema"、"这个字段在哪张表"、"口径对得上吗"。递归扫描工作区中的元数据文件(JSON / Markdown / CSV / Excel / YAML / DDL / 数据字典),并产出标准化的 Validation Result 和 Field Mapping。
description: 当需要确认候选表、字段、字段归属、字段类型、时间列、分区列和 join key 是否真实存在于工作区元数据中时使用。消费 requirements-analysis 的 requirements_output,产出 validation_result 和 field_mapping;不写 SQL,不调用 MCP
---
# Metadata Validator(元数据校验器)
# Metadata Validator元数据校验
## 概述(Overview)
## 目标
本 skill 在需求的"期望表/字段"和工作区元数据中的"实际 schema"之间架起桥梁。输出会被 `logic-planner``sql-context-builder` 原样消费,二者**不得**重复校验
把需求里“想用的表和字段”与真实元数据对齐,防止模型凭感觉编表名、字段名和关联键。下游只能使用本 skill 确认过的字段映射
核心原则:**绝不臆测表名、字段名或 join 关系。** 如果某候选在元数据中无法证实存在,将其作为 `pending_question` 暴露,状态停在 `NEED_USER_CONFIRMATION`
## 输入
## 何时使用(When to Use)
**使用场景:**
- `requirements-analysis` 已经产出候选表/字段,需要确认它们在真实元数据中存在
- 用户询问"这张表/这个字段是否存在"、"表 X 的元数据在哪份文件里"、"业务字段映射到哪个物理列"
- 需要检测 join key、时间列、可用于聚合的数值列
- 即将写 SQL,必须防止出现幻觉字段名
**不要使用场景:**
- 用户已经提供并确认了精确的表名+列名 — 直接进入 `logic-planner`
- 任务是无数据仓库上下文的纯代码生成
## 输入(Inputs)
1. 来自 `requirements-analysis` 的:
- `candidate_tables`: 用户提到或隐含的表名列表
- `candidate_fields`: 业务字段名及其建议所在表
- `business_logic`: 计算逻辑的简短描述
2. 工作区元数据:当前工作目录下任何符合元数据约定的文件(见下文)
## 工作流(Workflow)
```dot
digraph metadata_validator {
"接收候选表/字段" [shape=box];
"递归扫描工作区中的元数据文件" [shape=box];
"将每个文件解析为规范化的 (table, field, type) 记录" [shape=box];
"检查候选表是否存在" [shape=box];
"检查候选字段是否在其所属表中存在" [shape=box];
"对缺失字段做模糊匹配" [shape=box];
"检测 join key 与时间列" [shape=box];
"所有检查都通过?" [shape=diamond];
"构建 Field Mapping" [shape=box];
"输出 Validation Result (VALIDATED)" [shape=box];
"输出 Validation Result (NEED_USER_CONFIRMATION)" [shape=box];
"接收候选表/字段" -> "递归扫描工作区中的元数据文件";
"递归扫描工作区中的元数据文件" -> "将每个文件解析为规范化的 (table, field, type) 记录";
"将每个文件解析为规范化的 (table, field, type) 记录" -> "检查候选表是否存在";
"检查候选表是否存在" -> "检查候选字段是否在其所属表中存在";
"检查候选字段是否在其所属表中存在" -> "对缺失字段做模糊匹配";
"对缺失字段做模糊匹配" -> "检测 join key 与时间列";
"检测 join key 与时间列" -> "所有检查都通过?";
"所有检查都通过?" -> "构建 Field Mapping" [label="yes"];
"所有检查都通过?" -> "输出 Validation Result (NEED_USER_CONFIRMATION)" [label="no"];
"构建 Field Mapping" -> "输出 Validation Result (VALIDATED)";
}
```yaml
requirements_output:
status: READY_FOR_METADATA
candidate_tables: []
candidate_fields: []
join_hints: []
metadata_files: "当前工作区中的数据字典、DDL、schema、CSV 表头、Markdown 表格、Excel 等"
```
## 元数据发现(Metadata Discovery)
如果 `requirements_output.status` 不是 `READY_FOR_METADATA`,停止并回到 `requirements-analysis`
- 递归扫描**当前工作目录**(及其所有子目录) — 不要假设存在 `metadata/` 目录
- 文件名常常形似表名(例如 `loan_order.json``customer_info.md``dim_product.csv`),但**绝不要只信任文件名** — 必须打开文件,确认里面的表标识符
- 支持的格式(按内容自动识别,不按扩展名):
- JSON / JSONL
- YAML
- Markdown 表格 / 标题
- CSV(带表头)
- Excel(`.xlsx``.xls`) — 用 `openpyxl``pandas.read_excel`
- DDL / `CREATE TABLE` 语句
- 自由形式的数据字典(解析键值行或 `field | type | comment` 表格)
- 在校验之前,先把每个文件转成规范化的记录格式:
## 元数据查找顺序
```yaml
tables:
- table: <物理表名>
source_file: <相对路径>
fields:
- name: <字段名>
type: <string|int|long|double|decimal|date|timestamp|boolean|...>
comment: <可选>
```
1. 递归查看工作区中的元数据文件,不只相信文件名。
2. 优先读取结构化文件:DDL、JSON/YAML schema、CSV/Excel 数据字典、Markdown 表格。
3. 对每张表记录证据:文件路径、表名出现位置、字段名、类型、注释、枚举。
4. 文件名只能作为线索,不能作为存在性证据。
## 校验规则(Validation Rules)
## 校验规则
**全部**以下规则都要执行。任意一条失败 ⇒ 状态为 `NEED_USER_CONFIRMATION`
- 字段在别的表里存在,不等于在目标表里存在
- 字段名相似不等于字段可替换,必须保留候选并让用户确认。
- 时间字段有多个时必须问清楚事件时间、分区时间和统计归属。
- join key 有多个候选时必须问清楚,并标注基数风险。
- 金额、数量、比率类指标要确认类型、单位和精度。
- 结果表如果要写入,必须校验目标表存在性和字段兼容性;`INSERT OVERWRITE` 还需要用户显式确认。
1. **表存在性** — 每个候选表必须出现在解析后的元数据中
2. **字段存在性** — 每个候选字段必须出现在其候选所属表中
3. **字段归属** — 字段可能存在但属于另一张表;绝不能悄悄替换
4. **类型合理性** — 聚合目标(sum / avg / count)必须为数值型;时间过滤字段必须为 date/timestamp/字符串型日期
5. **必要字段** — 如果业务逻辑中常见字段缺失(统计指标、时间、join key、维度),要标记出来
6. **模糊匹配** — 对每个缺失字段,按名称相似度打分(`customer_id` ↔ `cust_id`、`cust_no`、`customer_no`)和 Levenshtein 距离,给出 Top-N
7. **join 检测** — 在已校验的表之间,查找共享的 `*_id`、`*_no`、`*_code` 列。如果存在多个可能的 join key,必须询问
8. **时间列消歧** — 列出每张表中所有时间类字段(`create_time`、`apply_time`、`txn_date`、`update_time`、`dt`);询问哪一个决定时间粒度
9. **覆盖度** — 验证维度、指标、过滤列、排序键是否都存在
## 工作顺序
## 禁止行为(Forbidden Behaviors)
1. 整理所有候选表和候选字段。
2. 从元数据中确认表是否存在。
3. 校验字段是否存在于正确表中,并记录类型和来源。
4. 校验指标字段是否适合聚合,时间字段是否适合时间过滤。
5. 校验 join key 两边都存在,记录类型一致性和基数假设。
6. 校验分区字段、状态枚举、金额单位等会影响结果的细节。
7. 对缺失项给出证据和候选替代,不猜。
8. 如果缺表、缺字段或 join/time 不明确,停止。
| 自我说服 | 现实 |
|---|---|
| "文件名是 `loan_order.json`,肯定就是这张表" | 文件名只是提示,必须解析文件内容确认。 |
| "字段存在于某处,所以 join 没问题" | 错误的表归属会让 join 失效。永远要校验归属。 |
| "用户八成指的是 `cust_no`,直接用吧" | 必须作为候选暴露并询问,绝不能自动替换。 |
| "时间字段我猜一个就行" | 多个时间字段时必须询问。粒度决定整条查询。 |
| "这份元数据够了,不必再扫" | 永远要递归扫描。一个文件可能描述多张表。 |
## 输出契约(Output Contract)
输出是一份单一的 YAML 文档,下游 skill 原样消费。
## 输出格式
```yaml
validation_result:
validated_tables:
- <table_name>
validated_fields:
- <table_name>.<field_name>
missing_tables: []
missing_fields:
- <field_name_not_found_anywhere>
candidate_fields:
<missing_field_name>:
- <candidate_1>
- <candidate_2>
candidate_tables:
<missing_table_name>:
- <candidate_1>
join_candidates:
- left: <table_a>.<field>
right: <table_b>.<field>
confidence: <high|medium|low>
time_field_candidates:
<table_name>:
- <field>
- <field>
status: VALIDATED | NEED_USER_CONFIRMATION
metadata_sources:
- <相对路径指向元数据文件>
pending_questions:
- "<面向用户的问题,最好给出 A/B/C 选项>"
- path: "元数据文件路径"
evidence: "表/字段证据摘要"
validated_tables:
- table: "物理表名"
role: fact | dimension | lookup | target | unknown
source_file: "元数据来源"
validated_fields:
- table: "表名"
column: "字段名"
type: "字段类型"
comment: "字段注释"
source_file: "元数据来源"
field_mapping:
<business_field_name>:
table: <物理表>
column: <物理字段>
type: <数据类型>
status: <VALIDATED | NEED_USER_CONFIRMATION>
"业务字段名":
table: "物理表名"
column: "物理字段名"
type: "字段类型"
role: dimension | metric | filter | time | partition | join_key | output
source_file: "元数据来源"
confidence: high | medium | low
joins:
- left: "表A.字段"
right: "表B.字段"
type: inner | left | right | full | unknown
cardinality: "1:1 | 1:N | N:1 | N:N | unknown"
confidence: high | medium | low
time_fields:
- table: "表名"
event_time: "事件时间字段"
partition_time: "分区字段,可为空"
missing_tables: []
missing_fields: []
alternatives:
"缺失项": ["可能候选"]
pending_questions:
- "需要用户确认的问题"
```
`field_mapping` 是下游 `logic-planner` 和 `sql-context-builder` 的**唯一权威来源**。如果某个业务字段没有映射,该需求无法继续 — 把它加入 `pending_questions`。
## 停止条件
## 完成判定(Completion Criteria)
仅当**以下全部**成立时,才允许状态 `VALIDATED`:
- 每个候选表都出现在 `validated_tables` 中
- 每个候选字段都有 `field_mapping` 条目
- 所有 join key 都已确定(或显然到可以用 `high` 置信度推断)
- 查询粒度对应的时间列已确定
- `pending_questions` 为空
其余情况 ⇒ `NEED_USER_CONFIRMATION` 并停止。**不得**继续进入 `logic-planner`。
只在所有必需表、字段、join key、时间字段和目标写入字段都确认后输出 `VALIDATED`。否则输出 `NEED_USER_CONFIRMATION`