ReAct Agent 学习日志(Day 3):从“能调用 API”到“会用工具做事”
写在前面:我是前端,但我想转向 AI
我是一名前端工程师。过去的我更熟悉组件、状态管理、交互细节与工程化;但最近我越来越清晰地感受到:AI 不再只是“一个能力点”,它正在变成新的生产力底座。
于是我决定认真投入,给自己一个明确的方向:专心学习 AI 技术,尝试转行。
今天是我学习的第 3 天。前两天我做的是“AI API 调用”的项目,目标很务实:先把请求、返回、流式输出、落盘、稳定性这些基础动作练熟。
在另一个项目(AI Content Automation Platform)的开发日志里,我把前两天的重点记得很直白:
- Day1:跑通了「输入主题 → AI 生成文章 → 前端展示 + 临时落盘」闭环,搭好 Docker、文档骨架与工程结构。
- Day2:把生成体验做成 SSE 流式,并补齐重试语义(Tenacity)、异步 DB 依赖与一套“断点续写”的设计草案。
那两天更像是在练“手感”:怎么把 AI 能力接进系统里。
但今天的主题明显更“像智能体”——我开始学习 ReAct Agent:让模型不仅能回答问题,还能决定要用哪些工具、按什么顺序做事、并在过程中不断修正。
ReAct 是什么:让模型学会“边想边做”
ReAct(Reason + Act)可以理解为一种非常朴素、但很有效的范式:
- Reason(思考):先分析要解决的问题、拆解子目标、给出下一步计划
- Act(行动):调用工具(读文件、查目录、算数据、发邮件……)去获取事实
- Observe(观察):拿到工具结果,更新认知,继续下一轮
它的魅力在于:
当问题需要“外部信息”时(比如读 Excel、查文件夹、执行脚本),模型不再硬编答案,而是会把任务变成一连串可验证的动作。
今天我用一个非常具体的问题来练 ReAct:
“9 月份的销售额是多少?”
这类问题的关键点是:
答案不在模型脑子里,而在本地数据文件里。模型必须学会找数据、读数据、算结果,最后再输出。
实战复盘:从目录开始,走到最终答案
下面这段复盘来自我今天一次完整的 ReAct 跑通过程(终端真实输出)。我把它理解成:一个智能体如何像人一样做数据分析。
1)先找数据:ListDirectory
模型的第一反应不是“我猜 9 月销售额是多少”,而是先承认:自己没有信息,需要去 ./data 里找文件。
它调用了 ListDirectory:
- 目标:列出数据目录有哪些文件
- 结果:发现了一个非常“像答案就藏在里面”的文件:
2023年8月-9月销售记录.xlsx
这一步很重要:从“问题”到“数据源”的映射。
人类做分析也一样——第一步不是算,而是定位数据。
2)再看结构:InspectExcel
找到 Excel 之后,模型并没有直接开始计算,而是先问:
“这个表有什么列?日期列叫什么?销售额怎么算?”
它调用了 InspectExcel,拿到了:
- 工作表名:
2023年8月-9月销售记录 - 列名:
品类 / 产品名 / 单价(元) / 销售量 / 销售日期 / 供应商 - 前 3 行样例数据(看到了日期格式
2023-08-02这种)
于是“9 月销售额”被拆成可执行公式:
销售额 = 单价(元) × 销售量
筛选条件 = 销售日期在 2023-09-01 ~ 2023-09-30
这一步是 ReAct 里我最喜欢的一点:
它会主动把“模糊问题”变成“可计算问题”。
3)最后计算:AnalyseExcel(PythonREPL)
当字段都明确后,模型调用 AnalyseExcel,并在工具内部生成并执行 Python 代码:
pd.read_excel(...)读取 Excelpd.to_datetime(df['销售日期'])转日期- 过滤 9 月
sum(单价 * 销售量)求和
最终得到结论:
9 月份的总销售额为:2851099 元
到这里,ReAct 的闭环就非常清晰了:
- 找文件
- 看表结构
- 写代码算
- 返回可验证的结果
同一个 Agent 的另一种用法:当文件命名不清晰时,先探索再决策
上面那个案例比较“理想”:数据文件名已经把范围写得很清楚(2023年8月-9月销售记录.xlsx),因此智能体能快速锁定目标文件。
但真实工作里经常不是这样——你可能只拿到一堆没有语义的文件名:1.xlsx / 2.xlsx / 3.pdf,甚至目录里还混着 .DS_Store、历史文章草稿等噪音。
这时候 ReAct 的优势更明显:它不会赌运气,而是会先做“低成本探查”(列目录、看表头、抽样几行),把不确定性压下去,再进入真正的分析环节。
我今天也跑了一个“更贴近真实”的问题来验证这一点:
“销售总额最大的产品是什么?”
下面是这条路径的原始日志(注意:这次目录里并没有明显命名的销售文件,智能体必须先 Inspect 再决定)。
我保留了完整的 Thought / Tool / Return,让你能看到它如何一步步把模糊问题落到可执行的数据计算上。
🤖:有什么可以帮您? 👨:销售总额最大的产品是什么
[Thought: 0] 先定位数据源:需要先查看 ./data 目录下有哪些文件
{"name":"ListDirectory","args":{"path":"./data"}}
[Tool Return] .DS_Store 2026-03-17-react-agent-learning.md 2.xlsx 1.xlsx 3.pdf
[Thought: 1] 文件名无语义,先 Inspect 其中的 Excel,判断哪个包含“产品名/单价/销售量”等字段
{"name":"InspectExcel","args":{"filename":"./data/1.xlsx","n":3}}
[Tool Return] 1.xlsx 列名:品类、产品名、单价(元)、销售量、销售日期、供应商
[Thought: 2] 确认可计算:销售总额=单价×销售量;按产品名分组汇总后取最大
{"name":"AnalyseExcel","args":{"query":"分析 ./data/1.xlsx 的“2023年8月-9月销售记录”,计算销售总额=单价×销售量,按产品名分组求和,返回销售总额最大产品及金额。","filename":"./data/1.xlsx"}}
[Tool Return] 销售总额最大的产品:PlayStation 5 销售总额:274945元
原始日志引用:完整的 ReAct 思考与行动(终端输出)
下面我把这次从 [Thought: 0] 到最终 FINISH 的过程,按段落拆成多段短引用(每段引用尽量控制在 300 字内),方便阅读与多平台发布。
🤖:有什么可以帮您? 👨:9月份的销售额是多少
[Thought: 0] 先找数据源:列出 ./data 目录,定位可能的销售数据文件
{"name":"ListDirectory","args":{"path":"./data"}}
[Tool Return] 2023年8月-9月销售记录.xlsx 供应商名录.xlsx 供应商资格要求.pdf
[Thought: 1] 文件名提示包含 8/9 月销售数据;下一步 InspectExcel 先确认列名与日期/金额字段
{"name":"InspectExcel","args":{"filename":"./data/2023年8月-9月销售记录.xlsx","n":3}}
[Tool Return] 列名:品类、产品名、单价(元)、销售量、销售日期、供应商(日期字段=销售日期,金额=单价×销售量)
[Thought: 2] 已确认可计算:筛选 2023-09 的记录,对每行做 单价×销售量,再求和
{"name":"AnalyseExcel","args":{"filename":"./data/2023年8月-9月销售记录.xlsx","query":"筛选销售日期在2023年9月1日至2023年9月30日的记录,计算销售额=单价(元)×销售量,并求和返回9月份总销售额。"}}
[Tool Return] 9月份的总销售额为:2851099元
{"name":"FINISH","args":{"the_final_answer":"9月份的销售额是2851099元"}}
这次学习最真实的收获:工程问题也是学习的一部分
如果只看“最终答对了”,会忽略今天其实花了大量时间在“让系统能跑起来”上。
1)LangChain 的模块迁移:旧 import 会直接跑崩
我踩到的第一个坑是:LangChain 新版本拆包/迁移很大。
代码里很多旧路径在新版本下都不存在了,比如:
- 以前在
langchain.*的东西,很多迁到了langchain_core.* - 集成、loader、vectorstore 很多迁到
langchain_community.* - text splitter 迁到
langchain_text_splitters - provider(OpenAI)迁到
langchain_openai
这意味着:写 Demo 时如果照着老教程复制 import,很可能装了 langchain 仍然 ImportError。
解决方式不是“乱装包”,而是把 import 按新生态迁移,并尽量在关键处做兼容处理。
2)依赖补齐:Excel/PDF 读取离不开 openpyxl / PyMuPDF
在智能体场景里,“能读文件”是硬前提。
否则模型再会推理,拿不到数据也只能干着急。
Excel / PDF 常见缺失依赖:
.xlsx:通常需要openpyxl(pandas 读取引擎).pdf:PyMuPDF(对应pymupdf,loader 才能工作)
当工具链缺依赖时,ReAct 往往会出现一种“看起来很聪明但做不了事”的回答:
它能讲清楚要怎么做,但最终会说“缺依赖,无法读取文件”。
这并不是模型的问题,而是工程环境没准备好。
3)API Key 的坑:不是“没读到”,而是“读到了但无效”
我还遇到过 401 鉴权错误。
这类问题最容易误判成“.env 没生效”,但其实从报错就能看出来:
只要请求发出去了,说明 key 已经被读取;401 更可能是 key 本身无效、复制不完整或被撤销。
从“调用 API”转向“智能体工程”,我越来越能体会到:
智能体不是一个脚本,而是一套系统。系统的稳定性,决定了智能体的上限。
我对 ReAct 的理解:它像“会写计划的前端同事”
作为前端,我以前习惯把复杂需求拆成任务列表:
- 先把数据接口打通
- 再把 UI 展示跑起来
- 再做异常处理与边界条件
今天看到 ReAct 的输出,我突然觉得很熟悉:
它也在做“拆解、排序、执行、复盘”。区别只是:
- 我写的是任务与代码
- 它写的是 Thought 与工具调用 JSON
如果说前两天的我是在学“怎么把 AI 接进来”,那今天的我开始学“怎么让 AI 真正做事”。
这一步给我的冲击是:AI 不再只是一个回答器,而更像一个可编排的执行者。
给同样在转型路上的你:第三天的我,想说几句真心话
学习 AI 的这几天,我的情绪其实很复杂:
- 有兴奋:第一次看到模型自己决定去读 Excel,并算出一个真实数字
- 有挫败:依赖装不上、版本不兼容、import 改来改去
- 有踏实:每解决一个坑,就像给自己搭了一块“可复用的底座”
我越来越确定一件事:
转行不是跳跃,而是迁移。
把过去的工程能力迁移到 AI 工程里,才会走得更稳。
我会继续写下去。
明天也许会更难,但也一定会更接近我想要的方向。
附:今天这个 Demo 的关键链路(用于读者快速理解)
- 问题:9 月销售额是多少
- 数据源:
./data/2023年8月-9月销售记录.xlsx - 工具链:
ListDirectory:发现文件InspectExcel:确认字段与样例AnalyseExcel:用 Python 计算单价(元) × 销售量的 9 月总和
- 结果:2851099 元