用Python的ReAct机制,让LLM主动调用本地API关灯、发邮件
用Python的ReAct机制让LLM主动调用本地API关灯、发邮件想象这样一个场景你对电脑说“我准备睡了关灯并把明天上午的会议提醒发到我邮箱”然后灯真的灭了邮件真的发出去了。这不是科幻电影而是ReAct机制赋予大语言模型LLM的“动手能力”。传统LLM只能被动生成文本像一位只动口不动手的顾问。而ReActReasoning Acting让LLM能主动推理并调用外部工具真正改变物理世界或数字世界的状态。本文将带你用Python从零搭建一个ReAct智能体让它能调用本地API关灯模拟硬件和发邮件SMTP全程代码可运行、可扩展。一、ReAct是什么为什么它能让LLM“动手”ReAct是2022年提出的一种LLM推理与行动协同范式。核心思想是让模型在生成最终答案前先输出“思考Thought”和“行动Action”的中间步骤并根据行动结果Observation调整后续推理。传统Chain-of-ThoughtCoT只有推理链没有外部交互传统工具调用Toolformer只有函数调用缺乏动态推理。ReAct把两者结合形成“思考→行动→观察→再思考”的闭环。例如用户说“关灯并发邮件”ReAct智能体可能这样思考Thought 1: 用户要求两个动作先关灯再发邮件。Action 1:turn_off_lamp()Observation 1:Lamp is offThought 2: 关灯成功现在发邮件。Action 2:send_email(recipientmeexample.com, subject明天会议, body上午10点)Observation 2:Email sentThought 3: 所有任务完成回复用户。这种显式的推理轨迹不仅可解释还能在行动失败时自我修正如重试或换方案。二、整体架构设计我们的系统由四部分组成LLM引擎选用OpenAI的GPT-3.5/4 API也可替换为本地开源模型如Qwen。工具函数Python函数执行具体操作关灯、发邮件模拟或真实调用本地API。ReAct控制器核心循环维护对话历史解析LLM输出的Thought/Action/Observation并执行工具。用户接口命令行输入问题输出最终结果。为了安全所有本地API调用都限制在用户明确授权的动作范围内且邮件发送使用测试环境配置。三、准备工作安装依赖与配置pipinstallopenai python-dotenv创建.env文件存放OpenAI密钥OPENAI_API_KEYsk-xxxxxxxxxxxxxxxxxxxxxxxx新建config.pyimportosfromdotenvimportload_dotenv load_dotenv()OPENAI_API_KEYos.getenv(OPENAI_API_KEY)四、定义工具函数关灯与发邮件为了演示我们模拟关灯操作打印状态并用SMTP发送真实邮件建议使用QQ/163邮箱的授权码。tools.pyimportsmtplibfromemail.mime.textimportMIMETextfromemail.headerimportHeader# 模拟灯的状态lamp_status{on:True}defturn_off_lamp()-str:关闭本地智能灯模拟globallamp_statusiflamp_status[on]:lamp_status[on]FalsereturnLamp is now OFFreturnLamp is already OFFdefturn_on_lamp()-str:开启本地智能灯模拟globallamp_statusifnotlamp_status[on]:lamp_status[on]TruereturnLamp is now ONreturnLamp is already ONdefsend_email(recipient:str,subject:str,body:str)-str: 通过SMTP发送邮件请替换为你的邮箱配置 # 配置你的邮箱信息建议用环境变量smtp_serversmtp.qq.com# 以QQ邮箱为例smtp_port465# SSL端口sender_emailyour_emailqq.compasswordyour_authorization_code# 授权码不是QQ密码try:msgMIMEText(body,plain,utf-8)msg[Subject]Header(subject,utf-8)msg[From]sender_email msg[To]recipientwithsmtplib.SMTP_SSL(smtp_server,smtp_port)asserver:server.login(sender_email,password)server.sendmail(sender_email,[recipient],msg.as_string())returnfEmail sent to{recipient}successfullyexceptExceptionase:returnfFailed to send email:{str(e)}为了安全实际生产环境应限制recipient为白名单且不要在代码中硬编码密码改用环境变量。五、工具描述与注册LLM需要知道有哪些工具可用、每个工具的参数和用途。我们构建一个工具注册表供ReAct控制器查询。tool_registry.pyfromtoolsimportturn_off_lamp,turn_on_lamp,send_email TOOLS[{name:turn_off_lamp,func:turn_off_lamp,description:关闭智能灯。无参数。,parameters:{}},{name:turn_on_lamp,func:turn_on_lamp,description:开启智能灯。无参数。,parameters:{}},{name:send_email,func:send_email,description:发送邮件。需要提供收件人、主题和正文。,parameters:{recipient:string, 收件人邮箱地址,subject:string, 邮件主题,body:string, 邮件正文}}]defget_tool_description():生成供LLM理解的工具列表描述desc你可以使用以下工具函数每次只调用一个工具。\nfortinTOOLS:descf-{t[name]}:{t[description]}\nift[parameters]:descf 参数:{t[parameters]}\nreturndescdefexecute_tool(name:str,**kwargs):根据工具名和参数执行对应函数fortinTOOLS:ift[name]name:returnt[func](**kwargs)returnfError: Tool{name}not found六、构建ReAct提示模板ReAct的关键在于提示工程。我们需要指导LLM按固定格式输出Thought、Action、Action Input并在最后输出Final Answer。prompt_builder.pyfromtool_registryimportget_tool_description SYSTEM_PROMPT你是一个能调用工具来完成任务的人工智能助手。你的回答必须遵循以下格式 Thought: 你对于当前情况的思考。 Action: 要调用的工具名称必须是以下列表中的之一。 Action Input: 工具的输入参数以JSON格式提供如果没有参数则写{{}}。 在收到工具的观察结果Observation后你可以继续思考并调用下一个工具或者输出最终答案。 当你已经获得足够信息并可以回答用户时使用以下格式 Thought: 我现在知道最终答案了。 Final Answer: 对用户的最终回复。 工具列表 {tool_description} 请严格遵守格式不要输出多余内容。 defbuild_initial_prompt(user_query:str)-list:tool_descget_tool_description()system_msgSYSTEM_PROMPT.format(tool_descriptiontool_desc)return[{role:system,content:system_msg},{role:user,content:user_query}]七、解析LLM输出LLM可能返回多行文本我们需要从中提取Thought、Action、Action Input或Final Answer。这里用正则表达式解析。parser.pyimportreimportjsondefparse_llm_output(text:str): 解析LLM的输出返回类型和内容 返回: (thought, content) 或 (action, name, kwargs) 或 (final, answer) linestext.strip().split(\n)thoughtNoneactionNoneaction_inputNonefinal_answerNoneforlineinlines:ifline.startswith(Thought:):thoughtline[len(Thought:):].strip()elifline.startswith(Action:):actionline[len(Action:):].strip()elifline.startswith(Action Input:):rawline[len(Action Input:):].strip()# 尝试解析JSONtry:action_inputjson.loads(raw)except:# 如果解析失败当作空字典或简单字符串处理ifraw{}orraw:action_input{}else:# 尝试提取键值对非严格JSONaction_input{input:raw}elifline.startswith(Final Answer:):final_answerline[len(Final Answer:):].strip()iffinal_answerisnotNone:return(final,final_answer)elifactionisnotNone:return(action,action,action_inputor{})else:# 如果没有明确Action但有Thought可能模型需要重新提示return(thought,thoughtortext)实际中LLM可能将Action Input写成{recipient:mexx.com,subject:提醒,body:开会}我们需要兼容。八、ReAct主循环推理-行动-观察控制器维护消息历史每次循环将用户输入和工具执行结果拼入对话直到LLM输出Final Answer或达到最大步数。react_loop.pyimportopenaifromconfigimportOPENAI_API_KEYfromprompt_builderimportbuild_initial_promptfromparserimportparse_llm_outputfromtool_registryimportexecute_tool openai.api_keyOPENAI_API_KEYdefrun_react_loop(user_query:str,max_steps5):messagesbuild_initial_prompt(user_query)step0final_answerNonewhilestepmax_steps:print(f\n--- Step{step1}---)# 调用LLMresponseopenai.ChatCompletion.create(modelgpt-3.5-turbo,messagesmessages,temperature0.2,# 低温度保证格式稳定)llm_outputresponse.choices[0].message.contentprint(LLM Output:\n,llm_output)# 解析result_typeparse_llm_output(llm_output)ifresult_type[0]final:final_answerresult_type[1]breakelifresult_type[0]action:_,action_name,action_kwargsresult_typeprint(fCalling tool:{action_name}with{action_kwargs})# 执行工具observationexecute_tool(action_name,**action_kwargs)print(Observation:,observation)# 将LLM输出和观察结果加入历史messages.append({role:assistant,content:llm_output})messages.append({role:user,content:fObservation:{observation}})else:# 如果解析为thought但没有action强制要求模型给出actionmessages.append({role:assistant,content:llm_output})messages.append({role:user,content:请提供 Action 和 Action Input 来继续。})step1iffinal_answerisNone:final_answer抱歉我在限定步骤内无法完成任务。returnfinal_answer九、组合运行关灯并发邮件现在把所有模块拼起来写一个main.pyfromreact_loopimportrun_react_loopif__name____main__:user_inputinput(请输入您的指令: )resultrun_react_loop(user_input)print(\n 最终答案 )print(result)测试一次对话用户输入关灯然后给我自己的邮箱发一封邮件主题是“晚安”内容是“今天辛苦了明天上午10点开会”。运行日志简化--- Step 1 --- LLM Output: Thought: 用户要求关灯并发送邮件。先关灯。 Action: turn_off_lamp Action Input: {} Calling tool: turn_off_lamp with {} Observation: Lamp is now OFF --- Step 2 --- LLM Output: Thought: 关灯成功。现在发送邮件。收件人是用户自己的邮箱主题“晚安”内容“今天辛苦了明天上午10点开会”。 Action: send_email Action Input: {recipient:your_emailqq.com,subject:晚安,body:今天辛苦了明天上午10点开会。} Calling tool: send_email with {recipient: your_emailqq.com, subject: 晚安, body: 今天辛苦了明天上午10点开会。} Observation: Email sent to your_emailqq.com successfully --- Step 3 --- LLM Output: Thought: 我现在知道最终答案了。 Final Answer: 已完成关灯并发送邮件到您的邮箱请查收。 最终答案 已完成关灯并发送邮件到您的邮箱请查收。十、进阶本地API真实调用上述turn_off_lamp是模拟。若要真实控制智能灯如Philips Hue或小米只需替换函数实现通过HTTP请求调用本地网关API。例如使用requests库importrequestsdefturn_off_lamp_real():urlhttp://192.168.1.100/api/your_token/lights/1/statepayload{on:False}resprequests.put(url,jsonpayload)ifresp.status_code200:returnLamp turned off via APIelse:returnfAPI error:{resp.text}同理邮件部分可用公司内部的邮件中继API。十一、安全性考量ReAct智能体调用本地API时必须防范指令注入和越权操作。建议参数白名单send_email的recipient限制为预先授权的邮箱列表。工具沙箱对执行环境进行隔离避免eval或exec危险函数。人工确认对关键操作如发邮件、开锁增加二次确认机制。日志审计记录所有Thought/Action/Observation便于追溯。十二、扩展支持多工具并行与流式输出当前每次只调用一个工具效率较低。可改进为在Action行支持多个工具调用如Action: turn_off_lamp, send_email。使用异步执行asyncio并行调用无依赖的工具。使用流式APIstreamTrue实时输出思考过程提升体验。十三、总结本文用200多行Python代码实现了完整的ReAct智能体让它能主动调用本地API关灯和发邮件。你学到的不仅是代码更是一种范式迁移LLM从文本生成器进化为任务执行者。ReAct的核心价值在于可解释性每一步思考都透明可见。容错性观察结果可反馈到下一步推理。可扩展性添加新工具只需注册函数和描述。未来你可以将ReAct连接到日历、数据库、物联网中枢甚至通过RPA控制企业软件。当LLM真正“动手”时自动化的边界将被重新定义。现在打开你的终端跑通这段代码对你的电脑说一句“关灯”——物理世界会给出回应。推荐阅读我的电子文档/书籍管理

相关新闻

Claude Code与Codex六大组件拆解,Coding Agent怎么把任务做稳

Claude Code与Codex六大组件拆解,Coding Agent怎么把任务做稳

周五傍晚的研发工位上,CI流水线突然飘红,摆在面前的需求简单直白,仅仅是修复会员跨月折扣的失败测试。交给编程智能体处理,它很快定位到日期边界的逻辑漏洞,修改代码之后,目标用例顺利由红转绿,…

2026/8/3 17:38:08 阅读更多 →
MATLAB实战:基于K-means聚类的图像分割系统构建与源码解析

MATLAB实战:基于K-means聚类的图像分割系统构建与源码解析

在图像处理与计算机视觉领域,图像分割是一项基础且关键的任务,其目标是将图像划分为多个具有相似属性(如颜色、纹理、亮度)的区域或对象。无论是医学影像分析、自动驾驶场景理解,还是工业质检,都离不开高效…

2026/8/3 17:37:08 阅读更多 →
《守望先锋》温斯顿生存指南:从暴毙复盘到团队协同

《守望先锋》温斯顿生存指南:从暴毙复盘到团队协同

这次我们来看一个《守望先锋》游戏中的典型场景分析:猩猩(温斯顿)玩家跳入敌阵瞬间被秒,然后回头责怪辅助不奶。这种情况在游戏中非常常见,但问题真的全在辅助身上吗?这篇文章将深入拆解这个场景&#xff0…

2026/8/3 17:37:08 阅读更多 →

最新新闻

Blender细节进阶:从程序化材质到光影渲染的全流程实战

Blender细节进阶:从程序化材质到光影渲染的全流程实战

1. 项目概述:为什么“细节补充”是Blender进阶的关键如果你已经能用Blender建出基础的模型,会一些简单的材质和动画,但总觉得自己的作品“差点意思”——不够真实、不够精致,或者效率低下,那么你遇到的就是典型的“细节…

2026/8/3 23:23:22 阅读更多 →
无人机+AI识别漏检率高达31%?教你用多光谱校准+时序融合算法实现99.2%召回率

无人机+AI识别漏检率高达31%?教你用多光谱校准+时序融合算法实现99.2%召回率

更多请点击: https://codechina.net 第一章:无人机AI识别漏检率高达31%?教你用多光谱校准时序融合算法实现99.2%召回率 传统可见光无人机巡检在复杂光照、植被遮挡或低对比度场景下,AI目标识别模型常因特征单一导致漏检——某省级…

2026/8/3 23:23:22 阅读更多 →
HyggeImaotai开发者指南:WPF界面与后端逻辑的实现架构

HyggeImaotai开发者指南:WPF界面与后端逻辑的实现架构

HyggeImaotai开发者指南:WPF界面与后端逻辑的实现架构 【免费下载链接】HyggeImaotai i茅台app接口自动化csharp wpf实现,挂机windows服务器每日自动预约, (╯□)╯︵ ┻━┻ 预约启动! 项目地址: https://gitcode.com/gh_mirrors/hy/Hygge…

2026/8/3 23:23:22 阅读更多 →
TVM设备与目标交互:从硬件抽象到高效部署的完整指南

TVM设备与目标交互:从硬件抽象到高效部署的完整指南

1. 从“黑盒”到“白盒”:为什么TVM的设备与目标交互如此重要? 如果你用过TensorFlow或者PyTorch,大概都经历过这样的场景:在笔记本上训练好的模型,满怀信心地部署到服务器或者边缘设备上,结果要么性能惨不…

2026/8/3 23:23:22 阅读更多 →
如何使用StyleGAN3-Editing进行人脸编辑?从入门到精通的完整教程

如何使用StyleGAN3-Editing进行人脸编辑?从入门到精通的完整教程

如何使用StyleGAN3-Editing进行人脸编辑?从入门到精通的完整教程 【免费下载链接】stylegan3-editing Official Implementation of "Third Times the Charm? Image and Video Editing with StyleGAN3" (AIM ECCVW 2022) https://arxiv.org/abs/2201.1343…

2026/8/3 23:23:22 阅读更多 →
Picoquic安全机制解析:TLS 1.3集成与加密配置最佳实践

Picoquic安全机制解析:TLS 1.3集成与加密配置最佳实践

Picoquic安全机制解析:TLS 1.3集成与加密配置最佳实践 【免费下载链接】picoquic Minimal implementation of the QUIC protocol 项目地址: https://gitcode.com/gh_mirrors/pi/picoquic Picoquic作为轻量级的QUIC协议实现,其安全机制核心基于TLS…

2026/8/3 23:22:21 阅读更多 →

日新闻

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

PC服务器具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构一、前言:具身智能需要“混合算力闭环系统”传统人工智能依赖云端静态数据集训练,不具备物理交互能力,无法适应真实世界的不确定性。具身智能(Embodied…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

前言构建机器人、具身智能这类分布式实时系统,通信底座直接决定整套系统的实时性、容错性、组网能力。分布式领域长期存在 4 类经典通信架构:点对点模式、Broker 中间代理模式、广播模式、以数据为中心(DDS)模式。很多开发者疑惑&…

2026/8/3 0:00:47 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 1:53:31 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/3 4:36:35 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/3 13:07:03 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/3 5:19:38 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/3 8:27:36 阅读更多 →