【智能体Agent】ReAct智能体的实现思路和关键技术
基于ReAct(Reasoning + Acting)框架的自主智能体
import re
from typing import List, Tuplefrom langchain_community.chat_message_histories.in_memory import ChatMessageHistory
from langchain_core.language_models.chat_models import BaseChatModel
from langchain.output_parsers import PydanticOutputParser, OutputFixingParser
from langchain.schema.output_parser import StrOutputParser
from langchain.tools.base import BaseTool
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.tools import render_text_description
from pydantic import ValidationError
from langchain_core.prompts import HumanMessagePromptTemplatefrom Agent.Action import Action
from Utils.CallbackHandlers import *class ReActAgent:"""AutoGPT:基于Langchain实现"""@staticmethoddef __format_thought_observation(thought: str, action: Action, observation: str) -> str:# 将全部JSON代码块替换为空ret = re.sub(r'```json(.*?)```', '', thought, flags=re.DOTALL)ret += "\n" + str(action) + "\n返回结果:\n" + observationreturn ret@staticmethoddef __extract_json_action(text: str) -> str | None:# 匹配最后出现的JSON代码块json_pattern = re.compile(r'```json(.*?)```', re.DOTALL)matches = json_pattern.findall(text)if matches:last_json_str = matches[-1]return last_json_strreturn Nonedef __init__(self,llm: BaseChatModel,tools: List[BaseTool],work_dir: str,main_prompt_file: str,max_thought_steps: Optional[int] = 10,):self.llm = llmself.tools = toolsself.work_dir = work_dirself.max_thought_steps = max_thought_steps# OutputFixingParser: 如果输出格式不正确,尝试修复self.output_parser = PydanticOutputParser(pydantic_object=Action)self.robust_parser = OutputFixingParser.from_llm(parser=self.output_parser,llm=llm)self.main_prompt_file = main_prompt_fileself.__init_prompt_templates()self.__init_chains()self.verbose_handler = ColoredPrintHandler(color=THOUGHT_COLOR)def __init_prompt_templates(self):with open(self.main_prompt_file, 'r', encoding='utf-8') as f:self.prompt = ChatPromptTemplate.from_messages([MessagesPlaceholder(variable_name="chat_history"),HumanMessagePromptTemplate.from_template(f.read()),]).partial(work_dir=self.work_dir,tools=render_text_description(self.tools),tool_names=','.join([tool.name for tool in self.tools]),format_instructions=self.output_parser.get_format_instructions(),)def __init_chains(self):# 主流程的chainself.main_chain = (self.prompt | self.llm | StrOutputParser())def __find_tool(self, tool_name: str) -> Optional[BaseTool]:for tool in self.tools:if tool.name == tool_name:return toolreturn Nonedef __step(self,task,short_term_memory,chat_history,verbose=False) -> Tuple[Action, str]:"""执行一步思考"""inputs = {"input": task,"agent_scratchpad": "\n".join(short_term_memory),"chat_history": chat_history.messages,}config = {"callbacks": [self.verbose_handler]if verbose else []}response = ""for s in self.main_chain.stream(inputs, config=config):response += s# 提取JSON代码块json_action = self.__extract_json_action(response)# 带容错的解析action = self.robust_parser.parse(json_action if json_action else response)return action, responsedef __exec_action(self, action: Action) -> str:# 查找工具tool = self.__find_tool(action.name)if tool is None:observation = (f"Error: 找不到工具或指令 '{action.name}'. "f"请从提供的工具/指令列表中选择,请确保按对顶格式输出。")else:try:# 执行工具observation = tool.run(action.args)except ValidationError as e:# 工具的入参异常observation = (f"Validation Error in args: {str(e)}, args: {action.args}")except Exception as e:# 工具执行异常observation = f"Error: {str(e)}, {type(e).__name__}, args: {action.args}"return observationdef run(self,task: str,chat_history: ChatMessageHistory,verbose=False) -> str:"""运行智能体:param task: 用户任务:param chat_history: 对话上下文(长时记忆):param verbose: 是否显示详细信息"""# 初始化短时记忆: 记录推理过程short_term_memory = []# 思考步数thought_step_count = 0reply = ""# 开始逐步思考while thought_step_count < self.max_thought_steps:if verbose:self.verbose_handler.on_thought_start(thought_step_count)# 执行一步思考action, response = self.__step(task=task,short_term_memory=short_term_memory,chat_history=chat_history,verbose=verbose,)# 如果是结束指令,执行最后一步if action.name == "FINISH":reply = self.__exec_action(action)break# 执行动作observation = self.__exec_action(action)if verbose:self.verbose_handler.on_tool_end(observation)# 更新短时记忆short_term_memory.append(self.__format_thought_observation(response, action, observation))thought_step_count += 1if thought_step_count >= self.max_thought_steps:# 如果思考步数达到上限,返回错误信息reply = "抱歉,我没能完成您的任务。"# 更新长时记忆chat_history.add_user_message(task)chat_history.add_ai_message(reply)return reply
结合LangChain框架和工具调用能力来逐步解决用户任务。
以下是代码的逐模块解析:
1. 核心结构
class ReActAgent:"""AutoGPT:基于Langchain实现"""
- 核心类:实现了ReAct范式(推理+行动循环)的自主智能体
- 核心能力:
- 多步思考推理
- 工具调用
- 长短期记忆管理
- 异常处理与自我修正
2. 关键静态方法
@staticmethod
def __format_thought_observation(...): # 格式化思考记录
@staticmethod
def __extract_json_action(...): # 提取JSON动作
- 功能:
__format_thought_observation:将思考过程、动作执行和观察结果格式化为可读文本,存入短期记忆__extract_json_action:用正则表达式提取模型输出中的最后一个JSON代码块(确保获取最新动作)
3. 初始化模块
def __init__(...):# 核心组件初始化self.llm = llm # 大语言模型self.tools = tools # 可用工具列表self.work_dir = work_dir # 工作目录self.max_thought_steps = ... # 最大思考步数# 输出解析系统self.output_parser = PydanticOutputParser(pydantic_object=Action)self.robust_parser = OutputFixingParser.from_llm(...)# 提示工程self.__init_prompt_templates()self.__init_chains()
- 关键技术点:
- 双解析器机制:
OutputFixingParser可在格式错误时自动修复输出 - Pydantic验证:确保动作符合预定义结构(Action模型)
- 工具描述渲染:
render_text_description将工具转化为自然语言描述
- 双解析器机制:
4. 提示工程系统
def __init_prompt_templates(self):with open(self.main_prompt_file) as f:self.prompt = ChatPromptTemplate.from_messages(...).partial(tools=..., # 工具描述tool_names=..., # 工具名称列表format_instructions=..., # 格式说明)
- 核心要素:
- 动态加载提示模板文件
- 包含:
- 聊天历史占位符
- 工具使用说明
- 输出格式要求
- 工作目录上下文
5. 执行流程控制
def run(...):while thought_step_count < self.max_thought_steps:# 单步思考action, response = self.__step(...)if action.name == "FINISH":break# 执行动作observation = self.__exec_action(action)# 记忆更新short_term_memory.append(...)
- ReAct循环:
- Reasoning:生成思考与动作(
__step) - Acting:执行工具调用(
__exec_action) - Observing:记录执行结果
- Loop:直到达到终止条件
- Reasoning:生成思考与动作(
6. 关键技术实现
6.1 单步推理 (__step)
def __step(...):inputs = {"input": task,"agent_scratchpad": "\n".join(short_term_memory),"chat_history": chat_history.messages,}# 流式处理LLM输出for s in self.main_chain.stream(inputs):response += s# 提取并解析动作json_action = self.__extract_json_action(response)action = self.robust_parser.parse(...)
- 输入组成:
- 任务目标
- 短期记忆(推理过程)
- 长期记忆(聊天历史)
- 流式处理:实时显示思考过程
- 错误恢复:自动修复格式错误的JSON输出
6.2 动作执行 (__exec_action)
def __exec_action(...):tool = self.__find_tool(action.name)try:observation = tool.run(action.args)except ValidationError:# 参数验证错误处理except Exception:# 通用错误处理
- 异常处理机制:
- 工具不存在
- 参数验证错误
- 运行时异常
- 观察反馈:将错误信息转化为自然语言,供后续推理使用
7. 记忆系统
# 短期记忆
short_term_memory = [] # 存储格式化的推理过程# 长期记忆
chat_history = ChatMessageHistory() # 保存完整对话记录
- 记忆类型:
- 短期记忆:当前任务的推理过程(最多保留max_thought_steps步)
- 长期记忆:跨会话的完整对话历史
8. 关键设计亮点
-
自愈式输出解析:
- 通过
OutputFixingParser实现格式错误自动修复 - 示例场景:当LLM返回非法JSON时,自动尝试修正
- 通过
-
渐进式推理:
# 示例输出格式 Thought: 我需要先查找用户信息 Action: {"name": "user_search", "args": {"id": 123}} Observation: 用户张三,年龄30岁- 通过
agent_scratchpad维护推理上下文
- 通过
-
工具发现机制:
- 动态渲染工具描述到提示词
- 支持工具的热插拔
-
多级异常处理:
- 工具不存在
- 参数验证错误
- 执行时异常
- 最大步数限制
9. 使用示例
# 初始化组件
llm = ChatOpenAI()
tools = [SearchTool(), Calculator()]
agent = ReActAgent(llm, tools, work_dir="/data")# 执行任务
result = agent.run(task="计算马云当前年龄的平方根",chat_history=ChatMessageHistory(),verbose=True
)
- 典型执行流程:
- 搜索"马云年龄" → 得到60岁
- 调用计算器计算√60 → 约7.746
- 返回最终结果
10. 可扩展性建议
-
增强记忆管理:
- 添加向量数据库长期记忆
- 实现记忆压缩/摘要
-
改进推理质量:
- 添加自我验证步骤
- 实现多路径推理
-
性能优化:
- 添加异步执行
- 实现工具并行调用
该实现展示了如何结合LangChain框架构建复杂的自主智能体系统,平衡了LLM的创造力和结构化工具调用的可靠性。
相关文章:
【智能体Agent】ReAct智能体的实现思路和关键技术
基于ReAct(Reasoning Acting)框架的自主智能体 import re from typing import List, Tuplefrom langchain_community.chat_message_histories.in_memory import ChatMessageHistory from langchain_core.language_models.chat_models import BaseChatM…...
Java进阶:Zookeeper相关笔记
概要总结: ●Zookeeper是一个开源的分布式协调服务,需要下载并部署在服务器上(使用cmd启动,windows与linux都可用)。 ●zookeeper一般用来实现诸如数据订阅/发布、负载均衡、命名服务、集群管理、分布式锁和分布式队列等功能。 ●有多台服…...
QT-绘画事件
实现颜色的随时调整,追加橡皮擦功能 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QColor> #include <QPoint> #include <QVector> #include <QMouseEvent> #include <QPainter> #include <Q…...
鸿蒙NEXT开发-端云一体化开发
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 目录 端云一体化开发基本概念 传统架构 端云一…...
大模型——股票分析AI工具开发教程
大模型——股票分析AI工具开发教程 在本教程中,我们将利用Google Gemini 2.0 Flash模型创建一个简单但有效的股票分析器。 你是否曾被大量的股票市场数据所淹没?希望有一个私人助理来筛选噪音并为您提供清晰、可操作的见解?好吧,你可以自己构建一个,而且由于 Python 的强…...
nexus 实现https 私有镜像搭建
1、安装nexus 1.1 安装JDK17 rpm -ivh jdk-17.0.13_linux-x64_bin.rpm 1.2 下载安装包解压到指定目录 tar zxvf nexus-3.77.2-02-unix.tar.gz -C /usr/local 2、运行nexus 默认8081端口 cd /usr/local/nexus-3.77.2-02 && bin/nexus start 3、配置nexus私有docker 镜…...
颈椎X光数据集(cervical spine X-ray dataset)
颈椎X光数据集(cervical spine X-ray dataset) 一.颈椎X光(1248张原始图像,无处理,jpg格式) 二.颈椎X光(1000张原始图像,无处理,jpg格式) 此数据…...
(动态规划 完全背包 零钱兑换)leetcode 322
本题为完全背包 与01背包的区别是 物品可以任意取 而01背包只能取一次 这就导致了状态转移方程的不同 1.当放不下:的时候 转移方程是一样的 取0到i-1 物品,背包容量为j的最优值 else 2.放得下:就是取 0到i-1 物品,背包容量为j的最优值和 “0到i的[j-w[i]]v…...
【AI大模型】DeepSeek + Kimi 高效制作PPT实战详解
目录 一、前言 二、传统 PPT 制作问题 2.1 传统方式制作 PPT 2.2 AI 大模型辅助制作 PPT 2.3 适用场景对比分析 2.4 最佳实践与推荐 三、DeepSeek Kimi 高效制作PPT操作实践 3.1 Kimi 简介 3.2 DeepSeek Kimi 制作PPT优势 3.2.1 DeepSeek 优势 3.2.2 Kimi 制作PPT优…...
Pytorch的一小步,昇腾芯片的一大步
Pytorch的一小步,昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息:PyTorch最新2.1版本宣布支持华为昇腾芯片! 1、 发生了什么事儿? 在2023年10月4日PyTorch 2.1版本的发布博客上,PyTorch介绍的beta版本…...
rabbitmq-amqp事务消息+消费失败重试机制+prefetch限流
1. 安装和配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency><dependency> <groupId>com.fasterxml.jackson.core</groupId> <arti…...
【HarmonyOS Next】自定义Tabs
背景 项目中Tabs的使用可以说是特别的频繁,但是官方提供的Tabs使用起来,存在tab选项卡切换动画滞后的问题。 原始动画无法满足产品的UI需求,因此,这篇文章将实现下面页面滑动,tab选项卡实时滑动的动画效果。 实现逻…...
Sass 模块化革命:深入解析 @use 语法,打造高效 CSS 架构
文章目录 前言use 用法1. 模块化与命名空间2. use 中 as 语法的使用3. as * 语法的使用4. 私有成员的访问5. use 中with默认值6. use 导入问题总结下一篇预告: 前言 在上一篇中,我们深入探讨了 Sass 中 import 语法的局限性,正是因为这些问题…...
【渗透测试】反弹 Shell 技术详解(一)
反弹 Shell 技术详解 一、前置知识 反弹 shell(Reverse Shell)是一种技术,攻击者利用它可以在远程主机上获得一个交互式的命令行接口。通常情况下,反弹 shell 会将标准输入(stdin)、标准输出(…...
python:pymunk + pygame 模拟六边形中小球弹跳运动
向 chat.deepseek.com 提问:编写 python 程序,用 pymunk, 有一个正六边形,围绕中心点缓慢旋转,六边形内有一个小球,六边形的6条边作为墙壁,小球受重力和摩擦力、弹力影响,模拟小球弹跳运动&…...
Windows 图形显示驱动开发-WDDM 3.2-本机 GPU 围栏对象(二)
GPU 和 CPU 之间的同步 CPU 必须执行 MonitoredValue 的更新,并读取 CurrentValue,以确保不会丢失正在进行的信号中断通知。 当向系统中添加新的 CPU 等待程序时,或者如果现有的 CPU 等待程序失效时,OS 必须修改受监视的值。OS …...
23种设计模式之《模板方法模式(Template Method)》在c#中的应用及理解
程序设计中的主要设计模式通常分为三大类,共23种: 1. 创建型模式(Creational Patterns) 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。 工厂方法模式࿰…...
DEV-C++ 为什么不能调试?(正确解决方案)
为了备战pat考试,专门下载了DEV C,然后懵圈的发现,怎么无法调试(╯□)╯︵ ┻━┻ 然后整了半天,终于在网上找到相应的解决方案!!!-> Dev C 5.11 调试初始设置 <- 一共四步…...
【C++设计模式】第五篇:原型模式(Prototype)
注意:复现代码时,确保 VS2022 使用 C17/20 标准以支持现代特性。 克隆对象的效率革命 1. 模式定义与用途 核心思想 原型模式:通过复制现有对象(原型)来创建新对象,而非通过new构造。关键用…...
深入 Vue.js 组件开发:从基础到实践
深入 Vue.js 组件开发:从基础到实践 Vue.js 作为一款卓越的前端框架,其组件化开发模式为构建高效、可维护的用户界面提供了强大支持。在这篇博客中,我们将深入探讨 Vue.js 组件开发的各个方面,从基础概念到高级技巧,助…...
4步攻克Python代码执行可视化:开发者调试效率提升指南
4步攻克Python代码执行可视化:开发者调试效率提升指南 【免费下载链接】viztracer VizTracer is a low-overhead logging/debugging/profiling tool that can trace and visualize your python code execution. 项目地址: https://gitcode.com/gh_mirrors/vi/vizt…...
六边形地理索引的终极指南:H3算法如何革新空间数据分析
六边形地理索引的终极指南:H3算法如何革新空间数据分析 【免费下载链接】h3 Hexagonal hierarchical geospatial indexing system 项目地址: https://gitcode.com/gh_mirrors/h3/h3 你是否曾为处理大规模地理空间数据而头疼?传统的地理索引系统在…...
为什么你的unipush消息收不到?详解个推通道状态检测与事件触发逻辑
为什么你的UniPush消息收不到?深度解析推送失效的7大关键因素 在移动应用开发中,消息推送是维系用户活跃度的核心功能之一。许多开发者在使用UniPush服务时,经常会遇到消息未能如期送达的困扰。本文将系统性地剖析消息推送失效的底层逻辑&…...
2025夏季技术实习「抢位战」:3步解锁2500+优质机会(附避坑指南)[特殊字符]
2025夏季技术实习「抢位战」:3步解锁2500优质机会(附避坑指南)🔥 【免费下载链接】Summer2026-Internships 2025年夏季技术实习机会集合! 项目地址: https://gitcode.com/GitHub_Trending/su/Summer2026-Internships…...
从晶体管到CPU:CMOS反相器延迟如何决定你的电脑主频
从晶体管到CPU:CMOS反相器延迟如何决定你的电脑主频 当你按下电脑电源键的瞬间,数十亿个晶体管在芯片上开始协同工作。这些微观开关的切换速度,直接决定了处理器主频的上限。而构成所有数字电路基础的CMOS反相器,其动态响应特性就…...
FLUX.1-dev LoRA微调指南:基于像素幻梦输出数据集训练专属风格
FLUX.1-dev LoRA微调指南:基于像素幻梦输出数据集训练专属风格 1. 前言:为什么需要LoRA微调 在像素艺术创作领域,每个艺术家都渴望拥有独特的视觉风格。FLUX.1-dev作为当前最先进的扩散模型,配合像素幻梦(Pixel Dream Workshop)…...
VMware虚拟机安装Ubuntu教程:创建独立的Qwen3-14B-AWQ模型测试环境
VMware虚拟机安装Ubuntu教程:创建独立的Qwen3-14B-AWQ模型测试环境 1. 为什么需要虚拟机测试环境 在测试大语言模型时,使用虚拟机可以避免污染宿主机环境。特别是像Qwen3-14B-AWQ这样的模型,依赖项复杂,直接在主机上安装可能会与…...
保姆级教程:用snntorch在MNIST上训练你的第一个脉冲神经网络(附完整代码)
从零开始:用snntorch构建你的第一个脉冲神经网络手记 第一次接触脉冲神经网络(SNN)时,我被它模拟生物神经元放电的特性深深吸引。与传统人工神经网络不同,SNN通过离散的脉冲信号传递信息,更接近人脑的工作机…...
SpringCloud Alibaba与Nacos版本不匹配?手把手教你解决‘Client not connected‘错误
SpringCloud Alibaba与Nacos版本兼容性实战:彻底解决Client not connected问题 微服务架构的复杂性往往隐藏在细节之中。当SpringCloud Alibaba项目启动时控制台突然抛出Client not connected, current status:STARTING的红色警告,不少开发者都会心头一紧…...
Windows 11下用VSCode+CMake+MinGW编译OpenCV 4.8.0,保姆级避坑指南
Windows 11下用VSCodeCMakeMinGW编译OpenCV 4.8.0全流程实战 最近在Windows 11上配置OpenCV开发环境时,发现很多教程都存在版本过时或Win11特有兼容性问题。本文将分享一套经过验证的最新工具链组合:VSCode 1.85CMake 3.28MinGW-w64 12.2OpenCV 4.8.0。不…...
