Agent Engineering 课程阅读
首页/课程一 · RAG 手写/Query 改写:让检索更准

在 GitHub 查看原文

本页目录

Lesson 07 — Query 改写:让检索更准

本课目标:搞懂为什么不能直接拿用户原话去检索,以及怎么改造 query 让检索命中率飙升

前 6 课优化的都是"文档侧"(embedding、chunking、混合检索、rerank)。这一课转向"问题侧"——用户的话往往不适合直接检索


1. 原始 query 为什么不好检索?

用户实际问的问题,往往长这样:

问题类型 例子 为什么不好检索
太短/太泛 "年假" 信息量太少,向量不够具体,召回一堆沾边的
口语化 "我想歇几天,咋整?" 和文档里的正式表述("带薪年假申请")语义距离远
指代不明 "那个表怎么填?" "那个"指什么?向量检索完全懵
多意图 "年假和病假有什么区别,分别怎么申请?" 一个 query 塞了两个问题,检索只能偏向一个
缩写/黑话 "PTO 政策?" 文档里写的是"带薪休假",字面不匹配

直接拿这些问题去检索,召回质量必然差。所以要先"改造"问题,再去检索。

🎯 核心认知:检索质量 = 文档侧质量 × 问题侧质量。前面优化了文档侧,现在轮到问题侧。


2. HyDE:用"假设答案"去检索

HyDE (Hypothetical Document Embeddings) 是个反直觉但很有效的技巧。

直觉

向量检索的原理是"问题和文档的向量要接近"。但有个矛盾: - 问题通常是疑问句、简短、口语化 - 文档通常是陈述句、完整、正式

它们的"语言形态"不同,即使语义相关,向量也可能不够近。

HyDE 的思路:既然文档是陈述句,那我就让模型先编一个"假设的答案文档",用这个假设文档去和真实文档匹配——陈述句匹配陈述句,更接近。

流程

用户问题:"我想歇几天,咋整?"
        │
        ▼
   ① 让 LLM 生成"假设答案"(一段看起来像文档的文字)
   "员工可申请带薪年假,入职满一年享有 5 天..."
        │
        ▼
   ② 把"假设答案"向量化(而不是把原问题向量化)
        │
        ▼
   ③ 用假设答案的向量去检索真实文档
        │
        ▼
   ④ 召回准确率大幅提升(陈述句 vs 陈述句,向量更近)

为什么有效?

因为 embedding 模型是在"文档语料"上训练的,它更擅长编码陈述性文本的语义。把口语问题转成假设文档,等于"翻译"成了 embedding 模型更熟悉的语言。

代价

多一次 LLM 调用(生成假设答案),有延迟和成本。但检索质量的提升通常值得。


3. 多查询展开 (Multi-Query)

一个问题可以从多个角度问,每个角度检索一次,合并结果。

流程

用户问题:"年假和病假有什么区别,分别怎么申请?"
        │
        ▼
   ① 让 LLM 把它拆成/改写成多个子问题:
      - "年假的天数和申请流程是什么?"
      - "病假需要什么材料,怎么申请?"
      - "年假和病假的区别是什么?"
        │
        ▼
   ② 每个子问题分别检索 top-K
        │
        ▼
   ③ 合并去重(用 RRF 或投票)
        │
        ▼
   ④ 覆盖更全面(一个复杂问题 → 多个简单问题,每个都好检索)

适用场景

  • 多意图问题("A 和 B 的区别/流程")
  • 需要从多个文档综合信息的问题
  • 用户问题太模糊,需要从多角度覆盖

4. 查询路由 (Query Routing)

不同类型的问题适合不同的检索策略:

问题类型 路由到
含编号/代码 BM25 为主(参考 Lesson 06)
语义模糊/口语 向量检索为主
需要精确数字/事实 metadata 过滤 + BM25
元问题("有哪些文档") 不检索,直接列目录

路由可以用 LLM 判断(让它分类问题类型),也可以用规则(正则匹配编号等)。

💡 本课重点讲 HyDE 和多查询展开(最常用、效果最显著),查询路由了解概念即可。


5. 本课代码会做什么

code.py 会做对比实验,让你看到 query 改写的威力:

① 原始 query 直接检索(基线)

拿一个口语化的烂问题直接检索,看召回质量。

② HyDE 改写后检索

让 LLM 生成假设答案,用假设答案检索,对比召回质量。

③ 多查询展开后检索

让 LLM 把问题展开成多个子问题,分别检索合并,对比召回质量。

三种方式用同一个文档库,量化对比谁召回了正确文档。


6. 跑起来

python lessons/07_query_rewrite/code.py

终端会打印三种方式的检索结果对比。重点看:口语化烂问题在"直接检索"时召不准,改写后召回质量明显提升。


下一课 Lesson 08 — RAG 评估 会讲:怎么用数据客观衡量 RAG 好不好,不凭感觉。