ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于LangChain的RAG-Agent系统实战:构建企业级智能应用

基于LangChain的RAG-Agent系统实战:构建企业级智能应用 在构建企业级智能应用时我们常常面临一个核心矛盾如何让大语言模型LLM既能利用其强大的通用推理能力又能精准地调用企业内部的专业知识和数据单纯的RAG检索增强生成系统虽然能提供知识但缺乏自主决策和工具调用的灵活性而一个简单的Agent智能体又可能因为缺乏专业知识而“信口开河”。将RAG与Agent结合构建一个具备“知识大脑”和“行动四肢”的智能体是解决这一问题的关键路径。本文将以一个实战项目为例手把手带你搭建一个基于LangChain的RAG-Agent系统。这个系统不仅能从你构建的私有知识库中精准检索信息还能根据问题复杂程度自主决定是直接回答、调用工具还是进行多步推理。无论你是想为内部系统添加一个智能问答助手还是希望打造一个能处理复杂流程的AI客服本文提供的完整代码和架构思路都能为你提供直接的参考。1. RAG-Agent 系统核心概念与架构设计在深入代码之前我们有必要厘清几个核心概念以及它们在本项目中的角色。RAG (Retrieval-Augmented Generation, 检索增强生成)RAG的核心思想是“先检索后生成”。当用户提出问题时系统首先从一个外部的知识库如向量数据库中检索出与问题最相关的文档片段然后将这些片段作为上下文与原始问题一并提交给大语言模型让模型基于这些可靠的参考信息来生成答案。这有效解决了LLM的“幻觉”问题并使其能够回答训练数据之外的最新或私有知识。Agent (智能体)在LangChain语境下Agent是一个具备推理能力的系统。它接收用户的输入利用一个大语言模型作为其“大脑”进行思考决定下一步该做什么。Agent可以访问一系列工具Tools例如计算器、搜索引擎API、数据库查询等。它会根据当前状态和目标自主选择调用哪个工具并处理工具的返回结果最终将整合后的信息返回给用户。RAG-Agent 融合架构我们的目标不是二选一而是让两者协同工作。其核心架构流程如下用户提问用户输入一个自然语言问题。Agent决策Agent以LLM为驱动首先分析问题。它需要判断“这是一个可以直接回答的简单问题还是一个需要查询知识库的专业问题或者是一个需要调用其他工具如计算、查询天气的请求”路径执行路径A直接回答对于问候、简单定义等问题Agent可能直接调用LLM生成回复。路径BRAG查询对于涉及私有知识的问题Agent会调用“知识库检索工具”。这个工具内部封装了从向量数据库检索相关文档的逻辑并将检索结果返回给Agent。路径C工具调用对于计算、查询等需求Agent调用相应的专用工具。生成与回复Agent获得工具包括RAG工具的返回结果后再次利用LLM进行信息整合与润色生成最终的自然语言回复给用户。这种架构的优势在于其动态决策能力。系统不再是固定的“检索-生成”流水线而是一个能根据问题意图智能选择最合适解决方案的“大脑”。2. 环境准备与项目初始化我们将使用Python和LangChain来构建这个系统。请确保你的开发环境已就绪。2.1 基础环境与依赖安装建议使用Python 3.8及以上版本。首先创建一个新的项目目录并初始化虚拟环境。# 创建项目目录 mkdir langchain-rag-agent-demo cd langchain-rag-agent-demo # 创建并激活虚拟环境 (以conda为例) conda create -n rag-agent python3.10 -y conda activate rag-agent # 使用pip安装核心依赖 pip install langchain langchain-community langchain-openai # 安装向量数据库客户端 (这里以Chroma为例轻量且易用) pip install chromadb # 安装文本嵌入模型 (这里使用OpenAI的embedding也可用本地模型) pip install openai # 安装用于网页内容加载的组件 pip install beautifulsoup4 lxml2.2 关键组件版本说明与API配置本项目基于LangChain 0.1.x版本构建其模块化程度更高。请确保你的主要依赖版本类似。运行pip list | grep langchain查看。本项目需要接入一个大语言模型LLM和一个文本嵌入模型Embedding Model。我们将使用OpenAI的API作为示例你也可以替换为Azure OpenAI、Anthropic或本地部署的模型如Ollama。重要你需要准备一个有效的OpenAI API Key。在项目根目录下创建一个名为.env的文件来管理密钥避免硬编码在代码中。# .env 文件内容 OPENAI_API_KEY你的-openai-api-key-here然后在代码中通过python-dotenv加载。安装该包pip install python-dotenv。3. 构建知识库文档加载、切分与向量化一个高质量的RAG系统根基在于知识库。这一步我们将私有文档处理成可供检索的向量。3.1 文档加载与文本分割我们假设知识库源文件是Markdown格式的文档存放在./knowledge_docs目录下。LangChain提供了多种文档加载器。# file: build_knowledge_base.py import os from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma from dotenv import load_dotenv # 加载环境变量 load_dotenv() def load_and_split_documents(directory_path): 加载指定目录下的所有文档并进行智能分割。 Args: directory_path: 存放知识文档的目录路径。 Returns: 分割后的文档列表。 # 使用DirectoryLoader加载所有.md文件 # 如果需要加载其他格式可以指定glob模式如 **/*.txt loader DirectoryLoader(directory_path, glob**/*.md, loader_clsTextLoader) documents loader.load() print(f成功加载 {len(documents)} 个文档。) # 使用递归字符分割器。这是最常用的分割策略。 # chunk_size: 每个文本块的最大字符数。 # chunk_overlap: 块与块之间的重叠字符数用于保持上下文连贯。 text_splitter RecursiveCharacterTextSplitter( chunk_size1000, # 根据你的文档内容调整通常500-1500 chunk_overlap200, # 重叠部分有助于避免在句子中间切断重要信息 separators[\n\n, \n, 。, , , , , , ] # 分割优先级 ) split_docs text_splitter.split_documents(documents) print(f文档被分割成 {len(split_docs)} 个文本块。) return split_docs if __name__ __main__: docs load_and_split_documents(./knowledge_docs) # 打印第一个块的内容预览 if docs: print(第一个文本块预览) print(docs[0].page_content[:500])关键参数解析chunk_size这是影响检索质量的核心参数。太小会导致信息碎片化太大会引入噪声。对于技术文档800-1200是一个不错的起点。chunk_overlap重叠部分能确保相关的上下文不会因为被切分到两个块而丢失对于提高检索召回率很重要。separators定义了分割文本的优先级按列表顺序尝试分割直到满足块大小要求。3.2 向量化与持久化存储将分割后的文本块转换为向量Embeddings并存入向量数据库Chroma中。# 接上段代码在同一个 build_knowledge_base.py 文件中 def create_vector_store(split_docs, persist_directory./chroma_db): 创建向量数据库并持久化存储。 Args: split_docs: 分割后的文档列表。 persist_directory: 向量数据库本地存储路径。 Returns: 向量存储对象。 # 初始化Embedding模型。这里使用OpenAI的text-embedding-3-small性价比高。 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) # 创建Chroma向量存储并将文档向量化后存入。 # persist_directory 指定存储路径下次可以直接加载无需重新计算。 vectorstore Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directorypersist_directory ) # 显式持久化虽然from_documents通常会保存但显式调用更安全 vectorstore.persist() print(f向量数据库已创建并保存至 {persist_directory}) return vectorstore if __name__ __main__: # 假设知识文档已放在 ./knowledge_docs 下 split_documents load_and_split_documents(./knowledge_docs) # 创建并保存向量库 vs create_vector_store(split_documents) print(知识库构建完成)运行此脚本后会在项目根目录下生成一个chroma_db文件夹里面存储了所有文本块的向量和元数据。之后我们可以直接加载这个数据库无需重复处理文档。4. 打造智能体Agent与工具Tools这是系统的“大脑”和“四肢”。我们将创建一个能使用多种工具的Agent其中最关键的就是我们自定义的“知识库检索工具”。4.1 定义核心工具知识库检索工具首先我们创建一个从已构建的向量库中检索信息的工具。# file: tools/retriever_tool.py from langchain.tools import Tool from langchain_community.vectorstores import Chroma from langchain_openai import OpenAIEmbeddings def get_retriever_tool(persist_directory./chroma_db): 创建并返回一个知识库检索工具。 # 加载之前构建的向量数据库 embeddings OpenAIEmbeddings(modeltext-embedding-3-small) vectorstore Chroma( persist_directorypersist_directory, embedding_functionembeddings ) # 从向量库创建检索器。search_kwargs 可以控制返回结果的数量和相似度阈值。 retriever vectorstore.as_retriever( search_kwargs{k: 4} # 返回最相关的4个文本块 ) def retrieve_docs(query: str) - str: 内部函数执行检索并将文档内容格式化为字符串。 docs retriever.invoke(query) # LangChain 0.1.x 使用 invoke content_list [f[文档片段 {i1}]: {doc.page_content} for i, doc in enumerate(docs)] return \n\n.join(content_list) # 创建LangChain Tool对象 # name: 工具名称Agent会根据这个名称来思考是否调用它。 # description: 工具描述这是最重要的部分必须清晰说明工具的功能和使用场景 # Agent的LLM根据描述来决定是否调用此工具。 # func: 工具被调用时执行的函数。 retriever_tool Tool( nameknowledge_base_retriever, description当用户的问题涉及到公司的产品信息、技术文档、内部流程、规章制度、历史数据等私有或专业知识时使用此工具。 输入应该是清晰、完整的问题描述。, funcretrieve_docs ) return retriever_tool工具描述description的写作要点这是指导Agent行为的关键。描述要具体说明在什么场景下使用这个工具。例如明确写出“当问题涉及公司产品、技术文档、内部流程时使用”这样Agent在遇到“我们产品的定价策略是什么”这类问题时就会倾向于调用此工具。4.2 定义其他辅助工具一个强大的Agent通常配备多种工具。我们再添加两个常用工具作为示例。# file: tools/calculator_tool.py from langchain.tools import Tool def get_calculator_tool(): 创建一个简单的计算器工具使用Python的eval生产环境需谨慎。 def calculate(expression: str) - str: try: # 警告在生产环境中直接使用eval有安全风险此处仅作演示。 # 应使用更安全的表达式解析库如asteval或严格限制输入。 result eval(expression) return f计算结果: {result} except Exception as e: return f计算错误: {e} calculator_tool Tool( namecalculator, description用于执行数学计算。输入一个有效的数学表达式例如 3 * 5 2 或 sqrt(16)。, funccalculate ) return calculator_tool# file: tools/web_search_tool.py # 注意此示例需要安装 duckduckgo-search: pip install duckduckgo-search from langchain.tools import DuckDuckGoSearchRun def get_web_search_tool(): 创建一个网络搜索工具需要互联网连接。 search_tool DuckDuckGoSearchRun() # 可以对其描述进行定制 search_tool.name web_search search_tool.description 当需要获取最新的、实时的、公开的新闻、事件、天气或通用知识时使用此工具进行网络搜索。 return search_tool4.3 创建智能体Agent我们将使用LangChain的“ReAct”代理框架它要求LLM为每一步的思考Reason和行动Act生成文本非常适合复杂任务。# file: agent/rag_agent.py from langchain.agents import AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate from tools.retriever_tool import get_retriever_tool from tools.calculator_tool import get_calculator_tool from tools.web_search_tool import get_web_search_tool from dotenv import load_dotenv import warnings warnings.filterwarnings(ignore) # 可选忽略一些警告信息 load_dotenv() def create_rag_agent(): 创建并返回一个集成了知识库检索工具的RAG-Agent。 # 1. 初始化大语言模型 # 使用gpt-3.5-turbo作为Agent的“大脑”性价比高。对于复杂任务可升级为gpt-4。 llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) # 2. 准备工具列表 tools [ get_retriever_tool(), # 我们的核心RAG工具 get_calculator_tool(), # 计算工具 get_web_search_tool(), # 网络搜索工具 # 可以在此处添加更多工具... ] # 3. 定义ReAct代理的提示词模板 # 这个模板指导LLM如何思考、使用工具和格式化输出。 react_prompt_template 请回答以下问题。你可以使用以下工具 {tools} 使用以下格式 问题需要回答的输入问题 思考你需要思考如何一步步解决问题 行动需要调用的工具名称必须是[{tool_names}]中的一个 行动输入传递给该工具的输入 观察工具返回的结果 ... (这个思考/行动/观察的循环可以重复多次) 思考我现在知道最终答案了 最终答案对原始问题的最终答案 开始 问题{input} 思考{agent_scratchpad} react_prompt PromptTemplate.from_template(react_prompt_template) # 4. 创建ReAct代理 agent create_react_agent(llm, tools, react_prompt) # 5. 创建代理执行器它负责运行代理循环 # handle_parsing_errorsTrue 能更优雅地处理LLM输出格式错误。 # verboseTrue 会打印详细的思考过程调试时非常有用。 agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, handle_parsing_errorsTrue, max_iterations5, # 限制最大迭代次数防止无限循环 early_stopping_methodgenerate # 当代理认为可以给出最终答案时停止 ) return agent_executor if __name__ __main__: # 测试Agent创建 agent create_rag_agent() print(RAG-Agent 创建成功)5. 完整系统集成与实战对话现在我们将所有组件集成起来创建一个命令行交互界面来测试我们的RAG-Agent。# file: main.py from agent.rag_agent import create_rag_agent import sys def main(): print(正在初始化 RAG-Agent 系统...) agent create_rag_agent() print(系统初始化完成) print(输入您的问题输入 quit 或 exit 退出) print(- * 50) while True: try: user_input input(\n您: ) if user_input.lower() in [quit, exit, q]: print(再见) break if not user_input.strip(): continue print(\nAgent 正在思考...) # 调用Agent执行 response agent.invoke({input: user_input}) print(f\n助手: {response[output]}) except KeyboardInterrupt: print(\n\n程序被中断。) break except Exception as e: print(f\n系统运行时出错: {e}) # 可以选择记录日志这里简单打印 import traceback traceback.print_exc() if __name__ __main__: main()5.1 运行与演示首先确保你的knowledge_docs目录下有一些Markdown格式的知识文件。例如创建一个product_guide.md# 产品X使用指南 产品X是我们公司旗舰的智能分析平台最新版本为v3.2。 ## 核心功能 1. 实时数据看板支持拖拽式配置数据刷新延迟低于5秒。 2. 预测模型内置基于时间序列的AI预测算法准确率高达92%。 3. 权限管理支持基于角色RBAC的精细权限控制。 ## 定价策略 - 基础版999元/月包含10个用户席位和基础看板功能。 - 专业版2999元/月包含所有功能50个用户席位以及专属技术支持。 - 企业版需联系销售定制。 ## 技术支持 如需帮助请访问内部帮助中心https://help.internal.com/x 或发送邮件至 supportcompany.com。然后按顺序运行构建知识库python build_knowledge_base.py看到“知识库构建完成”的提示。启动交互系统python main.py5.2 实战对话示例启动后你可以尝试不同类别的问题观察Agent的决策过程因为设置了verboseTrue。示例1查询知识库触发RAG工具您: 产品X的专业版多少钱一个月Agent思考过程简化思考用户问的是产品价格这属于公司产品信息应该使用知识库检索工具。行动调用knowledge_base_retriever。行动输入“产品X的专业版价格”观察工具返回了包含定价策略的文档片段。思考根据检索到的信息专业版是2999元/月。可以给出最终答案。最终答案产品X的专业版价格为2999元每月。示例2简单计算触发计算器工具您: 请计算一下如果买3个月的专业版总价是多少Agent思考过程思考这个问题需要计算。先检索一下是否有相关定价信息。行动调用knowledge_base_retriever。行动输入“专业版 价格 月度”观察检索到“专业版2999元/月”。思考现在需要计算 2999 * 3。这是一个数学计算使用计算器工具。行动调用calculator。行动输入“2999 * 3”观察计算结果: 8997最终答案购买3个月的专业版总价为8997元。示例3通用知识可能直接回答或搜索您: 今天的天气怎么样Agent思考过程思考这是一个关于实时天气的问题我的知识库中没有这类信息需要使用网络搜索工具。行动调用web_search。...获取搜索结果...最终答案根据最新信息今天北京晴最高气温25摄氏度...具体结果取决于搜索返回。通过以上示例你可以清晰地看到Agent如何像人类一样“思考”先判断问题类型再选择最合适的工具最后整合信息给出答案。6. 常见问题与排查思路在构建和运行RAG-Agent系统时你可能会遇到以下典型问题。问题现象可能原因排查与解决思路运行build_knowledge_base.py时报错No module named langchain_communityLangChain版本过高或过低模块路径发生变化。确认安装的langchain-community包是否存在。建议使用较新的0.1.x版本pip install langchain0.1.0 langchain-community0.0.10。检查导入语句是否正确。Agent不调用知识库工具总是直接回答或胡说八道1. 工具描述description不够清晰具体。2. LLM的temperature参数过高导致决策不稳定。3. 提示词Prompt未有效引导。1.优化工具描述在description中明确使用场景如“当问题涉及[你的公司名]的[具体领域]知识时使用”。2.降低温度创建LLM时设置temperature0使其决策更确定。3.强化提示词在react_prompt_template的系统指令部分明确要求“优先使用知识库工具回答专业问题”。知识库检索结果不相关1. 文本分割策略不佳chunk_size过大或过小。2. 检索器返回结果数量k不合适。3. 嵌入模型Embedding不适合你的领域。1.调整分割尝试不同的chunk_size如500, 800, 1000和chunk_overlap。2.调整检索数量修改search_kwargs{k: 3}或{k: 6}进行尝试。3.尝试其他Embedding模型如OpenAI的text-embedding-3-large或开源模型通过HuggingFaceEmbeddings加载。Agent陷入循环或迭代次数过多Agent可能无法从工具结果中解析出有效信息或提示词未明确停止条件。1.设置迭代上限在AgentExecutor中设置max_iterations5或更小。2.优化工具输出确保工具返回的字符串清晰、结构化便于LLM理解。3.检查工具描述确保工具能真正解决它声称能解决的问题。运行速度慢1. 网络延迟调用OpenAI API。2. 每次启动都重新构建向量库。3. Agent思考步骤过多。1.使用更快的模型如gpt-3.5-turbo比gpt-4快很多。2.持久化向量库确保使用了persist_directory后续直接加载。3.简化任务对于简单问题可以考虑使用更简单的zero-shotAgent而非ReAct。处理长文档时上下文超出LLM限制检索返回的多个文档片段总长度超过了LLM的上下文窗口。1.优化检索减少k值或使用similarity_score_threshold进行过滤只返回高相关片段。2.后处理在将检索结果交给Agent前使用LLM进行摘要或相关性重排序。7. 最佳实践与进阶优化建议一个基础的RAG-Agent系统搭建完成后可以从以下几个方面进行优化以提升其生产环境可用性。7.1 知识库质量优化预处理文档在加载文档前清理无关字符、页眉页脚、广告代码等噪声。混合检索结合向量检索语义相似和关键词检索如BM25可以提高召回率。LangChain的EnsembleRetriever可以轻松实现。元数据过滤在存储文档时为其添加元数据如文档类型、部门、更新时间。检索时可以添加过滤器例如“只检索最近一年的产品手册”。重排序Rerank初步检索出较多结果如10个后使用一个更精细的交叉编码器模型对结果进行重排序只将Top-K个最相关的结果送入LLM能显著提升答案质量。7.2 Agent能力增强记忆Memory为Agent添加对话记忆使其能处理多轮对话。可以使用ConversationBufferMemory并将其集成到Agent的提示词中。工具扩展根据业务需求集成更多工具如数据库查询工具查询结构化数据。内部API调用工具执行特定业务操作。文件读写工具。多Agent协作对于极其复杂的任务可以设计多个各司其职的Agent如“检索专家”、“分析专家”、“校验专家”使用LangGraph等框架来编排它们的工作流。7.3 系统性能与稳定性异步处理对于高并发场景使用LangChain的异步接口ainvoke,ainvoke来提高吞吐量。缓存对频繁出现的相似查询的Embedding计算结果或LLM响应进行缓存可以大幅降低成本并提高响应速度。限流与降级对API调用如OpenAI实施限流并设计降级策略如检索失败时转为基于通用知识回答并明确告知限制。监控与评估建立监控指标如请求延迟、工具调用成功率、用户反馈满意度。定期用一组标准问题测试系统评估答案准确率。7.4 安全与可控性工具调用权限控制并非所有用户都能调用所有工具。可以在Agent执行前根据用户身份对tools列表进行过滤。输入输出检查对用户输入进行清洗防止Prompt注入攻击。对工具特别是calculator的eval和LLM的输出进行内容安全检查。知识库更新机制建立流程当源文档更新时能自动或半自动地更新向量数据库避免知识过期。通过以上步骤你不仅拥有了一个可运行的RAG-Agent demo更掌握了一套构建企业级AI辅助系统的核心方法论。从高质量的知识库构建到灵活可扩展的Agent设计再到系统的优化与保障每一步都关乎最终应用的智能水平和可靠性。建议你以此项目为起点尝试接入真实的业务数据和API在实践中不断迭代打造真正解决业务痛点的智能体。
返回列表