HyDE 检索策略学习笔记

5 阅读3分钟

一、是什么?

HyDE(Hypothetical Document Embeddings,假设性文档嵌入)是一种 RAG 增强检索策略。

传统检索直接用用户的问题去匹配文档,而 HyDE 先让 LLM 根据问题生成一段假设性回答,再用这段回答去向量库中检索真实文档。

核心思想:用「像答案的文本」去找答案,语义更贴近,检索效果更好。

流程对比:

传统检索HyDE 检索
检索输入原始用户问题LLM 生成的假设性回答
语义匹配问题与文档可能有差距回答与文档语义更接近
额外消耗一次 LLM 调用

二、有什么用?

  • 用户问题模糊或较短,难以直接匹配文档
  • 知识库内容专业性强,与日常问法差异大
  • RAG 系统召回率不佳,需要提升检索质量
  • 适用于企业知识库问答、技术文档检索、智能客服等场景

三、核心组件

1. WeaviateVectorStore(向量数据库)

Weaviate 是开源向量数据库,LangChain 通过 WeaviateVectorStore 封装了存储和检索接口。

  • index_name:Weaviate 中的集合名称
  • text_key:存储原始文本的字段名
  • embedding:向量化模型(此处用千帆 Embeddings)
  • search_type="mmr":MMR 算法,兼顾相关性与结果多样性

2. HyDERetriever(自定义检索器)

继承 BaseRetriever,重写 _get_relevant_documents 方法实现 HyDE 逻辑。

3. LCEL 检索链

用 LangChain Expression Language(管道符 |)串联各组件,数据流如下:

用户 query
   ↓
RunnablePassthrough()      # 透传原始问题
   ↓
ChatPromptTemplate         # 构造生成假设回答的 prompt
   ↓
LLM(moonshot-v1-8k)      # 生成假设性回答文本
   ↓
StrOutputParser()          # 解析 LLM 输出为字符串
   ↓
Retriever(Weaviate MMR)  # 用假设回答检索真实文档
   ↓
返回 List[Document]

四、示例代码

python

from typing import List

import dotenv
import weaviate
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from langchain_core.language_models import BaseLanguageModel
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.retrievers import BaseRetriever
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI
from langchain_weaviate import WeaviateVectorStore
from weaviate.auth import AuthApiKey
from langchain_community.embeddings import QianfanEmbeddingsEndpoint

dotenv.load_dotenv()


class HyDERetriever(BaseRetriever):
    """HyDE 混合策略检索器"""
    retriever: BaseRetriever
    llm: BaseLanguageModel

    def _get_relevant_documents(
            self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List[Document]:
        # 1. 构建生成假设性文档的 prompt
        prompt = ChatPromptTemplate.from_template(
            "请用一段简洁的话(100字以内)来回答这个问题。\n"
            "问题: {question}\n"
            "回答: "
        )

        # 2. 构建 HyDE 检索链
        chain = (
                {"question": RunnablePassthrough()}
                | prompt
                | self.llm
                | StrOutputParser()
                | self.retriever
        )

        return chain.invoke(query)


# 1. 构建向量数据库与检索器
db = WeaviateVectorStore(
    client=weaviate.connect_to_wcs(
        cluster_url="<YOUR_CLUSTER_URL>",
        auth_credentials=AuthApiKey("<YOUR_API_KEY>"),
    ),
    index_name="DatasetDemo",
    text_key="text",
    embedding=QianfanEmbeddingsEndpoint(),
)
retriever = db.as_retriever(search_type="mmr")

# 2. 创建 HyDE 检索器
hyde_retriever = HyDERetriever(
    retriever=retriever,
    llm=ChatOpenAI(model="moonshot-v1-8k", temperature=0),
)

# 3. 执行检索
documents = hyde_retriever.invoke("关于 LLMOps 应用配置的文档有哪些?")
print(documents)
print(len(documents))

五、关键知识点

知识点说明
BaseRetrieverLangChain 自定义检索器基类,重写 _get_relevant_documents 即可接入任意链路
`LCEL 管道符`LangChain Expression Language,用 `` 连接组件,数据从左向右流动
RunnablePassthrough透传输入值,常用于在字典结构中保留原始 query
StrOutputParser将 LLM 返回的 AIMessage 对象转为纯字符串
MMR 算法Maximum Marginal Relevance,检索时兼顾相关性和多样性,避免返回重复文档
temperature=0使 LLM 输出稳定确定,适合生成假设性文档等任务