第 9 章 Semantic Plane:语义治理¶
本章学习目标 - 深入理解三层语义治理模型(Layer 1/2/3)与 9 类资产的设计动机 - 掌握语义资产的 Git 版本控制 + 本地 hooks + CI/CD + PR review + S3 发布 + 后台自动同步的完整端到端管道 - 理解语义治理资产如何被 R/V/G/D 四引擎运行时消费 - 掌握资产编写的快速上手与校验发布流程 - 对比 YAML 治理与 dbt 语义层 / Cube 的选型取舍 - 认清当前治理设计的工程权衡与改进方向
前置知识:第 5 章 RAG 检索(资产如何被消费)、第 2 章 整体架构(离线发布链路) 关联代码:
semantic-plane/、scripts/(CI 校验)、backend/app/agents/semantic_plane/(导入管道)、backend/app/services/semantic_sync.py(后台同步)
9.1 背景与动机¶
9.1.1 为什么需要语义治理¶
如 第 1 章 所述,NL2SQL 失败常因"同一个业务问题在不同上下文有不同答案"。语义治理就是把企业知识结构化为机器可读、可校验、可版本控制的资产,在生成 SQL 前约束 LLM。
9.1.2 治理 vs 元数据¶
普通元数据(如 information_schema)只描述"表结构是什么";语义治理还描述"这个字段在业务上意味着什么、应该怎么用、和别的字段什么关系"。后者是 LLM 无法从世界知识补全的企业特有知识——这是 TTD 把治理称为"一等公民"的原因。
9.1.3 为什么用 Git + YAML¶
语义治理资产选择 Git + YAML 而非数据库驱动,是经过权衡的决策:
| 维度 | Git + YAML(TTD) | DB-driven 元数据 |
|---|---|---|
| 版本控制 | Git 原生(每次变更有 commit、可 diff、可 revert) | 需自建审计表 |
| 协作审查 | PR Review(人类把关变更质量) | 在线编辑,审查弱 |
| 可编程性 | 高(CI 脚本自动化校验) | 中(应用层校验) |
| 冷启动 | 慢(手写 YAML) | 快(UI 编辑) |
| 离线可编辑 | 是(任何编辑器) | 否(需在线) |
TTD 选择 Git + YAML 是因为语义治理资产是高价值、低频变更、需严格审查的——这与代码的变更模式一致,适合用代码工程的方法管理(Git + CI + PR)。
9.2 设计原理¶
9.2.1 三层治理模型¶
| 层级 | 名称 | 内容 | 目录 | 解决的问题 |
|---|---|---|---|---|
| Layer 1 | Metadata Contracts | 表/列/指标定义、关联规则、Few-shot 示例 | domains/, few_shots/, join_rules/ |
"表结构是什么、指标怎么算、表之间怎么 join" |
| Layer 2 | Terminology Governance | 术语生命周期、消歧矩阵、同义词网络、术语关系 | terms/, term_relationships/ |
"GMV 到底指什么、和哪些词同义" |
| Layer 3 | Business Rules & Context | 业务规则表达式、上下文假设、约束条件 | business_rules/, business_contexts/ |
"同比的时间口径、华东区包含哪些省" |
这三层对应 ADR-12。层次清晰、职责分离,各层可独立演进。
9.2.2 9 类资产¶
| 资产类型 | 层级 | 用途 | 运行时消费 |
|---|---|---|---|
table_asset |
L1 | 表定义(含业务描述、域归属、PII 策略) | Engine V 向量检索 |
column_asset |
L1 | 列定义(含别名、数据类型、暴露策略) | Engine R+ 别名匹配、V 向量检索 |
metric_asset |
L1 | 指标定义(含 SQL 公式、源表) | Engine V 检索、规划器源表推导 |
join_rule |
L1 | 表间 join 规则 | 规划器 Steiner 树建图 |
few_shot_example |
L1 | few-shot 示例(问题→SQL) | Engine D 检索、Prompt 注入 |
business_term |
L1+2 | 术语定义(含 mapped_asset_id 绑定) | Engine R 精确匹配、术语绑定 |
term_relationship |
L2 | 术语关系(同义/反义/上下位) | Engine G 图遍历 |
business_rule |
L3 | 业务规则表达式 | Prompt 注入、护栏校验 |
business_context |
L3 | 业务上下文假设 | Prompt 注入 |
9.2.3 资产如何被运行时消费¶
| 消费方式 | 使用资产 | 引擎 | 说明 |
|---|---|---|---|
| RAG 检索 | table/column/metric/term/few-shot | Engine R/V/G | 四引擎并行检索相关资产 |
| 图遍历 | join_rule、term_relationship | Engine G | Cypher 遍历关系网 |
| 精确查找 | business_term (mapped_asset_id) | Engine R | 术语绑定强路由 |
| 规则注入 | business_rule | Prompt | 直接注入 SQL 生成 prompt |
| Few-shot 选择 | few_shot_example + 动态 few-shot | Engine D + Prompt | 历史成功案例复用 |
9.3 实现详解¶
9.3.1 目录结构¶
semantic-plane/
├── domains/ # Layer 1: table_asset(含 metrics/ 子目录)
├── terms/ # Layer 1+2: business_term
├── term_relationships/ # Layer 2: 术语关系
├── few_shots/ # Layer 1: few-shot 示例
├── join_rules/ # Layer 1: JOIN 规则
├── business_rules/ # Layer 3
├── business_contexts/ # Layer 3
└── schemas/ # 8 个 JSON Schema(资产结构定义)
9.3.2 ID 命名规范¶
资产 ID 用正则约束,确保全局唯一与可追溯:
table_asset:tbl_<domain>_<name>(如tbl_hm_fact_transaction)column_asset:col_<table>_<column>(如col_fact_txn_price)metric_asset:metric_<name>(如metric_gmv)business_term:term_<name>(如term_gmv)
9.3.3 SemVer 版本化¶
每条资产有 SemVer 版本号,CI 强制检查(check_version_bump.py):
- MAJOR:破坏性变更(如改了指标 SQL 定义)→ 触发全量重向量化
- MINOR:新增字段 → 增量更新
- PATCH:描述修正 → 不触发重向量化
9.3.4 端到端发布管道(Git → Hooks → CI → PR → S3 → 自动同步)¶
这是语义治理的核心工程链路——从业务开发编辑 YAML 到线上 RAG 索引生效的完整管道:
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#e8f0fe','primaryTextColor':'#202124','primaryBorderColor':'#1a73e8','lineColor':'#5f6368','secondaryColor':'#e0f2f1','tertiaryColor':'#f8f9fa'}}}%%
flowchart TB
subgraph Local["本地开发阶段"]
direction LR
EDIT["业务开发编辑 YAML<br/>semantic-plane/"]
HOOK["pre-commit hooks<br/>schema · sqlglot 快速校验"]
COMMIT["git commit"]
EDIT --> HOOK --> COMMIT
end
subgraph GitHub["GitHub 协作阶段"]
direction LR
PUSH["git push → 创建 PR"]
CI["GitHub Actions CI/CD<br/>4 个校验脚本自动运行"]
REVIEW["PR Review<br/>Governance Lead 审查"]
MERGE["合并到 main"]
PUSH --> CI --> REVIEW --> MERGE
end
subgraph Publish["发布阶段"]
direction LR
BUILD["build_changeset.py<br/>构建增量变更集"]
S3["自动发布到 S3<br/>语义资产快照 + manifest"]
BUILD --> S3
end
subgraph Sync["TTD 后台自动同步"]
POLL["Backend 语义层知识库<br/>定时轮询 S3 manifest hash"]
DETECT["检测到变更"]
PIPELINE["semantic_plane agent<br/>R+V+G pipeline"]
end
PIPELINE --> R["Upsert 关系表<br/>semlayer.* (Engine R)"]
PIPELINE --> G["MERGE AGE 图<br/>ttd_governance (Engine G)"]
PIPELINE --> V["生成 embedding<br/>pgvector (Engine V)"]
COMMIT --> PUSH
MERGE --> BUILD
S3 --> POLL --> DETECT --> PIPELINE
classDef bpProcess fill:#e8f0fe,stroke:#1a73e8,stroke-width:2px,color:#202124
classDef bpData fill:#e0f2f1,stroke:#0d7377,stroke-width:2px,color:#202124
classDef bpDecision fill:#fef7e0,stroke:#f9ab00,stroke-width:2px,color:#202124
classDef bpSuccess fill:#e6f4ea,stroke:#1e8e3e,stroke-width:2px,color:#202124
classDef bpInfo fill:#f3e8fd,stroke:#9334e6,stroke-width:2px,color:#202124
class EDIT,HOOK,COMMIT bpProcess
class PUSH,CI,REVIEW,MERGE bpDecision
class BUILD,S3 bpSuccess
class POLL,DETECT bpInfo
class PIPELINE bpProcess
class R,G,V bpData
阶段一:本地开发(Git 版本控制 + pre-commit hooks)¶
业务开发者在 semantic-plane/ 目录编辑 YAML 资产,使用任意 IDE。提交时触发 pre-commit hooks 做本地快速校验:
# .pre-commit-config.yaml 配置的钩子
# 1. YAML 格式校验
# 2. JSON Schema 基础校验(validate_all_yaml.py 子集)
# 3. ruff/ty 代码检查(若改了脚本)
本地 hooks 的目标是快速反馈——让开发者在提交前就发现明显错误,避免推到 CI 才失败。hooks 只跑快速校验子集,完整校验留给 CI。
阶段二:GitHub 协作(CI/CD + PR Review)¶
git push 后创建 PR,触发 GitHub Actions CI/CD 自动运行 4 个校验脚本:
| CI 脚本 | 作用 | 失败处理 |
|---|---|---|
validate_all_yaml.py |
JSON Schema 校验所有 YAML(结构完整性) | 阻断 PR merge |
validate_sql_definitions.py |
metric_asset 的 SQL 语法验证(用 sqlglot 解析) | 阻断 PR merge |
validate_cross_layer_refs.py |
跨层引用完整性(如 term 的 mapped_asset_id 是否存在) | 阻断 PR merge |
check_version_bump.py |
版本号递增检查(变更必须 bump version) | 强制 bump |
CI 通过后进入 PR Review——由 Governance Lead 审查变更质量。MAJOR 变更(如改指标定义)必须人工审批,MINOR/PATCH 可常规合并。这是人类把关语义质量的最后一道关卡。
阶段三:发布(S3)¶
PR 合并到 main 后,build_changeset.py 构建增量变更集(基于 git diff,只含变更的资产),发布到 S3:
- S3 存储语义资产快照 + manifest(含 hash、版本、时间戳)
- 增量发布减少传输量与处理时间
- 首次发布或 MAJOR 变更时用
build_full_changeset.py全量发布
阶段四:TTD 后台自动同步(S3 → RAG 索引)¶
这是"治理态到执行态"的最后一步,由 Backend 的 semantic_sync.py 服务自动完成:
- 轮询检测:Backend 后台服务定时轮询 S3 manifest hash,与本地记录对比,检测是否有变更
- 触发同步:检测到 hash 变化后,触发
semantic_planeagent(一个独立的 LangGraph 工作流) - R/V/G pipeline 执行:
- Engine R(关系表):Upsert 变更资产到
semlayer.*表(table_asset/column_asset/metric_asset 等) - Engine G(图):MERGE 变更资产到 Apache AGE
ttd_governance图(节点 + 边) - Engine V(向量):调用 DashScope text-embedding-v4 生成 embedding,写入 pgvector
*_embedding表
- Engine R(关系表):Upsert 变更资产到
- 软删除:S3 快照中缺失的资产被标记
deleted_at,不再参与检索(而非物理删除,保留可追溯) - change_log:记录同步状态(
pending → processing → completed/failed),失败自动重试
manifest hash 变化 → semantic_plane agent
├── scan_yaml(扫描变更)
├── validate(校验)
├── relational_upsert(Engine R)
├── graph_sync(Engine G)
├── generate_embeddings(Engine V)
├── record_changelog
└── cleanup_stale(软删除)
整个管道实现了"业务开发只管写 YAML,其余全自动"的体验——Git 版本控制 + hooks + CI + PR 保证质量,S3 + 后台同步保证自动生效,开发者无需手动操作数据库或重启服务。
9.3.5 快速上手(维护手册)¶
# 1. 安装依赖
uv sync
# 2. 编写/修改 YAML 资产(参考 schemas/ 下的 JSON Schema)
# 3. 本地校验(等价于 pre-commit hooks)
task sp:validate
# 4. 提交 + 推送 → 创建 PR
git add . && git commit -m "feat: add GMV metric"
git push origin feature/add-gmv
# 5. CI 自动校验 → PR Review → 合并 → 自动发布到 S3 → Backend 自动同步
资产编写 5 条约束:
- 双语必备:
_zh/_en成对(ADR-13) - PII 标注:
llm_exposure_policy: visible/masked/hidden(ADR-14) - 版本递增:任何变更必须 bump version
- 跨层引用完整:
mapped_asset_id必须指向真实存在的资产 - 质量评分:新资产需标注
quality_score,进入认证生命周期(draft → reviewed → certified → deprecated)
9.4 资产编写实战:新增"退货率"指标¶
本节以一个真实业务场景——"新增退货率指标"——展示从零编写语义资产的完整产出。假设数据团队需要支持"各品类退货率"查询。
9.4.1 业务理解¶
退货率 = 退货交易数 / 总交易数。在 H&M 数据集中,退货通过 price < 0 识别(业务规则:退货金额为负)。
9.4.2 编写资产(5 个文件)¶
1. business_rule(业务规则)¶
# file: business_rules/hm_return_rule.yaml
business_rule:
rule_id: "rule_hm_return_negative_price"
rule_name: "退货金额为负"
rule_type: "data_constraint"
description_zh: "退货交易的 price 字段为负值,正常购买为正值。"
description_en: "Return transactions have negative price; purchases have positive."
bound_assets:
- "gold_hm.fact_transaction.price"
sql_expression: "price < 0"
certification_status: "certified"
version: "1.0.0"
2. metric_asset(指标定义)¶
# file: metrics/return_rate.yaml
metric_asset:
metric_id: "met_hm_return_rate"
metric_name: "Return Rate"
business_definition_zh: >
退货率 = 退货交易数 / 总交易数。退货交易通过 price < 0 识别。
按品类分解可定位退货率上升的具体品类。
business_definition_en: >
Return rate = return count / total count. Returns identified by price < 0.
sql_definition: >
SELECT
ROUND(COUNT(*) FILTER (WHERE price < 0)::NUMERIC
/ NULLIF(COUNT(*), 0) * 100, 2) AS return_rate_pct
FROM gold_hm.fact_transaction
default_grain: "monthly"
allowed_dimensions: ["t_dat", "sales_channel_id"]
owner: "data-team@hm.com"
certification_status: "draft"
version: "1.0.0"
similar_metrics:
- metric_id: "met_hm_transaction_count"
difference: "退货率是比例指标,交易次数是绝对计数"
counter_examples:
- "退货率 ≠ 退货金额占比,前者按笔数算,后者按金额算"
common_questions:
- "各品类退货率是多少?"
- "退货率趋势如何?"
3. business_term(术语映射)¶
# file: terms/hm_return_term.yaml
business_term:
term_id: "term_hm_return_rate"
canonical_term: "退货率"
aliases: ["return rate", "退货比例", "退单率"]
term_type: "metric"
mapped_asset_id: "met_hm_return_rate"
mapped_asset_type: "metric"
confidence: 0.95
disambiguation_context: "若用户问'退货金额'则映射到 SUM(price) WHERE price < 0,非退货率"
4. join_rule(关联规则,复用已有)¶
退货率查询需 join fact_transaction 与 dim_article(按品类分解),复用已有 join_rule hm_fashion_joins.yaml 中的 fact_transaction ⟕ dim_article。
5. few_shot_example(参考示例)¶
# file: few_shots/hm_return_example.yaml
few_shot_example:
example_id: "fs_hm_return_by_category"
question: "各品类退货率是多少?"
expected_sql: >
SELECT a.index_group_name AS category,
ROUND(COUNT(*) FILTER (WHERE f.price < 0)::NUMERIC
/ NULLIF(COUNT(*), 0) * 100, 2) AS return_rate_pct
FROM gold_hm.fact_transaction f
JOIN gold_hm.dim_article a ON f.article_id = a.article_id
GROUP BY a.index_group_name
ORDER BY return_rate_pct DESC
route: "nl2sql_query"
certification_status: "approved"
9.4.3 验证与发布¶
# 1. 本地校验
ttd-publish-sp --dry-run # JSON Schema 校验 + 跨层引用检查
# 2. Git 提交
git add semantic-plane/
git commit -m "feat: add return_rate metric and term"
# 3. PR 审查 → 合并 → CI 自动发布到 S3
# 4. Backend 轮询检测到 manifest 变更 → 自动导入
# 5. 验证:提问"各品类退货率"应正确路由并生成 SQL
9.4.4 产出总结¶
新增一个业务指标需要产出 4-5 个资产文件(metric + term + rule + few_shot,join_rule 通常复用)。这体现了语义治理的前期投入——编写成本固定,但一旦发布,所有后续查询都受益(术语绑定自动路由、业务规则自动注入、few-shot 自动参考)。
9.5 方案选型对比¶
9.4.1 语义治理方案对比¶
| 维度 | TTD YAML 治理 | dbt 语义层 | Cube | DB-driven 元数据 |
|---|---|---|---|---|
| 存储 | Git YAML | dbt 项目(YAML+SQL) | Cube 配置 | 数据库表 |
| 版本控制 | Git 原生 | Git 原生 | Git | 需自建 |
| 校验 | pre-commit + CI 4 脚本 | dbt parse | Cube validator | 应用层 |
| 运行时消费 | R/V/G 检索 | 编译为 SQL | 语义层 API | 应用查询 |
| 冷启动成本 | 高(手写 YAML) | 中 | 中 | 低 |
| 发布方式 | Git+CI+PR+S3+自动同步 | dbt build | Cube refresh | 应用更新 |
| TTD 选择理由 | Git 版本控制 + 多引擎检索 + 全自动同步最契合治理诉求 |
9.4.2 Git-as-SSOT vs DB-driven¶
| 维度 | Git-as-SSOT(TTD) | DB-driven |
|---|---|---|
| 版本控制 | 强(Git commit/diff/revert) | 弱(需自建审计) |
| 协作 | PR Review | 在线编辑 |
| 冷启动 | 慢(写 YAML) | 快(UI 编辑) |
| 可编程性 | 高(CI 自动化) | 中 |
| 适合 | 高价值、低频变更、需审查 | 低价值、高频变更、快速迭代 |
当前实现可改进之处
- 资产类型冗余(9 类):对新手偏多,冷启动成本高。生产中数百张表时,手写 YAML 不可持续。改进:提供 CLI 脚手架 + LLM 辅助补全(从 schema 自动生成候选资产 + 业务描述候选,人工只校验),合并使用频率低的资产类型。
- 缺在线编辑:所有资产必须 Git 编辑 + PR,对非技术 Data Steward 不友好。改进:Admin Panel 增加资产在线编辑 + 提交 PR 的能力,降低协作门槛。
- 版本治理靠 CI 较重:每次变更需过 4 个 CI 校验脚本,开发反馈慢。改进:本地
task sp:validate快速反馈,CI 只做最终门控;增量校验只跑变更相关的子集。 - 同步是轮询式非事件驱动:Backend 定时轮询 S3 manifest hash,有延迟。改进:S3 事件通知 → webhook → Backend 立即同步,将一致性窗口压缩到秒级。
改进方向
语义治理的演进方向是降低冷启动成本 + 提升协作效率 + 实时同步。短期:CLI 脚手架 + LLM 辅助生成候选资产、S3 事件驱动同步。长期:在线编辑 + 自动认证(LLM 评估资产质量,高分自动认证,低分人工审核),让治理资产像代码一样可协作但更易上手。
9.6 小结与延伸阅读¶
本章要点:
- 三层治理模型:L1 元数据契约 / L2 术语治理 / L3 业务规则,9 类资产。
- 端到端发布管道:Git 版本控制 → pre-commit hooks 本地校验 → GitHub Actions CI/CD 4 脚本 → PR Review 审批 → 合并后自动发布到 S3 → Backend 后台轮询检测变更 → 自动执行 R/V/G pipeline 同步索引到各 RAG 存储。
- 资产经 R/V/G/D 四引擎检索消费,术语绑定贯穿全管道。
- SemVer 版本化 + 双语必备 + PII 分级是核心规范。
- "业务开发只管写 YAML,其余全自动"——Git+CI+PR 保证质量,S3+后台同步保证自动生效。
延伸阅读:
- dbt 语义层 — docs.getdbt.com/docs/build/about-semantic-layer
- Cube 语义层 — cube.dev/docs/data-modeling
- GitOps 原理 — opengitops.dev
下一章:第 10 章 Data Plane:数据执行环境——PG Supernode、pg_mooncake、MinIO 与 H&M 测试数据集。