《AI大模型应用开发实战从入门到精通共60篇》013、LangChain之Agents:赋予大模型使用工具的能力
013、LangChain之Agents赋予大模型使用工具的能力一个让我熬夜的Bug上个月做智能客服项目遇到个诡异问题用户问“帮我查一下北京今天PM2.5”大模型回复“好的我查一下”然后——卡住了。等了30秒模型开始胡编乱造空气质量数据。我盯着日志看了两小时发现模型根本没调用天气API它在用自己的“知识”瞎编。这就是典型的“大模型幻觉”场景。模型不是搜索引擎它不知道实时数据。但如果我们能让模型学会“使用工具”问题就解决了。LangChain的Agents就是干这个的。Agents到底是什么简单说Agent是一个“思考-行动-观察”的循环体。它不像Chain那样固定执行步骤而是让LLM自己决定下一步该做什么。核心流程收到用户问题LLM判断需要调用什么工具比如查天气API执行工具拿到结果把结果喂回给LLMLLM根据结果生成最终回答这个循环可以反复进行直到LLM认为任务完成。手写一个Agent从零搭建先装依赖别用最新版我踩过坑# 别用langchain0.2.0API改得面目全非# 推荐0.1.20稳定pip install langchain0.1.20openai python-dotenv定义工具函数注意函数签名必须带类型注解否则Agent认不出来fromlangchain.toolsimporttooltooldefget_weather(city:str)-str:获取指定城市的实时天气输入城市名称如北京# 这里假装调了真实API实际项目换成requestsweather_data{北京:晴25°CPM2.5指数35,上海:多云28°CPM2.5指数42,广州:阵雨30°CPM2.5指数28}returnweather_data.get(city,f未找到{city}的天气数据)这里有个坑docstring必须写清楚工具的功能和参数格式。LLM是通过docstring理解工具用途的写得太模糊它就会乱调用。创建Agentfromlangchain.agentsimportcreate_openai_functions_agentfromlangchain_openaiimportChatOpenAIfromlangchain.agentsimportAgentExecutor llmChatOpenAI(modelgpt-4,temperature0)# temperature设0别让模型太有“创意”工具调用需要确定性tools[get_weather]agentcreate_openai_functions_agent(llmllm,toolstools,# 这里用默认prompt就行别自己瞎改)agent_executorAgentExecutor(agentagent,toolstools,verboseTrue,# 打开日志调试神器max_iterations3,# 防止死循环重要)测试一下resultagent_executor.invoke({input:北京今天天气怎么样})print(result[output])输出日志会显示 Entering new AgentExecutor chain... Invoking: get_weather with {city: 北京} 北京晴25°CPM2.5指数35 北京今天天气晴朗气温25°CPM2.5指数35空气质量良好。完美。但别高兴太早真实场景比这复杂得多。多工具协作一个翻车案例给Agent加两个工具让它能查天气和算数学tooldefcalculate(expression:str)-str:计算数学表达式输入如23*4try:returnstr(eval(expression))except:return计算错误tools[get_weather,calculate]用户问“北京今天气温25度上海28度温差多少”Agent的思考过程verboseTrue能看到调用get_weather查北京 → 25°C调用get_weather查上海 → 28°C调用calculate计算28-25 → 3回答温差3°C看起来没问题但实际测试时Agent有时候会跳过工具调用直接说“温差3度”——它自己算的。这就是模型偷懒或者prompt没写好。解决办法在工具描述里强调“必须使用工具不要自己计算”。自定义Agent当默认行为不够用默认的OpenAI Functions Agent好用但有些场景需要自定义。比如我想让Agent先确认用户意图再行动fromlangchain.agentsimportAgentExecutor,create_react_agentfromlangchainimporthub# 用ReAct模式的promptprompthub.pull(hwchase17/react)# 自定义prompt模板fromlangchain.promptsimportPromptTemplate custom_promptPromptTemplate.from_template(你是一个智能助手可以调用工具获取信息。 工具列表 {tools} 工具名称{tool_names} 用户问题{input} 请按以下格式思考 思考我需要做什么 行动工具名称 行动输入工具参数 观察工具返回结果 ...重复思考-行动-观察直到得到答案 最终答案给用户的回答 {agent_scratchpad})agentcreate_react_agent(llm,tools,custom_prompt)注意自定义prompt很容易翻车。我建议先用默认prompt等跑通了再微调。别一上来就炫技。实战带记忆的Agent用户连续问问题Agent需要记住上下文fromlangchain.memoryimportConversationBufferMemory memoryConversationBufferMemory(memory_keychat_history,return_messagesTrue)agent_executorAgentExecutor(agentagent,toolstools,memorymemory,verboseTrue,max_iterations3,handle_parsing_errorsTrue# 解析错误时别崩优雅处理)测试连续对话用户“北京天气怎么样”Agent调用工具回答“晴25°C”用户“那上海呢”Agent应该记住“那上海呢”指的是天气调用工具查上海但实际测试发现有时候Agent会忘记上下文重新问“你要查哪个城市的天气”——这是memory没配置好或者prompt里没强调使用历史记录。踩坑记录Agent的七宗罪工具调用失败不重试API超时了Agent直接说“查不到”不会重试。解决方案在工具函数里加retry逻辑。死循环Agent反复调用同一个工具停不下来。max_iterations是救命稻草设个3-5次。幻觉工具参数模型会编造不存在的参数。比如get_weather只接受city它传个city北京, unitcelsius。解决方案工具参数尽量简单别搞复杂schema。工具选择错误有计算器和天气两个工具用户问“22等于几”Agent去调天气API。这是prompt没写好或者工具描述不清晰。忽略工具结果工具返回了数据Agent不看自己编答案。把temperature设低或者加system prompt强调“必须基于工具结果回答”。多轮对话丢失状态上面说过了memory配置要仔细检查。性能问题每次Agent循环都要调一次LLM成本高、延迟大。能一次解决的别让Agent绕圈子。个人经验什么时候用Agent别什么场景都上Agent。我现在的原则简单查询查天气、算算术用Chain就够了别杀鸡用牛刀需要多步推理“北京和上海温差多少哪个更热”Agent合适工具数量3个必须用Agent否则Chain逻辑会爆炸实时数据Agent工具是唯一解另外生产环境一定要加监控。我见过Agent在循环里调了20次API账单吓死人。设好max_iterations记录每次调用的token消耗。最后说一句别迷信Agent。它本质上是让LLM做决策LLM本身就不稳定。能用规则解决的问题别让模型掺和。Agent是最后的选择不是第一选择。