【智能体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…...
python爬虫系列课程8:js浏览器window对象属性
python爬虫系列课程8:js浏览器window对象属性 一、JavaScript的组成二、document常见属性对象三、navigator对象一、JavaScript的组成 JavaScript可以分为三个部分:ECMAScript标准、DOM、BOM。 ECMAScript标准:即JS的基本语法,JavaScript的核心,描述了语言的基本语法和数…...
Java基础系列:深入理解八大基本数据类型及避坑指南
目录 一、基本数据类型概述 八大类型速查表 二、各类型详解与常见陷阱 1. 整型家族(byte/short/int/long) 2. 浮点型(float/double) 3. 字符型(char) 4. 布尔型(boolean) 三…...
贝塞尔曲线学习
1、一阶贝塞尔曲线 一阶贝塞尔曲线其实是一条直线——给定点 P0、P1,线性贝塞尔曲线就是一条两点之间的直线,公式如下: 一阶曲线很好理解, 就是根据t来线性插值。 void MainWindow::mousePressEvent(QMouseEvent *e) {list.append(e->pos…...
机器学习(六)
一,决策树: 简介: 决策树是一种通过构建类似树状的结构(颠倒的树),从根节点开始逐步对数据进行划分,最终在叶子节点做出预测结果的模型。 结构组成: 根节点:初始的数据集…...
kotlin高级用法总结
Kotlin 是一门功能强大且灵活的编程语言,除了基础语法外,它还提供了许多高级特性,可以帮助你编写更简洁、高效和可维护的代码。以下是 Kotlin 的一些高级用法,涵盖了协程、扩展函数、属性委托、内联类、反射等内容。 协程&#x…...
OCPP扩展机制与自定义功能开发:协议灵活性设计与实践 - 慧知开源充电桩平台
OCPP扩展机制与自定义功能开发:协议灵活性设计与实践 引言 OCPP作为开放协议,其核心价值在于平衡标准化与可扩展性。面对不同充电桩厂商的硬件差异、区域能源政策及定制化业务需求,OCPP通过**扩展点(Extension Points)…...
docker目录挂载与卷映射的区别
在 Docker 中,目录挂载(Bind Mount)和卷映射(Volume Mount)的命令语法差异主要体现在路径格式上,具体表现为是否以斜杠(/)开头。以下是两者的核心区别及使用场景的总结: …...
【江协科技STM32】ADC数模转换器-学习笔记
ADC简介 ADC(Analog-Digital Converter)模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁,ADC是一种将连续的模拟信号转换为离散的数字信号的设备或模块12位逐次逼近型…...
【kubernetes】service
目录 1. 说明2. 原理2.1 服务注册2.2 服务发现2.3 负载均衡 3. Service的类型3.1 ClusterIP3.2 NodePort3.3 LoadBalancer3.4 ExternalName 4. 使用场景 1. 说明 1.kubernetes中的service主要用于提供网络服务,并实现微服务架构中的几个核心功能:全自动…...
嵌入式学习笔记-卡尔曼滤波,PID,MicroPython
文章目录 卡尔曼滤波卡尔曼滤波的核心思想卡尔曼滤波的数学模型1. 状态转移模型(预测系统状态)2. 观测模型(预测测量值) 卡尔曼滤波的五个关键步骤1. 预测状态2. 预测误差协方差3. 计算卡尔曼增益4. 更新状态5. 更新误差协方差 卡…...
什么是hive
Apache Hive 是一个基于 Hadoop 生态系统构建的数据仓库工具,主要用于处理和分析大规模的结构化数据。它允许用户通过类似 SQL 的查询语言(HiveQL)进行数据操作,而无需直接编写复杂的 MapReduce 程序。以下是 Hive 的核心特点和应…...
MAC电脑常用操作
环境:M3芯片 ,macOS15.2 🚀 快捷键 🖥️ 窗口管理 ✅ 退出/进入全屏模式 • 浏览器等应用:⌘ Command Ctrl F ✅ 最小化当前窗口 • ⌘ Command M • 💡 隐藏窗口但保留应用在后台运行 ✅ 关闭当前标…...
leetcode 1287. 有序数组中出现次数超过25%的元素 简单
给你一个非递减的 有序 整数数组,已知这个数组中恰好有一个整数,它的出现次数超过数组元素总数的 25%。 请你找到并返回这个整数 示例: 输入:arr [1,2,2,6,6,6,6,7,10] 输出:6提示: 1 < arr.length…...
3.8【Q】cv
这个draw_line函数的逻辑和功能是什么?代码思路是什么?怎么写的? 这个t是什么?t.v[0]和t.v[1],[2]又是什么? void rst::rasterizer::draw(rst::pos_buf_id pos_buffer, rst::ind_buf_id ind_buffer, rst::Primitive ty…...
upload-labs文件上传
第一关 上传一个1.jpg的文件,在里面写好一句webshell 保留一个数据包,将其中截获的1.jpg改为1.php后重新发送 可以看到,已经成功上传 第二关 写一个webshell如图,为2.php 第二关在过滤tpye的属性,在上传2.php后使用b…...
PyTorch中Tensor对象的属性和方法
目录 一、核心属性 复数支持 转置与视图操作 元信息 梯度相关 二. 常用方法 基本操作 转置与视图 数学运算 深度学习相关 3. 使用示例 梯度计算 设备管理 自定义反向传播 4. 注意事项 总结 一、核心属性 1.requires_grad: _bool: 该…...
C++20 格式化库:强大的字符串格式化工具
文章目录 格式化语法常见用法1. 填充和对齐2. 数值格式化3. 进制格式化4. 自定义类型 示例代码注意事项 C20 的格式化库是一个强大的工具,用于处理字符串的格式化操作。它提供了类似于 Python 中 str.format() 的功能,但语法和用法更符合 C 的风格。以下…...
[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中
[傻瓜式教学]如何将MathType公式编辑器内嵌到WPS工具栏中 将MathType公式编辑器内嵌到WPS工具栏中 下载好所需文件 我用夸克网盘分享了「mathtype安装教程超简单易上手.zip」,点击链接即可保存。打开「夸克APP」 链接:https://pan.quark.cn/s/4726c684…...
分析TCP三次握手与四次挥手
TCP(传输控制协议)通过三次握手建立连接,四次挥手终止连接,确保数据传输的可靠性。 TCP的三个控制标志位: SYN——用于建立连接,同步序列号。 ACK——用于确认收到的数据。 FIN——用于终止连接。 ISN…...
【深度学习】宠物品种分类Pet Breeds Classifier
文章目录 宠物品种数据集制作宠物品种标签图像预处理Presizing 损失函数loss观察模型的性能提升模型的性能learning rate finder使用CLR算法训练选择学习率的策略重新训练 迁移学习微调fine_tunefit_one_cycle有判别力的学习率 选择epoch的数量更深的网络架构 宠物品种数据集 …...
【从零开始学习计算机科学】HLS算子调度
算子调度 调度是HLS 中的核心问题,为无时序或部分时序的输入指定时钟边界,其对最终结果质量具有很大的影响。调度会影响时钟频率、延时、吞吐率、面积、功耗等多种因素。 调度的输入是控制数据流图,其节点表示算子/操作,有向边表示数据依赖,控制依赖,优先依赖。如果没有…...
centos 安装composer 教程
打开命令行 php -r "copy(https://getcomposer.org/installer, composer-setup.php);" sudo php composer-setup.php --install-dir/usr/local/bin --filenamecomposer composer --version sudo chmod us /usr/local/bin/composer Super18120/article/details/14388…...
C语言_数据结构总结2:动态分配方式的顺序表
0——静态分配内存的顺序表和动态分配内存的顺序表的相同之处和不同之处 相同之处 基本操作逻辑相同:无论是静态分配还是动态分配的顺序表,其核心的操作逻辑是一致的。例如插入操作都需要将插入位置之后的元素依次后移,删除操作都需要将删除…...
嵌入式人工智能应用-第6章 人脸检测
嵌入式人工智能应用 人脸检测 嵌入式人工智能应用1 人脸检测1.1 CNN 介绍1.2 人脸检测原理1.3 MTCNN介绍1.4 NCNN介绍2 系统安装2.1 安装依赖库NCNN2.2 运行对应的库3 总结1 人脸检测 1.1 CNN 介绍 卷积神经网络。卷积是什么意思呢?从数学上说,卷积是一种运算。它是我们学习…...
关于无感方波启动预定位阶段
一、预定位的核心目标与原理 消除启动不确定性 无位置传感器下,转子初始位置未知,直接换相可能导致反转或失步。预定位通过施加固定方向磁场,强制转子对齐至预定角度(通常0或60电角度),建立初始位置基准。 …...
WSL安装及问题
1 概述 Windows Subsystem for Linux(简称WSL)是一个在Windows 10\11上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层。它是由微软与Canonical公司合作开发,开发人员可以在 Windows 计算机上同时访问 Windows 和…...
MySQL中的脏读与幻读:概念、影响与解决方案
在数据库事务处理中,脏读和幻读是两种常见的并发问题,可能导致数据不一致或逻辑错误。本文将结合实际场景,深入解析两者的原理及解决方案。 一、脏读(Dirty Read) 1. 概念解析 脏读指一个事务读取了另一个事务未提交…...
基于SpringBoot的商城管理系统(源码+部署教程)
运行环境 数据库:MySql 编译器:Intellij IDEA 前端运行环境:node.js v12.13.0 JAVA版本:JDK 1.8 主要功能 基于Springboot的商城管理系统包含管理端和用户端两个部分,主要功能有: 管理端 首页商品列…...
HeidiSQL:一款免费的数据库管理工具
HeidiSQL 是一款免费的图形化数据库管理工具,支持 MySQL、MariaDB、Microsoft SQL、PostgreSQL、SQLite、Interbase 以及 Firebird,目前只能在 Windows 平台使用。 HeidiSQL 的核心功能包括: 免费且开源,所有功能都可以直接使用。…...
