基于LangChain1.0最新版API,构建了RAGAgent智能检索问答系统。系统集成大语言模型、文本嵌入模型与向量存储器,实现网页文档加载、递归分片及向量入库。提供工具调用型与上下文注入型两种Agent方案,分别适用于复杂多轮问答与简单单轮场景,代码完整可运行。
本文代码均为可直接运行的完整代码,基于LangChain最新版API编写,无过时语法,放心食用~

长期稳定更新的攒劲资源: >>>点此立即查看<<<
在大型语言模型落地应用中,RAG(检索增强生成)技术占据重要位置。它有效解决了大模型“知识过时、胡编乱造、领域知识不足”等关键短板。本文将手把手搭建一套基于LangChain的RAG Agent智能检索问答系统,覆盖从依赖安装到两种主流实现方案的全部步骤,附带完整可运行代码,可即拿即用。
使用以下命令一次性安装核心依赖:
pip install langchain langchain-text-splitters langchain-community bs4 python-dotenv
安装完成后,即可开始配置三大核心组件。
构建RAG Agent的本质是组装三个核心模块:对话大模型、文本嵌入模型、向量存储器。以下逐一配置。
# 导入对话模型及环境变量配置依赖from langchain_openai import ChatOpenAIimport osfrom dotenv import load_dotenv# 加载.env文件中的环境变量(私密密钥管理,规范开发)load_dotenv()# 配置通义千问大模型(qwen-max)参数model_name = "qwen-max"api_key = os.getenv("DASHSCOPE_API_KEY")base_url = os.getenv("DASHSCOPE_BASE_URL")# 初始化聊天模型:低随机性保证回答严谨,适配知识类问答场景model = ChatOpenAI(model=model_name,api_key=api_key,base_url=base_url,temperature=0.1,# 温度值越低,回答越精准、确定性越强)
temperature设为0.1,属于低随机性设置,确保回答精准、不跑偏。知识问答场景下此设置尤为重要。
# 导入HuggingFace嵌入模型from langchain_huggingface import HuggingFaceEmbeddings# 初始化嵌入模型,行业主流轻量级高质量选型# 特点:文本表征能力强、适配中文+英文,首次运行自动缓存至本地,无需重复下载embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
嵌入模型选用all-mpnet-base-v2,轻量且性能优秀,同时支持中英文。首次运行会自动缓存至本地,后续无需重复下载。
# 导入内存级向量存储库from langchain_core.vectorstores import InMemoryVectorStore# 初始化内存向量库,轻量化无部署,无需持久化磁盘,适合快速开发/演示场景# 绑定已初始化的嵌入模型,实现文本-向量的自动转换与匹配vector_store = InMemoryVectorStore(embeddings)
内存级向量库在开发演示阶段使用便捷,无需部署与持久化。若需用于生产环境,可替换为Chroma或Pinecone等持久化向量库。
RAG的核心前置步骤是将网页上的非结构化文本转化为结构化的向量知识库。整个流程分为三步,每步均为标准做法。
# 导入网页加载器及网页解析依赖import bs4from langchain_community.document_loaders import WebBaseLoader# 网页解析规则:只提取指定class的核心内容(标题/头部/正文),过滤冗余HTML标签,提升数据质量bs4_strainer = bs4.SoupStrainer(class_=("post-title", "post-header", "post-content"))# 初始化网页加载器,指定爬取路径+解析规则loader = WebBaseLoader(web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),bs_kwargs={"parse_only": bs4_strainer},)# 加载网页文档至上下文docs = loader.load()# 校验加载结果:确保成功加载1篇文档assert len(docs) == 1# 输出文档总字符数,直观查看文本体量print(f" 文档加载完成,总字符数:{len(docs[0].page_content)}")
此处仅抓取post-title、post-header、post-content三个class的内容,过滤无关页面元素,提升数据质量。
# 导入递归字符分割器from langchain_text_splitters import RecursiveCharacterTextSplitter# 初始化文本分割器,采用行业最优的递归分割策略text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000,# 单个文本块最大字符数,适配嵌入模型输入长度限制chunk_overlap=200,# 相邻文本块重叠字符数,避免关键信息被截断,保留上下文关联性add_start_index=True, # 记录文本块在原始文档中的起始索引,便于溯源匹配内容)# 对加载的文档进行分片处理all_splits = text_splitter.split_documents(docs)# 输出分片结果print(f" 文档分片完成,原始文档切分为 {len(all_splits)} 个子文档")
chunk_size=1000、chunk_overlap=200的参数组合效果良好:既保证单个文本块长度适中,又避免关键信息被截断。同时记录起始索引,便于后续溯源。
# 将所有文本分片存入向量存储器,自动完成「文本→向量」转换+存储document_ids = vector_store.add_documents(documents=all_splits)# 预览前3个文本块的唯一标识IDprint(f" 向量入库完成,文本块ID预览:{document_ids[:3]}")
入库步骤完全自动化,将分好的文本块导入向量库即可完成知识库构建。输出前三个ID用于确认。
RAG的精髓在于:大模型回答问题时,先到知识库检索相关信息,再基于检索内容生成答案。以下提供两种工业界主流方案,按需选用,均可直接运行。
自定义一个检索工具,让大模型自主决定何时调用它,然后基于检索结果生成答案。此方式具备“工具调用思维”,尤其适合复杂多轮问答或多步骤查询场景,灵活性极强。
# 导入工具装饰器,封装自定义检索工具from langchain.tools import tool# 封装检索工具:返回检索到的上下文内容+原始文档对象,指定返回格式规范def retrieve_context(query: str):"""核心检索工具:根据用户查询语句,从向量库中检索相关上下文信息,辅助回答问题"""# 相似度检索:返回匹配度最高的2条文本内容(k值可按需调整)retrieved_docs = vector_store.similarity_search(query, k=2)# 格式化拼接检索结果:带上元数据+文本内容,提升大模型理解效率serialized_context = "nn".join((f"Source: {doc.metadata}nContent: {doc.page_content}")for doc in retrieved_docs)# 返回格式化文本 + 原始文档,兼顾可读性与溯源性return serialized_context, retrieved_docs# 构建工具调用型智能体from langchain.agents import create_agent# 配置智能体核心参数:绑定大模型+检索工具+系统提示词tools = [retrieve_context]# 系统提示词:明确智能体能力边界与行为准则,精准引导大模型调用工具system_prompt = ("你是一个专业的问答助手,你可以调用检索工具获取外部知识库的上下文信息。n""请务必使用检索工具辅助回答用户的查询问题,确保答案的准确性和事实性。")# 初始化工具调用型RAG Agentagent = create_agent(model, tools, system_prompt=system_prompt)
query = ("What is the standard method for Task Decompositionnn""Once you get the answer, look up common extensions of that method.")print("===== 工具调用型RAG Agent 回答结果 =====")for event in agent.stream({"messages": [{"role": "user", "content": query}]},stream_mode="values",):event["messages"][-1].pretty_print()
此测试案例典型:先问任务分解的标准方法,再问其常见扩展。智能体需自行判断是否调用检索工具,并可能执行多次检索。流式输出可实时观察思考链条,体验直观。
通过中间件(middleware)实现“全自动检索+上下文注入”。无需显式定义工具,智能体在回答前自动完成检索,将结果注入系统提示词。整个过程对开发者透明,代码极简,运行效率高,适用于简单单轮问答场景。
# 构建上下文注入型智能体from langchain.agents.middleware import dynamic_prompt, ModelRequest# 定义动态提示词中间件:自动检索+注入上下文,无感知完成检索逻辑def prompt_with_context(request: ModelRequest) -> str:"""核心中间件:从请求中提取用户最新问题,检索相关上下文并注入系统提示词"""# 提取用户最新的查询语句last_query = request.state["messages"][-1].text# 自动执行相似度检索,获取相关上下文retrieved_docs = vector_store.similarity_search(last_query)# 格式化拼接检索到的文本内容docs_content = "nn".join(doc.page_content for doc in retrieved_docs)# 构造带上下文的系统提示词,让大模型基于外部知识回答system_message = ("你是一个专业且乐于助人的问答助手,请严格基于下方提供的上下文信息回答用户问题:nn"f"{docs_content}")return system_message# 初始化上下文注入型RAG Agent:无需传入工具,中间件自动完成检索逻辑agent = create_agent(model, tools=[], middleware=[prompt_with_context])
# 测试提问:基础单轮查询,验证上下文注入效果query = "What is task decomposition"# 流式输出回答结果print("n===== 上下文注入型RAG Agent 回答结果 =====")for step in agent.stream({"messages": [{"role": "user", "content": query}]},stream_mode="values",):step["messages"][-1].pretty_print()
一个简单问题,中间件自动完成检索,代码量相比方案一显著减少。适用于单轮问答场景,一键搞定。
本文完整实现了基于LangChain的RAG Agent智能检索问答系统,从环境配置到文档处理再到两种Agent方案构建,全流程覆盖。代码可直接复制运行,两种主流方案适配不同业务场景。RAG作为LLM落地的核心技术之一,这套代码稍加改造即可迁移至PDF、本地文档等知识库场景,实用性强。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述