☰
AI Agent入门实战:从ReAct循环到工具调用与避坑指南
2026/10/16 5:46:08 网站建设 项目流程

看到这个标题我挺有感触的。这几年做技术分享,见过太多人把 AI Agent 说成玄学,好像不精通强化学习、不啃完几篇顶会论文就玩不转似的。但实际上,对于已经有编程基础的程序员来说,入门 AI Agent 的难度比想象中低得多,它更考验的是你对工程边界的理解、对流程拆解的耐心,而不是数学推导能力。

这篇内容不搞理论轰炸,我会从一个小白程序员最容易上手、也最不容易跑偏的路径切入:先把 Agent 的神奇外衣剥掉,看清它本质上是什么;再带你从零跑通第一个能用的 Agent;最后把我自己踩过的、以及带人入门时最常见的一堆坑直接摆出来,省得你再花一个月去趟。我尽量写得直白点,适合那种Python会写点、HTTP知道是啥、但对 Prompt 和大模型只停留在"用过ChatGPT"的人。读完你应该能建立一个立体的学习框架,而不是收藏了一堆碎片。

1. 先拆掉概念滤镜:AI Agent 到底是个什么东西

很多教程开口就是"Agent 是能感知环境、自主决策、执行动作的智能体",这句话一听就头大。咱换个说法:Agent 就是一个懂得拆解任务、会调用工具、并且有短期记忆的代码执行流程。

1.1 从"聊天机器人"到"Agent"的思维转变

你用过 ChatGPT 对吧?你问一句,它答一句,这个过程本质上是一个单轮或多轮的文本补全——它把我们的话拼接成上下文,然后预测最合理的下一个字符。但当你让它"帮我查一下明天的天气,然后提醒我该穿什么衣服"时,它如果只是个聊天模型,它只能给你一段编造的建议,因为它不知道明天的天气,也没有查的工具。

Agent 的介入就是改变这个逻辑:它先把你的目标存起来,分解成"查天气"和"根据结果给穿衣建议"两个小任务。对大模型说,"你需要调用天气查询工具,参数是地点和时间"。大模型输出一个结构化的调用指令,Agent 框架拿着这个指令去真的请求天气 API,拿到结果后再塞回给大模型,最终由大模型输出穿衣建议。

你看,Agent 不是一个全新的技术,而是一种将"大模型的推理能力"和"程序世界的确定性工具"组合起来的工作流范式。

1.2 你已经在做的"函数调用"就是它的雏形

如果你写过代码调过第三方 API,其实你已经具备理解 Agent 的基础了。传统程序里,你写if weather == 'rain': print('带伞'),这是由你来决定逻辑分支。在 Agent 里,这个逻辑分支变成了:把当前状态交给大模型,让大模型从你预设的工具列表里选一个function来调用。

所以,我给初学者的第一个建议是:千万别把 Agent 当人工智能来学,把它当"一个由大模型驱动路由的程序"来学。这个视角一旦建立,你的第一反应就不是恐惧未知,而是去思考:我的程序该提供哪些工具给模型选?每个工具暴露什么参数?模型什么时候该选工具,什么时候该直接回答?

把握住这一点,后面所有的技术选型、Prompt 设计、流程编排,全都是在围绕这个核心做优化。

2. 学习路线规划:小白入门的三个阶段和两件必做的功课

网上那种 40 集视频课,我劝你别收藏了,大概率吃灰。我给小白朋友推荐一条相对高性价比的路径,分三个阶段,每个阶段都有明确的产出物。

2.1 阶段一:会调模型,读懂结构化输出

第一步不是学什么 LangChain,而是先用 SDK 把大模型的接口调用跑通。比如你写一个 Python 脚本,调用任意一家大模型厂商的对话接口,传一个简单的 Prompt,拿到返回结果。

这一步的关键是搞懂三件事:

  • system、user、assistant三种角色的消息如何配合;
  • temperature、top_p这些采样参数对输出风格的影响(先无脑记住:想稳定就调低温度,想发散就调高);
  • 如何请求模型输出JSON 格式的结果(比如让它输出{"action": "query_weather", "args": {"city": "北京"}})。

为什么强调结构化输出?因为 Agent 和普通聊天的最大区别就是要让代码能解析模型的决策。如果模型的输出是一段自由文本,你的程序很难稳定地根据它执行动作。

2.2 阶段二:实现一个 ReAct 循环,理解"思考-行动-观察"

第二阶段的里程碑,是手动实现一个极简的 ReAct 循环。ReAct 的全称是 Reason and Act,是目前绝大多数 Agent 框架的工作内核。这个循环只有四步:

  1. 思考(Thought):模型根据当前目标和已有信息,决定下一步该干什么。
  2. 行动(Action):模型输出一个工具调用指令,比如search_web("中国人口数量")。
  3. 观察(Observation):程序真的去执行这个搜索,把返回的页面摘要作为文本返回给模型。
  4. 循环:模型看到观察结果,再次推理判断是否已经能回答用户,如果不能就继续发起下一个行动。

如果你能不用任何框架,用纯 Python 的while循环 + 大模型接口把上面这个流程写出来,你对 Agent 的理解就已经超过 60% 的所谓"传道者"了。我在带人入门的时候,强烈禁止他们一上来就碰现成的编排框架,原因就在这:框架封装了太多细节,会让新手误以为"调个 Agent 类就能解决一切问题"。

2.3 阶段三:用框架做复杂任务管理

有了徒手实现的基础,再上框架比如 LangChain、LlamaIndex 或者 Semantic Kernel 等,你就完全看得懂它的文档在讲什么了。框架帮你解决的是重复劳动:维护对话记忆、管理多工具调用的路由、解析模型输出、处理重试和降级等等。

在框架阶段,建议练习用列表和表格记录每类组件的用途,比如:

组件类型核心用途小白必学
Model I/O管理大模型调用和 Prompt 模板必须
Memory短期和长期记忆存储必须
Tools封装外部能力给模型调用必须
Chains串联多步骤流程进阶
Agents / Executor决策路由与动作执行核心

这个阶段要戒掉"代码生成器思维"——框架不是让你复制粘贴跑通就完事,你要能说清楚每个节点上的数据流动:用户输入进来是一段字符串,经过格式化变成消息数组,模型返回一个结构体,路由判断是退出还是继续。

2.4 一个重要提醒:英语比技术本身更卡你的瓶颈

有一说一,现在做大模型开发,第一手信息基本都在英文世界。框架的文档、官方示例、Changelog、Github 的 Issue 讨论,全是英文。哪怕你四级没过,也请养成"先用英文关键词搜、看不懂再用翻译工具"的习惯。这能让你避开大量的用二手信息炒冷饭的中文博客,效率至少翻倍。

3. 动手实操:从零实现一个带工具的迷你 Agent

理论说得再多,不如亲手写一次。下面我分享的这套代码,几乎是我带人入门时的"标准作业"。它不依赖任何 Agent 框架,只依赖一个大模型的 SDK,完整展示了 ReAct 循环的核心逻辑。

3.1 准备工作与工具选型

你需要准备:

  • Python 3.9 以上的环境;
  • 一个能调用的大模型 API 密钥(以常见的 OpenAI 兼容接口为例);
  • requests库。

我个人建议在小白阶段,模型就选市面上主流旗舰模型的最便宜版本,比如gpt-4o-mini或者国产各家的大模型 lite 版。原因很简单:入门阶段最重要的是把流程跑通,而不是追求推理天花板。大参数模型虽然聪明,但成本和响应速度在 Debug 阶段会让你很崩溃。

3.2 定义工具与构造提示词

假设我们做一个"查询日期对应的节假日及适宜活动"的 Agent。它有两个工具:

  • get_holiday(date_str):返回当天是什么节日,不内置真实数据,模拟查询过程。
  • get_movie_recommendation(holiday_name):根据节日返回一个电影推荐。

关键的 Prompt 结构是一个函数清单的描述,用 JSON 模式告诉模型当前有哪些工具可用。我的模板通常长这样:

你是一个智能助手。你可以根据用户的目标,选择调用下面的工具来获取信息并给出回答。 可用工具列表: { "tools": [ { "name": "get_holiday", "description": "查询指定日期对应的节日名称,参数为日期,格式YYYY-MM-DD", "parameters": {"type": "object", "properties": {"date_str": {"type": "string"}}} }, { "name": "get_movie_recommendation", "description": "根据节日名称获取适合观看的电影推荐", "parameters": {"type": "object", "properties": {"holiday_name": {"type": "string"}}} } ] } 你的回答必须遵循以下格式: 如果下一步需要调用工具,请严格输出JSON: {"action": "get_holiday", "action_input": "2027-08-15"} 如果已经获取足够信息并可以回答用户,请输出: {"action": "final", "action_input": "你的最终回答"}

这个 Prompt 一点都不高级,但非常实用。它的核心是把路由决策收敛到一个严格的二选一:要么继续调用工具,要么结束并回答。

3.3 主流程代码

下面用一个 Python 文件展示核心调用逻辑。为了阅读清晰,我省略了 API 请求封装细节,只留 Agent 循环。要注意,这只是一个教学演示版本,生产环境需要加超时、重试和记忆截断。

import json import re import requests # 模拟工具函数 def get_holiday(date_str): # 真实场景这里会查询接口,这里 mock 返回 if "05-01" in date_str: return "劳动节" elif "10-01" in date_str: return "国庆节" elif "08-15" in date_str: return "端午节" return "普通工作日" def get_movie_recommendation(holiday_name): movie_map = { "劳动节": "《工薪阶层的奋斗》", "国庆节": "《家国万里》", "端午节": "《龙舟少年》", "普通工作日": "《下班后的宁静》" } return movie_map.get(holiday_name, "《随机彩蛋》") def call_llm(messages): # 伪代码,替换为实际的大模型调用 SDK 或 HTTP 请求 response = requests.post( "https://your-llm-api.example.com/chat/completions", headers={"Authorization": "Bearer YOUR_KEY"}, json={"model": "your-model", "messages": messages, "temperature": 0.2} ) return response.json()["choices"][0]["message"]["content"] def extract_json(text): # 容错:从模型输出中提取第一个 JSON 对象 match = re.search(r"\{.*\}", text, re.S) if match: return json.loads(match.group()) raise ValueError(f"无法解析模型输出: {text}") def run_agent(user_goal): messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_goal} ] # 最大迭代轮次,避免死循环 max_steps = 5 for step in range(max_steps): # 1. 思考与决策 raw_output = call_llm(messages) print(f"\n[Step {step+1}] 模型原始输出: {raw_output}") # 2. 解析动作 action = extract_json(raw_output) action_name = action.get("action") action_input = action.get("action_input") # 3. 执行动作或退出 if action_name == "final": print(f"最终回答: {action_input}") return action_input elif action_name == "get_holiday": observation = get_holiday(action_input) elif action_name == "get_movie_recommendation": observation = get_movie_recommendation(action_input) else: observation = "未知工具,请重试" # 4. 将观察结果回传给模型 messages.append({"role": "assistant", "content": raw_output}) messages.append({"role": "user", "content": f"工具返回的观察结果: {observation}"}) # 超步数保护 fallback = "循环次数超限,停止继续执行。" print(fallback) return fallback if __name__ == "__main__": run_agent("今天是2027年8月15日,有什么适合看的电影吗?")

3.4 运行逻辑分步解读

让我们手推一下,当用户输入"今天是 2027 年 8 月 15 日,有什么适合看的电影吗?"时,程序会发生什么:

  • Step 1:模型拿到用户问题,判断自己不知道节日数据,于是输出{"action": "get_holiday", "action_input": "2027-08-15"}。你的程序解析 JSON,调用get_holiday,拿到"端午节"。
  • Step 2:程序把"端午节"作为观察结果塞回给模型。模型发现还需要知道端午节看什么电影,于是再次调用工具get_movie_recommendation("端午节"),拿到"《龙舟少年》"。
  • Step 3:此时模型有了全部信息,输出{"action": "final", "action_input": "8月15日是端午节,推荐你看《龙舟少年》!"}。循环结束。

这个过程中每一步的打印输出,我建议你在本地跑的时候都留好,它就是调试 Agent 时你唯一的眼睛。

3.5 为什么这么设计:从"瘫痪"到"指挥"的要点

这个迷你 Demo 有三个设计要点,值得你在后续学习里反复品味:

第一,将工具描述嵌入系统 Prompt,让模型知道"自己拥有什么能力"。模型的工具使用能力很大程度取决于你描述得清不清楚,参数名必须和你代码里的字段严格对应,否则模型会臆造参数。

第二,把模型输出当成数据而非代码来执行。我们只是解析 JSON 然后查表调用预设函数,绝不可以用eval直接执行模型返回的内容。这一点是安全红线,很多新手一上来图省事就直接 eval,一旦模型输出被恶意注入,整个系统就沦陷了。

第三,最大步数保护是必需品。模型在复杂任务里非常容易出现"思考中"的循环——比如反复调用查询工具却不结束。没有max_steps的兜底,你的 Token 账单会迅速爆炸。

4. 小白避坑指南:我见过的那些"看起来正常但就是不对"的报错

说实话,我见过太多人在入门环节被坑到怀疑人生。技术本身不难,难的是排错经验不够。我把最常见的四类坑直接列出来,你对照着检查,能省很多事。

4.1 结构化输出的"震动模式":模型偶尔不按 JSON 输出怎么办

  • 症状:模型大多数时候输出正常 JSON,偶尔在复杂指令下输出"好的,我将调用工具:get_holiday("2027-08-15")"这种带解释的文本,你的json.loads直接崩溃。
  • 解决思路:不要指望模型 100% 遵守 JSON 格式。建议在解析层加一层容错:用正则提取第一个花括号到最后一个花括号之间的内容再做解析。如果解析失败,就把错误信息返回给模型,让它"自我纠正"重新输出一次。这是 Agent 开发里最常见的兜底手段之一,非常有效。
  • 底层逻辑:让错误成为对话上下文的一部分,模型会根据新信息修正上一次的错误输出,比单纯重试的成功率高得多。

4.2 Prompt 里的"参数双写":工具描述和实际执行不一致

  • 症状:你写工具函数时定义的参数是city,但描述里为了让人读起来通顺写了"查询某个城市的天气,参数为城市名",模型就会输出{"action": "get_weather", "action_input": "北京"},而你代码里找的是city字段,结果取不到任何值。
  • 解决思路:工具描述里的parameters里的属性名,必须和代码参数名一字不差。而且建议在描述里附带参数格式示例,比如{"date_str": "2027-08-15"},模型会模仿示例来输出,稳定性大幅提升。
  • 实操心得:我后来养成的习惯是给模型看一个"完整动作示例",效果比单纯描述好十倍。

4.3 上下文爆炸:对话轮次稍长,请求体变得巨大

随着工具观察结果的累积,消息列表会越来越长。比如你把一篇 5000 字的搜索结果整个塞回上下文,下一轮请求携带的历史消息已经消耗掉大量 Token 配额,甚至超出模型的最大上下文窗口。

  • 解决方案:对话记忆需要管理,不能无脑追加。常见做法是:
    • 只保留最近的 N 轮消息,旧的系统级摘要替代;
    • 工具返回的观察结果进行文本截断,比如只取前 1000 个字符;
    • 设置总的 Token 预算(比如 8000 Token),超过后自动裁剪最早的非关键消息。

4.4 功能可以跑但效果烂:工具路由"失灵"

有一种很气人的情况:Agent 明明接入了好几个搜索工具,但模型就是死认某一个,哪怕这个工具经常返回空结果。这种情况的核心原因通常是工具 description 写得不够有区分度。你想想,模型只能凭文字描述来决定"该用哪个工具",如果两个工具的描述都写着"搜索信息",它大概率无从选择。加上一句"优先使用,适合实时性要求高的查询"这类限定,路由准确率会有一个明显跃升。

4.5 关于成本控制的一个忠告

小白调试 Agent 时最肉疼的是花钱如流水。我建议你养成一个习惯:先在代码里打印完整的 message 列表再测试小规模交互。这样可以清楚地看到每次请求携带了多少内容,有没有做无用功。另外一个技巧是把temperature调低到 0,不是为了质量而是为了减少试错时的随机性——排查 BUG 时,你希望模型输出是可复现的,而不是换个词就换条路。

5. 进阶之路:从"玩具"到"可靠工具"的四个关键转身

到这里你已经能亲手跑通一个最小闭环了,接下来怎么继续往前走?我建议按照下面四个方向选一个深入钻研。

5.1 从"单轮工具调用"到"多步骤任务编排"

迷你 Demo 里只有一两步调用,但真实需求往往需要更多步骤。比如"帮我规划一次三天旅行",Agent 得先查机票、查酒店、查天气、查景点,再综合这些信息做计划。这个阶段你需要学习"任务分解"和"成果合并",可以尝试把一个大目标拆成多个子任务,每个子任务的输出作为下一个子任务的输入。

建议练习:实现一个"信息收集汇总" Agent,让它在多个工具间依次查询,最终生成一份结构化根文。

5.2 从"短期记忆"到"持久记忆"

目前的 Agent 每次对话结束就忘了你是谁,这在真实场景远远不够。你可以尝试引入一个向量数据库,把每次对话的核心结论或用户偏好存储起来,下次对话时先做相似度检索,把历史记忆作为上下文注入。这一步可以顺带把 RAG(检索增强生成)入门了。

5.3 从"代码触发"到"事件驱动"

真实世界的系统不会等你手动调用,它们可能通过 Webhook、消息队列、定时任务来触发。进阶的方向是学会把 Agent 封装成异步服务,让它能接收外部事件并自动决策。这需要你补一点消息队列和任务调度的基本功,但对工程能力的锻炼价值很大。

5.4 从"我用框架"到"我懂框架"

用到一定程度,你会发现框架为了通用性牺牲了灵活性。很多团队最后都会基于自己的业务场景,写一套轻量的内部 Agent 框架。如果你能理解现有框架的设计模式(比如如何抽象工具、如何管理状态、如何处理错误重试),你就能自己动手裁剪一个适合自己业务场景的迷你框架,到时候你在组里的话语权会完全不同。

6. 学习资源与工具箱推荐(不恰饭,纯自用)

最后分享一份我平时带人用的资源清单,没有商业推广,都是实测过好用的。

6.1 官方文档是爸爸,社区博客是参考

不管用什么框架,首选的永远是该框架的官方文档和官方 API 参考。社区博客的作用是帮你建立直觉,但极容易过期——大模型领域基本每个月都在变,一篇三个月前的教程可能已经完全不适用了。

  • 官方教程永远是最新且准确的一手信息;
  • 看博客时学会看写作日期,太老的直接跳过;
  • 尽量用英文原版,翻译会导致专有名词混乱。

6.2 必做练习场景清单

我建议你在学习过程中,至少亲手完成下面三个练习,每一个都能覆盖大量核心概念:

难度场景考察点
入门做一个"果蔬识别推荐" Agent工具定义、结构化输出、基于观察结果二次推理
中等做一个"文章撰写流水线",先搜索资料,再生成大纲,最后写正文多步编排、上下文传递、长文本截断
进阶做一个"文件操作助手",让模型调用本地函数创建、重命名、整理文件安全性设计、路径校验、Action 白名单

这三个项目做完,你对 Agent 的工程应用基本就有底气了。

我个人的经验是:学 Agent 不怕笨,怕的是不求甚解地跑通别人写好的脚本。你跟着跑通了十个 Demo,不如亲手从一行print开始搭出一个哪怕很蠢的 Agent。前者给你短暂的成就感,后者给你排查任何问题时的冷静感。

最后一次建议:把这篇文章收藏起来,但别只是收藏。今天就用那节 3.3 的代码,哪怕是照抄一遍,也比看十篇教程管用。等你跑通第一版,再回头来看前面那些概念,你会发现自己已经在山腰上了,后面的风景远比你想象的辽阔。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询