你在同学群里收到一句微信:“上次那家店,你记得吧?我们周五去的。”你点开相册想找那家店的招牌菜照片,却愣住了——几百张照片躺在那里,而你能用的线索只有“那家店”“周五”这几个词。翻来翻去,眼睛花了也找不到。这时有个朋友出了个主意:别急着翻,你先假装自己已经想起它是哪家店,把想象中的场景写下来——“人民路那家川菜馆,招牌毛血旺,辣得冒汗,靠窗坐……”写完之后再拿着这封信去翻相册,目标一下子清晰了。这就是 HyDE(Hypothetical Document Embeddings,假设文档嵌入)的底层直觉:短查询信息太少,不如先让大模型把查询“脑补”成一段假设存在的答案文档,再用这段文档的向量去检索真正的文档。它不需要任何标注数据,却在长尾查询、复杂查询上让检索召回率显著提升,成了 RAG(检索增强生成)时代最受关注的查询扩展方法之一。
对 AI 从业者来说,掌握 HyDE 意味着你多了一把“零样本提升召回”的钥匙:不碰训练数据、不改索引结构,只靠一条 LLM 指令就能让 RAG 系统在模糊查询上明显变聪明——这是面试、论文、生产调优都能直接兑现的技能。
目录
可视化演示
展示HyDE假设文档嵌入方法,将查询经LLM生成假设答案文档,再嵌入检索提升召回率,零样本场景下无需训练数据即可增强检索效果。
本节配有交互动效(进入视口后自动加载,约 3KB)。
HyDE假设文档嵌入 查询生成:短查询经LLM生成假设答案文档,丰富语义信息 文档嵌入:对假设文档而非原始查询进行嵌入检索 零样本提升:无需训练数据,利用LLM知识增强召回 HyDE: Q → LLM → D_hyp → Embed → Retrieve HyDE通过假设文档嵌入显著提升检索召回率
短查询的困境
你在同学群里收到一句微信:“上次那家店,你记得吧?我们周五去的。”你点开相册想找那家店的招牌菜照片,却愣住了——几百张照片躺在那里,而你能用的线索只有“那家店”“周五”这几个词。翻来翻去,眼睛花了也找不到。这就是短查询的困境:不是没有答案,而是提问给出的信息太少,少到无法从海量内容里定位目标。
在信息检索里,这个“相册”就是文档库,你的那句模糊微信就是查询。现代稠密检索先把查询和文档分别编码成高维向量,再比较两个向量的相似度。可查询太短时,编码出来的向量“贫瘠”得像一张只有两个像素的照片,和任何一张文档照片都很难重合——学术上叫语义鸿沟。具体表现为三种情形:词汇不匹配——用户说“辣”,文档写“花椒”“藤椒”,表面词不同;稀疏表示——查询只有几个词,向量非零维度极少;长尾难题——冷门话题在库里本来就没几篇相关文档,相似度普遍偏低,排在前面的常常是噪声。
传统方法面对这些问题只能干瞪眼:BM25 靠词频统计,对同义词毫无办法;稠密检索虽然理解了语义,但输入向量太“薄”,照样找不准。问题不在“搜”这个动作,而在“搜之前手里只有三个词”。
相册还是那本相册,问题出在手里那三个词太干瘪。如果能让三个词先“膨胀”成一段像样的话、再拿去搜——故事的转折就从这里开始。
- 分子点积把两个向量的每一维相乘再累加,方向越一致值越大,向量“胖瘦”的绝对值也混在里面。
- 分母模长分别算出两个向量的长度做归一化,消除文本长度带来的偏差。
- 余弦比值点积除以模长积,结果落在 -1 到 1 之间,只保留“方向像不像”的信息。
- 取最大值对文档库里所有候选文档各算一次相似度,挑分数最高的那篇作为检索结果。
HyDE 的核心思想:先答后搜
你换了个思路:既然想不起来,不如先假装自己已经想起了。你拿起笔,凭印象写下一封“假设的回信”:“对,就是人民路那家川菜馆,招牌毛血旺,辣得冒汗,我们坐窗边……”写完后,你拿着这封信去翻相册,眼睛立刻有方向了——找川菜馆、找那盘红油油的毛血旺、找靠窗的桌子。
这正是 HyDE 的直觉:与其用光秃秃的查询去检索,不如先让大模型“凭空”写一篇假设存在的答案文档,再用这篇文档的向量去找真正的文档。论文里管这叫“先假设,后检索”。流程分两步:第一步,把用户查询喂给大语言模型,让它输出一段“如果答案存在,它大概长这样”的文字;第二步,把这段假设文档交给嵌入模型编码,再去文档库做相似度检索。全程不需要任何标注数据,零样本可用。
这里的关键词是“语义增强”:假设文档是从查询出发、由世界知识补全的完整陈述。它虽然不一定真实,却天然站在“答案”这一侧。短查询像一张写在纸巾上的三个字,假设文档则是一封有开头有细节的信,两者在向量空间里的“势力范围”完全不同。
相册还是那个相册,嵌入模型还是那个嵌入模型,变的只是检索前手里拿的东西——从三个字变成一封信。这封信未必准确,但它提供了足够的“话头”,让向量搜索第一次有机会对准靶心。
- 生成假设文档大模型以用户查询为条件,采样出一段“答案长这样”的文字,这是 HyDE 与普通查询扩展最大的不同。
- 编码成向量嵌入模型把假设文档压成稠密向量,把语义信息浓缩进几何位置。
- 库内比对拿假设文档向量去和每篇候选文档向量算余弦相似度,找出“长得像”的邻居。
- 取最相似文档返回相似度最高的文档作为最终召回,交给下游 RAG 或重排模块。
生成环节:让大模型写假设回信
回信写得好不好,直接决定翻相册的成败。如果那封信写的是“那家店在商场五楼,灯很亮”,你依然找不到川菜馆;如果写的是“人民路川菜馆,毛血旺,水煮鱼,花椒,靠窗”,照片立刻浮出水面。HyDE 的生成环节同理,是整条链路的命门。
LLM 的输入要经过一个指令模板,比如:“请根据以下查询,写一段可能作为其答案的文档。查询:{}”。模板的作用是告诉模型:别回答我,别给结论,给我一篇“看起来像馆藏文献”的文字。在零样本设定下,模板是通用的一句话;在领域场景中,可以注入领域约束——政策检索就让它写“政策评估报告摘录”,医学检索就让它写“病例摘要”,让假设文档与目标文档同域同风格。
生成质量直接决定后续召回上限:细节越贴近真实文档的词汇分布,向量越容易找到邻居;反之,空话连篇的假设文档只会把检索带向任何一篇泛泛而谈的文章。实践中,模型越大、指令越明确,假设文档的“仿真度”越高,但也意味着更高的延时和成本,需要在效果与开销之间做取舍。
想象你给朋友发微信求助,朋友回你一篇小作文帮你回忆。小作文里每一条具体细节——菜名、街道、灯光——都是检索时的“锚点”。HyDE 的生成环节,就是在制造锚点。
- 模板注入把用户查询拼进指令模板,明确告诉模型“要生成一篇文章而不是一句话答案”。
- 条件概率采样模型按前面 token 的条件概率逐个生成后续 token,每一步都依赖上文。
- 得到完整假设采样结束得到整段假设答案文档,交给下一步编码。
嵌入与检索:把回信变成向量去找
回信写好了,接下来要“拿着信找照片”。你不会把整封信当尺子去量每张照片,而是先给信抽出一个简明的特征——就像人脸识别先提取五官特征。嵌入模型干的正是这件事:把假设文档压缩成一个稠密向量,同时让语义相近的文本在向量空间里挨得近。这一步叫向量编码,输出的向量就是“回信的照片”。
编码完成后,检索阶段用余弦相似度衡量假设文档向量与每篇候选文档向量的夹角。夹角越小越相似。大规模场景下不会暴力遍历所有文档,而是用 ANN 索引(如 HNSW、FAISS)做近似最近邻搜索,牺牲微量精度换取毫秒级响应。得到候选集后,按相似度降序排列,取 top-k 进入下游——比如 RAG 的生成模块。
这里有一个容易忽略的点:向量本身并不“理解”文字,它只是在几何空间里让相近的内容聚在一起。正如照片特征向量并不知道什么是“川菜”,却能让川菜馆的照片聚成一簇。HypDE 的假设文档因为词汇丰富,恰好落在目标文档簇的中心附近,于是比短查询更容易“入围”。
从“写回信”到“拍回信的照片”,这一步让假设文档从文字变成了可计算的距离。后面的故事,就是数字登场了。
- 假设文档向量嵌入模型给假设文档一个固定维数的高维坐标,语义相近则坐标相近。
- 文档向量集合文档库里 N 篇文档各自编码成向量,构成被检索的向量空间。
- 余弦相似度逐一计算假设向量与每个文档向量的夹角余弦,得到 N 个分数。
- 取 top-k按分数降序排列,保留前 k 个作为召回结果,供下游重排或生成使用。
效果评估:命中率说了算
怎么知道“照信翻相册”这招管不管用?你得统计成功率:把 100 个模糊查询拿来做实验,看看返回的前 k 篇结果里到底有几篇是真正相关的。这就是召回率的衡量——直觉上,它回答的是“该找到的找到了几成”。
实验里,HyDE 在零样本设定下跑赢 BM25 和典型的稠密检索基线(如直接用 Contriever 对查询编码检索)。最惊艳的是长尾查询:越冷门、越模糊的问题,提升越明显,因为假设文档把稀薄的语义“喂饱”了。相反,在意图非常清晰的查询上,HyDE 的增益会缩水,甚至因为多余生成而拖慢速度。
消融实验进一步拆解贡献:去掉 LLM 改用简单模板拼接,效果骤降;更换不同指令模板,波动不大但方向一致;用更大的 LLM 生成,提升有限但成本更高。这说明 HyDE 的增益主要来自“假设文档”这个载体,而不是某个特定模型的魔法。
就像做菜谱测评要看“按这个菜谱做出来的菜有几分像原版”,评估环节用数字把“这封信帮没帮上忙”说清楚。能上数字的直觉,才敢搬进生产环境。
- 相关集合评估集里人工标注好的相关文档集合,是评测的“标准答案”。
- 返回集合系统检索后返回的前 k 篇文档,k 通常取 10 或 20。
- 交集大小两个集合重合的文档数,代表“找对了几篇”。
- 求比值重合数除以相关总数,得到 0 到 1 之间的召回率。
局限与改进:写歪了怎么办
凡事都有另一面。假设回信可能写错店名、编错地址——LLM 的幻觉会污染假设文档,让检索朝着错误的方向猛冲;写回信本身也要时间,每来一个查询就多一次 LLM 推理,延迟直线上升;如果查询本身很清楚,绕这一圈纯属多此一举。这三个问题分别对应:幻觉风险、推理开销、清晰查询失灵。
工程上常用“融合检索”来对冲风险:把 HyDE 的语义分与传统稀疏检索(BM25)的关键词分做线性加权,两路互补。语义路负责“说得像”,关键词路负责“拼得准”,谁也别想独自带偏。此外还可以加幻觉检测、限制生成长度、只在查询长度低于阈值时启用 HyDE,让这套“降级策略”把 HyDE 从论文玩具变成可上线的组件。
融合的本质是承认任何单一信号都不完美:BM25 对同义词失明,HyDE 对幻觉敏感,但两者叠加时,各自的盲区会被对方覆盖。
回信会写歪,但我们可以不把宝全押在一封信上。多带一本词典(BM25)、多带一个指南针(领域指令模板),这套“信 + 词典”的组合,才是生产级 HyDE 的日常姿态。
- HyDE 语义分假设文档向量与文档的余弦相似度,负责捕捉“语义像不像”。
- BM25 关键词分稀疏检索对词频和稀有度的统计打分,负责“关键词拼得准不准”。
- 融合系数α 在 0 到 1 之间取值,α=0 退化为纯 BM25,α=1 退化为纯 HyDE。
- 线性融合总分由两路加权求和,多路互补降低单路风险。
AI 应用场景
企业 RAG 客服的模糊投诉召回
阶段:RAG 检索召回阶段
解决的问题:真实用户经常发来“上次那个事怎么还没好”“你们是不是搞错了”这种模糊消息,直接送去检索知识库,几乎匹配不到任何工单。HyDE 先把投诉扩展成一段“假设处理方案文档”,包含业务关键词、流程步骤、异常类型,再检索工单库,召回率明显上升。
具体案例:某 SaaS 公司客服机器人接到“上次说的那个账单问题”时,先用 LLM 生成一段“账单核对失败、扣款金额不符、需提交退款申请”的假设工单描述,再用向量检索命中历史工单,最终让首次解决率提升 22%。
政策评估研究的文献检索
阶段:查询扩展与检索召回
解决的问题:政策研究者常提出“社区养老政策对独居老人生活质量的影响”这类复合问题,直接检索返回的是泛泛的政策文件。HyDE 让 LLM 先写一段“假设的评估报告”,包含效果指标、群体特征、干预机制,再检索研究文献库,显著提升相关论文的召回率。
具体案例:某政策研究院使用 HyDE 检索 50 万篇社科文献,将“适老化改造效果”相关文献的 Recall@10 从 0.31 提升到 0.47,节省了研究员大量人工筛文时间。
医学循证检索的初步筛查
阶段:医学文献检索的召回阶段
解决的问题:医生输入“老年患者术后谵妄的干预”这种口语化查询时,与正式医学文献存在巨大词汇鸿沟。HyDE 先让 LLM 生成一段“假设的临床研究摘要”,包含 MeSH 风格术语、干预措施、结局指标,再检索 PubMed 类文献库,把相关随机对照试验排到前面。
具体案例:某医疗 AI 团队在循证医学问答系统中引入 HyDE,对 200 条临床查询测试,召回相关文献的比例提高约 35%,同时不增加任何标注数据成本。
Python 演示
# -*- coding: utf-8 -*-# HyDE 的最小模拟:用双字切分 + 词频加权模拟嵌入,对比直接查询与假设文档检索import mathfrom collections import Counter DOCS = [ "人民路川菜馆的毛血旺又辣又香,靠窗座位适合看夜景", "甜品店的提拉米苏带咖啡酒味,二楼音乐舒缓", "那家火锅店锅底偏麻,香菜牛肉丸是招牌", "川菜馆的水煮鱼用大量花椒,麻辣层次分明", "日料店的三文鱼刺身很新鲜,芥末微辣",] QUERY = "那家很辣的川菜店"HYPOTHESIS = "那家店是川菜馆,招牌是毛血旺和水煮鱼,花椒很足,很辣,在人民路" def tokenize(text): # 双字切分模拟词边界,保留"辣"和"川菜"等语义单位 return [text[i:i + 2] for i in range(len(text) - 1)] def embed(text): counter = Counter(tokenize(text)) return {w: 1 + math.log(v) for w, v in counter.items()} def norm(vec): return math.sqrt(sum(x * x for x in vec.values())) def cosine(a, b): common = set(a) & set(b) dot = sum(a[w] * b[w] for w in common) return dot / (norm(a) * norm(b)) def rank(text): vec = embed(text) scores = [(i, cosine(vec, embed(d))) for i, d in enumerate(DOCS)] scores.sort(key=lambda x: x[1], reverse=True) return scores def main(): print("== 直接查询排序 ==") for i, s in rank(QUERY): print("doc%d: %.3f" % (i + 1, s)) print("== 假设文档排序 ==") for i, s in rank(HYPOTHESIS): print("doc%d: %.3f" % (i + 1, s)) if __name__ == "__main__": main()
return [text[i:i + 2] for i in range(len(text) - 1)]双字切分是“伪分词”,用相邻字对模拟语义单元,足够演示词汇重叠。counter = Counter(tokenize(text))统计每个字对出现的次数,词频越高代表越重要。{w: 1 + math.log(v) for w, v in counter.items()}对词频取对数平滑,模仿 TF-IDF 的“越稀有越关键”思想。common = set(a) & set(b)只取两段文本共有的词,因为余弦相似度只关心共同维度。dot = sum(a[w] * b[w] for w in common)点积累加,方向一致时数值更大。return dot / (norm(a) * norm(b))归一化后得到余弦相似度,结果在 0 到 1 之间。scores.sort(key=lambda x: x[1], reverse=True)按相似度降序排列,输出检索排名。HYPOTHESIS = "..."这就是“假设回信”:比查询多出“毛血旺”“花椒”“水煮鱼”等细节,正是它们抬高了命中率。
常见误区
误区我以为 HyDE 和很多检索增强方法一样,先要收集一批“查询-相关文档”标注对,把模型微调一遍才敢上线。零样本?听起来太理想了。
正解HyDE 恰恰以零样本为核心卖点。它直接复用现成的大语言模型来生成假设文档,再复用现成的嵌入模型做编码,两个模型都不需要针对当前文档库做任何训练或微调。就像你不需要把朋友培训成侦探,他本来就会帮你把模糊的话补成完整回忆。
为何常见:因为前后看了太多需要微调精排模型的 RAG 教程,默认认为“提升检索效果”必然伴随训练环节,忽略了 HyDE 是纯推理期的查询端改造。
误区生成假设文档时,我总想让 LLM 多写点,越详尽越全面。结果检索效果反而变差,我很困惑。
正解假设文档不是越长越好,而是要“与目标文档同域同风格”。如果生成出大量无关细节——比如餐厅的装修、服务的态度——向量会被这些噪声拖离目标簇,反而排出一堆不相干结果。回信写太多家常,照样翻不到照片。
为何常见:人们直觉认为“信息多 = 检索准”,忽略了嵌入向量是整体压缩,多余内容会稀释核心语义。
误区既然召回率提升了这么多,那 HyDE 应该是把原来的嵌入模型升级成了更强的版本吧?
正解HyDE 不替换任何嵌入模型,它只做查询端的改写。原始的 query 先被 LLM 扩写成假设文档,然后仍然走原来的嵌入模型、原来的向量索引、原来的检索管线。比喻说,你只是把“问话”改成了“回信”,翻照片用的相册和眼睛还是同一副。
为何常见:因为效果提升的直觉容易被归因到“某个组件变强了”,而 HyDE 的巧妙之处恰恰在于组件都没变,变的是输入形态。
误区我在系统里接上 HyDE 后,部分查询的延迟增加了、结果也没变好,是不是我哪里写错了?
正解HyDE 不是银弹。对已经清晰、具体、意图明确的长查询,生成假设文档的增益很小,反而白白多一次 LLM 推理延迟;如果 LLM 幻觉严重,甚至会把检索带偏。生产环境应设置触发条件,比如查询长度低于阈值或初步召回得分过低时才启用。
为何常见:看到论文里 Recall@k 的平均提升数字,容易忽略它主要来自长尾模糊查询,而平均值的背后是大量普通查询没有收益。
面试题
Q1. HyDE 中的“假设文档”主要由谁生成?
- A.嵌入模型编码生成
- B.大语言模型生成← 正确答案
- C.用户手动标注
- D.文档库自动聚类
答案:B。HyDE 的核心动作就是先让大语言模型根据查询写出一段假设存在的答案文档。A 是生成之后的编码环节,C 违背了零样本设定,D 与生成无关。记住“写回信的是 LLM,不是相册”。
Q2. HyDE 主要弥补了短查询的什么不足?
- A.查询响应速度慢
- B.语义信息量不足← 正确答案
- C.存储空间占用大
- D.模型参数规模小
答案:B。短查询只有寥寥几个词,编码出的向量信息贫瘠,难以与文档向量对齐。HyDE 用假设文档补足词汇和语义信息,让向量“有话可说”。速度、存储、参数都不是检索召回层面的问题。
Q3. HyDE 最终用来检索文档的向量来自哪里?
- A.原始查询嵌入
- B.假设文档嵌入← 正确答案
- C.查询与假设平均
- D.文档向量求平均
答案:B。HyDE 的关键区别就是放弃原始查询向量,改用 LLM 生成的假设文档的嵌入去检索。A 是普通稠密检索,C 会稀释假设文档的语义,D 是全局统计量,都与 HyDE 无关。
Q4. 下列哪些情况更适合用 HyDE?
- A.用户查询简短模糊← 正确答案
- B.长尾冷门话题← 正确答案
- C.毫秒级实时检索
- D.零样本无标注场景← 正确答案
答案:ABD。HyDE 在短查询、长尾、零样本场景下收益最大。C 不选,因为每查询一次就多一次 LLM 生成,延迟明显上升,不适合毫秒级实时链路。A、B、D 正是论文验证的最强适用面。
Q5. 假设文档能提升召回的根本原因是什么?
- A.文本更长词数更多
- B.语义接近真实文档← 正确答案
- C.向量维度更低
- D.排序完全确定
答案:B。表面上看是“字变多了”,本质是假设文档的词汇分布和句式结构贴近真实目标文档,填补了查询与文档之间的词汇鸿沟。维度由嵌入模型决定,不会变低,排序也不可能“完全确定”,所以 C、D 不对。
Q6. HyDE 的典型局限包括哪些?
- A.LLM幻觉引入噪声← 正确答案
- B.生成增加推理开销← 正确答案
- C.清晰查询提升有限← 正确答案
- D.任何场景优于BM25
答案:ABC。幻觉会让假设文档偏离真相,检索跟着偏航;LLM 生成带来额外延迟;对已经清晰的查询,绕圈生成假设文档收益极小。D 过于绝对,HyDE 并非在所有场景都优于 BM25,所以才需要融合。
Q7. 若 LLM 生成的假设文档严重偏离真实答案,会发生什么?
- A.检索质量反而下降← 正确答案
- B.召回率一定上升
- C.嵌入模型自动纠正
- D.检索结果不受影响
答案:A。向量检索只会找“像假设文档”的文档。假设文档写歪了,检索结果就跟着歪,甚至比直接用短查询更差。嵌入模型不具备纠错能力,它只是忠实地把“歪”的内容编码成向量。
Q8. HyDE 与伪相关反馈(PRF)的共同点是什么?
- A.先用检索结果再扩展
- B.查询扩展为丰富内容← 正确答案
- C.依赖大语言模型
- D.不依赖嵌入模型
答案:B。两者都通过“扩展查询内容”来弥补信息不足。A 是 PRF 的做法,HyDE 不先检索;C 是 HyDE 的做法,PRF 不一定用 LLM;D 错误,两者都依赖检索和嵌入打分。共同点只有“查询被变丰富”。
Q9. 融合检索中结合 HyDE 与 BM25 的目的是什么?
- A.语义与关键词互补← 正确答案
- B.降低总体延迟
- C.提升整体鲁棒性← 正确答案
- D.完全消除幻觉
答案:AC。HyDE 擅长语义相似,BM25 擅长精确词匹配,两者互补能降低单路信号失灵的抖动,提升鲁棒性。融合不会降低延迟(反而加了一路计算),也不可能完全消除幻觉,故 B、D 不选。
Q10. HyDE 属于哪一类检索优化方法?
- A.查询扩展← 正确答案
- B.索引压缩
- C.排序学习
- D.文档聚类
答案:A。HyDE 把短查询改写成假设文档,本质是查询扩展的一种——只不过扩展的内容由 LLM 生成,而不是词典或词向量。它不碰索引结构、不做排序训练、不聚类文档,所以 B、C、D 都不对。