跳转至

第 5 章 检索增强:R/V/G/D 四引擎 RAG

本章学习目标 - 深入理解 RAG 范式演进(Naive RAG → Advanced RAG → Modular RAG)及 TTD 在其中的位置 - 掌握 TTD 的 R/V/G/D 四引擎检索架构与并行/串行协作机制 - 深度理解 Reranker 重排算法、术语绑定强路由、补偿检索(Corrective RAG)的实现 - 掌握混合检索理论(稀疏检索 + 稠密检索 + 图检索的融合) - 认清当前 RAG 实现的工程权衡与改进方向

前置知识第 4 章 Agent 编排第 9 章 Semantic Plane(资产类型) 关联代码backend/app/skills/rag.pybackend/app/skills/reranker.pybackend/app/skills/corrective_retrieval.py


5.1 背景与动机

5.1.1 为什么 NL2SQL 需要专门的 RAG

通用 RAG(如文档问答)检索的是"知识 chunks"——一段段文本,用向量相似度召回即可。而 NL2SQL 检索的是结构化元数据——表定义、列属性、指标公式、join 规则、术语映射、业务规则。这些元数据有本质不同的访问模式:

检索需求 例子 适合的引擎
精确匹配 "GMV 是什么" → 查术语定义 R(关系查询,精确)
语义模糊 "和销售相关的表" → 向量相似度 V(pgvector,模糊)
关系推理 "fact_transaction 能 join 到哪些表" G(图遍历,关系)
经验复用 "上次类似查询怎么写的" D(动态 few-shot)

单一检索引擎无法同时优化这四种模式。TTD 的解法是 R/V/G/D 四引擎并行检索 + Reranker 融合重排

5.1.2 RAG 范式演进

AI Agent 理论关联:RAG 范式演进

RAG(Retrieval-Augmented Generation)技术经历了清晰的三个范式阶段(参考 survey: arxiv.org/abs/2312.10997):

Naive RAG(朴素 RAG) - 流程:Index → Retrieve → Generate。把文档切块、向量化、检索 top-k、拼进 prompt。 - 问题:召回不准(单路向量检索)、无重排(top-k 顺序未必相关)、上下文冗余(token 浪费)、无质量评估(检索差也硬生成)。

Advanced RAG(进阶 RAG) - 改进:在检索前(pre-retrieval)做 query 改写/扩展;检索后(post-retrieval)做重排(rerank)、压缩(compress);多路召回(hybrid retrieval)。 - 代表:LlamaIndex、LangChain RAG 的标准实践。

Modular RAG(模块化 RAG) - 核心思想:把 RAG 拆为可插拔的模块——检索、路由、重排、压缩、融合、校验、自纠错。按需组合。 - 关键模块: - Router:决定是否检索、检索什么 - Fusion:多查询结果融合(如 RRF, Reciprocal Rank Fusion) - Corrective RAG (CRAG):检索后自评估,质量差时触发重新检索或改写(arxiv.org/abs/2401.15884) - Self-RAG:LLM 自主决定何时检索、检索什么、是否采纳检索结果(arxiv.org/abs/2310.11511) - 代表:Microsoft GraphRAG(文档知识图谱社区摘要)、TTD 的四引擎 RAG。

TTD 的 Engine G 与 Microsoft GraphRAG 是不同概念

两者都叫"GraphRAG"但机制完全不同:Microsoft GraphRAG 对文本文档做实体/关系抽取,构建分层知识图谱并用社区摘要回答全局问题;TTD 的 Engine G 是对人工编写的元数据资产(Table/Column/Metric/Term 节点)做 NL2Cypher 图遍历,用于 join 路径发现与术语网络推理,数据面为 Apache AGE 图 ttd_governance。下文凡提及"GraphRAG 图增强"均指 TTD 的 Engine G,详见 第 8 章 8.3.3

TTD 的位置:R+V 是 Advanced RAG 的多路召回,G 是 GraphRAG 的图增强,D 是经验复用,corrective_retrieval 是 CRAG 的工程实现,术语绑定是 NL2SQL 特有的强路由信号。横跨了 Advanced 到 Modular RAG。

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#e8f0fe','primaryTextColor':'#202124','primaryBorderColor':'#1a73e8','lineColor':'#5f6368','secondaryColor':'#e0f2f1','tertiaryColor':'#f8f9fa'}}}%%
flowchart LR
    A["朴素 RAG<br/>单向量检索<br/>Index → Retrieve → Generate"] --> B["模块化 RAG<br/>多路召回 + 重排<br/>Hybrid + RRF Fusion"]
    B --> C["GraphRAG<br/>图结构增强<br/>Knowledge Graph + Community Summary"]
    C --> D["Self-RAG / Corrective-RAG<br/>自评估 + 自纠错<br/>检索质量反馈环"]
    D --> E["TTD 四引擎 RAG<br/>R+V+G+D 融合 + 术语绑定<br/>+ Reranker + 补偿检索"]

    classDef bpProcess  fill:#e8f0fe,stroke:#1a73e8,stroke-width:2px,color:#202124
    classDef bpExternal fill:#f8f9fa,stroke:#dadce0,stroke-width:2px,color:#5f6368
    classDef bpInfo     fill:#f3e8fd,stroke:#9334e6,stroke-width:2px,color:#202124

    class A,B,C,D bpProcess
    class E bpInfo

5.2 设计原理

5.2.1 四引擎架构

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#e8f0fe','primaryTextColor':'#202124','primaryBorderColor':'#1a73e8','lineColor':'#5f6368','secondaryColor':'#e0f2f1','tertiaryColor':'#f8f9fa'}}}%%
flowchart TB
    Q["用户问题<br/>embedding + search_terms"] --> RAG["RAGRetriever<br/>检索编排器"]

    subgraph Parallel["并行检索 asyncio.gather"]
        direction LR
        E1["Engine R<br/>术语精确匹配<br/>ILIKE semlayer.business_term<br/>< 5ms"]
        E1b["Engine R+<br/>列别名字典匹配<br/>AliasDictionary<br/>< 5ms"]
        E2["Engine V<br/>向量语义召回<br/>pgvector HNSW<br/>10-50ms"]
        ED["Engine D<br/>动态 Few-Shot<br/>sim ≥ 0.95 + approved<br/>10-30ms"]
    end

    RAG --> E1
    RAG --> E1b
    RAG --> E2
    RAG --> ED

    E1 --> Merge["合并 + 术语绑定<br/>term_bindings<br/>贯穿全管道"]
    E1b --> Merge
    E2 --> Merge
    ED --> Merge

    Merge --> E3["Engine G<br/>图遍历 · AGE Cypher<br/>join 路径发现<br/>10-100ms · 串行"]
    E3 --> Out["retrieval_results<br/>graph_context<br/>term_bindings"]

    classDef bpProcess  fill:#e8f0fe,stroke:#1a73e8,stroke-width:2px,color:#202124
    classDef bpData     fill:#e0f2f1,stroke:#0d7377,stroke-width:2px,color:#202124
    classDef bpInfo     fill:#f3e8fd,stroke:#9334e6,stroke-width:2px,color:#202124
    classDef bpDecision fill:#fef7e0,stroke:#f9ab00,stroke-width:2px,color:#202124

    class Q,RAG bpProcess
    class E1,E1b,E2,ED bpData
    class Merge bpDecision
    class E3 bpInfo
    class Out bpSuccess

5.2.2 四引擎职责深度解析

引擎 目标表 访问模式 为什么需要它
Engine 1 (R) semlayer.business_term LLM 提取的 search_terms 逐词 ILIKE 术语必须精确匹配——"GMV"不能靠向量相似度近似,必须查到精确定义
Engine 1b (R+) semlayer.column_asset (AliasDictionary) 字典精确匹配列别名 列别名是语言无关的,"amt"→"amount" 靠字典匹配比向量准
Engine 2 (V) 8 张 *_embedding pgvector cosine similarity, top-k, threshold=0.65 语义模糊召回主力——"和销售相关的表"靠向量相似度
Engine 3 (G) Apache AGE ttd_governance Cypher 遍历, depth=3 关系推理——join 路径、术语网络、治理边界靠图遍历
Engine D semlayer.dynamic_few_shot_cache cosine similarity ≥ 0.95 + approved 经验复用——从修复成功中自学习的 few-shot

并行与串行

Engine 1+1b+2+D 并行执行asyncio.gather),Engine 3 串行(依赖上游 asset_ids 做图遍历)。这是依赖关系决定的——图遍历需要先知道有哪些 asset,才能遍历它们的关系。

5.2.3 术语绑定强路由

这是 TTD RAG 的核心创新,也是区别于通用 RAG 的关键。当 Engine 1 命中了带 mapped_asset_id 的术语(如"GMV" → metric_gmv),这个绑定作为强路由信号贯穿全管道:

_term_bindings = [
    {"term_id": "term_gmv", "canonical_term": "GMV",
     "mapped_asset_type": "metric", "mapped_asset_id": "metric_gmv"},
]
  1. Reranker:术语绑定列/指标的相似度绝对赋值为 0.95(即 boost 到 0.95,覆盖其原始 cosine 分数,因为术语绑定是高置信度强信号);其父表分数加性提升 +0.25;不含绑定列的表加性降权 -0.10。最终分数经 max(0, min(score, 1.0)) 截断归一化到 [0, 1] 再排序。
  2. Prompt Assembler:注入"## 术语绑定约束",明确告知 LLM 必须从哪取该列
  3. Guardrails:Layer 4 术语绑定语义校验,拦截引用到错误表的 SQL
  4. Corrective Retrieval:检测到绑定违规时,优先按绑定关系拉取正确表

详见 ADR-16。这个机制把"术语消歧"从"LLM 的自觉"变为"全链路强制的硬约束"——这是 TTD 提升 SQL 准确性的核心手段。


5.3 实现详解

5.3.1 检索编排(简化伪代码)

# backend/app/skills/rag.py(简化)
async def data_retrieval(state):
    embedding = state["question_embedding"]
    qu = state["query_understanding"]
    search_terms = from_query_understanding(qu)  # 复用 QU 的 LLM 输出,零额外调用

    # Engine 1+1b+2+D 并行
    term_hits, keyword_hits, vector_results, dynamic_few_shots = await asyncio.gather(
        exact_term_match(query, search_terms),       # Engine 1 (R)
        keyword_column_search(query),                 # Engine 1b (R+)
        pgvector_search(embedding, top_k=20),         # Engine 2 (V)
        dynamic_few_shot_cache.search_similar(embedding),  # Engine D
    )

    # Engine R+ 无条件合并:术语绑定的列始终注入
    merge_keyword_hits(vector_results, keyword_hits)

    # Engine D merge:只注入 approved + sim ≥ 0.95
    if dynamic_few_shots:
        vector_results["few_shots"].extend(dynamic_few_shots)

    # 构建术语绑定视图
    term_bindings = build_term_bindings(term_hits, vector_results["terms"])

    # Engine 3 (G) 串行:依赖上游 asset_ids
    graph_context = await graph_traversal(all_asset_ids)

    return {
        "retrieval_results": {**vector_results, "_term_bindings": term_bindings},
        "graph_context": graph_context,
    }

5.3.2 Reranker 四阶段重排

backend/app/skills/reranker.py 实现检索后优化。这是 Advanced RAG 的 post-retrieval 模块:

阶段 动作 理论依据
1. 术语绑定提升 绑定列/指标相似度绝对赋值 0.95(覆盖原始 cosine),父表 +0.25,无绑定表 -0.10,最终截断到 [0,1] 强信号优先——术语绑定是高置信度信号
2. QU 信号重排 匹配 metric/entity 加分,certified 资产加分 查询理解信号应影响检索排序
3. 动态列裁剪 保留 metric/dimension/filter 相关、PK/FK/时间列 上下文压缩——只保留相关列,省 token
4. Join 路径简化 按 fanout 风险去重,优先 low risk 避免高扇出 join 导致重复计数

重排算法理论

检索重排(Reranking)是 RAG 提升精度的关键环节。主流方法:

  • Cross-encoder 模型:把 query 和 document 拼接输入 BERT 类模型,输出相关性分数。精度最高但慢(每个 query-doc 对都要前向传播)。代表:BGE-reranker、Cohere Rerank。
  • Bi-encoder + 近似最近邻:query 和 doc 分别编码,向量相似度召回。快但精度低。
  • 规则重排:基于领域信号(如术语绑定、certified 状态)手工规则加分/降权。快、可解释、领域定制性强,但精度不及模型。

TTD 当前用规则重排(阶段 1-2),优势是快且可解释,劣势是精度不及 cross-encoder 模型。改进方向见 5.4。

5.3.3 Token 预算分配

为避免上下文爆炸,按类别分配 prompt 空间(上下文压缩,Advanced RAG 的 compress 模块):

类别 预算占比
tables 30%
columns 25%
metrics 15%
few_shots 10%
join_rules 10%
business_rules 10%

5.3.4 嵌入策略

Engine V 的向量检索依赖一套完整的嵌入策略。本节说明模型选择、向量维度、索引配置与 8 张嵌入表的完整枚举。

模型与维度

说明
嵌入模型 text-embedding-v4(DashScope) 通过 TTD_EMBEDDING_MODEL 配置,默认见 附录 B
部署 schema 向量宽度 vector(1024) data-plane/sql/001_create_schema.sql 中所有 *_embedding 表的列定义
索引类型 HNSW USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 128)
存储策略 SET STORAGE PLAIN 避免列压缩导致 HNSW 索引性能退化
相似度算子 cosine similarity 阈值 TTD_SIMILARITY_THRESHOLD = 0.65

诚实声明:嵌入维度不一致

代码库存在维度不一致:ADR-7backend/app/models/registry.py 的 builtin 默认值为 1536,但部署 schema(001_create_schema.sql)实际列为 vector(1024)。Admin DB 配置路径默认 1024。这意味着若 builtin 路径返回 1536 维嵌入写入 vector(1024) 列会报错。当前以部署 schema 的 1024 维为准,维度统一已列为改进项(第 16 章)。详见 第 10 章 Schema 深潜

8 张 *_embedding 表完整枚举

# 表名 主键引用 对应资产 所属治理层
1 semlayer.table_asset_embedding table_id → table_asset 表资产 Layer 1
2 semlayer.column_asset_embedding column_id → column_asset 列资产 Layer 1
3 semlayer.metric_asset_embedding metric_id → metric_asset 指标资产 Layer 1
4 semlayer.business_term_embedding term_id → business_term 术语 Layer 2
5 semlayer.few_shot_embedding example_id → few_shot_example Few-shot 示例 Layer 1
6 semlayer.business_rule_embedding rule_id → business_rule 业务规则 Layer 3
7 semlayer.business_context_embedding context_id → business_context 业务上下文 Layer 3
8 semlayer.join_rule_embedding join_rule_id → join_rule Join 规则 Layer 1

注:semlayer.sql_cachequestion_embedding vector(1024))与 semlayer.dynamic_few_shot_cache 也含向量列,但它们是缓存表而非资产嵌入表,不计入上述 8 张。

归一化与更新策略

  • 嵌入生成时机:语义资产经发布管道同步到数据面时,由 backend/app/agents/semantic_plane/nodes.py 调用 DashScope 批量生成嵌入并 upsert 到对应 *_embedding 表。
  • 模型版本追踪:每张表含 model_id + model_version 列,嵌入迁移时可按版本筛选重建。
  • 迁移策略(未实现):若 text-embedding-v4 升级到 v5,需全量重建 8 张表的嵌入。当前无自动化迁移工具,已列为改进项。

5.3.5 补偿检索(Corrective Retrieval)

Guardrails 失败后,corrective_retrieval.py 用错误信息重新检索补充上下文——这是 Corrective RAG(CRAG) 的工程实现:

  • 检测到术语绑定违规 → 优先按绑定关系拉取正确的表和列
  • 检测到列引用错误 → 拉取可用列清单
  • 通用错误 → 基于错误信息重新检索

Corrective RAG(CRAG)理论

CRAG(arxiv.org/abs/2401.15884)的核心思想:检索质量不够时不硬生成,而是评估检索结果质量,低质量时触发"纠正"——改写查询重新检索或补充检索。这与 Self-RAG(arxiv.org/abs/2310.11511)一脉相承,Self-RAG 让 LLM 自主决定何时检索、是否采纳。

TTD 的 corrective_retrieval 是 CRAG 的简化版:不评估检索质量(无 retrieval confidence score),而是在 guardrails 失败后才触发补充检索。改进方向是把检索评估前置(pre-generation),而非等生成失败后才纠正。

5.3.6 Engine D 动态 Few-Shot 质量控制

从 SQL 修复成功案例自动学习 {question, sql} 对,但有三步审批门控:

record_success() → review_status = 'pending_review'(不参与 RAG)
Admin 审批 → approve / reject
search_similar() → 仅返回 approved + sim ≥ 0.95 + confidence ≥ 0.9 + fail_count ≤ 3

详见 第 7 章


5.4 检索失败模式分析

四引擎并非万无一失——下面列出 5 种典型检索失败场景,每种给出根因、现象与当前 fallback 行为。这些是 TTD 在 H&M 数据集上实际遇到或可预见的模式。

# 失败场景 根因 现象 当前 fallback / 缓解
1 术语缺失 用户用了未在 business_term 资产中登记的业务词(如"客单价"未定义) Engine T 无匹配;Engine V 召回的表/列与用户意图不符;SQL 引用错误列 Layer 2c/2d 护栏拦截列引用错误 → corrective_retrieval 重试;若仍失败返回 clarification_required根本修复需补充术语资产。
2 向量漂移 用户问题的 embedding 与资产 embedding 语义距离远(如口语化"卖得最好的"vs 登记文本"销量排行") Engine V top-k 召回 precision 低;threshold=0.65 过滤后结果为空 Reranker 的术语绑定信号可补偿(若术语命中);Engine R 的精确匹配可兜底;空结果时降级到全表扫描式 Prompt(列出所有相关表)。改进方向:query rewriting(16.3.1)。
3 图遍历超时 NL2Cypher 生成了深度过大或全图扫描的 Cypher(如 MATCH (n)-[*]-(m) 无深度限制) Engine G 超过 TTD_GRAPH_TRAVERSAL_TIMEOUT_MS(默认 3s);返回空或部分结果 超时自动降级到 SQL 流水线(_route_after_graph_rag → fallback_sql);图遍历有最大深度限制。改进方向:GraphRAG 护栏(16.6.3)。
4 多义术语冲突 同一术语映射到多个资产(如"价格"可指 fact_transaction.price 也可指某个计算指标) Engine T 返回多个 mapped_asset_id;Reranker 无法确定唯一绑定 取置信度最高者;若多个绑定的相似度差 < 0.1 则触发 HITL 让用户消歧。改进方向:术语资产补充 disambiguation_context
5 join 路径不存在 用户问题涉及的两张表在语义图中无连通路径(Steiner 树无解) 规划器无法生成 join 拓扑;SQL 生成缺少 join 上下文 降级为单表查询 + Prompt 提示"无法关联,请分别查询";返回 partial_result 状态。根本修复需补充 join_rule 资产。

失败模式与资产质量强相关

上述 5 种失败中,3 种(术语缺失、多义冲突、join 路径不存在)的根本修复都依赖语义资产补充,而非算法改进——这印证了"治理优先"原则:检索质量的上限由资产质量决定,引擎与算法只能逼近这个上限。这也是 第 9 章 强调资产编写重要性的原因。


5.5 方案选型对比

5.4.1 向量引擎对比

维度 pgvector Milvus Qdrant Pinecone
部署 PG 扩展(一体化) 独立服务 独立服务 SaaS
事务一致性 与 PG 共享事务
性能 中(HNSW)
规模 百万级 十亿级 十亿级 十亿级
运维 低(随 PG) 低(托管)
TTD 选择理由 与 R/G 共享 PG,事务一致,运维简单

5.4.2 图引擎对比

维度 Apache AGE Neo4j NebulaGraph
部署 PG 扩展 独立服务 独立服务
查询语言 Cypher (openCypher) Cypher nGQL
性能
规模 超大
TTD 选择理由 与 R/V 共享 PG,一体化

5.4.3 自建 RAG vs 框架

维度 自建(TTD) LlamaIndex LangChain RAG
控制力 最高
定制性 最高
开发成本
TTD 选择理由 四引擎混合检索 + 术语绑定是高度定制需求,框架难以直接支持

性能与质量指标(设计目标)

以下为 Engine V 检索与 Reranker 的设计目标值,TTD 尚未进行系统化实测

指标 设计目标 说明
Engine V 召回延迟 10-50ms pgvector HNSW 检索,8 张表并行
Reranker 延迟 < 10ms 纯规则重排,无模型前向传播
检索 precision ≥ 0.8 相关表/列进入 top-k 的比例
检索 recall ≥ 0.9 应召回资产的实际召回比例
术语绑定命中率 ≥ 0.7 含明确术语的问题命中 mapped_asset_id 的比例

评估基础设施见 第 15 章,改进路线见 第 16 章

当前实现可改进之处

  1. 缺查询改写/多查询生成:当前直接用原问题 embedding 检索,无 query rewriting 或 multi-query generation。复杂问题(如"对比华东和华北的 GMV 趋势")单次检索召回不全。改进:引入 query decomposer 生成多个子查询并行检索,再合并去重(参考 RAG-Fusion, arxiv.org/abs/2402.03367)。
  2. Reranker 用规则而非 cross-encoder 模型:当前 Reranker 是基于术语绑定与 QU 信号的手工规则,而非 BGE-reranker / Cohere Rerank 等 cross-encoder 模型。规则快但精度不及模型。改进:支持 Admin 配置的 Reranker 模型(代码已预留 get_reranker_config),在精度要求高的场景启用。
  3. 无检索评估闭环自动化:虽有 retrieval_evaluator,但只在 deep_analysis 路由启用,且不自动触发重新检索。改进:将 Self-RAG 的自评估机制常态化——每次检索后评估,低分自动触发 corrective_retrieval,而非只在 guardrails 失败后。
  4. pgvector 在大规模下性能受限:百万级 embedding 时 HNSW 索引尚可,但千万级会退化。改进:抽象 VectorStore 接口,生产态可选 Qdrant/Milvus。

改进方向

RAG 的演进方向是更智能的检索前(pre-retrieval)与检索后(post-retrieval):检索前做 query 改写与分解,检索后做模型重排与自评估纠错。TTD 已有 corrective_retrieval(post),缺的是 query 改写(pre)。补齐这一环能让四引擎 RAG 从"被动召回"升级为"主动检索"。


5.6 小结与延伸阅读

本章要点

  1. TTD 的 R/V/G/D 四引擎覆盖精确匹配、语义召回、关系推理、经验复用四种检索模式,横跨 Advanced 到 Modular RAG。
  2. Engine 1+1b+2+D 并行,Engine 3 串行(依赖上游 asset_ids)。
  3. 术语绑定强路由是核心创新,贯穿检索→重排→Prompt→护栏→自愈五层。
  4. Reranker 四阶段重排(术语提升→QU 信号→列裁剪→Join 简化)+ Token 预算分配控制上下文质量。
  5. 补偿检索是 Corrective-RAG 的工程实现,在 guardrails 失败后补充上下文重试。

延伸阅读

下一章第 6 章 SQL 生成与语义规划——检索之后如何用语义规划器 + LLM 生成可信 SQL,以及五层护栏如何守护。