概览
LLM 最强大的应用之一是复杂的问答 (Q&A) 聊天机器人。这些应用程序可以回答有关特定源信息的问题。这些应用程序使用一种称为检索增强生成 (RAG) 的技术,或 RAG。 本教程将展示如何基于非结构化文本数据源构建一个简单的问答应用程序。我们将演示:概念
我们将涵盖以下概念:- 索引 (Indexing):用于从源中提取数据并对其进行索引的管道。这通常发生在单独的过程中。
- 检索和生成 (Retrieval and generation):实际的 RAG 过程,它在运行时接收用户查询并从索引中检索相关数据,然后将其传递给模型。
预览
在本指南中,我们将构建一个应用程序来回答有关网站内容的问题。我们将使用的特定网站是 Lilian Weng 的 LLM Powered Autonomous Agents 博客文章,该文章允许我们针对帖子的内容进行提问。 我们可以用约 40 行代码创建一个简单的索引管道和 RAG 链来实现这一点。请参阅下面的完整代码片段:展开以查看完整代码片段
展开以查看完整代码片段
设置
安装
本教程需要这些 langchain 依赖项:LangSmith
您使用 LangChain 构建的许多应用程序将包含多个步骤,其中涉及多次 LLM 调用。随着这些应用程序变得越来越复杂,能够检查链或 Agent 内部究竟发生了什么变得至关重要。最好的方法是使用 LangSmith。 在上面的链接注册后,请确保设置环境变量以开始记录跟踪:组件
我们需要从 LangChain 的集成套件中选择三个组件。 选择聊天模型:- OpenAI
- Anthropic
- Azure
- Google Gemini
- Bedrock Converse
- OpenAI
- Azure
- AWS
- VertexAI
- MistralAI
- Cohere
- Memory
- Chroma
- FAISS
- MongoDB
- PGVector
- Pinecone
- Qdrant
- Redis
1. 索引
索引通常按如下方式工作:- 加载 (Load):首先我们需要加载数据。这是通过 Document Loaders 完成的。
- 拆分 (Split):文本拆分器 将大型
Documents拆分为更小的块。这对于索引数据和将其传递给模型都很有用,因为大块更难搜索,并且无法放入模型的有限上下文窗口中。 - 存储 (Store):我们需要一个地方来存储和索引我们的拆分,以便以后可以搜索它们。这通常使用 VectorStore 和 Embeddings 模型来完成。

加载文档
我们需要首先加载博客文章内容。我们可以为此使用 DocumentLoaders,它们是从源加载数据并返回 Document 对象列表的对象。DocumentLoader:将数据从源加载为 Documents 列表的对象。
- 集成:160+ 集成可供选择。
BaseLoader:基本接口的 API 参考。
拆分文档
我们加载的文档超过 42k 个字符,太长了,无法放入许多模型的上下文窗口中。即使对于那些可以在上下文窗口中容纳整篇文章的模型,模型也很难在非常长的输入中找到信息。 为了处理这个问题,我们将把Document 拆分成块以进行嵌入和向量存储。这应该有助于我们在运行时仅检索博客文章中最相关的部分。
正如在 语义搜索教程 中一样,我们使用 RecursiveCharacterTextSplitter,它将使用常见的分隔符(如换行符)递归地拆分文档,直到每个块的大小合适。这是用于通用文本用例的推荐文本拆分器。
存储文档
现在我们需要索引我们的 66 个文本块,以便我们可以在运行时搜索它们。按照 语义搜索教程,我们的方法是 嵌入 每个文档拆分的内容,并将这些嵌入插入到 向量存储 中。给定输入查询,我们就可以使用向量搜索来检索相关文档。 我们可以使用在 教程开始 时选择的向量存储和嵌入模型,在一个命令中嵌入和存储所有文档拆分。Embeddings:文本嵌入模型的包装器,用于将文本转换为嵌入。
VectorStore:向量数据库的包装器,用于存储和查询嵌入。
这完成了管道的 索引 部分。此时,我们有一个可查询的向量存储,其中包含我们博客文章的分块内容。给定一个用户问题,我们理想情况下应该能够返回回答该问题的博客文章片段。
2. 检索和生成
RAG 应用程序通常按如下方式工作:
RAG Agents
RAG 应用程序的一种形式是作为一个带有检索信息工具的简单 Agent。我们可以通过实现一个包装向量存储的 工具 来组装一个最小的 RAG Agent:- 生成查询以搜索任务分解的标准方法;
- 收到答案后,生成第二个查询以搜索它的常见扩展;
- 收到所有必要的上下文后,回答问题。
RAG 链
在上面的 Agentic RAG 公式中,我们允许 LLM 酌情生成 工具调用 以帮助回答用户查询。这是一个很好的通用解决方案,但也有一些权衡:| ✅ 优点 | ⚠️ 缺点 |
|---|---|
| 仅在需要时搜索 – LLM 可以处理问候、后续跟进和简单查询,而无需触发不必要的搜索。 | 两次推理调用 – 执行搜索时,需要一次调用生成查询,另一次调用生成最终响应。 |
上下文搜索查询 – 通过将搜索视为具有 query 输入的工具,LLM 会根据对话上下文构建自己的查询。 | 控制力降低 – LLM 可能会在实际需要时跳过搜索,或者在不需要时发出额外的搜索。 |
| 允许多次搜索 – LLM 可以执行多次搜索以支持单个用户查询。 |
返回源文档
返回源文档
上面的 RAG 链 将检索到的上下文合并到该运行的单个系统消息中。正如在 Agentic RAG 公式中一样,我们有时希望在应用程序状态中包含原始源文档以访问文档元数据。我们可以通过以下方式对两步链情况执行此操作:
- 向状态添加一个键来存储检索到的文档
- 通过 pre-model hook 添加一个新节点来填充该键(以及注入上下文)。
下一步
现在我们已经通过createAgent 实现了一个简单的 RAG 应用程序,我们可以轻松地合并新功能并深入了解:
- 流式传输 token 和其他信息以获得响应式用户体验
- 添加 对话记忆 以支持多轮交互
- 添加 长期记忆 以支持跨对话线程的记忆
- 添加 结构化响应
- 使用 LangSmith Deployment 部署您的应用程序
将这些文档连接 到 Claude、VSCode 等,通过 MCP 获得实时解答。

