【学习笔记】AI Agent智能体学习—ReAct框架

一、概念

ReAct智能体框架(Reasoning and Acting Agent Framework)是一种结合推理(Reasoning)行动(Acting)的智能体架构,可以通过动态环境感知、多步决策和反馈调整,实现复杂任务的自动化解决。其名称中的“React”强调智能体需在动态环境中快速响应(React)环境变化,并通过推理-行动循环持续优化策略。

React智能体的核心逻辑遵循“感知 ➔ 推理 ➔ 行动 ➔ 观察”的循环过程,具体流程如下:
步骤功能实现方法
感知(Perception)获取环境状态信息从传感器、数据库或外部接口(如API)读取数据
推理(Reasoning)分析信息并生成策略基于规则引擎、知识图谱或大语言模型(LLM)生成多步计划
行动(Acting)执行决策动作调用API、发送控制指令或模拟用户操作(如点击按钮)
观察(Observation)获取行动后的反馈捕捉环境变化(如页面更新、API响应)并更新内部状态

二、示例

假设任务为“查找爱因斯坦的出生地”,可能的输出如下:

3 问题:爱因斯坦的出生地是哪里?

Thought 1: 需要先访问维基百科首页
Action 1: click[Wikipedia首页]
Observation 1: 已进入维基百科主页

Thought 2: 应该搜索爱因斯坦的词条
Action 2: search[Albert Einstein]
Observation 2: 爱因斯坦词条页面加载完成

Thought 3: 在“早年生活”部分查找出生地
Action 3: click[早年生活]
Observation 3: 显示“出生于德意志帝国符腾堡王国乌尔姆”

Action 4: finish[]
Observation 4: 任务完成

关键步骤解析

  1. 初始化环境
    env.reset(idx=3) 返回问题“爱因斯坦的出生地是哪里?”,并重置为初始状态(如打开浏览器)。

  2. 多步交互

    • 第1步:LLM生成Thought 1(访问维基百科),执行click[Wikipedia首页]动作,环境返回页面加载成功的观察结果。

    • 第2步:LLM生成Thought 2(搜索“爱因斯坦” ),执行search[爱因斯坦]动作,环境返回搜索爱因斯坦后的页面加载成功的观察结果。

    • 第3步:LLM定位到词条中的“早年生活”部分,找到出生地信息。

    • 第4步:强制finish[]提交答案。

在爱因斯坦的示例中,代码的每一步思考(Thought)均基于之前的所有观察(Observation)生成,而非一次性生成所有步骤。以下是具体逻辑:

1. 生成流程:逐步迭代

代码通过循环(for i in range(1, 8)逐轮生成 Thought 和 Action,并在每轮结束后将 Observation 添加到上下文中。
这意味着:

  • Thought 2 的生成会参考 Observation 1

  • Thought 3 的生成会参考 Observation 1 和 Observation 2,依此类推。


2. 观察(Observation)的核心作用
作用说明示例
动态更新上下文将环境反馈加入提示(prompt += step_str),为后续步骤提供最新信息第1步的 Observation 1 包含“维基百科主页加载完成”,LLM在第2步中可据此知道当前处于主页,需执行搜索动作
支持状态感知帮助LLM理解当前环境状态,避免重复或无效操作若 Observation 3 显示“早年生活”部分未找到,LLM可能生成“尝试其他章节”的思考
终止条件判断根据观察结果提前结束任务(如 done=True当 Observation 4 包含答案时,直接触发 finish[]

3. 爱因斯坦示例的完整流程

假设任务为“查找爱因斯坦的出生地”,代码运行步骤如下:

步骤生成逻辑上下文内容观察反馈的作用
第1步初始提示 + 问题问题:爱因斯坦的出生地是哪里?无历史观察
第2步初始提示 + 问题 + Thought 1 + Action 1 + Observation 1Observation 1: 已进入维基百科主页告知LLM当前处于主页,需执行搜索动作
第3步初始提示 + 问题 + 前两轮记录 + Observation 2Observation 2: 爱因斯坦词条页面加载完成告知LLM已进入词条页面,需定位具体章节
第4步初始提示 + 问题 + 前三轮记录 + Observation 3Observation 3: 显示‘出生于乌尔姆’触发LLM生成终止动作

三、代码展示

def webthink(idx=None, prompt=webthink_prompt, to_print=True):
    
    # 初始化环境并获取问题
    # env.reset() 返回问题字符串,并重置环境状态
    question = env.reset(idx=idx)  
    
    # 调试模式:打印当前问题索引和内容
    if to_print:
        print(f"[问题 {idx}]", question)
    
    # 将当前问题拼接到提示词模板
    # 示例:webthink_prompt + "爱因斯坦的出生地是哪里?\n"
    prompt += question + "\n"  
    
    # 初始化统计指标
    n_calls = 0    # 总LLM调用次数
    n_badcalls = 0 # 格式错误的调用次数
    max_retries = 2 # 单步最大重试次数
    
    # 主循环:最多进行7轮思考-动作迭代
    for step in range(1, 8):  
        valid_response = False  # 标记当前步骤是否生成有效响应
        thought_action = ""     # 保存LLM生成的原始响应
        
        # 重试机制:允许每个步骤重试生成符合格式的响应
        for retry in range(max_retries + 1):  
            n_calls += 1  # 每次调用LLM计数
            
            # 构建当前步骤的提示词
            # 示例:prompt + "Thought 1:"
            current_prompt = prompt + f"Thought {step}:"  
            
            # 调用LLM生成响应
            # stop参数确保LLM在生成Action或Observation时停止
            thought_action = llm(
                current_prompt,
                stop=[f"\nAction {step}:", f"\nObservation {step}:"]
            ).strip()  
            
            # 验证响应是否包含必要的Action标签
            if f"\nAction {step}: " in thought_action:
                valid_response = True
                break  # 格式正确则退出重试循环
            else:
                n_badcalls += 1
                if to_print:
                    print(f"[步骤{step} 重试{retry+1}] 响应缺少Action标签")
        
        # 最终失败处理:强制终止任务
        if not valid_response:
            # 提取第一行作为Thought,设置默认动作
            thought = thought_action.split('\n')[0]
            action = "finish[]"  # 安全终止指令
            if to_print:
                print(f"[警告] 步骤{step}无法生成有效动作,强制终止")
            break  # 退出主循环
        
        # 正常解析逻辑
        try:
            # 分割Thought和Action部分
            # 示例输入:"需要访问维基百科\nAction 1: click[主页]"
            # 输出:thought="需要访问维基百科", action="click[主页]"
            thought, action = thought_action.split(f"\nAction {step}: ")
        except:
            # 次级错误处理:重新生成Action部分
            thought = thought_action.split('\n')[0]
            action = llm(
                prompt + f"Thought {step}: {thought}\nAction {step}:",
                stop=["\n"]
            ).strip()
            n_calls += 1  # 额外调用计数
        
        # 动作格式化:首字母小写处理
        # 示例:将"Click[主页]"转为"click[主页]"
        formatted_action = action[0].lower() + action[1:]  
        
        # 执行动作并获取环境反馈
        # env.step()返回四元组:(obs, reward, done, info)
        obs, r, done, info = env.step(formatted_action)  
        
        # 清理观察结果:移除换行符避免干扰后续提示
        obs = obs.replace('\n', ' ')  
        
        # 构建当前步骤完整记录
        step_str = (
            f"Thought {step}: {thought}\n"
            f"Action {step}: {action}\n"
            f"Observation {step}: {obs}\n"
        )
        prompt += step_str  # 将当前步骤追加到上下文
        
        # 调试模式:打印当前步骤详情
        if to_print:
            print(step_str)
        
        # 检查终止条件
        if done:
            break  # 提前退出循环
    
    # 未完成时的强制终止处理
    if not done:
        # 执行预设的终止动作(如提交答案)
        obs, r, done, info = env.step("finish[]")
        if to_print:
            print("[超时终止]", info, '\n')
    
    # 汇总统计信息
    info.update({
        'n_calls': n_calls,       # 总调用次数
        'n_badcalls': n_badcalls, # 格式错误次数
        'traj': prompt            # 完整交互轨迹(用于复现)
    })
    return info

调用示例及输出

场景描述

任务:查找爱因斯坦的出生地
环境预设动作:

  • click[xxx]:模拟点击页面元素

  • search[xxx]:在搜索栏执行搜索

  • finish[]:提交最终答案

代码调用
# 初始化环境和LLM
env = WikiEnv()  # 假设已实现维基百科导航环境
llm = GPT4()     # 假设已封装GPT-4接口

# 定义提示词模板
webthink_prompt = """你是一个网页导航助手,请按以下格式操作:
1. 用Thought描述思考过程
2. 用Action执行具体动作(支持click[...]/search[...]/finish[])
---
当前任务:"""

# 执行任务(处理索引为3的问题)
result = webthink(
    idx=3, 
    prompt=webthink_prompt,
    to_print=True
)

# 打印统计结果
print("\n==== 任务统计 ====")
print(f"总耗时:{result['n_calls']*2}s")  # 假设每次LLM调用耗时2秒
print(f"成功步骤:{result['traj'].count('Observation')}")
print(f"格式化错误率:{result['n_badcalls']/result['n_calls']:.1%}")

输出日志

[问题 3] 爱因斯坦的出生地是哪里?

Thought 1: 需要访问维基百科首页
Action 1: click[Wikipedia首页]
Observation 1: 已进入维基百科主页

Thought 2: 应搜索爱因斯坦的词条
Action 2: search[Albert Einstein]
Observation 2: 爱因斯坦词条页面加载完成

Thought 3: 需要查看"早年生活"部分
Action 3: click[早年生活]
Observation 3: 显示"出生于德意志帝国符腾堡王国乌尔姆"

[超时终止] {'answer': '乌尔姆'} 

==== 任务统计 ====
总耗时:8s
成功步骤:3
格式化错误率:0.0%

关键机制图解

          +-------------------+
          |  初始化环境       |
          |  获取问题        |
          +-------------------+
                   |
                   v
          +-------------------+
          |  生成Thought i    |
          |  和Action i      |←[重试机制]
          +-------------------+
                   |
                   v
          +-------------------+
          |  执行动作         |→[错误处理]
          |  获取Observation | 
          +-------------------+
                   |
                   v
          +-------------------+
          |  更新上下文       |
          |  检查终止条件     |→[循环继续/终止]
          +-------------------+

四、应用

场景案例React智能体的作用
自动化测试网页功能验证模拟用户操作路径,自动发现并报告异常
智能助手多步骤任务执行(如订机票+酒店)分解任务为子动作,依次执行并协调结果
游戏AI策略类游戏实时分析战场态势,动态调整单位部署
工业控制生产线故障诊断结合传感器数据推理故障原因,触发维修指令

五、挑战

  • 上下文长度限制:长程任务可能导致提示(Prompt)过长,需结合检索增强(RAG)或记忆压缩技术。

  • 推理效率:LLM的延迟较高,需优化轻量化模型或缓存机制。

  • 安全性与可解释性:确保动作符合伦理约束,并提供决策依据的可追溯性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值