深入学LangChain 官方文档(十一)Retrieval 检索入口首

深入学 LangChain 官方文档(十一)Retrieval 检索入口首讲

本篇对应的官方文档

本篇讲解范围

本篇主要从"客服怎样依据最新退款政策回答"出发,建立索引与查询双阶段、Retrieval 与 RAG 的关系、三类 RAG 架构及最小代码闭环。生产向量数据库选型、复杂 rerank、多模态检索、Graph RAG 和完整评测平台留给后续专题。

上一章把执行政策放到了明确的调用边界,新的问题马上跟了上来:模型需要回答的内容,未必已经在当前上下文里。

用户问客服 Agent:"耳机已经拆封,还能七天无理由退货吗?"模型当然能直接给出一句话,但这句话很难让人放心。

退款政策会更新,不同商品可能有例外,企业内部规则也不在模型训练数据里。即使碰巧答对,系统仍然解释不了它依据的是哪个版本、哪一条规定。

Retrieval(检索)改变的是回答前的信息路径,不需要修改模型参数。问题到来后,系统先从外部知识源取回相关证据,再把数量有限、来源可追踪的内容交给模型。

检索和生成接在一起,才是通常所说的 Retrieval-Augmented Generation,也就是 RAG(检索增强生成)。

这里有两个词要抓住。"运行时"意味着知识不必在训练阶段进入模型;"相关"意味着系统只取当前问题需要的片段,不会把整本政策手册塞进上下文。

接下来沿着取证链往下拆:先划清 Retrieval、Memory 与业务数据库的责任,再把原始政策处理成带来源的 Document 和 chunk。

随后看 embedding、vector store 与 retriever 怎样返回候选证据,最后比较三类 RAG 架构,并把空结果、噪声、过期和越权放进工程验收。

闭卷回答依赖模型已有参数,无法跟随企业政策更新;运行时取证会在问题到来后查询当前知识源,把相关片段连同来源一起交给模型。RAG 的增量不是笼统地"知道更多",而是让本次回答建立在可更新、可追踪的外部证据上。

沿着取证路径继续走,第一步是把"找证据"和"写答案"分开。

一、Retrieval 负责取证,RAG 负责基于证据生成

官方文档先点出模型的两项限制:上下文窗口装不下整个语料库,训练得到的知识也不会自动跟随企业政策更新。Retrieval 接收查询,从外部系统取回相关信息,正面处理这两个限制。

但检索结果还不是面向用户的回答。它通常是一组 Document,每个对象包含 page_content 和可选 metadata

应用还要决定片段怎样整理、放进哪一段 model context,以及证据不够时怎样要求模型停止猜测。把检索、注入和生成连起来,才构成 RAG。

三者的输出边界很清楚:

  • Retrieval 的输出是候选证据;
  • Generation 的输出是面向用户的回答;
  • RAG 的质量取决于证据能否被正确取回,也取决于模型是否只在证据边界内作答。

如果检索漏掉"拆封耳机不适用"的例外条款,模型写得再流畅也补不回来。反过来,正确条款已经取回,prompt 却允许模型随意混入常识,答案还是会跑出证据范围。

所以 RAG 不是接上向量库就结束,而是一条要逐段验收的证据供应链。

二、Retrieval、Memory 与业务数据库各自回答不同问题

第 09 篇讲过 Memory 以后,很容易把所有"将来还要读取的信息"放进同一个概念。退款政策、用户偏好和订单状态确实都会再次出现,责任却完全不同。

Retrieval 回答"当前问题需要哪些外部知识证据",适合政策、手册、FAQ、技术文档和历史报告。

Memory 保存的是用户或线程已经发生的内容,以及可以复用的偏好,例如用户希望中文简洁回答。业务数据库维护当前权威事实,例如订单是否发货、退款是否到账。

一次客服回答可能同时用到三类信息。此时要看的是每条路径最终对哪类事实负责,而不是底层用了什么存储产品。

政策条款从知识库检索,表达偏好从 Memory 读取,订单状态回交易系统查询,三条路径分别承担知识证据、交互连续性和业务真相。把业务事实向量化后当作唯一答案,或把政策正文塞进用户记忆,都会让更新与权威边界失控。

有些企业已经建好了 SQL、CRM、文档搜索或内部知识 API。使用 LangChain 并不要求把这些系统全部搬进新的向量库。

现有系统可以直接作为 Agentic RAG 的工具,也可以由确定性步骤先查,再把结果注入 2-Step RAG。LangChain 提供的是组合接口,不是强制迁移方案。

三、检索系统分成索引阶段和查询阶段

最小语义检索系统包含两条发生时间不同的链路。

索引阶段读取原始资料,把文件、网页或数据库记录转成标准 Document。长文档经过 text splitter 切成更小的 chunk,embedding model 再把文本映射为向量,vector store 同时保存向量、原文与 metadata。

这条链路随政策发布或更新运行,不会在每次用户提问时重做整本手册。

查询阶段才发生在用户提问时。问题被映射到同一向量空间,系统执行相似度搜索或 retriever 查询,取回少量候选 Document,再交给后面的 RAG 链路。

两阶段共用 embedding 语义和 metadata 规则,负载、延迟与失败方式却不相同。

索引链把来源文档处理成可搜索的向量和元数据,查询链只处理当前 query 并返回 top-k Document。索引失败会造成知识缺失或过期,查询失败则表现为空结果、低相关结果或延迟,两条链必须分开监控。

这个区分会直接影响更新策略。退款政策第 3.2 条修改后,应该只重建受影响的文档或 chunk,并更新版本字段。没有稳定文档 ID 却反复全量追加,很容易留下新旧重复。

查询端面对的是另一组约束:租户、语言、商品分类和生效日期都可能进入过滤条件,不能只凭语义相似度取前几名。

四、Document、chunk 与 metadata 共同定义证据单元

LangChain 用 Document 统一表达检索内容。page_content 保存参与搜索和生成的正文。

metadata 则保存回溯和过滤需要的信息,例如 sourcesectionversioneffective_datetenant_id 与权限标签。

原始政策通常太长,需要先切分。chunk 过大,一个向量会混入多个主题,查询"耳机拆封"可能拉回整章售后制度;chunk 过小,主规则与例外条件又会被拆开,模型只看见"支持七天退货",漏掉下一句"不适用于拆封音像和特定卫生商品"。

政策被切成可以独立召回的 chunk,每个 chunk 同时保留正文与来源、章节、版本、生效日期等 metadata。切分边界决定语义是否完整,metadata 决定结果能否过滤、引用、更新和删除,两者共同构成证据单元。

切分不只是字符计数。标题层级、段落、表格行、代码块和条款编号都可能是语义边界。初期可以用通用 splitter 建立基线,再拿真实问题观察:命中片段能否独立表达判断,前后文是否必须一起返回,重复 chunk 是否挤占 top-k。

metadata 也不能只留文件名。客服答案要引用"2026-07 版售后政策 3.2 条",这些字段就必须在索引阶段保存。华东租户只能读取自己的内部政策时,tenant_id 过滤要在检索前生效,不能等内容取回后再让模型忽略。

文档生命周期还需要稳定标识。可以给原始文档保存 document_id,切分结果保存可重复计算的 chunk_id,再记录内容哈希。

政策只改一节时,索引任务就能删掉旧 chunk、写入新 chunk,而不是把整份文件又追加一遍。缺少稳定 ID 的知识库看似结果丰富,实际可能是同一条款的三个历史版本一起占满 top-k。

删除也属于索引合同。员工手册撤回、租户解除授权或用户要求删除资料后,原文件、向量、缓存与派生摘要都要同步处理。只在 metadata 标记"已删除",旧向量却仍能进入候选集,等于把合规问题推给生成阶段。

可靠知识库必须回答得出:一条证据从哪里来,现在是否有效,还有哪些派生数据需要一起失效。

五、embedding 搜索的是语义邻近,不是事实正确

embedding model 把文本转成数值向量。语义相近的文本通常会落在更近的位置,所以用户问"拆开包装还能退吗",也可能命中"商品启封后不适用无理由退货",两边不需要使用完全相同的关键词。

query 与文档 chunk 经同一 embedding model 进入向量空间,"拆开包装"和"商品启封"因为语义接近而距离更近。这个距离只表示相关性,不能证明条款有效、来源可信或答案正确;版本与权限仍由 metadata 和业务规则约束。

相似度不是事实置信度。旧条款可能与问题高度相似,却早已失效;营销文章可能更贴近用户措辞,却不具备政策权威性;互相冲突的文档也可能一起进入前几名。

VectorStore 通常支持字符串或向量查询、同步或异步调用、是否返回分数,以及 similarity 或 maximum marginal relevance 等策略。

similarity_search(query, k=4) 只是起点,生产系统还要叠加 metadata filter、最小相关阈值、去重与多源排序。

Retriever 把"给定非结构化 query,返回一组 Document"抽象成统一接口。内部可以使用向量搜索、关键词检索、数据库查询、外部搜索服务,甚至组合多个 retriever。上层 RAG 只依赖返回的 Document,底层策略就可以替换。

这层抽象也方便测试。开发阶段可以用内存向量库验证消息与生成链路,生产时再换成企业搜索 API;只要 Document 与 metadata 合同不变,上层无需重写。

反过来,工具只返回一段没有来源边界的长字符串,后续的过滤、引用、去重和评测就都失去了对象。

候选形成可以拆成四步:先应用租户与权限过滤,再计算语义相关性;随后选择 top-k 或兼顾多样性的结果;最后检查分数、来源和重复度,判断证据是否足够进入生成。

检索不是从全库直接抓几个最近向量。租户、权限、版本和生效日期先缩小合法候选集,相似度与多样性策略再形成 top-k。过滤过晚会产生越权,k 过小容易漏掉例外,k 过大则会把噪声带进上下文。

候选证据下一步怎样进入模型,取决于检索固定发生在生成之前,还是由 Agent 或校验循环决定检索时机。

六、三类 RAG 架构的差别在"谁决定何时检索"

官方总览把常见 RAG 分成 2-Step、Agentic 和 Hybrid。三者可以共用同一个知识库,区别落在检索时机、控制权和验证步骤。

2-Step RAG:每次回答前固定检索。 用户问题先进入 retriever,证据和问题再一起交给模型。调用次数有上限,延迟比较可预测,适合 FAQ、文档问答和"没有证据就不应回答"的场景。

代价是用户只说"谢谢"时也可能触发无用检索,复杂问题通常也只有一次查询机会。

2-Step 的固定路径是 query → retrieve → context → model → answer。检索一定发生,控制强、调用数可预测;答案质量也直接受单次 query、top-k 和上下文拼装影响。

Agentic RAG:把检索暴露为工具。 Agent 先判断当前问题是否需要外部知识,第一次结果不足时还可以改写 query 再查。

研究助手、多知识源或需要在检索与其他工具间交替的任务更适合这种方式。代价是延迟和调用次数不稳定,还要防止 Agent 跳过检索、反复检索或选错知识源。

Agent loop 把 retriever 当作工具,模型根据当前 messages 决定是否查询以及查询什么,Document 再以 ToolMessage 回到下一轮推理。检索时机更灵活,也因此需要调用限制、准确的工具描述和无证据拒答规则。

Hybrid RAG:在固定链和 Agent 之间加入校验。 常见流程先改写含糊问题,检索后判断相关性,不足时重新检索,生成后再检查答案是否得到证据支持。它适合质量要求高的行业问答,但每个判断节点都会增加成本,循环也必须有明确上限。

Hybrid 在检索前后加入 query 改写、相关性判断和答案校验,证据不足就回到检索,不让模型直接补全。循环换来更强控制,也必须设置终止条件并记录每次改写,避免质量检查演变成无限调用。

选择架构时不用按"高级程度"排序。退款政策每次都必须引用文档,2-Step 往往简单可靠;需要跨多个来源调查原因时,Agentic 更灵活;监管场景要求证据校验和稳定拒答,再考虑加入 Hybrid 节点。

七、把检索结果注入上下文时,要保留来源边界

拿到 Document 以后,常见做法是把若干 page_content 拼成 context,再连同用户问题交给模型。片段不是越多越好,至少要保留明确的分隔、来源标识和指令边界。

可以为每个片段编号,并附上 source、section、version。system prompt 要求模型只根据这些片段回答,证据不够时说明缺少依据,关键结论引用对应编号。这样做不能从数学上消灭幻觉,却让追踪和评测有了具体对象。

多个片段共同构成一个判断时,还要处理它们之间的关系。主规则和例外条款分别命中,不能简单按分数排序后截断。

可以恢复同一章节的邻近片段,或用 metadata 把条件和结论放回一起。不同版本彼此冲突时,也应由应用先判断有效版本,而不是交给模型碰运气。

Token 预算要在拼装前确定。系统指令、用户问题、检索证据和回答分别预留空间,再在证据预算内按相关性、权威性与多样性挑选片段。把 k 从 4 直接提到 20 往往只会增加延迟和噪声;每个进入 model context 的 chunk 都应该补充一条必要证据。

答案引用最好绑定内部文档 ID,不要只让模型手写"来源:售后政策"。生成后,应用根据引用 ID 渲染标题和链接,并核对该 ID 确实属于本轮候选集。文档以后移动或改名,追踪关系仍然存在,模型也更难凭空编造来源。

知识片段中即使出现"忽略之前规则",它仍然是待引用的数据,不会因此升级为系统指令。消息层级和分隔格式要足够清楚,敏感工具权限也不能交给检索文本决定。Retrieval 负责提供知识,没有权限改写 Agent 的控制政策。

八、四类失败需要回到不同环节修复

RAG 回答错误时,先改 prompt 往往治标不治本。把失败归类以后,才能找到真正需要修复的位置。

空结果:用户措辞与文档差异太大、过滤过严、索引漏文档或阈值过高。应该检查索引覆盖、query 改写和 filter,不能让模型在空 context 里猜。

噪声结果:chunk 过大、k 过高、重复文档太多或来源混杂。修复点在切分、去重、rerank 和来源权重。

过期冲突:新旧政策并存,或两个权威来源结论不同。需要用版本、生效日期和权威等级过滤,无法自动裁决的冲突要交给用户或人工流程。

越权结果:权限过滤发生在向量搜索之后,或缓存键没有包含租户和角色。模型的一句"不要泄露"挡不住这种错误,非法文档必须在检索层就被排除。

空结果回查索引覆盖和 query,噪声回查切分与排序,过期冲突回查版本治理,越权回查过滤与缓存隔离。它们都会表现成"模型答错",真正的修复位置却分布在四条不同路径上。

失败责任清楚以后,最小代码只需要保留建库、查询、返回证据和生成回答四个动作。

九、最小代码闭环:先建证据库,再让 Agent 按需检索

示例用三条简化政策构建内存向量库。Document.metadata 保存条款和版本,search_refund_policy 把检索封装成工具;Agent 收到问题以后自行决定是否调用,再根据工具结果回答。

python 复制代码
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_core.documents import Document
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_openai import ChatOpenAI, OpenAIEmbeddings


documents = [
    Document(
        page_content="未拆封商品自签收次日起七日内可申请无理由退货。",
        metadata={"section": "3.1", "version": "2026-07", "source": "售后政策"},
    ),
    Document(
        page_content="耳机等直接接触皮肤的商品,包装启封后不适用无理由退货。",
        metadata={"section": "3.2", "version": "2026-07", "source": "售后政策"},
    ),
    Document(
        page_content="商品存在质量问题时,可提交检测结果进入质量退货流程。",
        metadata={"section": "4.1", "version": "2026-07", "source": "售后政策"},
    ),
]

vector_store = InMemoryVectorStore(
    embedding=OpenAIEmbeddings(model="text-embedding-3-small")
)
vector_store.add_documents(documents)


@tool
def search_refund_policy(query: str) -> str:
    """检索当前退款政策,并返回带条款和版本的候选证据。"""
    results = vector_store.similarity_search(query, k=2)
    if not results:
        return "未检索到可用政策;不要根据常识回答。"

    return "\n\n".join(
        f"[{doc.metadata['source']} {doc.metadata['version']} "
        f"第{doc.metadata['section']}条]\n{doc.page_content}"
        for doc in results
    )


model = ChatOpenAI(
    model="qwen3.7-plus",
    api_key="YOUR_API_KEY",
    base_url="YOUR_OPENAI_COMPATIBLE_ENDPOINT",
)

agent = create_agent(
    model=model,
    tools=[search_refund_policy],
    system_prompt=(
        "回答退款问题前先检索政策。只依据工具返回的条款作答;"
        "证据不足时明确说明,并在结论后标注条款与版本。"
    ),
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "耳机拆封后还能无理由退货吗?"}]}
)
print(result["messages"][-1].content)

输入先进入 Agent loop。模型根据工具描述生成 search_refund_policy 调用,工具用 query 做相似度搜索,返回两个带 metadata 的证据片段。

工具结果进入下一轮模型调用,最终答案从 result["messages"][-1] 取得。

没有结果时,工具明确返回"不要根据常识回答",让空证据成为一条可见状态。

这段代码只实现最小机制。生产系统还要在搜索前加入租户、权限、版本和生效日期过滤;embedding 与 vector store 需要持久化;结果要记录文档 ID,方便答案追踪。

外部接口失败也要与"确实没有匹配文档"区分。InMemoryVectorStore 适合演示,不能替代生产知识库。

闭环从来源摄取和版本化索引开始,经过权限过滤、语义检索、上下文注入与引用式回答,再把真实问题、命中文档和答案结果交给评测。链路对象都可追踪以后,团队才能判断错误来自知识、检索还是生成。

对象能够逐层追踪,评测也就不能再停留在笼统的答案印象上。

十、评测对象不是"回答好不好"这一项

RAG 至少要分三层评测。检索层检查目标证据是否进入 top-k、无关片段比例、权限和版本过滤;生成层检查答案是否得到证据支持、关键条件有没有遗漏、引用能否对应真实片段;系统层再观察延迟、成本、空结果率与更新时效。

评测集应该来自真实问题,不能只让开发者照着文档标题编写。用户会使用简称、错别字、上下文指代和模糊说法,"拆了还能退吗"比"耳机包装启封后是否适用无理由退货"更接近生产流量。

每个问题最好标记期望证据 ID,而不只是保存一个标准答案,这样检索错误与生成错误才能分开。

上线后还要记录 query、filter、命中文档 ID、分数、版本、最终引用和用户反馈,同时对敏感字段脱敏。文档更新时重跑受影响问题,可以提前发现新版本破坏旧正确答案的回归。

还要单独准备一组系统本来就不该回答的问题:知识库没有覆盖的商品、权限之外的内部政策、无法自动裁决的冲突条款。合格结果是稳定进入拒答、澄清或人工升级,不是勉强给出一句听起来合理的话。把"不知道"纳入评测,RAG 才能堵住召回率之外的猜测缺口。

成本也要按阶段拆开。索引成本随文档更新发生,在线成本来自 query embedding、检索、可能的 rerank 和模型调用。高峰期延迟上升时,只有分别记录各阶段耗时,才能判断向量库变慢、过滤失效,还是 Agent 发起了额外检索。

十一、回到主线:可靠回答始于可靠证据

Retrieval 的机制并不神秘:模型不知道或当前窗口装不下的知识,在问题到来时从外部系统取回。

真正困难的是把它变成可靠供应链------来源要权威,chunk 要语义完整,metadata 要支持版本与权限,查询要召回相关证据,生成要守住证据边界,失败还要能够定位。

实践顺序可以收成一条线:先划清知识、记忆与业务事实的责任;再分开索引和查询;用 Document + metadata 建立可回溯证据;根据控制需求选择 2-Step、Agentic 或 Hybrid RAG;最后从检索、生成和系统三个层次验收。

到这里,单个 Agent 已经拥有模型、工具、状态、记忆、Middleware 和 Retrieval。但能力继续增加,新的压力也会出现:一个上下文窗口要同时装下多少领域知识,一组工具还能不能由同一个角色准确选择,不同团队维护的专业能力又由谁协调?

下一篇我们将进入 Multi-agent 与 Frontend的学习。它不会推倒这些零件,而是继续回答两件事:当单 Agent 的上下文和工具开始过载时,控制权怎样拆分;后端执行状态又怎样变成用户能看懂、能操作的界面状态。

相关推荐
BraveWang1 天前
【LangChain 1.x】08、Agent 核心入门|create_agent、中间件、结构化与流式输出
langchain
qiten_0071 天前
LangChain核心组件深入理解第四篇 -- Tool Agent运行的手和脚
大数据·人工智能·langchain
phltxy1 天前
LangChain文本向量与检索器实践
人工智能·深度学习·语言模型·langchain
phltxy1 天前
LangChain从模型输出到RAG数据管道实战
服务器·人工智能·深度学习·语言模型·langchain
闲猫2 天前
LangChain / Core components / Models
开发语言·python·langchain
早点睡啊Y2 天前
深入学 LangChain 官方文档(一):总览、安装与快速开始
linux·服务器·langchain
知行合一。。。2 天前
LangChain--08--中间件(Middleware)
中间件·langchain
fenglllle2 天前
langchain简单对话demo
人工智能·langchain
早点睡啊Y2 天前
深入学LangChain 官方文档(五)Agent 核心循环首讲
langchain