假设文档嵌入增强

HyDE (Hypothetical Document Embeddings)

HyDE 假设文档嵌入是 RAG 检索增强的前置技巧:先让 LLM 根据用户问题幻想一段理想答案文档,再把该幻想文档做 Embedding 并检索,解决了问题 embedding 与答案 embedding 语义空间不对称导致的召回差问题。

详细解释

HyDE(Hypothetical Document Embeddings,假设文档嵌入) 是 2022 年 CMU + 斯坦福的论文《Precise Zero-Shot Dense Retrieval without Relevance Labels》提出的方法,是 RAG 产品里”花小钱大提升”的 Top 3 技巧之一,实现只要加一次 LLM 调用,就能让 Recall@10 涨 10–20%

它解决的是 RAG 里的”不对称”痛点:

  • 知识库 Document 里存的是【答案】形式的文本(陈述句、段落长、专业术语多);
  • 用户的 Query 是【问题】形式的文本(疑问句、短语短、口语化、表述千奇百怪);
  • 同一件事,用”问题腔”写的 Embedding 和用”答案腔”写的 Embedding 在向量空间里可能离得挺远 → 直接用用户 Query 去 Embedding 检索,经常把最相关的答案排到 10 名开外。

HyDE 的做法(三步,很反直觉但很有效):

  1. 先”编”一段假设文档:把用户问题丢给 LLM,告诉它”假设你知道正确答案,请写一段 200 至 500 字的理想答案文档”。这段很可能是编造的(含 幻觉),没关系。
  2. 把这段幻觉答案拿去 Embedding:不对用户问题做 Embedding,而是对”幻想出来的假设答案”做 Embedding。
  3. 用这个假设答案向量去检索真实知识库:因为”假设答案”的语气、长度、关键词分布都和真实文档在同一个语义空间——向量更接近——召回效果往往好很多。

核心洞察:哪怕 HyDE 生成的假设文档事实是错的,它的”用词风格、句式、术语结构”已经比用户原问题更贴近真实答案了,Embedding 相似度排序依然会更准。 事实错误在后续被真实知识库覆盖掉,不影响最终答案。

RAG 不同检索方案的 Recall 对比(公开榜 MIRACL、BEIR 平均值)

检索方案Recall@10(公开基准平均)额外开销
纯关键词 BM2551%0
单 Embedding 向量检索(Query → 向量 → Top-K)63%Embedding 模型推理
HyDE(假设答案 → 向量 → 检索)77%多一次 LLM 调用(几百 tokens)
HyDE + 向量 + BM25 混合(RRF 融合)84%再 + 一次 BM25
再叠 Rerank(重排) Top-50 → Top-591%再多一次 Rerank 调用

实现 HyDE 的最小代码

from openai import OpenAI
client = OpenAI(api_key="wm-xxxx", base_url="https://api.weimeta.cn/v1")

def hyde_retrieve(user_query: str, n_docs=5):
    # 第一步:让 LLM 幻想一段假设答案(允许它"编",不要限制)
    hyde_doc = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0.7,  # 稍微高一点,让它写得更"像真实文档"
        messages=[
            {"role":"system","content":(
                "你是一个资深文档撰写者。请根据用户的问题,"
                "写一段约 300 字的理想答案文档片段。"
                "不要做任何免责声明,直接陈述事实。"
                "即使你不确定具体数据,也要按照该领域权威文档的风格写。"
            )},
            {"role":"user","content": user_query},
        ],
        max_tokens=800,
    ).choices[0].message.content or ""

    # 第二步:把这段幻想文档拿去做 Embedding(和知识库用同一个 Embedding 模型)
    hypo_vec = client.embeddings.create(
        model="text-embedding-3-large", input=hyde_doc
    ).data[0].embedding

    # 第三步:用假设文档的 vec 去向量库检索真实 Top-K
    real_docs = vector_db.search(hypo_vec, top_k=n_docs + 20)
    return real_docs, hyde_doc  # hyde_doc 可以返回给前端做调试展示

适用/不适用场景 + 进阶技巧

适用

  • 用户 Query 很短 / 口语化(“唯元智创咋收费的?“这种)
  • 知识库文档很专业、冗长(白皮书、法律合同、产品手册)
  • 你发现”用户换个问法同样答案排名差别巨大”(鲁棒性差)

不适用

  • 用户 Query 本身就是”答案腔”(用户直接粘贴了一段文档问”这在哪页”)——直接 Embedding 更好
  • 极致低延迟(HyDE 多一次 LLM 调用,多 0.5–2 秒延迟)——可以把 HyDE 作为”首屏没结果时的降级补召”,不放在主路径

进阶技巧

  1. 多 HyDE 融合:一次生成 3 条不同假设答案(Temperature=0.9 多样),取 3 个向量的均值 / 做 3 次检索再 RRF 融合,Recall 再 +5–10%。
  2. HyDE Prompt 按领域定制:法律场景就说”请写成《XX 合同条款释义》的风格”;产品场景就”请写成产品官方 Documentation 风格”。和知识库真实文风越像,HyDE 的收益越大。
  3. 唯元智创 RAG 管线:已内置 HyDE 开关 + 多 HyDE 融合 + 调试可视化(后台 UI 能看到”假设文档长成啥样、最终召回的 Top-10 分数”),一行参数就打开。

常见问题

HyDE 生成的是幻觉内容,不会把检索带偏吗?
一般不会。关键理解:HyDE 只影响”Embedding 空间的相似度排序”,不会把幻觉内容喂给最终生成阶段的 LLM。只要你的 HyDE 写完了就丢弃,只拿它的向量去搜真实知识库,最后给 LLM 的全是真实文档原文,事实错误会被覆盖。唯一可能带偏的极端情况:你知识库根本就没有相关文档 + HyDE 把相似性”引导”到了错误主题——此时可以和原 Query Embedding 做混合检索(加权平均或 RRF)来兜底。
HyDE 应该用强模型还是便宜模型跑?
推荐中等偏便宜:gpt-4o-mini / Qwen2.5 14B 这个级别性价比最高。原因:我们要的是”像文档的腔调和用词”,不是”事实正确性”——这个级别模型足以写出”像真实答案的文风、长度、术语搭配”;再贵的模型(GPT-4o/Claude)主要提升的是事实准确性,对 HyDE 的文风帮助不大,白白多花 5–10 倍钱。
HyDE 和 Query Expansion(查询扩展)是一回事吗?
思路同源但程度不同。Query Expansion 通常是给原 Query 补近义词、同义词(把”笔记本”扩展到”笔记本电脑/Notebook/Laptop”);HyDE 是直接让 LLM “写一整篇答案出来”再去嵌入。HyDE 是一种极端的、由生成模型驱动的 Query Expansion。实践上两者可以叠加:先做关键词扩展,再 HyDE,再融合两个向量检索结果——这在 BEIR 公开榜上是当前 SOTA 级别的召回组合。