趋近智
构建ReAct智能体需要理解其核心控制流程和交互模式。手动构建这个智能体,能够让您对操作机制、提示词设计的复杂性以及编排思-行-观察循环所面临的难点有全面的理解,这些内容通常在更高级的框架中被抽象化。
我们的目标不是复刻一个功能全面的库,而是实现ReAct的核心逻辑。我们假设您可以使用LLM API(如OpenAI的GPT模型、Anthropic的Claude或自托管模型),并熟练掌握Python以进行API调用和处理响应。
实现一个ReAct智能体需要几个相互连接的构成部分:
search,calculator)。Thought:智能体的下一步推理。Action:要使用的工具及其输入(例如,Action: search[query: recent advancements in LLM agents])。Final Answer:当智能体认为任务完成时的最终回复。处理LLM输出格式的变化和潜在的解析失败,需要周全的设计(例如,使用正则表达式,或者在LLM支持的情况下,请求结构化输出如JSON)。Final Answer,则终止并返回答案。Action:
Observation。Thought、Action和Observation追加到暂存区。该交互遵循一种明确的模式,通常可视化为一个循环。
ReAct智能体通过格式化提示、调用LLM、解析响应、根据行动可能执行工具、将结果格式化为观察,并循环直到获得最终答案,从而在其暂存区中迭代地构建上下文。
我们来概述Python伪代码中的核心循环结构。这主要侧重于流程,而非具体的API或解析细节。
import re # 用于基本解析示例
# 假设llm_call(prompt)存在并返回LLM文本响应
# 假设tools = { "tool_name": {"description": "...", "function": callable} } 存在
def execute_react_agent(question, tools, llm_call, max_steps=10):
""" 执行ReAct智能体循环 """
scratchpad = "" # 存储思-行-观察历史
tool_descriptions = "\n".join([f"- {name}: {details['description']}" for name, details in tools.items()])
for step in range(max_steps):
# 1. 格式化提示
prompt = f"""你是一个使用ReAct框架来回答问题的助手。
可用工具:
{tool_descriptions}
请使用以下格式:
思: 你的推理步骤。
行: 要采取的行动,应该是[{', '.join(tools.keys())}]中的一个或'Final Answer'。工具请使用Action: tool_name[input]格式。
观察: 行动的结果。
... (此思/行/观察循环重复)
问题: {question}
{scratchpad}思:""" # 提示LLM以思考开始
# 2. LLM调用
response = llm_call(prompt).strip()
# 立即将LLM的思考过程追加到暂存区
scratchpad += f"思: {response}\n"
print(f"--- 步骤 {step+1} ---")
print(f"思: {response}")
# 3. 解析响应 (简化示例)
action_match = re.search(r"Action: (.*?)(?:\[(.*?)\])?$", response, re.MULTILINE)
final_answer_match = re.search(r"Final Answer: (.*)", response, re.MULTILINE | re.DOTALL)
if final_answer_match:
# 4a. 检测到最终答案
final_answer = final_answer_match.group(1).strip()
print(f"最终答案: {final_answer}")
return final_answer
if action_match:
action_name = action_match.group(1).strip()
action_input = action_match.group(2).strip() if action_match.group(2) else ""
scratchpad += f"Action: {action_name}[{action_input}]\n"
print(f"行: {action_name}[{action_input}]")
if action_name in tools:
# 5. 执行工具
try:
tool_function = tools[action_name]["function"]
observation = tool_function(action_input)
except Exception as e:
observation = f"执行工具 {action_name} 出错:{e}"
# 6. 格式化观察并更新暂存区
observation_str = str(observation) # 确保它是字符串
scratchpad += f"观察: {observation_str}\n"
print(f"观察: {observation_str}")
else:
scratchpad += "Observation: 指定了未知工具。\n"
print("指定了未知工具。")
else:
# 处理LLM未输出有效Action或Final Answer的情况
scratchpad += "Observation: 响应格式无效。停止。\n"
print("响应格式无效。停止。")
return "智能体因响应格式无效而失败。"
return "智能体在达到最大步骤数后停止。"
# 示例用法(需要定义llm_call和tools)
# result = execute_react_agent("2加2是多少?", my_tools, my_llm_call)
# print(f"\n最终结果: {result}")
Observation步骤中理解。在工具内优雅地处理错误并在观察中报告它们,这一点很重要。暂存区的增长,它会占用上下文窗口空间并增加API成本。对于长期运行的任务,可采用策略,例如对暂存区早期部分进行概括,或使用更高级的内存技术(第3章会介绍)。Final Answer:和达到最大步骤数后,考虑其他终止标准,例如重复行动、特定错误模式,或者如果您的解析器或LLM提供,则考虑置信度得分。构建这个自定义智能体,即使是使用简化组件,也能阐明构建自主系统中的基本挑战和固有的设计选择。它在使用或扩展更复杂的智能体框架之前,提供了扎实的基础。
简洁的语法。内置调试功能。从第一天起就可投入生产。
为 ApX 背后的 AI 系统而构建
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造