跳转至

第 3 章 关键设计决策(ADR)

本章学习目标 - 理解 TTD 18 个关键架构决策的上下文、选择与后果 - 对每个决策掌握"反思与改进方向",理解哪些是主流实践、哪些是工程权衡 - 学会用 ADR 格式记录架构决策,便于在自己的项目中复用

前置知识第 2 章 整体架构 关联代码:散布于 backend/semantic-plane/data-plane/scripts/


决策总览

ADR 决策名称 影响范围
ADR-1 双面板分离 (Two-Plane Separation) 整体架构
ADR-2 R/V/G 三引擎架构 (Triple-Engine) 数据存储
ADR-3 Supervisor 轻量化 Agent 编排
ADR-4 显式路由决策 (Explicit Routing) Agent 编排
ADR-5 SQL 护栏五层验证 安全
ADR-6 Chat-First API 迁移 API 层
ADR-7 多模型注册与降级链 模型层
ADR-8 语义版本化元数据 治理流程
ADR-9 双数据库连接池 运行时
ADR-10 SQL-Only 缓存策略 性能
ADR-11 治理叠加层 (Governance Overlays) 多租户
ADR-12 三层治理模型 元数据治理
ADR-13 双语必备 (Bilingual Requirement) 元数据规范
ADR-14 PII 分级暴露 安全与隐私
ADR-15 LLM 驱动查询分解 检索管道
ADR-16 术语绑定强路由 全管道
ADR-17 Better Auth 统一认证 认证与授权
ADR-18 语义查询规划器 (Advisory Mode) SQL 管道

ADR 稳定性评级

稳定性 含义 ADR
稳定 已固化,短期无变更计划 ADR-1(双面板)、ADR-2(三引擎)、ADR-5(五层护栏)、ADR-6(Chat-First)、ADR-8(语义版本化)、ADR-9(连接池)、ADR-12(三层治理)、ADR-13(双语)、ADR-17(Better Auth)
可能修订 有已知演进方向,但当前仍有效 ADR-3(Supervisor 回访)、ADR-4(路由反馈环)、ADR-7(嵌入维度统一)、ADR-10(缓存策略扩展)、ADR-11(RLS 硬隔离)、ADR-14(PII 策略细化)、ADR-18(规划器默认路径)
已知演进 明确计划变更 ADR-15(查询分解已部分实现)、ADR-16(术语绑定 AST 化)

ADR 决策依赖关系

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#e8f0fe','primaryTextColor':'#202124','primaryBorderColor':'#1a73e8','lineColor':'#5f6368','secondaryColor':'#e0f2f1','tertiaryColor':'#f8f9fa'}}}%%
flowchart TB
    %% 核心依赖链(治理→安全)
    ADR1[ADR-1<br/>双面板分离]
    ADR12[ADR-12<br/>三层治理模型]
    ADR16[ADR-16<br/>术语绑定强路由]
    ADR5[ADR-5<br/>SQL 五层护栏]

    %% 第一层派生
    ADR1 --> ADR2[ADR-2<br/>三引擎架构]
    ADR1 --> ADR11[ADR-11<br/>治理叠加层]
    ADR11 --> ADR12
    ADR12 --> ADR16
    ADR16 --> ADR5
    ADR12 --> ADR8[ADR-8<br/>语义版本化]

    %% 第二层派生
    ADR2 --> ADR7[ADR-7<br/>多模型注册]
    ADR7 --> ADR10[ADR-10<br/>SQL 缓存]

    %% 编排链
    ADR3[ADR-3<br/>Supervisor 轻量]
    ADR4[ADR-4<br/>显式路由]
    ADR15[ADR-15<br/>查询分解]
    ADR3 --> ADR4 --> ADR15 --> ADR16

    %% 安全链
    ADR17[ADR-17<br/>Better Auth]
    ADR14[ADR-14<br/>PII 分级暴露]
    ADR17 --> ADR14

    %% 规划器链
    ADR18[ADR-18<br/>语义规划器]
    ADR18 --> ADR5

    classDef bpSuccess  fill:#e6f4ea,stroke:#1e8e3e,stroke-width:2px,color:#202124
    classDef bpInfo     fill:#f3e8fd,stroke:#9334e6,stroke-width:2px,color:#202124
    classDef bpError    fill:#fce8e6,stroke:#d93025,stroke-width:2px,color:#202124
    classDef bpProcess  fill:#e8f0fe,stroke:#1a73e8,stroke-width:2px,color:#202124

    class ADR1,ADR12,ADR16,ADR5 bpSuccess
    class ADR2,ADR3,ADR4,ADR17 bpInfo
    class ADR7,ADR8,ADR10,ADR11,ADR14 bpProcess
    class ADR15,ADR18 bpError

关键依赖链:ADR-1(双面板)→ ADR-12(三层治理)→ ADR-16(术语绑定)→ ADR-5(五层护栏) 是治理到安全的完整链条——治理资产定义术语,术语绑定驱动检索与重排,护栏在生成后兜底校验。任何一环变更都会影响下游。

如何阅读本章

每条 ADR 包含:上下文(为什么需要决策)→ 决策(选了什么)→ 后果(正负面)→ 反思与改进方向(批判性评估)。 带 标记的决策涉及明显的工程权衡,存在已知的演进方向。


ADR-1: 双面板分离 (Two-Plane Separation)

上下文

元数据治理需要版本控制、代码审查、可追溯的变更历史;运行时查询需要低延迟、高吞吐的数据库访问。两者在迭代节奏与扩缩容策略上存在根本差异——治理是"慢节奏、高质量、人类审查",查询是"快节奏、低延迟、机器执行"。

决策

将系统拆分为两个面板:

  • Semantic Plane:治理资产以 YAML 存储在 Git,通过 pre-commit hooks + CI 校验 + PR 审查管理变更
  • Data Plane:运行时执行层,用 PostgreSQL(本地)/ Redshift(生产)提供查询

后果

正面 负面
Git 原生版本控制与审查 需要额外的同步管道
治理资产可独立于服务部署 存在短暂一致性窗口
开发者用熟悉 IDE 编辑元数据 需要 CI 校验保证 YAML 合法性

反思与改进方向

这是业界主流且正确的决策,与 dbt 的"代码即配置"理念一致。当前实现有一个不足:同步管道是单向且非实时的,从 YAML 发布到运行时生效有延迟(轮询 S3 manifest hash)。

改进方向

引入变更通知(如 S3 事件 → webhook → Backend 立即同步),将一致性窗口从"下次轮询"压缩到秒级。同时支持回滚到任意 Git commit 对应的快照。


ADR-2: R/V/G 三引擎架构 (Triple-Engine)

上下文

NL2SQL 存在三种截然不同的检索模式:精确匹配、语义召回、关系推理。单一存储引擎无法同时优化——关系库做向量检索慢、向量库做关系查询弱、图库做精确查询不顺手。

决策

采用 Relational + Vector + Graph 三引擎并存,统一部署在同一 PostgreSQL 实例(PG Supernode),外加 Engine D(动态 Few-Shot)构成完整检索能力。

引擎 技术 用途
Relational PostgreSQL 结构化 CRUD、精确查询
Vector pgvector Embedding 语义检索
Graph Apache AGE 关系图谱、路径推理
Dynamic Few-Shot pgvector 在线学习 few-shot

后果

正面 负面
每种检索模式获得最佳性能 每条资产存储多份(结构化+向量化+图化)
单一 PG 实例减少运维开销 需维护三份写入一致性
可按需组合多种检索 调试需理解三种存储模型

反思与改进方向

这是一个有争议的工程权衡。业界更常见的做法是"专用引擎":向量用 Milvus/Qdrant,图用 Neo4j,关系用 PG。把它们都塞进 PG 扩展(pgvector + AGE)的好处是运维简单、事务一致;代价是 AGE 在大规模图上的性能远不如专用图库,pgvector 的 HNSW 索引也不如专用向量库高效

但在当前规模(H&M 数据集、百级资产)下,PG Supernode 的一体化优势(单一连接池、共享事务、低运维)大于性能劣势。这是"先简单后优化"的工程策略。

改进方向

保持 PG Supernode 作为开发态"一体化"方案,但在生产态支持可选的存算分离:向量检索可切换到 Qdrant/Milvus,图推理可切换到 Neo4j。抽象出 VectorStore / GraphStore 接口,让引擎可插拔。详见 第 5 章 选型对比。


ADR-3: Supervisor 轻量化 (Lightweight Supervisor)

上下文

早期设计中 Supervisor 承载意图解析、路由、检索、生成全部逻辑,单文件超 1000 行,测试困难,修改任一功能需回归全链路。

决策

Supervisor 极轻量:只做 embedding 计算 + governance overlay 解析,然后委托 Query Understanding → Router。

后果

正面 负面
单一职责,易测试 Supervisor 对全局上下文感知弱
修改路由不影响 Supervisor 委托链变长,调试需跨节点

反思与改进方向

轻量 Supervisor 让代码清晰,但牺牲了全局上下文——Supervisor 不知道后续节点的状态,无法做跨节点的智能调度。例如,当检索结果很差时,理想情况下 Supervisor 应该能提前介入决策(换路由或要求澄清),但当前它只在入口出现一次。

改进方向

引入"Supervisor 回访"机制:在关键决策点(如检索后、SQL 生成后)让 Supervisor 或一个轻量"监督节点"评估状态,决定是否调整后续路径。这是向"自适应编排"演进的方向。


ADR-4: 显式路由决策 (Explicit Routing)

上下文

需要决定查询的执行路径。学习式路由(用 ML 分类器预测路由)更灵活但不可解释;显式映射(意图→路由表)可预测但覆盖面有限。

决策

采用 7 条显式路由(非 ML 学习),用 _INTENT_TO_ROUTE 映射表决定路径,确保可预测、可审计。

后果

正面 负面
路由决策完全可审计 无法处理预料之外的意图
新增路由只需加映射条目 意图分类错误会导致整条路径错误
无需训练数据 意图空间扩展需手动维护映射

反思与改进方向

显式路由在安全敏感场景是合理选择,但完全静态缺乏自学习。当用户意图不在预设 7 类中时,系统只能 fallback,无法自动发现新模式。

改进方向

保留显式路由作为默认,但增加"路由效果反馈环":记录每条路由的失败率与用户满意度,当某意图在某路由上频繁失败时,提示维护者考虑新增路由或调整映射。这是"确定性为主、数据驱动改进"的折中。


ADR-5: SQL 护栏五层验证

上下文

LLM 生成的 SQL 可能语法错误、含危险操作、引用不存在的列、违反术语绑定、或扫垮生产库。需要多层独立校验。

决策

五层校验:①语法解析 ②策略禁词 ③AST 列引用 ④术语绑定语义 ⑤EXPLAIN 成本估算。

后果

正面 负面
多层独立校验,纵深防御 五层串行增加延迟
每层可独立测试 层间有重复(如列校验与术语绑定)

反思与改进方向

五层护栏是安全设计的良好实践,但当前部分层用正则表达式实现(如术语绑定校验用正则匹配 wrong_table.column),脆弱且易绕过。

改进方向

将正则校验升级为基于 sqlglot AST 的结构化校验——解析 SQL 为语法树后,在树上做列引用与术语绑定检查,既准确又能处理复杂 SQL 结构(子查询、CTE、窗口函数)。详见 第 6 章


ADR-6: Chat-First API 迁移

上下文

早期 API 是单次查询式(/query + /stream),不支持多轮对话与历史管理。需要迁移到会话式 API。

决策

/api/v1/chats 为核心的 Chat-First API,SSE over POST 流式响应。

后果

正面 负面
原生支持多轮对话与历史 SSE over POST 非标准 EventSource
SSE 流式体验好 无浏览器原生自动重连

反思与改进方向

Chat-First 是正确方向。SSE over POST(而非 GET EventSource)是因为需要传 body,但牺牲了浏览器原生 EventSource 的自动重连。

改进方向

SSE 重连可考虑用 Last-Event-ID 头实现断点续传,提升弱网体验。


ADR-7: 多模型注册与降级链

上下文

不同任务(理解/生成/洞察)适合不同模型;单一模型可能不可用,需要降级。

决策

任务驱动路由(非提供商驱动),代码默认 + Admin DB 覆盖两层配置,每个模型配 Fallback 链。

当前代码默认值

Task 默认模型 Fallback
supervisor / intent_parsing / query_understanding / planner / follow_up deepseek-v4-flash qwen3.7-max → deepseek-v4-pro
sql_generation / sql_repair deepseek-v4-pro qwen3.7-max → deepseek-v4-flash
insights / visualization / sql_explanation / knowledge_qa qwen3.7-max deepseek-v4-pro → deepseek-v4-flash
Embedding text-embedding-v4(部署 schema 1024 维;builtin 默认 1536,待统一)

嵌入维度不一致

代码库存在维度不一致:backend/app/models/registry.py 的 builtin 默认值为 1536,但部署 schema(data-plane/sql/001_create_schema.sql)所有 *_embedding 表实际列为 vector(1024)。当前以部署 schema 的 1024 维为准。维度统一已列为改进项(第 16 章),详见 第 5 章 5.3.4第 10 章 Schema 深潜

版本说明

以上是 backend/app/models/registry.py 的当前代码默认值。支持 Admin DB 在线覆盖。

后果

正面 负面
按任务特性选最优模型 配置复杂度增加
Fallback 提升可用性 Fallback 模型质量可能下降

反思与改进方向

任务驱动路由是好的,但当前内置配置绑死 DashScope(DeepSeek/Qwen 都走 DashScope 的 OpenAI 兼容接口),迁移到其他供应商成本高。

改进方向

抽象 provider 层,让每个模型独立配置 provider/api_key/base_url,支持 OpenAI/Anthropic/本地模型(Ollama/vLLM)无缝切换。这也是脱离单一供应商依赖的必要演进。


ADR-8: 语义版本化元数据

上下文

元数据资产会变更,需要版本控制来判断是否需要重新向量化(MAJOR 变更触发全量重向量化)。

决策

SemVer 版本号 + CI 强制检查(check_version_bump.py),MAJOR 变更触发全量重向量化。

后果

正面 负面
变更影响可追踪 版本号管理增加心智负担
重向量化自动化 需维护 CI 校验

反思与改进方向

SemVer 对元数据是合理选择。但全量重向量化成本高,MAJOR 变更时可能影响在线服务。

改进方向

支持增量重向量化:只对变更的资产重新生成 embedding,而非全量。通过 changeset 的 diff 精确定位变更资产。


ADR-9: 双数据库连接池

上下文

ORM 操作(Admin 管理)与 raw SQL(Agent pipeline)有不同的连接需求,混用连接池会相互影响。

决策

双池分离:ORM 池(SQLAlchemy async)+ Raw 池(psycopg async)。

后果

正面 负面
互不影响,各自调优 连接数翻倍
职责清晰 需维护两套配置

反思与改进方向

这是合理的工程实践。需注意连接总数 = 实例数 × (ORM池 + Raw池),多实例时可能耗尽 PG 连接。

改进方向

引入连接池监控(已有 Prometheus 指标),根据负载动态调整池大小;或考虑用 PgBouncer 做连接复用。


ADR-10: SQL-Only 缓存策略

上下文

是否缓存查询结果?缓存结果会带来数据新鲜度问题;只缓存 SQL 则保证每次拿最新数据。

决策

只缓存生成的 SQL 文本(pgvector 相似度 ≥ 0.92 命中,TTL 15 分钟),不缓存执行结果。

后果

正面 负面
数据始终新鲜 命中缓存仍需执行 SQL
避免脏数据 对"慢查询"加速有限

反思与改进方向

这是数据敏感场景的正确取舍——宁愿慢一点也不要脏数据。但对"昨天的数据"这类低新鲜度要求的查询,可以更激进。

改进方向

引入分级缓存策略:对明确标注"可容忍 N 分钟延迟"的查询(如历史报表),可选缓存结果;对实时查询,保持 SQL-Only。让缓存策略由治理资产声明,而非全局一刀切。


ADR-11: 治理叠加层 (Governance Overlays)

上下文

多租户/多区域场景下,不同上下文需要不同的治理约束(如某租户不能看某域数据)。

决策

按 tenant/region/industry/compliance_pack 注入治理上下文,在 Supervisor 阶段一次性解析,下游共享。

后果

正面 负面
治理上下文统一 叠加层只是上下文注入
一次解析全链共享 数据库层无强制隔离

反思与改进方向

叠加层是"软治理"——靠 LLM 遵守 prompt 中的约束,不是数据库层的硬隔离。在高安全场景这不够。

改进方向

叠加 PostgreSQL Row-Level Security(RLS)做硬隔离:即使 LLM 生成越权 SQL,数据库层也会拒绝。这是从"软治理"到"纵深防御"的必要升级。


ADR-12: 三层治理模型

上下文

企业知识有不同层次:结构定义、术语消歧、业务规则。混在一起管理会混乱。

决策

三层治理:Layer 1 元数据契约 / Layer 2 术语治理 / Layer 3 业务规则与上下文。

后果

正面 负面
层次清晰,职责分离 资产类型多(9 类),学习成本高
各层可独立演进 跨层引用需 CI 校验

反思与改进方向

三层模型是合理的认知框架,但9 类资产对新手偏多。详见 第 9 章

改进方向

提供资产编写的脚手架工具(CLI 交互式生成 + LLM 辅助补全),降低冷启动成本;合并使用频率低的资产类型。


ADR-13: 双语必备 (Bilingual Requirement)

上下文

系统需支持中英双语用户与多语言 LLM 检索。

决策

所有元数据同时维护 _zh/_en 字段,CI 强制校验成对存在。

后果

正面 负面
多语言检索与展示 编写工作量翻倍
CI 保证一致性 维护两套描述易漂移

反思与改进方向

双语对国际化场景必要,但维护成本高。

改进方向

引入 LLM 辅助翻译:写一种语言,CI 自动生成另一种语言的候选,人工校验。降低双语维护成本。


ADR-14: PII 分级暴露

上下文

不同列的敏感度不同,需要对 LLM 区分暴露策略。

决策

llm_exposure_policy: visible/masked/hidden,hidden 列完全从 LLM 上下文移除(不参与 embedding)。

后果

正面 负面
PII 保护精细 需人工标注每列策略
hidden 列不泄露给 LLM masked 的脱敏样本可能误导

反思与改进方向

分级暴露是好的设计。但masked 的脱敏样本可能让 LLM 误解数据分布

改进方向

masked 策略应附带"这是脱敏样本,真实分布不同"的明确提示,避免 LLM 基于脱敏数据做错误推断。


ADR-15: LLM 驱动查询分解

上下文

早期用正则分词提取搜索关键词,语言相关、领域相关,效果差。

决策

用 LLM(复用 Query Understanding 输出)提取搜索关键词,零额外 LLM 调用。

后果

正面 负面
语言无关、领域无关 依赖 QU 的 LLM 输出质量
零额外延迟 QU 失败时无 fallback

反思与改进方向

复用 QU 输出是巧妙的优化。但 QU 失败时检索会受影响。

改进方向

保留一个轻量的正则 fallback,当 QU 输出异常时退化到正则分词,保证检索不中断。


ADR-16: 术语绑定强路由 (Term Binding Strong Routing)

上下文

术语(如"GMV")到物理列的映射需要贯穿全管道,否则 LLM 可能把"价格"引用到错误的表。

决策

mapped_asset_id 贯穿检索→重排→Prompt→护栏→自愈五层,作为强路由信号。

后果

正面 负面
术语消歧强制正确 需预先维护术语绑定
全链路可追溯 绑定错误会污染全链

反思与改进方向

这是 TTD 的核心创新点之一,显著提升了 SQL 准确性。是值得保留的好设计。

改进方向

增加术语绑定的"置信度"概念:当术语匹配模糊时,不强绑定而是提供候选,让 LLM 在约束下选择。避免错误绑定的硬污染。


ADR-17: Better Auth 统一认证

上下文

需要统一身份源,避免 Backend 维护第二套认证。

决策

Better Auth 托管在 Next.js,签发 RS256 JWT,Backend 通过 JWKS 本地验签,admin/user 两级角色。

后果

正面 负面
单一身份源 认证耦合到 Next.js
本地验签低延迟 角色模型简单(仅 admin/user)

反思与改进方向

Better Auth 是合理选择。但角色模型过简单,无 Organization/Team/RBAC。

改进方向

演进到基于角色的访问控制(RBAC)+ 资源级权限,支持多团队协作。这与 ADR-11 的 RLS 升级配套。


ADR-18: 语义查询规划器 (Advisory Mode)

上下文

纯 LLM 生成 SQL 在复杂 join 上易出错;纯确定性编译 SQL 灵活性不足。

决策

Advisory 模式:用 KMB Steiner 树做 join 路由 + 代数重写提供建议,不直接编译 SQL,而是增强 LLM 生成。失败安全回退为空。

后果

正面 负面
确定性规划 + LLM 灵活性 Advisory 太弱,LLM 可能忽略建议
失败不阻塞管道 建议采纳率难度量

反思与改进方向

Advisory 模式是务实的折中,但"建议"可能被 LLM 忽略,削弱了规划器的价值。

改进方向

两步走:短期增加"建议采纳率"指标,量化规划器效果;长期在 Phase 4 让规划器成为默认路径,LLM SQL 仅用于 fallback/repair(这与现有 Rollout 路线图一致)。详见 第 6 章


小结

本章要点

  1. 18 条 ADR 覆盖架构、编排、安全、模型、治理、性能各维度。
  2. 多数决策是业界主流实践(ADR-1/5/9/10/17),部分是工程权衡(ADR-2 三引擎一体、ADR-3 轻量 Supervisor、ADR-11 软治理、ADR-18 Advisory 模式)。
  3. 每条 ADR 都附反思与改进方向,这些改进点汇总在 第 16 章 演进路线

下一章第 4 章 Agent 编排与状态机——进入 AI Agent 内核,详解 LangGraph 图拓扑、7 路由、状态机与修复循环。