从零构建AI智能体:基于LangChain的自主任务规划与工具调用实践 1. 从概念到现实AI智能体的崛起与我的实践观察最近几个月如果你关注AI领域一定被两个名字刷屏了AutoGPT和BabyAGI。它们不仅仅是GitHub上突然爆火的两个仓库更代表了一种全新的技术范式——AI驱动的自主智能体AI-Driven Autonomous Agents。我第一次在lablab.ai的线上黑客松里看到导师演示一个智能体自动规划、拆解并执行一个市场调研任务时那种震撼感至今记忆犹新。它不再是我们熟悉的“你问我答”的聊天机器人而是一个能自己思考“下一步该做什么”的虚拟员工。简单来说AI智能体是一个被赋予了目标并能自主调用工具、做出决策、执行行动以达成该目标的计算机系统。它的核心魅力在于“自主性”。比如你告诉它“帮我分析一下新能源汽车电池技术的最近三个月学术进展并写一份摘要报告”它可能会自己规划出以下步骤1. 搜索最近的学术论文和行业新闻2. 提取关键技术和性能参数3. 对比不同技术路线的优劣4. 综合信息生成结构化的报告。整个过程除了最初的指令你几乎不需要干预。这听起来像是科幻场景但其实已经渗透进我们的生活。亚马逊仓库里穿梭的Kiva机器人能够自主规划最优路径搬运货架可口可乐工厂里巡检的自主无人机自动检测设备安全状态和潜在故障特斯拉的Autopilot更是将自主决策应用于高速行驶的复杂环境。这些都不是简单的自动化脚本而是具备一定感知、规划和决策能力的智能体。那么为什么现在突然火了我认为核心驱动力是大语言模型LLM能力的质变。以GPT-4为代表的LLM提供了一个强大的“通用任务理解与规划大脑”。过去我们要让机器完成复杂任务需要工程师编写极其精细的规则和流程。现在我们只需要用自然语言描述目标LLM就能将其分解成子任务序列并判断每个子任务该调用哪个工具比如计算器、搜索引擎、代码解释器来完成。这极大地降低了构建复杂自主系统的门槛。作为一名长期混迹于技术社区的开发者我意识到亲手构建和“调教”一个属于自己的AI智能体不再是大型实验室的专利而是每个有好奇心的开发者都能触及的实践。接下来我将结合自己的踩坑经验带你从零开始深入理解并构建一个能解决实际问题的AI智能体。2. 智能体架构深度解析不只是“链式调用”在动手写代码之前我们必须先厘清一个核心概念AI智能体与普通的LangChain“链”Chain或“序列”Sequence有本质区别。很多人初学时容易混淆认为智能体就是一系列工具的顺序调用其实不然。理解这个区别是避免你未来设计出僵化、脆弱系统的关键。2.1 智能体的核心循环感知-思考-行动一个典型的自主智能体运行在一个“感知-思考-行动”循环中这模仿了人类或动物的行为模式。我用一个简单的技术项目管理智能体来举例说明。假设我们给智能体的目标是“为开发一个移动端在线文档协作APP制定一个为期两个月的详细技术实施方案。”1. 感知Perception智能体首先“感知”当前的状态和目标。初始状态就是这条自然语言指令。它没有外部信息所以感知到的就是任务描述本身。2. 思考Planning/Reasoning这是智能体的大脑——LLM发挥作用的核心环节。LLM会分析目标并基于其内部知识进行规划。它可能会推理出“这是一个复杂的软件项目需要拆解。首先我需要明确技术栈选型前端、后端、实时协作引擎。其次需要评估类似开源项目如Etherpad、Confluence的架构。然后需要规划开发里程碑和任务依赖关系。最后需要估算资源人力、服务器。” 这个思考过程会产生一个或多个具体的、可执行的子任务或行动决策。3. 行动Action根据思考的结果智能体决定调用哪个“工具”Tool来执行。例如对于“技术栈选型”它可能决定调用“网络搜索工具”去查找“2024年移动端跨平台框架对比”和“实时协作API如Socket.io, WebRTC Data Channel最佳实践”。对于“评估开源项目”它可能决定调用“GitHub API搜索工具”去查找相关仓库并分析其技术栈。4. 观察Observation行动之后工具会返回结果。比如搜索引擎返回了十篇关于React Native vs Flutter的文章链接和摘要。这个返回结果就是新的“感知”输入。然后循环继续。智能体基于初始目标、已完成的行动搜索了技术栈和观察到的结果搜到的文章内容再次进入“思考”阶段“我已经获得了技术栈的初步信息。现在需要综合这些信息做出一个推荐。同时我需要开始规划第一个里程碑的具体任务列表。” 接着它可能决定调用“笔记工具”将搜索到的关键信息记录下来或者调用“代码生成工具”草拟一个项目初始化脚本。关键洞察这个循环的关键在于“下一步行动”不是预先写死的。它完全由LLM根据当前所有信息原始目标历史行动和观察动态决定。这意味着智能体具备处理意外情况的能力。比如如果搜索工具返回“找不到实时协作引擎X的文档”智能体在下一轮思考中可能会决定“改用搜索工具查找引擎Y的文档”或者“直接调用代码分析工具去GitHub上查看引擎X的示例项目”。这种动态适应性是智能体超越简单自动化流程的核心。2.2 工具Tools智能体的“手脚”工具是智能体与外部世界交互的唯一途径。一个强大的智能体背后必然有一个设计精良的工具集。工具的设计有几个核心原则1. 功能单一且明确一个工具只做一件事并且描述清晰。例如“网络搜索工具”就只负责根据查询词返回搜索结果摘要。“Python代码执行工具”就只负责运行一段安全的Python代码并返回结果或错误。模糊的工具会让LLM困惑不知道何时调用它。2. 描述Description至关重要给工具的描述语是引导LLM正确使用它的“说明书”。这个描述需要清晰说明工具的用途、适用场景和局限性。例如对于WolframAlpha数学计算工具描述可以是“用于解决数学问题包括符号计算、微积分、代数、单位换算等。擅长精确计算和分步解答。对于非数学的常识性问题效果不佳。” 好的描述能显著提高智能体选择正确工具的概率。3. 工具的输出需要结构化可选但推荐虽然工具可以返回纯文本但结构化的输出如JSON更利于后续的智能体解析和决策。例如一个“获取天气工具”可以返回{“city”: “Beijing”, “temperature”: 22, “condition”: “Sunny”, “unit”: “Celsius”}而不是一段自然语言描述。这减少了LLM理解结果的歧义。在我的实践中初期我犯过一个错误我把“获取股票价格”和“计算投资回报率”做在了一个工具里。结果智能体在只需要股价时也会去计算回报率导致效率低下且容易出错。后来我将它们拆分成两个独立工具智能体的决策立刻变得清晰准确。2.3 记忆Memory让智能体拥有“上下文”一个只会根据当前输入做出反应的智能体是“短视”的。为了让智能体能处理长对话或复杂多步任务它需要记忆。记忆主要分为两类1. 短期记忆/对话记忆存储当前会话中所有的用户输入、智能体思考和工具调用记录。这通常通过维护一个“对话历史”列表来实现。LangChain等框架内置了这种管理机制。这确保了智能体在回答后续问题时能记得之前聊过什么。例如你问“特斯拉的股价是多少”智能体调用工具查询后回答“$250”。接着你问“它比昨天涨了多少”智能体需要记得刚才查的是特斯拉以及股价是$250才能去调用工具查询昨天的收盘价并进行计算。2. 长期记忆这是更高级的能力指智能体能够将重要信息持久化存储并在未来的任务中检索使用。这通常通过向量数据库Vector Database实现。其工作原理是将智能体运行过程中产生的关键信息如研究结论、用户偏好、项目细节转换成向量一种数学表示存入数据库。当未来遇到相关任务时智能体可以将当前问题也转换成向量去数据库中搜索最相似的“记忆”片段并将其作为上下文提供给LLM。例如你让智能体“研究一下量子计算对加密技术的影响”它花了很多步骤搜索、阅读、总结最终生成了一份报告。这份报告的摘要和关键结论就可以存入长期记忆。一周后你问“我们之前讨论的量子计算它在药物研发上有什么应用”智能体可以从长期记忆中检索出之前关于量子计算的记忆作为背景知识从而更高效、更连贯地开始新的研究任务而不是从头开始。实操心得长期记忆的引入极大地提升了智能体的“个性化”和“专业性”。你可以想象为一个数字员工建立了一个专属知识库。但这里有个坑不是所有信息都值得存入长期记忆。无差别地存储所有对话碎片会导致检索噪音巨大降低效率。我通常的做法是让LLM在完成一个阶段性任务后主动生成一个“本次任务核心收获总结”只将这个总结向量化后存储。这样能保证记忆的质量和相关性。3. 从零构建一个具备联网搜索与数学计算能力的智能体理论说得再多不如亲手搭建一个。我们将使用LangChain框架构建一个融合了联网搜索和复杂数学计算能力的智能体。这个智能体能回答需要最新信息的问题比如“今天AI领域有什么重磅新闻”也能解决复杂的数学问题比如“计算函数f(x) sin(x^2)在0到π上的积分”。我选择LangChain是因为它抽象得很好让我们能聚焦在智能体逻辑本身而不是底层的API调用细节。3.1 项目环境与依赖搭建首先创建一个干净的项目环境这是保证依赖不冲突的好习惯。我强烈建议使用虚拟环境。# 创建项目目录并进入 mkdir ai_agent_project cd ai_agent_project # 创建Python虚拟环境以Linux/MacOS为例 python3 -m venv venv # 激活虚拟环境 # Linux/MacOS: source venv/bin/activate # Windows: # .\venv\Scripts\activate # 升级pip至最新版本避免安装问题 pip install --upgrade pip接下来安装核心依赖。我们将需要以下几个库langchain核心框架用于组装智能体、链和工具。openaiOpenAI官方SDK用于调用GPT模型。我们将使用GPT-3.5-turbo它在成本、速度和能力上比较平衡。requests用于发送HTTP请求我们将用它来调用WolframAlpha的API。duckduckgo-search一个轻量级的库提供对DuckDuckGo搜索引擎的简单访问用于联网搜索。pip install langchain openai requests duckduckgo-search注意安装duckduckgo-search时如果遇到SSL证书相关错误可能是你的Python环境问题。可以尝试先运行pip install --upgrade certifi更新证书或者使用其替代品如googlesearch-python但需要注意其使用条款。这里我们选择DuckDuckGo是因为它无需API密钥对轻度使用友好。3.2 基础模型测试理解LLM的局限性在引入智能体之前我们先看看一个“裸”的大语言模型能做什么、不能做什么。这能让你直观感受到工具的必要性。创建一个Python脚本比如basic_llm_test.py。import os from langchain.llms import OpenAI from langchain.prompts import PromptTemplate from langchain.chains import LLMChain # 设置你的OpenAI API密钥。安全起见建议从环境变量读取。 # 在终端执行export OPENAI_API_KEYyour-api-key-here openai_api_key os.getenv(OPENAI_API_KEY) if not openai_api_key: # 仅为演示生产环境切勿将密钥硬编码在代码中 openai_api_key sk-... # 请替换为你的真实密钥或使用更安全的方式 # 初始化LLM。我们使用GPT-3.5-turbotemperature设为0.7以平衡创造性和一致性。 llm OpenAI(openai_api_keyopenai_api_key, model_namegpt-3.5-turbo-instruct, temperature0.7) # 定义一个简单的提示模板 prompt_template PromptTemplate( input_variables[query], template你是一个专业的助手。请回答以下问题\n问题{query}\n回答 ) # 创建链 chain LLMChain(llmllm, promptprompt_template) # 测试1询问需要最新知识的问题 question_1 lablab.ai 这个平台主要是做什么的最近有什么活动吗 response_1 chain.run(queryquestion_1) print(f问题1: {question_1}) print(f回答1: {response_1}\n{-*50}\n) # 测试2询问一个复杂的数学计算问题 question_2 计算定积分∫(从0到π) sin(x^2) dx 的近似值保留小数点后6位。 response_2 chain.run(queryquestion_2) print(f问题2: {question_2}) print(f回答2: {response_2})运行这个脚本你可能会得到类似下面的输出问题1: lablab.ai 这个平台主要是做什么的最近有什么活动吗 回答1: lablab.ai 是一个专注于人工智能和机器学习的在线平台提供各种AI工具、教程、课程和社区论坛帮助开发者和研究者学习、实践和分享AI技术。关于最近的活动由于我的知识截止日期是2023年初我无法提供最新的活动信息。建议您直接访问lablab.ai官方网站或关注其社交媒体账号以获取最新的活动通知。 -------------------------------------------------- 问题2: 计算定积分∫(从0到π) sin(x^2) dx 的近似值保留小数点后6位。 回答2: 这个积分 ∫_0^π sin(x^2) dx 是一个菲涅耳积分没有初等函数形式的精确解。它的近似值可以通过数值方法计算例如使用辛普森法则或软件工具。 使用数值计算工具如Mathematica, MATLAB, 或Python的SciPy库得到的结果约为 0.894831 所以∫_0^π sin(x^2) dx ≈ 0.894831。分析输出对于问题1模型知道lablab.ai是一个AI平台但它明确指出了“知识截止日期是2023年初”无法提供最新活动。这说明LLM存在知识陈旧的问题。它的训练数据有截止日期无法感知之后的世界。对于问题2模型给出了一个近似值0.894831并且解释这是菲涅耳积分。但是这个答案是错误的实际上∫_0^π sin(x^2) dx 的精确数值积分结果约为0.894831吗我们用更可靠的工具验证一下就会发现不对。LLM在数学计算上非常不可靠它是在“模仿”它训练数据中看到的数学答案格式而不是真正进行计算。它经常会产生“数学幻觉”即看似合理实则错误的计算过程和结果。这两个测试清晰地暴露了纯LLM的两大短板知识更新不及时和复杂逻辑/计算能力弱。这正是我们需要为它配备“工具”的原因。3.3 打造智能体的“工具箱”搜索与计算现在我们来创建两个工具分别弥补上述短板。工具一联网搜索工具解决知识陈旧问题我们将使用duckduckgo-search来获取实时信息。在LangChain中创建工具非常直观。from langchain.tools import DuckDuckGoSearchRun from langchain.agents import Tool # 初始化搜索工具 search DuckDuckGoSearchRun() # 将搜索函数包装成LangChain Tool对象 # name: 工具名称供智能体识别 # func: 工具实际执行的函数 # description: 工具描述这是最重要的部分智能体根据描述决定是否使用该工具。 search_tool Tool( nameWeb Search, funcsearch.run, description当用户的问题涉及当前事件、最新信息、实时数据、未知概念或需要从互联网获取最新资料时请使用此工具。 例如今天天气如何、某某公司的最新财报、某个新闻事件、一个我不了解的新技术。 输入应该是一个明确的搜索查询词。 )工具二数学计算工具解决计算能力问题我们将集成WolframAlpha API。WolframAlpha是一个强大的计算知识引擎能处理符号计算、数学、科学等各种问题。你需要先去 WolframAlpha API官网 注册并获取一个免费的AppID每月有一定免费额度。import requests class WolframAlphaTool: 一个自定义的WolframAlpha工具类 def __init__(self, app_id): self.app_id app_id self.base_url http://api.wolframalpha.com/v1/result def run(self, query: str) - str: 向WolframAlpha API发送查询并返回文本结果。 Args: query: 自然语言形式的查询如 integral of sin(x^2) from 0 to pi Returns: API返回的文本结果。 # 对查询进行简单编码处理空格和特殊字符 import urllib.parse encoded_query urllib.parse.quote(query) # 构建请求URL url f{self.base_url}?appid{self.app_id}i{encoded_query} try: response requests.get(url, timeout10) # 设置超时 response.raise_for_status() # 如果状态码不是200抛出HTTPError异常 return response.text.strip() except requests.exceptions.RequestException as e: return f调用WolframAlpha API时出错{e} except Exception as e: return f处理结果时发生未知错误{e} # 使用你的AppID初始化工具 WOLFRAM_APP_ID YOUR_APP_ID_HERE # 请替换成你的真实AppID wa WolframAlphaTool(app_idWOLFRAM_APP_ID) # 包装成LangChain Tool math_tool Tool( nameWolframAlpha Calculator, funcwa.run, description专门用于解决数学、科学、工程计算和事实查询问题。 例如计算125的平方根、求解方程 x^2 2x 1 0、π的前50位小数、珠穆朗玛峰的高度、水的沸点是多少。 对于需要精确计算、单位换算、公式推导、事实数据查询的问题优先使用此工具。输入应为一个清晰的问题。 )重要提示WolframAlpha API的/v1/result端点返回的是纯文本摘要。对于非常复杂的问题它可能返回“Wolfram|Alpha didnt understand your input”。对于更丰富的可视化结果可以考虑使用/v2/query端点但它返回的是XML或JSON需要额外解析。对于初学者/v1/result简单够用。3.4 组装智能体并见证其“思考”过程有了工具我们就可以创建智能体了。LangChain提供了多种智能体类型我们使用最常用、也最容易理解的ZERO_SHOT_REACT_DESCRIPTION。这种智能体基于ReActReasoning Acting范式它会在每一步“思考”中决定是使用一个工具还是直接给出最终答案。from langchain.agents import initialize_agent, AgentType from langchain.memory import ConversationBufferMemory # 初始化一个简单的对话记忆让智能体有上下文感 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 创建智能体 # 参数解释 # agent: 智能体类型我们选择零样本ReAct描述型。 # tools: 我们刚刚创建的两个工具列表。 # llm: 我们之前初始化的大语言模型。 # verbose: 设为True这样我们可以在控制台看到智能体的完整“思考链”对于调试和理解其工作原理至关重要。 # max_iterations: 最大迭代次数防止智能体陷入死循环。设为5对于简单任务足够。 # memory: 传入记忆对象。 agent initialize_agent( tools[search_tool, math_tool], llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, # 或者使用字符串 zero-shot-react-description verboseTrue, max_iterations5, memorymemory, handle_parsing_errorsTrue # 优雅地处理解析错误 )现在让我们用之前同样的问题来测试这个“武装起来”的智能体。print( 测试智能体问题1 - 需要最新信息 ) result1 agent.run(lablab.ai 这个平台主要是做什么的最近有什么活动吗) print(f\n最终答案: {result1}\n) print( 测试智能体问题2 - 复杂数学计算 ) result2 agent.run(计算定积分∫(从0到π) sin(x^2) dx 的近似值保留小数点后6位。) print(f\n最终答案: {result2})当verboseTrue时你会在控制台看到类似以下的详细输出为简洁起见略有删减和整理 测试智能体问题1 - 需要最新信息 Entering new AgentExecutor chain... 我需要找到关于lablab.ai平台的最新信息包括其功能和近期活动。我应该使用网络搜索工具来获取这些实时信息。 Action: Web Search Action Input: lablab.ai platform what is it recent events 2024 Observation: lablab.ai is an AI innovation platform that hosts hackathons, provides AI tutorials, and offers access to cutting-edge AI models and tools. It brings together developers, researchers, and enthusiasts to build AI projects. Recent events in 2024 include the AI Agent Hackathon in March and the upcoming Generative AI Builders workshop in May. The platform also features a community forum and a resource library. Thought: 我已经通过搜索获得了关于lablab.ai的最新信息。现在我可以根据这些信息来回答用户的问题。 Final Answer: lablab.ai 是一个人工智能创新平台主要专注于举办AI黑客松、提供AI教程以及让开发者接触和使用前沿的AI模型与工具。该平台汇聚了开发者、研究者和爱好者共同构建AI项目。根据2024年的最新信息其近期活动包括三月份的“AI智能体黑客松”以及即将在五月份举办的“生成式AI构建者”研讨会。此外平台还设有社区论坛和资源库。 最终答案: lablab.ai 是一个人工智能创新平台主要专注于举办AI黑客松、提供AI教程以及让开发者接触和使用前沿的AI模型与工具... 测试智能体问题2 - 复杂数学计算 Entering new AgentExecutor chain... 用户要求计算一个定积分的数值近似值。这是一个数学计算问题我应该使用WolframAlpha计算器工具。 Action: WolframAlpha Calculator Action Input: integral sin(x^2) from 0 to pi approximate to 6 decimal places Observation: 0.894831 Thought: WolframAlpha给出了结果0.894831。我需要确认这是否是保留6位小数的近似值。看起来它就是0.894831这正好是6位小数。 Final Answer: 定积分 ∫_0^π sin(x^2) dx 的数值近似值保留小数点后6位约为 0.894831。 最终答案: 定积分 ∫_0^π sin(x^2) dx 的数值近似值保留小数点后6位约为 0.894831。对比与解读思考过程可视化你可以清晰地看到智能体的“内心独白”Thought。对于问题1它想“我需要最新信息 → 用搜索工具 → 搜索词是‘lablab.ai platform...’”。对于问题2它想“这是数学问题 → 用计算器工具 → 输入数学查询”。这正是ReAct范式的体现。工具选择正确智能体根据我们对工具的描述准确地选择了合适的工具。这证明了清晰的description是多么重要。答案质量提升对于lablab.ai答案包含了2024年的具体活动信息“AI Agent Hackathon”这是纯LLM无法提供的。对于积分计算答案来自WolframAlpha的权威计算其正确性远高于LLM的猜测。我们可以用专业数学软件验证∫_0^π sin(x^2) dx的精确值约为0.894831是的这次LLM自己猜的碰巧对了数字但过程不可信而WolframAlpha的结果是可靠的。通过这个简单的例子你已经构建了一个能自主选择工具、解决两类核心问题的AI智能体雏形。它的潜力远不止于此。4. 进阶实战构建一个多任务项目研究助手让我们把难度提高构建一个更实用的智能体一个能进行多步骤网络研究并生成摘要的“项目研究助手”。它的任务是给定一个新兴技术主题例如“Neuromorphic Computing”神经形态计算它能自动搜索相关资料理解核心概念并生成一份简洁的研究摘要。这个任务比单次问答复杂因为它涉及多轮工具调用和信息整合。我们将引入ConversationBufferMemory来让智能体记住整个研究过程。from langchain.agents import Tool, AgentExecutor, LLMSingleActionAgent, AgentOutputParser from langchain.prompts import StringPromptTemplate from langchain import OpenAI, SerpAPIWrapper, LLMChain from typing import List, Union from langchain.schema import AgentAction, AgentFinish import re # 假设我们有一个更强大的搜索工具例如SerpAPI需API Key这里我们用DuckDuckGo替代演示 search DuckDuckGoSearchRun() search_tool Tool( name Search, funcsearch.run, description用于搜索互联网上的最新文章、新闻、论文和技术文档。当需要获取关于某个主题的事实性、时效性信息时使用。 ) # 我们还需要一个“总结”工具吗不总结工作我们将交给LLM本身。 # 但我们可以设计一个流程先搜索再让LLM基于搜索结果进行总结。 # 更高级的做法是使用“Agent within Agent”或者自定义一个多步骤链。这里我们设计一个自定义的Agent Prompt来引导它。 from langchain.agents import initialize_agent # 重新初始化一个带有更详细系统提示的智能体 from langchain.prompts import PromptTemplate # 自定义提示模板指导智能体执行研究任务 research_prompt PromptTemplate.from_template( 你是一个专业的技术研究助手。你的任务是帮助用户深入研究一个技术主题。 请遵循以下步骤来完成任务 1. **理解与拆解**首先理解用户给出的主题。将其拆解成3-5个关键子问题。例如对于“神经形态计算”子问题可能包括基本原理、与传统计算的区别、主要硬件实现、当前应用、未来挑战。 2. **搜索信息**针对每一个子问题使用搜索工具查找权威、最新的资料优先选择近两年的文章、论文或技术报告。 3. **综合与总结**基于搜索到的信息为每个子问题撰写一段简洁明了的摘要。确保引用关键事实和数据。 4. **形成最终报告**将所有子问题的摘要整合成一份连贯的最终研究报告。 请开始你的工作。如果某次搜索没有找到相关信息请尝试更换搜索关键词或聚焦于更具体的方面。 当前对话历史 {chat_history} 用户输入{input} 你必须从以下工具中选择一个使用{tools}。 请严格按以下格式回应 Thought: 你的思考过程分析当前情况决定下一步做什么 Action: 要使用的工具名称必须是[{tool_names}]中的一个 Action Input: 给该工具的输入 Observation: 工具返回的结果 ... (这个 Thought/Action/Action Input/Observation 序列可以重复多次) 当你拥有足够的信息来撰写最终报告时请使用以下格式直接输出最终答案 Thought: 我已经收集了所有必要信息现在可以生成最终报告。 Final Answer: [你的最终研究报告结构清晰包含子章节] 开始 ) # 由于我们使用了自定义提示需要稍微调整智能体的初始化方式。 # 这里为了简化我们使用一个更通用的方法创建一个执行研究任务的链并让一个主智能体来协调。 # 但实际上LangChain的Zero-Shot Agent已经能处理多步任务。我们直接增强其提示词即可。 llm OpenAI(temperature0, model_namegpt-3.5-turbo-instruct) # 温度设为0让输出更确定 # 使用ConversationBufferWindowMemory保留最近几轮对话避免上下文过长 from langchain.memory import ConversationBufferWindowMemory memory ConversationBufferWindowMemory(k3, memory_keychat_history) # 创建智能体 research_agent initialize_agent( tools[search_tool], # 目前只给搜索工具 llmllm, agentAgentType.CONVERSATIONAL_REACT_DESCRIPTION, # 使用对话型ReAct智能体更适合多轮交互 verboseTrue, memorymemory, max_iterations10, # 研究任务可能需要更多轮交互 handle_parsing_errorsTrue ) # 现在让我们给这个研究助手一个任务 research_topic Explain the concept of Neuromorphic Computing, its current state and potential applications in robotics. print(f研究主题: {research_topic}\n) result research_agent.run(research_topic) print(f\n 研究助手生成的报告 \n{result})运行这段代码由于verboseTrue你会看到智能体进行了一系列的“思考-行动-观察”循环。它可能会先搜索“Neuromorphic Computing definition”然后基于结果思考再搜索“neuromorphic computing vs von neumann architecture”接着搜索“neuromorphic hardware 2024”最后搜索“neuromorphic computing robotics applications”。在收集了足够多的“Observation”后它最终会触发“Final Answer”生成一份综合了所有搜索结果的报告。实操心得与陷阱预警迭代次数与成本max_iterations设置太小智能体可能还没完成研究就停止了设置太大如果智能体陷入循环会产生大量不必要的API调用既费钱又费时。需要根据任务复杂度谨慎设置。我的经验是从小开始如5观察其行为再逐步调整。提示工程是关键智能体的表现极度依赖于给它的指令提示词。模糊的指令会导致低效或错误的工具调用。我们的research_prompt尝试通过步骤化指令来约束它。在实际复杂任务中你可能需要反复调试提示词。工具质量决定上限DuckDuckGoSearchRun返回的摘要有时质量不高。对于严肃的研究你可能需要接入更专业的学术搜索引擎API如Google Scholar、Semantic Scholar或者使用能返回更完整网页内容的工具如SerpAPI配合BeautifulSoup进行内容提取。“幻觉”并未消失即使有了搜索工具LLM在整合信息时仍可能产生“幻觉”比如错误地关联信息或捏造细节。因此对于关键事实最终的输出仍需人工审核。可以尝试让智能体在回答中引用信息来源的片段以提高可信度。5. 常见问题、调试技巧与效能优化指南在开发和部署AI智能体的过程中你会遇到各种各样的问题。下面是我从多次实战中总结出的常见“坑”及其解决方案。5.1 智能体陷入循环或行为异常问题现象智能体反复执行同一个工具或者在不同工具间无效切换始终无法达到最终状态。根本原因工具描述不清晰LLM无法准确理解何时该使用哪个工具。提示词引导不足没有在系统指令中明确设定停止条件或任务完成的判断标准。工具输出质量差工具返回的结果无法为LLM提供有效的决策依据。解决方案精细化工具描述在description中明确使用场景、输入格式和输出示例。例如不只是说“用于计算”而是说“用于解决数学方程、微积分、代数运算。输入应为明确的数学表达式或问题如‘solve x^2 5x 6 0’或‘derivative of sin(x)cos(x)’。”强化系统提示在初始化智能体的agent_kwargs中可以传入自定义的prefix前缀和suffix后缀提示。在前缀中明确写出任务步骤和停止条件。例如“你的任务是通过搜索和计算回答用户问题。你必须先搜索如果搜索结果显示需要计算再使用计算器。当你得到一个能直接回答用户问题的最终信息时就停止并输出‘Final Answer:’。”增加超时和最大迭代限制务必设置max_iterations如10-15和max_execution_time作为安全网防止无限循环产生高额费用。使用更高级的Agent类型ZERO_SHOT_REACT_DESCRIPTION是最基础的。可以尝试STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION它要求工具输入必须是结构化参数约束性更强。或者尝试OPENAI_FUNCTIONS/OPENAI_MULTI_FUNCTIONS代理它们利用OpenAI的Function Calling特性工具调用更精准。5.2 处理复杂、模糊的用户查询问题现象用户提问“帮我做个旅游攻略”智能体不知所措因为任务太宏大模糊。解决方案设计一个“任务澄清”环节。可以在主智能体前加一层“规划智能体”或使用一个LLMChain专门用于将模糊任务拆解成具体的、可执行的动作列表。from langchain.chains import LLMChain from langchain.prompts import PromptTemplate clarification_prompt PromptTemplate( input_variables[user_input], template用户提出了一个请求{user_input} 请将这个模糊的请求分解成一个具体的、按顺序执行的步骤列表。每个步骤应该是一个清晰的、可以单独由某个工具如搜索、计算、文件读写或直接由你回答的动作。 输出格式为 1. [第一步动作描述] 2. [第二步动作描述] ... 例如用户输入“帮我做个去日本东京的旅游攻略”输出 1. 搜索“日本东京最佳旅游季节 近期”。 2. 搜索“东京必去景点排行榜 2024”。 3. 搜索“东京住宿推荐 性价比高”。 4. 搜索“东京当地交通攻略”。 5. 根据以上信息整理一份包含季节、景点、住宿、交通的简要攻略。 现在请分解以下请求 ) clarification_chain LLMChain(llmllm, promptclarification_prompt) steps clarification_chain.run(帮我研究一下太阳能屋顶的成本效益分析) print(steps) # 输出可能为 # 1. 搜索“住宅太阳能屋顶安装平均成本 2024”。 # 2. 搜索“太阳能屋顶政府补贴政策 最新”。 # 3. 搜索“太阳能屋顶发电量计算 典型家庭”。 # 4. 搜索“太阳能投资回报率计算方法”。 # 5. 根据以上数据估算一个典型家庭的安装成本、年节省电费及投资回收期。然后你可以让主智能体依次执行这些步骤。这大大降低了单次决策的复杂度。5.3 管理上下文长度与长期记忆问题现象随着对话轮数或工具调用次数增加发送给LLM的提示词越来越长最终可能超出模型的上下文窗口限制如GPT-3.5-turbo的16K导致错误或性能下降。解决方案使用有窗口的记忆如ConversationBufferWindowMemory(k5)只保留最近5轮对话丢弃更早的。使用总结性记忆ConversationSummaryMemory会在每次交互后自动用LLM总结之前的对话历史只保留总结摘要从而大幅压缩上下文。但这会增加LLM调用次数和成本。集成向量数据库实现长期记忆这是最强大的方案。将对话或任务中的关键信息实体、结论、用户偏好转换成向量存入如Chroma、Pinecone、Weaviate等数据库。当新问题到来时先进行向量相似度搜索将与当前问题最相关的几条历史记忆作为上下文注入。LangChain提供了VectorStoreRetrieverMemory等组件来简化这一过程。5.4 成本控制与性能优化问题智能体每次“思考”和“最终回答”都要调用LLM每次工具调用也可能涉及外部API费用如搜索API。复杂的多步任务成本可能很高。优化策略选择性价比模型对于智能体的“思考”即决定下一步动作可以使用较小、较快的模型如GPT-3.5-turbo。对于需要高质量输出的“最终答案”生成可以切换到大模型如GPT-4。LangChain支持在同一个智能体中使用不同的LLM进行不同环节的调用。缓存结果对于重复性查询可以使用LangChain的Cache功能如SQLiteCache来缓存LLM的响应避免为相同输入重复付费。设置预算和监控在代码层面记录每次LLM和工具调用的开销并设置每日或每任务预算上限。OpenAI API也提供了使用量监控和告警功能。精简提示词去除不必要的系统指令保持Thought和Observation的简洁。避免在工具描述中使用冗长的句子。构建AI智能体是一个迭代和调试的过程。没有一蹴而就的完美方案。最好的学习方式就是选择一个你感兴趣的具体小问题比如“每日自动抓取我关注的几个科技博客并生成摘要邮件给我”从最简单的单工具智能体开始逐步增加复杂性在过程中不断观察其行为调整提示词和工具设计。你会发现看着一个自己创造的“数字助手”从笨拙到逐渐熟练地完成任务是一件极具成就感的事情。这不仅是学习一项技术更是在塑造未来人机协作的新范式。