Agent 开发:ReAct 循环与工具调用实战——从单次调用到自主 Agent

接上篇《Agent 开发入门:Function Call 实战》。上篇讲的是"单次调工具",本篇让它循环起来------这就是 Agent 从"工具人"变成"自主执行者"的关键一步。

目录

[一、从 Function Call 到 Agent:只差一个"循环"](#一、从 Function Call 到 Agent:只差一个"循环")

[二、ReAct 四步循环(背下来,面试必考)](#二、ReAct 四步循环(背下来,面试必考))

[三、完整可运行代码(ReAct Agent)](#三、完整可运行代码(ReAct Agent))

[四、工具设计 4 件套(决定 Agent 聪明不聪明)](#四、工具设计 4 件套(决定 Agent 聪明不聪明))

五、工程化必备:4个防崩措施

六、过关清单

七、常见坑(5个)

八、面试必答


一、从 Function Call 到 Agent:只差一个"循环"

单次调用做不到"查上海→查北京→算差值"这种连续任务,需要循环:

思考(下一步干嘛)→ 行动(调工具)→ 观察(看结果)→ 再思考......直到能回答

这就是 ReAct 范式(Reasoning + Acting)。

一句话:模型当调度器,工具当执行器,循环当流程引擎。

二、ReAct 四步循环(背下来,面试必考)

① 思考 Thought:模型决定"下一步该干嘛/该调哪个工具"

② 行动 Action:真正去调那个工具

③ 观察 Observation:拿到工具返回的结果

④ 再思考:拿着结果判断"够了没?不够再循环"

后端类比:while循环+状态机------模型是决策者,每轮根据状态决定下一步。

终止条件:① 模型判断够了直接回答 ② 达到max_iterations上限

三、完整可运行代码(ReAct Agent)

工具1:天气

复制代码
def get_weather(city: str) -> str:

    data = {"上海": 28, "北京": 22, "广州": 31}

    if city not in data:

        raise ValueError(f"没有 {city} 的天气数据")

    return f"{city}当前气温 {data[city]} 摄氏度"

工具2:计算

复制代码
def calc(expr: str) -> str:

    try:

        return f"计算结果:{eval(expr, {'__builtins__': {}})}"

    except Exception as e:

        return f"计算出错:{e}"

Agent 循环(ReAct)

复制代码
def run_agent(user_msg: str, max_iter: int = 5):

    messages = [{"role": "user", "content": user_msg}]

    for i in range(max_iter):

        resp = client.chat.completions.create(

            model="gpt-4o-mini", messages=messages, tools=TOOLS)

        msg = resp.choices[0].message

        if not msg.tool_calls:  # 模型觉得够了→直接回答

            print("[思考] 无需再调工具,直接回答")

            return msg.content

        messages.append(msg)

        for tc in msg.tool_calls:

            name, args = tc.function.name, json.loads(tc.function.arguments)

            print(f"[思考] 调工具 {name}({args})")

            try:

                result = FUNC_MAP[name](**args)      # 行动

            except Exception as e:

                result = f"工具执行失败:{e}"

            print(f"[观察] {result}")

            messages.append({"role": "tool", "tool_call_id": tc.id, "content": str(result)})

    return "(已达最大轮数,仍未能确定答案)"

运行输出(能看到循环):

思考 调工具 get_weather({'city': '上海'})

观察 上海当前气温 28 摄氏度

思考 调工具 get_weather({'city': '北京'})

观察 北京当前气温 22 摄氏度

思考 调工具 calc({'expr': '28-22'})

观察 计算结果:6

思考 无需再调工具,直接回答

上海28度,北京22度,差6度。

注意:模型自动连续调了3次工具(上海→北京→算差)------这就是"自主"。

四、工具设计 4 件套(决定 Agent 聪明不聪明)

name:工具名

description:给模型看的说明书(靠它决定用不用)

parameters:参数schema

func:真干活的代码

最常被忽略的坑:模型只看description,写含糊就乱选工具。

五、工程化必备:4个防崩措施

异常捕获(try/except)

max_iterations(防死循环)

结果清洗(别喂垃圾)

结构化错误(让模型兜底)

六、过关清单

☐ Agent能自主完成"多工具串联"任务

☐ 能讲清"思考-行动-观察"循环(ReAct)

☐ 改description能观察模型选工具行为变化

☐ 工具出错时Agent能捕获不崩溃

☐ 设了max_iterations防死循环

七、常见坑(5个)

  1. description写太泛→乱选工具(写清何时用/输入输出)

  2. schema类型不对→填参报错(严格type+required)

  3. 工具没异常捕获→一个挂全崩(try/except)

  4. 无限循环→烧token(max_iterations)

  5. 原生错误喂回模型→被带偏(先清洗)

八、面试必答

Q:Agent怎么防止死循环?

A:① max_iterations轮数上限 ② 工具返回结构化错误让模型纠偏 ③ 异常捕获+超时。核心是"循环必须有终止条件"。

下一篇预告:《Agent 开发:多 Agent 协作实战------LangGraph 编排从策划到执行》。欢迎关注专栏「后端转AI实战指南」,持续更新。

📌 配套代码:(Star支持)

backend-to-ai-guide/react_agent_demo/README.md at main · cxy-ai-gongfang/backend-to-ai-guide · GitHub

【官方权威来源】

  1. ReAct论文 --- Yao et al. (2022), ICLR 2023, arXiv:2210.03629(ReAct范式原始出处)

https://arxiv.org/abs/2210.03629

  1. OpenAI Function Calling 官方文档(工具JSON Schema/tool_calls)

https://platform.openai.com/docs/guides/function-calling

  1. OpenAI Agents 官方指南(Agent循环/终止条件)

https://platform.openai.com/docs/guides/agents

  1. LangChain Agents 官方文档(Agent抽象/ReAct执行器)

https://python.langchain.com/docs/concepts/agents/

【内部整理来源】

  1. 《后端转AI应用工程师·实战电子书》第5天上午「单Agent工具调用」章节(ReAct原理/工具4件套/代码)

  2. 《求职最短路径·半天计划》Day 5(过关清单与验收标准)

  3. 《Agent开发》(第二周-Agent模式/第三周-ReAct反思)

版权说明:本文为原创技术分享,代码示例基于 OpenAI 官方 API 用法编写,可自由学习使用。

相关推荐
️学习的小王1 小时前
基于UDP实现简易聊天室(基础版)——Python实现
网络·python·udp
小刘快学习1 小时前
品牌舆情监测的接入思路:从采集到预警的链路
人工智能
Wang's Blog1 小时前
AI Agent白手起家41: LangChain 链的高级应用:函数、记忆、路由与容错
langchain
Ai-_Man1 小时前
豆包智能体内容批量导出:哪些该存、存成什么、怎么存v
人工智能·ai·小程序·word
XS0301061 小时前
Spring AI:两种内置 Advisor 快速实现 RAG
java·人工智能·spring
阿部多瑞 ABU1 小时前
新-潘多拉降临操场
人工智能
不爱说话郭德纲1 小时前
我只给了 TRAE Work 一张差评截图,它最后却把自己的 P0 结论推翻了?
前端·后端·架构
小妖同学学AI1 小时前
拒绝手动SSH:用战斗机与AI混沌构建的硬核Homelab架构
人工智能
W_326001 小时前
Python 组合数据类型——序列(列表 & 元组)
开发语言·python