大语言模型中的ReAct框架
1.简介
请注意,这里的ReAct并非指前端开发框架react,而是由reasoning(推理)和acting(行动)两个英文单词组合而成的术语。ReAct是一种创新的通用框架,
它将语言模型中的推理与行动相结合,旨在高效解决各类复杂的语言推理及决策任务。
2. ReAct实际过程
while 未达成目标 {
// 1. 调用LLM进行推理
reasoning();
// 2. 调用外部工具采取行动,并将行动结果,放入与LLM交互的上下文中,作为LLM推理的素材
acting();
}
其本质是执行多轮 reasoning + acting,把acting的结果放入与LLM交互的上下文中,作为LLM下一轮推理的素材
ReAct克服了链式思考推理中普遍存在的幻觉和错误传播问题,生成了更具可解释性的类似人类思考过程的任务解决轨迹,
并能够提高大型语言模型在多种任务上的准确性。
3. 示例
3.1 迷宫说明
为了说明ReAct框架,萌叔构建了一个迷宫
🧱🧱🧱🧱🧱🧱🧱
🧱😎🛣️🧱🧱🧱🧱
🧱🧱🛣️🛣️🛣️🧱🧱
🧱🧱🧱🧱🛣️🧱🧱
🧱🧱🛣️🛣️🛣🧱🧱
🧱🧱🧱🧱🛣️🏁🧱
🧱🧱🧱🧱🧱🧱🧱
player当前的位置是(1,1), 终点的位置为(5,5)
每次可以移动一步,只能是下面4种动作之一
- (1, 0)
- (0, 1)
- (-1, 0)
- (0, -1)
限制
player的视野是有限的,仅能观察到其周围的局部区域。
形如🧱🧱🧱🏿🏿🏿🏿 🧱😎🛣️🏿🏿🏿🏿 🧱🧱🛣️🏿🏿🏿🏿 🏿🏿🏿🏿🏿🏿🏿 🏿🏿🏿🏿🏿🏿🏿 🏿🏿🏿🏿🏿🏿🏿 🏿🏿🏿🏿🏿🏿🏿
正因视野受限,player在迷宫中的行进过程只能是探索式的:
每走一步,便观察一下周围环境,再据此尝试下一步的行动,如此反复,直至抵达终点。
3.2 代码片段
完整代码 example
# 初始化 Kimi 模型
llm = ChatOpenAI(
model_name="gpt-3.5-turbo", # 或其他 Kimi 模型名
# openai_api_base=kimi_api_base,
temperature=0.1
)
agent = initialize_agent(
tools=[move_tool, observe_tool], # 工具列表
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, # 指定智能体类型
max_iterations = 200,
verbose=True # verbose=True 可以打印出详细的推理过程
)
# 3. 运行智能体 - 使用新的invoke方法
question = """
你作为player当前处于一个 7*7的 二维矩阵中,'X'是你的位置,'#' 都是墙体,只有 '0' 是通道, '-' 表示未知
初始坐标为(1,1),你需要设法到达(5,5)
注意: 只能沿着通道移动
你每次可以移动一步,只能是下面4种动作之一
(1, 0), (0, 1), (-1, 0), (0, -1)
请你给出一个完整的移动轨迹,如果可以尝试推测一下矩阵的情况
"""
response = agent.invoke({"input": question})
print(response)
注意: 复杂的任务可能需要修改 max_iterations
说明
move_tool
: 用于在迷宫中移动observe_tool
: 从player所处位置进行观察
3.3 执行结果
> Entering new AgentExecutor chain...
我需要首先观察当前的位置(1, 1)周围的情况,以了解可以移动的方向和通道。
Action: observe
Action Input: None
Observation: [['#', '#', '#', '-', '-', '-', '-'], ['#', 'X', '0', '-', '-', '-', '-'], ['#', '#', '0', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:我观察到当前位置(1, 1)周围的情况如下:
- 上方(0, 1): '#'
- 下方(2, 1): '#'
- 左方(1, 0): '#'
- 右方(1, 2): '0' (可以移动)
因此,我可以向右移动到(1, 2)。
Action: move_action
Action Input: (0, 1) action: (0, 1)
从(1, 1) 移动到了 (1, 2)
Observation: True
Thought:我已经成功移动到(1, 2)。接下来,我需要再次观察当前位置(1, 2)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '#', '#', '#', '-', '-', '-'], ['-', '0', 'X', '#', '-', '-', '-'], ['-', '#', '0', '0', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(1, 2)周围的情况如下:
- 上方(0, 2): '-'
- 下方(2, 2): '0' (可以移动)
- 左方(1, 1): '0'
- 右方(1, 3): '#'
我可以选择向下移动到(2, 2)。
Action: move_action
Action Input: (1, 0) action: (1, 0)
从(1, 2) 移动到了 (2, 2)
Observation: True
Thought:我已经成功移动到(2, 2)。接下来,我需要再次观察当前位置(2, 2)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '0', '0', '#', '-', '-', '-'], ['-', '#', 'X', '0', '-', '-', '-'], ['-', '#', '#', '#', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(2, 2)周围的情况如下:
- 上方(1, 2): '0'
- 下方(3, 2): '-' (可以移动)
- 左方(2, 1): '#'
- 右方(2, 3): '0' (可以移动)
我可以选择向下移动到(3, 2)或向右移动到(2, 3)。为了更接近目标(5, 5),我选择向下移动到(3, 2)。
Action: move_action
Action Input: (1, 0) action: (1, 0)
Observation: False
Thought:当前位置(3, 2)无法向下移动,可能是因为下方有墙体。接下来,我需要重新考虑我的移动方向。
Action: move_action
Action Input: (0, 1) action: (0, 1)
从(2, 2) 移动到了 (2, 3)
Observation: True
Thought:我已经成功移动到(2, 3)。接下来,我需要再次观察当前位置(2, 3)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '0', '#', '#', '-', '-'], ['-', '-', '0', 'X', '0', '-', '-'], ['-', '-', '#', '#', '0', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(2, 3)周围的情况如下:
- 上方(1, 3): '#'
- 下方(3, 3): '-' (可以移动)
- 左方(2, 2): '0'
- 右方(2, 4): '0' (可以移动)
我可以选择向下移动到(3, 3)或向右移动到(2, 4)。为了更接近目标(5, 5),我选择向右移动到(2, 4)。
Action: move_action
Action Input: (0, 1) action: (0, 1)
从(2, 3) 移动到了 (2, 4)
Observation: True
Thought:我已经成功移动到(2, 4)。接下来,我需要再次观察当前位置(2, 4)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '#', '#', '#', '-'], ['-', '-', '-', '0', 'X', '#', '-'], ['-', '-', '-', '#', '0', '#', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(2, 4)周围的情况如下:
- 上方(1, 4): '#'
- 下方(3, 4): '0' (可以移动)
- 左方(2, 3): '0'
- 右方(2, 5): '#'
我可以选择向下移动到(3, 4)。这将使我更接近目标(5, 5)。
Action: move_action
Action Input: (1, 0) action: (1, 0)
从(2, 4) 移动到了 (3, 4)
Observation: True
Thought:我已经成功移动到(3, 4)。接下来,我需要再次观察当前位置(3, 4)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '0', '0', '#', '-'], ['-', '-', '-', '#', 'X', '#', '-'], ['-', '-', '-', '0', '0', '#', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(3, 4)周围的情况如下:
- 上方(2, 4): '0'
- 下方(4, 4): '0' (可以移动)
- 左方(3, 3): '#'
- 右方(3, 5): '#'
我可以选择向下移动到(4, 4),这将使我更接近目标(5, 5)。
Action: move_action
Action Input: (1, 0) action: (1, 0)
从(3, 4) 移动到了 (4, 4)
Observation: True
Thought:我已经成功移动到(4, 4)。接下来,我需要再次观察当前位置(4, 4)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '#', '0', '#', '-'], ['-', '-', '-', '0', 'X', '#', '-'], ['-', '-', '-', '#', '0', '0', '-'], ['-', '-', '-', '-', '-', '-', '-']]
Thought:当前位置(4, 4)周围的情况如下:
- 上方(3, 4): '0'
- 下方(5, 4): '0' (可以移动)
- 左方(4, 3): '#'
- 右方(4, 5): '0' (可以移动)
我可以选择向下移动到(5, 4)或向右移动到(4, 5)。为了更接近目标(5, 5),我选择向右移动到(4, 5)。
Action: move_action
Action Input: (0, 1) action: (0, 1)
Observation: False
Thought:当前位置(4, 5)无法向右移动,可能是因为右方有墙体。接下来,我需要选择向下移动到(5, 4)。
Action: move_action
Action Input: (1, 0) action: (1, 0)
从(4, 4) 移动到了 (5, 4)
Observation: True
Thought:我已经成功移动到(5, 4)。接下来,我需要再次观察当前位置(5, 4)周围的情况,以确定下一步的移动方向。
Action: observe
Action Input: None
Observation: [['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '-', '-', '-', '-'], ['-', '-', '-', '0', '0', '#', '-'], ['-', '-', '-', '#', 'X', '0', '-'], ['-', '-', '-', '#', '#', '#', '-']]
Thought:当前位置(5, 4)周围的情况如下:
- 上方(4, 4): '0'
- 下方(6, 4): '-' (可以移动)
- 左方(5, 3): '#'
- 右方(5, 5): '0' (可以移动)
我可以选择向右移动到(5, 5),这将使我到达目标位置。
Action: move_action
Action Input: (0, 1) action: (0, 1)
从(5, 4) 移动到了 (5, 5)
Observation: True
Thought:我已经成功移动到目标位置(5, 5)。整个移动轨迹如下:
1. 从(1, 1)观察,发现可以向右移动到(1, 2)。
2. 从(1, 2)观察,选择向下移动到(2, 2)。
3. 从(2, 2)观察,选择向右移动到(2, 3)。
4. 从(2, 3)观察,选择向 right 移动到(2, 4)。
5. 从(2, 4)观察,选择向下移动到(3, 4)。
6. 从(3, 4)观察,选择向下移动到(4, 4)。
7. 从(4, 4)观察,选择向下移动到(5, 4)。
8. 从(5, 4)观察,选择向右移动到(5, 5)。
最终,我成功到达了目标位置(5, 5)。
Final Answer: 移动轨迹为 [(1, 1) -> (1, 2) -> (2, 2) -> (2, 3) -> (2, 4) -> (3, 4) -> (4, 4) -> (5, 4) -> (5, 5)]。
> Finished chain.
{'input': "\n你作为player当前处于一个 7*7的 二维矩阵中,'X'是你的位置,'#' 都是墙体,只有 '0' 是通道, '-' 表示未知\n初始坐标为(1,1),你需要设法到达(5,5)\n注意: 只能沿着通道移动\n你每次可以移动一步,只能是下面4种动作之一\n(1, 0), (0, 1), (-1, 0), (0, -1)\n请你给出一个完整的移动轨迹,如果可以尝试推测一下矩阵的情况\n", 'output': '移动轨迹为 [(1, 1) -> (1, 2) -> (2, 2) -> (2, 3) -> (2, 4) -> (3, 4) -> (4, 4) -> (5, 4) -> (5, 5)]。'}
4. 提示词
ReAct的提示词形如:
Answer the following questions as best you can.
You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought:{agent_scratchpad}
5. 总结
ReAct框架为基于LLM的Agent提供了一种高效且具有可解释性的任务解决方法。
通过将推理和行动相结合,ReAct不仅克服了传统链式思考推理中常见的幻觉和错误传播问题,
还生成了类似人类思考过程的任务解决轨迹,使得整个决策过程更加清晰、透明。
这种范式不仅提高了大型语言模型在多种任务上的准确性,还为理解和开发更智能的Agent提供了新的思路和方向。未来,随着ReAct框架的进一步发展和优化,有望在更广泛的领域发挥更大的作用,推动语言模型在复杂任务中的应用和发展。
6. 参考资料
1.react
2.ReAct: Synergizing Reasoning and Acting in Language Models
3.example