AI Agent初探:让LLM自己决定该调用什么工具

序言:如果你还在用if-else判断用户意图,然后手动调用不同API,这篇文章能让你少写一半代码。

一、从"流水线工人"到"项目经理"

上个月,我帮朋友做了一个智能助手Demo。需求听起来很普通:用户问天气,就调天气API;用户问数学题,就调计算器;用户问新闻,就调搜索引擎。

我一开始用Chain的思路写。代码大概长这样:

python 复制代码
if "天气" in user_input:
    result = weather_api(user_input)
elif "计算" in user_input or "等于" in user_input:
    result = calculator(user_input)
elif "新闻" in user_input:
    result = search_engine(user_input)
else:
    result = llm.chat(user_input)

写了三天,覆盖了大概二十种意图。第四天,用户问了一句:"帮我查一下明天北京气温,然后算一下华氏度是多少。"

我当场傻眼。

这句话包含两个任务:先查天气,再算温度转换。而且用户没明确说"查天气",而是说"查一下气温"------我的if-else匹配不到。更麻烦的是,查完天气后的结果要传给计算器,两个工具之间需要数据传递。

那一刻我突然意识到:Chain的思路在这里行不通了。

Chain是什么?Chain是流水线。你设计好步骤A→B→C,输入进去,按固定顺序执行,输出结果。它像工厂里的流水线工人,每个工位只做一件事,但流程是死的,不会变。

Agent是什么?Agent是项目经理。你给它一个目标,它自己分析需要哪些资源、按什么顺序调用、中间结果怎么处理。它像一个人类助理,收到"帮我订一张明天去上海的机票,要早班机,然后帮我查一下上海明天的天气",自己会拆解任务、调用工具、整合结果。

Chain是人推流程,Agent是AI推流程。 这个区别,决定了它们各自适合什么场景。

二、ReAct:Agent的"思考-行动-观察"循环

Agent之所以能自主决策,背后依赖的是一个叫ReAct的框架。ReAct是Reasoning(推理)和Acting(行动)的缩写,它的核心逻辑可以用一个循环概括:

Thought → Action → Observation → Thought → Action → Observation → ... → Final Answer

这个循环听起来抽象,但拆解一下就很清晰。

Thought:模型在"想什么"

当Agent收到用户的问题,它不会直接回答,而是先输出一段"内心独白"------也就是Thought。这段Thought是模型对自己当前处境的分析。

比如用户问:"明天北京气温多少华氏度?"

模型的Thought可能是:"用户想知道北京明天的气温,并且要以华氏度为单位。我需要先查询北京明天的气温(摄氏度),然后再把摄氏度转换成华氏度。第一步,调用天气API获取北京明天的气温。"

Thought的价值在于:它把模型的推理过程外化了。 你不需要写if-else,模型自己判断该做什么。

Action:模型决定"做什么"

想清楚之后,模型输出Action。Action包含两个部分:工具名称(Action)和输入参数(Action Input)。

接上例,模型会输出:

复制代码
Action: weather_api
Action Input: 北京明天

AgentExecutor接收到这个Action,就会去调用对应的工具函数,把"北京明天"传进去。

Observation:工具返回"看到了什么"

工具执行完后,返回结果给模型。这个结果叫Observation。

比如天气API返回:"北京明天晴,气温15-25摄氏度。"

模型收到Observation后,进入下一轮循环:

新的Thought:"我已经拿到了北京明天的气温,是15-25摄氏度。用户要的是华氏度,所以我需要把摄氏度转换成华氏度。取中间值20摄氏度进行转换。华氏度 = 摄氏度 × 9/5 + 32 = 20 × 1.8 + 32 = 68华氏度。"

新的Action

复制代码
Action: calculator
Action Input: 20 * 9 / 5 + 32

新的Observation:"68"

Final Thought:"我已经得到了最终答案。北京明天气温约20摄氏度,换算成华氏度是68°F。"

Final Answer:"北京明天气温约68华氏度(20摄氏度)。"

这就是ReAct的完整循环。它不是一次性给出答案,而是让模型像人类一样,一步一步地思考、行动、观察、再思考,直到问题解决。

三、实战:给Agent配备三件"武器"

理解了原理,我们来动手搭一个。给Agent配备三个工具:搜索引擎、计算器、天气查询。然后扔给它一个复合问题,看它怎么自主拆解。

第一步:定义工具

每个工具都是一个Python函数,用@tool装饰器包装,让LangChain能识别它。

python 复制代码
from langchain.tools import tool

@tool
def search_engine(query: str) -> str:
    """用于搜索互联网上的实时信息,比如新闻、百科、最新事件。
    当用户问到你不知道的、需要最新数据的问题时,使用这个工具。"""
    # 实际项目中这里调百度/谷歌/Bing API
    return f"搜索结果:关于'{query}'的最新信息是......"

@tool
def calculator(expression: str) -> str:
    """用于执行数学计算。输入应该是一个合法的数学表达式,
    比如 '3 * 5 + 2'、'100 / 4'、'2 ** 10'。"""
    try:
        return str(eval(expression))
    except:
        return "计算出错,请检查表达式格式"

@tool
def weather_api(city: str) -> str:
    """用于查询指定城市的天气信息。输入应该是城市名称,
    比如 '北京'、'上海'、'纽约'。"""
    # 实际项目中这里调天气API
    weather_data = {
        "北京": "明天晴,15-25°C",
        "上海": "明天多云,18-26°C",
        "纽约": "明天雨,10-15°C"
    }
    return weather_data.get(city, "暂不支持该城市天气查询")

注意每个工具的docstring(函数说明)。 Agent靠这些说明来决定什么时候调用哪个工具。说明写得越清晰,Agent的决策越准确。

第二步:创建Agent

python 复制代码
from langchain.agents import create_react_agent, AgentExecutor
from langchain_openai import ChatOpenAI
from langchain import hub

# 加载ReAct的Prompt模板
prompt = hub.pull("hwchase17/react")

# 初始化模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 工具列表
tools = [search_engine, calculator, weather_api]

# 创建ReAct Agent
agent = create_react_agent(llm, tools, prompt)

# 用AgentExecutor包装,负责执行循环
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,  # 打印每步的Thought/Action/Observation
    max_iterations=5,  # 最多循环5次,防死循环
    handle_parsing_errors=True  # 解析出错时自动重试
)

第三步:运行复合需求

python 复制代码
result = agent_executor.invoke({
    "input": "帮我查一下明天北京气温,然后算一下华氏度是多少"
})
print(result["output"])

如果开了verbose=True,你会在控制台看到Agent的完整思考过程:

复制代码
> Entering new AgentExecutor chain...
Thought: 用户想知道北京明天的气温,并且要求换算成华氏度。
我需要分两步:先查询北京明天的气温,再把摄氏度转成华氏度。
Action: weather_api
Action Input: 北京
Observation: 明天晴,15-25°C
Thought: 我已经拿到了北京明天的气温范围15-25°C。
为了换算成华氏度,我取中间值20°C进行计算。
华氏度 = 20 * 9 / 5 + 32
Action: calculator
Action Input: 20 * 9 / 5 + 32
Observation: 68.0
Thought: 我已经得到了最终答案。
Final Answer: 北京明天气温约68华氏度(对应20摄氏度,实际范围15-25°C即59-77°F)。
> Finished chain.

注意Agent的自主行为:

  1. 它自己判断出需要先查天气,而不是直接计算;
  2. 它从天气结果中提取了温度数值;
  3. 它自己决定取中间值20°C进行换算;
  4. 它主动调用计算器执行公式;
  5. 最后整合信息,给出完整答案。

整个过程,你没有写一行if-else,没有手动传递中间结果,没有硬编码任务顺序。Agent自己把活干完了。

四、AgentExecutor:幕后指挥官

Agent能自主决策,但谁来控制这个"思考-行动"的循环?答案是AgentExecutor。

AgentExecutor是LangChain中负责运行Agent的核心组件。它的工作逻辑可以概括为:

  1. 把用户问题和工具说明拼成Prompt,发给LLM;
  2. LLM返回Thought + Action;
  3. AgentExecutor解析Action,调用对应工具;
  4. 工具返回Observation,拼进历史记录;
  5. 把更新后的历史再次发给LLM,进入下一轮;
  6. 直到LLM输出Final Answer,或者达到终止条件。

这个循环看似简单,但生产环境中有两个坑必须处理。

坑一:无限循环

如果模型"钻牛角尖",一直在同一个工具上反复调用,循环就永远结束不了。比如查询天气失败后,模型不断重试,陷入死循环。

解决方案:max_iterations

python 复制代码
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    max_iterations=5  # 最多执行5轮,超限强制终止
)

max_iterations是AgentExecutor的保险丝。无论模型多么执着,5轮之后强制结束,避免资源耗尽。

坑二:输出格式错乱

LLM偶尔不按ReAct格式输出。比如它可能输出:

复制代码
Thought: 我需要查询天气
好的,我来帮您查询一下,请稍等...
Action: weather_api
Action Input: 北京

中间那句"好的,我来帮您查询一下"是多余的废话,导致AgentExecutor解析Action时失败,直接抛异常崩溃。

解决方案:handle_parsing_errors

python 复制代码
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    handle_parsing_errors=True  # 解析错误时,把错误信息反馈给LLM,让它重新生成
)

当设置为True时,AgentExecutor不会直接崩溃,而是把解析错误包装成一条Observation回传给模型:"你的输出格式不对,请严格按照Thought/Action/Action Input的格式输出。"模型收到反馈后,通常会修正格式,重新生成正确的Action。

这个参数在生产环境必须开启。开发阶段可以关掉,方便看到原始报错;但上线后,没有它,一次格式错乱就能让整个服务500错误。

其他关键参数

  • verbose :开发时设为True,打印每轮Thought/Action/Observation,方便调试;上线后设为False,减少日志噪音。
  • return_intermediate_steps :设为True时,返回结果会包含每轮的工具调用详情,适合做审计日志;平时不需要。
  • early_stopping_method:当达到max_iterations但还没拿到Final Answer时,是强制返回提示语("force"),还是让模型基于已有信息生成一个最终答案("generate")。推荐用"generate",体验更好。

五、Agent不是万能药:它适合什么,不适合什么

写到这里,有必要泼一盆冷水。Agent很酷,但不是所有场景都适合。

适合用Agent的场景:

  • 任务步骤不确定,需要根据中间结果动态调整。比如"查天气→算温度→根据温度推荐穿衣",中间每一步都可能影响下一步。
  • 需要调用多个不同类型的工具,且调用顺序不固定。比如客服机器人,可能涉及查订单、算退款、搜知识库、发邮件,顺序完全取决于用户问题。
  • 问题本身需要多轮推理才能解决。比如"某公司去年营收增长20%,今年Q1营收是去年的1.2倍,请计算今年Q1相比前年同期的增长率",需要拆解成多个计算步骤。

不适合用Agent的场景:

  • 流程完全固定的任务。比如"翻译→润色→输出",用Chain更稳定、更快、成本更低。Agent的自主决策在这里是多余的,反而增加了不确定性。
  • 对延迟极度敏感的场景。Agent每轮循环都要调一次LLM,一个复杂任务可能调3-5次,延迟是Chain的3-5倍。
  • 对确定性要求极高的场景。比如金融交易、医疗诊断,一步错步步错,不适合让模型自主决策。

一句话总结:Chain是"按剧本演戏",Agent是"即兴发挥"。剧本好的戏,别让它即兴。

六、写在最后:从"调API"到"搭团队"

写完这个Demo,我对Agent最大的感受是:它改变了我和AI的关系。

以前用Chain,我是导演,AI是演员。我写好剧本,AI按台词念。剧本越细,效果越可控,但灵活性越差。

现在用Agent,我是老板,AI是项目经理。我定目标、配资源(工具),AI自己排计划、调资源、交结果。我只需要在关键节点验收,在出问题时兜底。

这种转变,和当年从"手写汇编"到"用高级语言"、从"单体应用"到"微服务"的演进很像------不是人在退化,而是人在进化到更高的抽象层。

当然,Agent目前还不完美。它偶尔会选错工具,偶尔会在循环里打转,偶尔会把简单问题复杂化。但这些问题,随着模型能力的提升和框架的成熟,正在快速改善。LangChain 1.0已经把ReAct循环标准化成了create_agent一个函数,10行代码就能搭一个生产级Agent。

如果你还在用if-else手动分发用户意图,不妨试试Agent。让它自己决定该调用什么工具,你会发现:代码少了,灵活性高了,AI真的开始像"智能体"而不是"应答机"了。

相关推荐
小小测试开发1 小时前
AI 编程助手实战:8 小时搭建睡眠噪音追踪系统
人工智能
Bruce_Liuxiaowei1 小时前
OpenAI双杀_40亿部署公司+Daybreak安全AI_博客初稿
人工智能·安全·ai·大模型
小程故事多_801 小时前
深度解析Claude Code,AI编码助手的底层架构与工作原理
java·人工智能·架构·智能体
Soari1 小时前
开启 AI 艺术创作之门:深度拆解 Stable Diffusion web UI,打造私有化文生图最强阵地
人工智能·ui·stable diffusion
sunneo1 小时前
00-系列开篇-AI-Agent的行为密码
人工智能·产品运营·aigc·产品经理·ai-native
AI品信智慧数智人1 小时前
[特殊字符]AI 数智人全场景实时解决方案|山东品信智慧科技,开启人机交互新纪元✨
人工智能·科技·人机交互
sunneo1 小时前
01-当AI-Agent学会制造信息缺口
人工智能·产品运营·aigc·产品经理·ai-native
Python私教1 小时前
HTML还是Markdown:AI时代文档格式的正确选择
人工智能
拓朗工控1 小时前
拓朗工控MXM GPU工控机:赋能制造、交通与边缘AI的算力新引擎
人工智能·制造·mxm工控机