LangChain 实现灵活 Agents 与 RAG 集成实战
背景与目标
在传统的检索增强生成(RAG)系统中,通常的做法是无论用户问题是否涉及外部知识,都会强制调用检索器去查询向量数据库。这种机制虽然保证了信息的准确性,但在处理通用对话或模型自身已掌握的知识时,会引入不必要的延迟和成本。
为了优化这一过程,我们需要让程序具备判断能力:仅在必要时才去检索,不必要时直接使用大模型的原有数据来回答。本文将介绍如何使用 LangChain 的 Agents(智能体)模块,将 Retriever(检索器)封装为工具,赋予大模型自主决定是否使用检索能力的权限。
1. 构建基础检索器 (Retriever)
首先,我们需要一个可用的检索器实例。这通常涉及加载文档、分块、向量化并存储到向量数据库中。以下是基于 Web 页面内容的标准构建流程:
import bs4
from langchain import hub
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 加载网页内容
loader = WebBaseLoader(
web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("post-content", "post-title", "post-header")
)
),
)
docs = loader.load()
# 文本分块
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 创建向量库
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
# 初始化检索器
retriever = vectorstore.as_retriever()
在此步骤中,我们使用了 WebBaseLoader 加载特定博客文章,并通过 RecursiveCharacterTextSplitter 进行文本切分,最后利用 Chroma 向量数据库存储嵌入向量。生成的 对象将在后续作为 Agent 的工具被调用。


