尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

AI Agent开发实战:从工具调用到RAG集成,打造智能业务助手

AI Agent开发实战:从工具调用到RAG集成,打造智能业务助手 最近在尝试将大语言模型应用到实际业务场景时你是否也遇到过这样的困境模型虽然知识渊博但回答总是泛泛而谈无法精准调用工具、执行复杂任务或利用私有数据这正是传统大模型应用的瓶颈。而AI Agent智能体的出现为我们打开了新的大门。它让大模型从一个“百科全书”变成了一个能思考、会规划、可行动的“智能助手”。本文将为你系统拆解 AI Agent 的开发全流程从核心概念到环境搭建再到利用 LangChain 框架构建具备规划、工具调用和记忆能力的智能体并最终整合 RAG检索增强生成技术打造一个能利用私有知识库的专属智能体。无论你是刚接触 AI 应用开发的新手还是希望将 Agent 技术落地的开发者都能从这篇实战指南中获得清晰的路径和可运行的代码。1. AI Agent 核心概念从“聊天”到“行动”在深入代码之前我们必须厘清 AI Agent 究竟是什么以及它如何工作。1.1 什么是 AI Agent简单来说一个 AI Agent 是一个能够感知环境、进行决策并执行行动以实现特定目标的软件实体。它不再仅仅是一个问答机而是一个具备自主性的“智能体”。其核心思想是赋予大语言模型LLM“思考-行动-观察”的循环能力。模型根据目标进行思考规划决定下一步该做什么行动然后观察行动的结果观察并基于此进行下一轮思考直至任务完成或无法继续。1.2 AI Agent 的核心组成模块一个典型的 AI Agent 系统通常包含以下几个关键组件规划模块Planning Agent 的核心“大脑”。它将复杂任务分解为可执行的子任务序列或在多个可选动作中进行推理和选择。这通常由大语言模型驱动。工具调用模块Tool Calling Agent 的“手”和“脚”。LLM 本身无法直接操作外部世界如搜索网络、查询数据库、执行代码。工具是一系列预定义的函数Agent 通过调用这些函数来影响环境。例如search_web(query),execute_python_code(code),query_database(sql)。记忆模块Memory Agent 的“经验”。记忆使 Agent 能够保留对话历史、任务上下文和之前行动的结果从而在长程交互中保持一致性。记忆分为短期记忆如当前对话和长期记忆如向量数据库存储的知识。行动执行模块Action Execution 负责实际运行被选中的工具并将执行结果返回给规划模块作为下一轮“观察”的输入。1.3 为什么需要 RAGRAGRetrieval-Augmented Generation检索增强生成是提升 Agent 在特定领域表现的关键技术。当 Agent 需要处理公司内部文档、产品手册、私有代码库等非公开信息时直接询问通用大模型往往得不到准确答案。RAG 的工作流程是当用户提出问题时系统首先从私有知识库通常是向量数据库中检索出最相关的文档片段然后将这些片段作为上下文连同原始问题一起提交给大模型从而生成一个基于可靠信源的、更准确的回答。将 RAG 与 Agent 结合就诞生了Agentic RAG使得 Agent 不仅能使用工具还能在需要时主动从知识库中检索信息来辅助决策和生成。2. 环境准备与工具选型工欲善其事必先利其器。在开始构建 Agent 之前我们需要搭建好开发环境。2.1 基础环境配置本文以Python作为主要开发语言因为它拥有最丰富的 AI 开发生态。操作系统 Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04) 均可。Python 版本 推荐使用 Python 3.9 或 3.10。更高的版本如 3.11也基本兼容但某些库可能存在细微的依赖问题。包管理工具 使用pip。强烈建议使用虚拟环境如venv或conda来隔离项目依赖。创建并激活虚拟环境以 venv 为例# 创建虚拟环境 python -m venv ai_agent_env # 激活虚拟环境 # Windows ai_agent_env\Scripts\activate # macOS/Linux source ai_agent_env/bin/activate2.2 核心库安装我们将使用LangChain作为构建 Agent 的主要框架它抽象了与多种 LLM 的交互、工具定义、记忆管理和链式调用极大简化了开发流程。# 安装 LangChain 核心库及 OpenAI 集成我们使用 OpenAI 的模型作为“大脑” pip install langchain langchain-openai # 安装用于文本分割和向量化的库 pip install langchain-text-splitters # 安装向量数据库客户端这里以 Chroma 为例轻量且易用 pip install chromadb # 安装用于网页内容提取的库用于构建知识库 pip install beautifulsoup4 requests # 可选安装 LangChain 社区工具包包含更多实用工具 # pip install langchain-community2.3 大模型 API 配置本文示例将使用 OpenAI 的 GPT 系列模型如 gpt-3.5-turbo。你需要一个 OpenAI API Key。访问 OpenAI Platform 注册并获取 API Key。在代码中通过环境变量设置 API Key切勿将密钥硬编码在代码中提交到版本控制系统。# 在命令行中设置环境变量临时 # Windows set OPENAI_API_KEYyour-api-key-here # macOS/Linux export OPENAI_API_KEYyour-api-key-here或者在项目根目录创建.env文件写入OPENAI_API_KEYyour-api-key-here然后安装python-dotenv库 (pip install python-dotenv) 在代码中加载。3. 核心组件拆解与实战让我们从零开始一步步构建 AI Agent 的各个核心模块。3.1 规划模块与大模型对话规划模块的本质是让 LLM 理解我们的指令并做出决策。在 LangChain 中这通过ChatOpenAI等聊天模型类来实现。# 文件core_llm.py import os from langchain_openai import ChatOpenAI from dotenv import load_dotenv # 加载环境变量中的 API Key load_dotenv() # 初始化 LLM # temperature 控制创造性越高越随机对于 Agent 的规划通常设为较低值如0.1以保证稳定性 llm ChatOpenAI(modelgpt-3.5-turbo, temperature0.1, api_keyos.getenv(OPENAI_API_KEY)) # 测试与 LLM 的简单对话 from langchain_core.messages import HumanMessage messages [HumanMessage(content你好请介绍一下你自己。)] response llm.invoke(messages) print(fAI: {response.content})3.2 工具调用模块赋予 Agent “手脚”工具是函数我们需要告诉 LLM 这些函数是干什么的、怎么调用。LangChain 提供了tool装饰器来轻松创建工具。# 文件custom_tools.py from langchain.agents import tool from datetime import datetime # 定义一个简单的计算器工具 tool def calculator(expression: str) - str: 用于计算数学表达式。输入应为一个字符串格式的数学表达式如 3 5 * 2。 try: # 警告直接使用 eval 有安全风险仅用于演示。生产环境应使用更安全的解析库如 ast.literal_eval或自定义解析逻辑。 result eval(expression) return f计算结果{expression} {result} except Exception as e: return f计算错误{e} # 定义一个获取当前时间的工具 tool def get_current_time(query: str ) - str: 获取当前的日期和时间。输入参数可以忽略或传入任意字符串。 now datetime.now() return f当前时间是{now.strftime(%Y-%m-%d %H:%M:%S)} # 将工具放入列表供 Agent 使用 tools [calculator, get_current_time] # 测试工具 if __name__ __main__: print(calculator.invoke(3 5 * 2)) print(get_current_time.invoke())3.3 记忆模块让 Agent 拥有“记忆”记忆分为两类对话记忆Conversation Memory 存储当前会话的上下文。长期记忆Long-term Memory 通常结合向量数据库存储可供检索的历史知识或文档。对话记忆示例# 文件conversation_memory.py from langchain.memory import ConversationBufferMemory # 创建一个对话缓冲区记忆 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 模拟对话 memory.chat_memory.add_user_message(我叫小明。) memory.chat_memory.add_ai_message(你好小明) memory.chat_memory.add_user_message(我最喜欢的颜色是蓝色。) # 从记忆中加载变量通常用于构造提示词 loaded_memory memory.load_memory_variables({}) print(loaded_memory[chat_history]) # 输出会包含之前的对话历史3.4 构建你的第一个简单 Agent现在我们将规划模块LLM、工具和记忆组合起来创建一个能根据对话历史使用工具的简单 Agent。# 文件simple_agent.py import os from langchain_openai import ChatOpenAI from langchain.agents import initialize_agent, AgentType from langchain.memory import ConversationBufferMemory from custom_tools import calculator, get_current_time # 导入之前定义的工具 from dotenv import load_dotenv load_dotenv() # 1. 初始化 LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0, api_keyos.getenv(OPENAI_API_KEY)) # 2. 准备工具列表 tools [calculator, get_current_time] # 3. 初始化记忆 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 4. 创建 Agent # AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION 适合带记忆的对话式Agent agent initialize_agent( tools, llm, agentAgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, memorymemory, verboseTrue, # 设置为 True 可以看到 Agent 的思考过程非常有用 handle_parsing_errorsTrue # 优雅地处理解析错误 ) # 5. 运行 Agent print( 第一次对话 ) response1 agent.invoke({input: 嗨请计算一下 15 除以 3 等于多少}) print(fAgent: {response1[output]}\n) print( 第二次对话依赖记忆) response2 agent.invoke({input: 很好那现在几点了}) print(fAgent: {response2[output]}\n) print( 第三次对话复杂指令) response3 agent.invoke({input: 用我上次问你的那个算式的结果加上当前时间的小时数再告诉我。}) # 注意这个任务需要 Agent 记住“15/35”的结果并调用 get_current_time 工具然后进行推理计算。 # 由于工具返回的是字符串Agent 需要从中提取数字。这考验了其规划和工具使用能力。 print(fAgent: {response3[output]})运行此脚本你将看到verboseTrue模式下 Agent 详细的思考链ReAct 模式Thought思考要做什么Action选择哪个工具Action Input工具的输入Observation工具执行结果最后是Final Answer。4. 进阶实战构建具备 RAG 能力的智能体Agentic RAG现在我们进入更实用的阶段构建一个能查询私有知识库的智能体。假设我们有一个公司产品手册的 PDF 文档我们需要 Agent 能回答关于产品的问题。4.1 构建知识库向量数据库首先我们需要将文档内容处理并存入向量数据库。# 文件build_knowledge_base.py import os from langchain_community.document_loaders import PyPDFLoader # 用于加载PDF from langchain_text_splitters import RecursiveCharacterTextSplitter # 用于文本分割 from langchain_openai import OpenAIEmbeddings # 用于生成文本向量 from langchain_chroma import Chroma # 向量数据库 from dotenv import load_dotenv load_dotenv() # 1. 加载文档 # 假设你的产品手册 PDF 名为 product_manual.pdf loader PyPDFLoader(product_manual.pdf) # 请确保文件路径正确 documents loader.load() # 2. 分割文本 # 将长文档分割成小块以便嵌入和检索 text_splitter RecursiveCharacterTextSplitter( chunk_size1000, # 每个块的最大字符数 chunk_overlap200, # 块之间的重叠字符数有助于保持上下文 separators[\n\n, \n, 。, , , , , 、, , ] # 分割符优先级 ) chunks text_splitter.split_documents(documents) print(f原始文档页数{len(documents)} 分割后块数{len(chunks)}) # 3. 生成嵌入并存入向量数据库 embeddings OpenAIEmbeddings(api_keyos.getenv(OPENAI_API_KEY)) # 指定持久化路径 persist_directory ./chroma_db # 创建并持久化向量库 vectordb Chroma.from_documents( documentschunks, embeddingembeddings, persist_directorypersist_directory ) vectordb.persist() # 将数据写入磁盘 print(f知识库已构建并保存至{persist_directory})4.2 创建 RAG 检索链接下来创建一个检索链它负责根据问题从向量库中找到相关文档。# 文件rag_retriever.py from langchain_chroma import Chroma from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain.chains import RetrievalQA from dotenv import load_dotenv load_dotenv() # 1. 加载已构建的向量数据库 persist_directory ./chroma_db embeddings OpenAIEmbeddings(api_keyos.getenv(OPENAI_API_KEY)) vectordb Chroma(persist_directorypersist_directory, embedding_functionembeddings) # 2. 将向量数据库转换为检索器 retriever vectordb.as_retriever( search_kwargs{k: 3} # 每次检索返回最相关的 3 个文档块 ) # 3. 创建 LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0, api_keyos.getenv(OPENAI_API_KEY)) # 4. 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 将检索到的文档“塞”进提示词 retrieverretriever, return_source_documentsTrue, # 返回源文档便于调试 verboseTrue ) # 5. 测试 RAG 链 if __name__ __main__: query 你们产品的主要特性是什么 result qa_chain.invoke({query: query}) print(f问题{query}) print(f答案{result[result]}) print(\n--- 参考来源 ---) for i, doc in enumerate(result[source_documents][:2]): # 显示前两个来源 print(f[来源 {i1}] {doc.page_content[:200]}...) # 截取前200字符4.3 将 RAG 链封装为 Agent 的工具现在我们将这个强大的 RAG 问答能力封装成一个工具这样我们的 Agent 就可以在需要查询产品知识时主动调用它。# 文件rag_agent_tool.py from langchain.agents import tool from rag_retriever import qa_chain # 导入上一步创建的 qa_chain tool def query_product_handbook(question: str) - str: 查询公司产品手册回答关于产品功能、规格、使用方式等问题。 输入应为一个明确的问题。 try: result qa_chain.invoke({query: question}) answer result[result] # 可以在这里添加对答案的后处理比如截断或格式化 return answer except Exception as e: return f查询产品手册时出错{e}4.4 组装终极智能体工具 RAG 记忆最后我们创建一个拥有计算器、时间查询和产品手册查询三大能力的全能 Agent。# 文件super_agent.py import os from langchain_openai import ChatOpenAI from langchain.agents import initialize_agent, AgentType from langchain.memory import ConversationBufferMemory from custom_tools import calculator, get_current_time from rag_agent_tool import query_product_handbook from dotenv import load_dotenv load_dotenv() # 1. 初始化 LLM llm ChatOpenAI(modelgpt-3.5-turbo, temperature0.1, api_keyos.getenv(OPENAI_API_KEY)) # 2. 工具列表现在包含 RAG 工具 tools [calculator, get_current_time, query_product_handbook] # 3. 初始化记忆 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 4. 创建功能强大的 Agent super_agent initialize_agent( tools, llm, agentAgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION, memorymemory, verboseTrue, handle_parsing_errorsTrue, max_iterations5 # 限制最大迭代次数防止死循环 ) # 5. 运行测试 print( 测试1基础工具调用 ) response super_agent.invoke({input: 现在的时间是多少}) print(fAgent: {response[output]}\n) print( 测试2RAG 知识查询 ) response super_agent.invoke({input: 根据产品手册我们的旗舰产品支持哪些操作系统}) print(fAgent: {response[output]}\n) print( 测试3混合任务需要记忆和规划) # 这是一个复杂任务先查产品价格再计算折扣。 # 假设产品手册里有价格信息并且我们通过对话告诉了Agent折扣率。 super_agent.invoke({input: 用户想知道我们旗舰产品的价格。}) # 触发RAG查询 response super_agent.invoke({input: 很好。如果给这位用户打8.8折最终应付多少钱请计算。}) # Agent需要1.记住上一步查询到的价格。2.调用计算器工具进行乘法运算。 print(fAgent: {response[output]})5. 常见问题与排查思路在开发 AI Agent 过程中你可能会遇到以下典型问题。问题现象可能原因排查与解决思路Agent 陷入循环不停调用同一个工具1. 工具返回的结果无法让 LLM 做出最终决策。2.max_iterations设置过高或未设置。3. 提示词Prompt设计有缺陷未明确停止条件。1. 检查工具函数确保其返回清晰、结构化的结果。2. 设置合理的max_iterations如 5-10。3. 在系统提示词中强调“当你拥有足够信息时必须给出最终答案”。4. 启用verboseTrue观察思考过程。LLM 无法正确选择工具1. 工具描述docstring不够清晰。2. 工具太多LLM 混淆。3. 使用的 LLM 能力不足如模型太小。1. 为每个工具编写精确、示例化的文档字符串。2. 精简工具集或对工具进行分类。3. 升级到更强大的模型如 gpt-4。4. 使用AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION它支持更结构化的工具描述。RAG 检索结果不相关1. 文本分割策略不当块太大或太小。2. 嵌入模型不适合该领域文本。3. 检索器返回的文档数量k值不合适。1. 调整chunk_size和chunk_overlap尝试不同的分割符。2. 尝试不同的嵌入模型如text-embedding-3-small。3. 调整search_kwargs{“k”: 3}中的 k 值。4. 在检索后添加一个“重排序”步骤使用交叉编码器对结果进行精排。API 调用超时或报错1. 网络问题。2. API Key 无效或余额不足。3. 请求速率超限。1. 检查网络连接。2. 在 OpenAI 控制台验证 API Key 状态和余额。3. 在代码中添加重试机制和指数退避。4. 对于生产环境考虑使用代理或负载均衡。记忆混乱或丢失上下文1. 记忆缓冲区溢出。2. 记忆键memory_key在链中未正确传递。3. 使用了不兼容的记忆类型与 Agent 类型。1. 使用ConversationSummaryMemory或ConversationBufferWindowMemory来限制记忆长度。2. 确保在初始化 Agent 和调用时使用了相同的memory_key。3. 查阅 LangChain 文档确认你选择的AgentType与Memory类是兼容的。6. 最佳实践与工程化建议要将一个演示级的 Agent 转化为稳定、可维护的生产系统需要关注以下几点6.1 提示词工程优化Agent 的表现极大程度依赖于给 LLM 的指令系统提示词。LangChain 的 Agent 有默认提示词但针对特定领域优化能大幅提升效果。明确角色与目标在系统提示词开头清晰定义 Agent 的角色、能力和边界。格式化输出要求要求 LLM 以特定格式如 JSON输出思考过程和工具调用便于解析。提供少量示例在提示词中加入一两个思维链Chain-of-Thought示例引导模型更好地进行规划。6.2 工具设计的健壮性输入验证与清理在工具函数内部对输入参数进行严格的类型检查和内容清洗防止恶意或异常输入导致错误。错误处理与友好反馈工具执行失败时应捕获异常并返回对 LLM 友好的错误信息而不是抛出堆栈跟踪。工具功能单一化每个工具只做一件事保持功能纯粹这能提高 LLM 理解的准确性和代码的可维护性。6.3 可观测性与日志结构化日志记录每一次 Agent 的调用、LLM 的请求与响应、工具的执行结果和耗时。这对于调试和性能分析至关重要。链路追踪为每个用户会话或任务分配唯一 ID便于追踪完整的“思考-行动”链条。关键指标监控监控 Token 消耗、API 延迟、工具调用成功率、任务完成率等业务和技术指标。6.4 安全与权限控制工具访问权限不是所有用户都能调用所有工具。需要设计权限层在 Agent 决定调用工具前校验当前用户是否有权执行该操作。输入输出过滤对用户输入和 LLM 生成的内容进行安全过滤防止提示词注入、信息泄露或生成有害内容。沙箱环境对于执行代码如Python_REPL工具或访问敏感系统的工具必须在严格的沙箱环境中运行。6.5 性能与成本优化缓存对频繁且结果不变的 LLM 请求如固定的知识查询和工具调用结果进行缓存。异步处理对于耗时较长的工具调用如网络请求使用异步模式以避免阻塞主线程。模型选择根据任务复杂度选择合适的模型。简单的分类或格式化任务可以使用更小、更快的模型复杂的规划再使用大模型。Agent 流程优化对于确定性强、步骤固定的任务可以考虑使用更高效的LLMChain或SequentialChain来代替通用的 ReAct Agent以减少 LLM 的调用次数。从理解 Agent 的核心思想开始我们一步步实现了工具调用、记忆管理和 RAG 集成。关键在于将复杂问题分解先用 LangChain 搭建一个能使用简单工具的对话智能体再引入向量数据库构建知识库最后将 RAG 能力封装成工具让 Agent 在需要时主动检索。
返回列表