1. 从“单步执行”到“循环思考”:为什么我们需要ReAct模式?

如果你最近在折腾AI应用,尤其是想让它帮你完成一些稍微复杂点的任务,比如“查一下今天北京的天气,然后根据天气推荐一个适合的户外活动,最后把这个推荐用邮件发给我”,你可能会发现,直接给大模型一个指令,它要么会卡住,要么会给你一个笼统的、甚至错误的答案。这背后的核心矛盾在于:当前的大语言模型(LLM)本质上是一个“单步推理机”。你给它一个输入,它基于庞大的训练数据,生成一个看起来合理的输出。但对于需要多步骤、依赖外部信息、且步骤间有逻辑关联的任务,这种“一次性生成”的模式就力不从心了。

这就引出了我们今天要深入探讨的 ReAct模式 。它不是一个全新的模型,而是一种让AI智能体(Agent)工作的 范式 。你可以把它理解为给AI装上了一套“思考-行动”的循环操作系统。想象一下,你让一个实习生去完成一个调研任务,聪明的实习生不会直接冲出去乱找,而是会先想:“我需要哪些信息?第一步该查什么资料?查到的资料是否回答了问题?如果没有,下一步该问谁?” ReAct模式就是让AI智能体模仿这个“先想后做,边做边想”的过程。

在AI Agent的开发领域,ReAct几乎成了构建实用型智能体的“标配”思路。无论是处理需要调用搜索引擎、数据库API的复杂查询,还是操作软件、分析文档的自动化流程,ReAct框架都提供了一套清晰、可解释、且效果显著的行动蓝图。它解决了纯“推理”模型(如Chain-of-Thought)缺乏行动能力,以及纯“行动”模型(如早期的一些API调用Agent)缺乏规划能力的弊端,将两者有机结合,形成了“在思考中行动,在行动中思考”的良性循环。

2. ReAct模式的核心架构拆解:Thought, Action, Observation

ReAct模式的名字来源于其核心的三个环节: Reasoning(思考/推理)、Acting(行动)、Observing(观察) 。这三个步骤构成一个循环,直到任务完成或达到终止条件。我们来逐一拆解,看看每个环节具体在做什么,以及为什么这样设计。

2.1 Reasoning(思考):制定计划与策略

这是循环的起点,也是智能体区别于简单工具调用的关键。在这一步,智能体基于 当前的任务目标 已有的历史信息 (包括之前的行动和观察结果),进行内部推理,决定下一步要做什么。

思考环节的输出通常是一段自然语言描述 ,例如:

  • “要回答用户关于北京天气的问题,我需要先获取今天的天气数据。我应该调用天气查询工具。”
  • “根据查到的‘小雨’天气,户外活动不适合。我需要搜索‘小雨天 室内活动 北京’。”
  • “我已经收集了天气信息和活动推荐,现在需要将这些信息整合成一封友好的邮件正文。”

这个环节的价值在于:

  1. 可解释性 :我们可以清晰地看到AI的“思路”,这比一个黑箱输出要可靠得多。如果结果出错,我们可以回溯它的思考过程,定位问题是在规划阶段还是执行阶段。
  2. 任务分解 :它将一个宏大的、模糊的用户指令(“帮我规划一个周末”)分解成一系列具体的、可执行的子任务(查天气、找餐厅、订票)。
  3. 动态调整 :思考不是一成不变的。如果上一步行动(Action)的结果(Observation)出乎意料,思考环节可以即时调整后续计划。比如,调用天气API失败了,思考环节可能会输出:“天气API调用失败,我尝试换用搜索引擎直接搜索天气关键词。”

在实际的Prompt设计或代码实现中,我们通常会要求模型在思考时遵循一些模板,比如:

Thought: 我现在需要解决什么问题?我目前知道什么?我下一步应该做什么?为什么?

2.2 Acting(行动):执行具体操作

思考完成后,智能体需要将“想法”转化为“动作”。这就是行动环节。行动通常是 对外部环境的干预 ,目的是获取信息或改变状态。

行动的核心是“工具调用”(Tool Calling) 。智能体自身不具备实时获取网络信息、计算或操作软件的能力,这些能力由一系列“工具”提供。一个行动的本质就是选择并调用一个合适的工具,并传入正确的参数。

常见的工具类型包括:

  • 信息获取工具 :搜索引擎API、数据库查询、知识图谱查询、文件读取。
  • 计算与处理工具 :计算器、代码解释器、数据格式转换器。
  • 状态操作工具 :发送邮件、创建日历事件、控制智能家居、在GUI界面点击按钮。

行动环节的输出是一个结构化的调用指令 ,例如:

  • Action: search_weather[location="北京"]
  • Action: google_search[query="北京 小雨 室内 活动 推荐"]
  • Action: send_email[to="user@example.com", subject="周末活动推荐", body=...]

工具的设计至关重要。工具的数量、功能边界、输入输出格式的清晰度,直接决定了智能体能力的天花板。一个好的工具应该像一把瑞士军刀里的单个工具——功能单一、接口明确、可靠。

2.3 Observing(观察):收集反馈与结果

行动执行后,会有一个结果。这个结果可能是成功的数据(如天气信息JSON),也可能是失败的错误信息(如“API密钥无效”)。观察环节就是接收并处理这个结果,将其转化为智能体能够理解和用于下一轮思考的文本信息。

观察环节的输出也是一段自然语言描述 ,但它是对客观结果的摘要或转述,而不是推理。例如:

  • Observation: 查询成功。北京今天白天多云转阴,傍晚有小雨,气温15-22°C,东风2-3级。
  • Observation: 搜索到5条相关结果。第一条是‘北京雨天必去的10个室内博物馆’,链接为...
  • Observation: 邮件发送失败,错误原因为‘收件人邮箱地址格式不正确’。

观察环节的关键作用:

  1. 信息整合 :将结构化的API响应、冗长的网页内容或错误代码,提炼成简洁、关键的信息点,供下一轮思考使用。
  2. 错误处理 :暴露执行过程中的问题,为智能体提供修正策略的依据。
  3. 状态更新 :让智能体感知到环境因它的行动而发生的变化,这是实现多步任务的基础。

至此,一个完整的“思考-行动-观察”循环结束。智能体会将本次循环的 Thought Action Observation 全部记录到“工作记忆”或“上下文”中,然后开启下一个循环,直到思考环节输出 Thought: 我已经完成了用户的所有要求,现在可以给出最终答案了。 并最终输出 Final Answer: ...

3. 从零构建一个ReAct智能体:以“天气活动推荐”为例

理论讲得再多,不如亲手实现一遍。下面我将以一个经典的“天气活动推荐助手”为例,手把手拆解如何构建一个具备ReAct能力的智能体。我们将使用Python和流行的LangChain框架来演示核心逻辑,但请记住,框架只是工具,理解模式本身才是关键。

3.1 第一步:定义任务与工具集

首先,我们必须明确智能体的边界和能力。我们的目标是: 根据用户提供的城市,查询天气,并基于天气情况推荐一项活动。

为此,我们需要两个核心工具:

  1. 天气查询工具 :输入城市名,返回天气概况(如:晴、雨、温度)。
  2. 活动推荐工具 :输入天气条件,返回一个具体的活动建议。

在真实场景中,这些工具可能对应着真实的API。这里我们模拟它们的实现:

# 模拟工具函数
def get_weather(location: str) -> str:
    """模拟天气查询工具。"""
    # 这里本该调用如OpenWeatherMap的API
    weather_data = {
        "北京": "晴朗,气温25°C",
        "上海": "多云,气温22°C",
        "广州": "雷阵雨,气温28°C",
        "伦敦": "小雨,气温15°C"
    }
    return weather_data.get(location, f"未找到{city}的天气信息。")

def recommend_activity(weather_condition: str) -> str:
    """模拟活动推荐工具。基于天气关键词推荐。"""
    recommendations = {
        "晴朗": "推荐去公园野餐或骑行。",
        "多云": "适合户外散步或参观露天市集。",
        "小雨": "可以去博物馆、美术馆或者找一家咖啡馆看书。",
        "雷阵雨": "最好待在室内,可以看电影、玩桌游。"
    }
    for key in recommendations:
        if key in weather_condition:
            return recommendations[key]
    return "根据天气,建议进行轻松的室内活动。"

3.2 第二步:设计ReAct提示词(Prompt)模板

这是驱动大模型进行“思考”的引擎。一个好的Prompt模板需要清晰地定义角色、步骤格式、可用工具和规则。

REACT_PROMPT_TEMPLATE = """
你是一个智能生活助手。请使用以下工具,通过思考-行动-观察的步骤来帮助用户。
你的最终目标是根据用户提供的城市,查询天气并推荐一个活动。

你可以使用的工具:
1. get_weather: 输入一个城市名称,返回该城市的天气情况。参数格式:{{“location”: “城市名”}}
2. recommend_activity: 输入一段天气描述,返回一个活动推荐。参数格式:{{“weather_condition”: “天气描述”}}

你必须严格按照以下格式响应:
Thought: 你需要先思考当前情况、目标和下一步计划。
Action: 调用工具的名称,如果调用工具,必须严格按照参数格式输入JSON。
Observation: 调用工具后返回的结果。

当你认为已经收集到足够信息,可以给出最终答案时,你的响应格式必须是:
Thought: 我已经完成了任务。
Final Answer: 你的最终回答,应包含天气和推荐。

开始!
用户的问题是:{user_input}

之前的历史步骤(如果是第一次,则为空):
{history}

现在,开始你的第一次思考。
"""

这个模板的设计要点:

  • 角色设定 :明确了智能体的身份和总体目标。
  • 工具规格 :清晰列出了工具名、功能和 严格的参数格式 。这是减少模型幻觉的关键。
  • 格式强制 :明确要求模型必须输出 Thought: Action: Observation: 标签。这便于程序进行解析。
  • 上下文注入 {history} 占位符用于传递之前的循环记录,实现多步推理的记忆。
  • 终止条件 :定义了如何判断任务完成(输出 Final Answer )。

3.3 第三步:实现ReAct循环引擎

现在,我们需要编写一个循环控制器,它负责:1. 组装Prompt;2. 调用大模型;3. 解析模型输出;4. 执行工具调用;5. 收集结果并进入下一轮。

import json
import re

class SimpleReActAgent:
    def __init__(self, llm, tools):
        self.llm = llm  # 大语言模型实例,如OpenAI的ChatCompletion
        self.tools = {tool.__name__: tool for tool in tools}  # 工具字典
        self.history = []

    def parse_response(self, response_text):
        """解析模型返回的文本,提取Thought, Action, Observation/Answer。"""
        thought = re.search(r'Thought:\s*(.*?)(?=\nAction:|\nFinal Answer:|\nObservation:|$)', response_text, re.DOTALL)
        action = re.search(r'Action:\s*(\w+)\s*(\{.*?\})?', response_text)
        final_answer = re.search(r'Final Answer:\s*(.*)', response_text, re.DOTALL)
        observation = None # Observation 由环境返回,不在此解析

        parsed = {}
        if thought:
            parsed['thought'] = thought.group(1).strip()
        if action:
            parsed['action'] = action.group(1).strip()
            if action.group(2):
                try:
                    parsed['action_input'] = json.loads(action.group(2).strip())
                except json.JSONDecodeError:
                    parsed['action_input'] = action.group(2).strip()
        if final_answer:
            parsed['final_answer'] = final_answer.group(1).strip()

        return parsed

    def run(self, user_input, max_steps=5):
        print(f"用户问题: {user_input}")
        self.history = []

        for step in range(max_steps):
            # 1. 构建当前Prompt
            history_str = "\n".join(self.history)
            prompt = REACT_PROMPT_TEMPLATE.format(user_input=user_input, history=history_str)

            # 2. 调用大模型
            response = self.llm.invoke(prompt) # 假设llm.invoke返回文本
            print(f"\n--- 步骤 {step+1} ---")
            print(f"模型原始响应:\n{response}")

            # 3. 解析响应
            parsed = self.parse_response(response)
            if not parsed:
                return "错误:无法解析模型响应。"

            # 记录思考
            if 'thought' in parsed:
                self.history.append(f"Thought: {parsed['thought']}")
                print(f"Thought: {parsed['thought']}")

            # 4. 检查是否结束
            if 'final_answer' in parsed:
                print(f"任务完成!")
                return parsed['final_answer']

            # 5. 执行行动
            if 'action' in parsed:
                action_name = parsed['action']
                action_input = parsed.get('action_input', {})
                print(f"Action: {action_name}({action_input})")

                if action_name in self.tools:
                    try:
                        # 执行工具调用
                        if isinstance(action_input, dict):
                            observation_result = self.tools[action_name](**action_input)
                        else:
                            observation_result = self.tools[action_name](action_input)
                    except Exception as e:
                        observation_result = f"工具调用错误: {e}"
                else:
                    observation_result = f"错误:未知工具 '{action_name}'。"

                # 6. 记录观察
                obs_text = f"Observation: {observation_result}"
                self.history.append(f"Action: {action_name}({json.dumps(action_input)})")
                self.history.append(obs_text)
                print(obs_text)
            else:
                # 如果没有Action也没有Final Answer,可能模型出错了
                return "错误:模型响应中未找到有效的Action或Final Answer。"

        return f"达到最大步数 ({max_steps}) 仍未完成任务。"

# 模拟一个简单的LLM(实际中替换为OpenAI, Anthropic等API调用)
class MockLLM:
    def invoke(self, prompt):
        # 这是一个极度简化的模拟,实际模型会根据Prompt生成动态内容。
        # 这里我们根据输入返回一个预设的、符合ReAct格式的响应序列。
        if "北京" in prompt:
            if "Action" not in prompt: # 第一次调用
                return """Thought: 用户想知道北京的天气和活动推荐。我需要先调用get_weather工具获取北京天气。
Action: get_weather
{"location": "北京"}"""
            else: # 第二次调用(在收到天气观察后)
                return """Thought: 我观察到北京天气是“晴朗,气温25°C”。这是一个好天气。现在我需要调用recommend_activity工具,基于“晴朗”这个条件来推荐活动。
Action: recommend_activity
{"weather_condition": "晴朗"}"""
        return "Thought: 我无法处理这个请求。"

# 运行智能体
if __name__ == "__main__":
    llm = MockLLM()
    tools = [get_weather, recommend_activity]
    agent = SimpleReActAgent(llm, tools)

    result = agent.run("北京今天天气怎么样?适合做什么活动?")
    print(f"\n最终结果:\n{result}")

运行上述简化示例,你会看到类似以下的输出,清晰地展示了ReAct循环:

用户问题: 北京今天天气怎么样?适合做什么活动?

--- 步骤 1 ---
模型原始响应:
Thought: 用户想知道北京的天气和活动推荐。我需要先调用get_weather工具获取北京天气。
Action: get_weather
{"location": "北京"}
Thought: 用户想知道北京的天气和活动推荐。我需要先调用get_weather工具获取北京天气。
Action: get_weather({"location": "北京"})
Observation: 晴朗,气温25°C

--- 步骤 2 ---
模型原始响应:
Thought: 我观察到北京天气是“晴朗,气温25°C”。这是一个好天气。现在我需要调用recommend_activity工具,基于“晴朗”这个条件来推荐活动。
Action: recommend_activity
{"weather_condition": "晴朗"}
Thought: 我观察到北京天气是“晴朗,气温25°C”。这是一个好天气。现在我需要调用recommend_activity工具,基于“晴朗”这个条件来推荐活动。
Action: recommend_activity({"weather_condition": "晴朗"})
Observation: 推荐去公园野餐或骑行。

--- 步骤 3 ---
模型原始响应:
Thought: 我已经完成了任务。
Final Answer: 北京今天天气晴朗,气温25°C。这样的好天气,推荐去公园野餐或骑行。
任务完成!

最终结果:
北京今天天气晴朗,气温25°C。这样的好天气,推荐去公园野餐或骑行。

4. ReAct模式实战中的核心挑战与调优策略

当你真正开始用ReAct模式开发智能体时,会发现理想很丰满,现实却很“骨感”。直接套用基础模板,智能体可能很快就会陷入死循环、调用错误工具或者产生荒谬的推理。下面是我在多个项目中总结出的核心挑战和应对策略。

4.1 挑战一:模型的“规划与推理”能力不足

问题表现 :模型输出的 Thought 过于简短或逻辑混乱,比如直接跳步(没查天气就直接推荐)、工具选择错误(该用 search 时用了 calculator )、或者陷入循环思考(“我需要查天气,我需要查天气...”)。

根因分析 :这本质上是当前大语言模型的局限性。尽管它们在语言理解上很强,但进行多步、严谨的逻辑规划,尤其是在工具使用约束下,仍然是一个难题。Prompt的指令不够清晰,或者上下文窗口中的示例不足,都会放大这个问题。

调优策略

  1. 少样本示例(Few-shot Prompting) :在Prompt模板中,直接提供1-3个完整的、成功的ReAct循环示例。这是提升效果最显著的方法之一。示例必须精准展示从用户问题到最终答案的完整 Thought-Action-Observation 链条。
    示例:
    用户:旧金山天气如何?适合跑步吗?
    Thought: 用户想知道旧金山的天气和是否适合跑步。我需要先获取天气信息。
    Action: get_weather
    {"location": "旧金山"}
    Observation: 旧金山今天多云,气温18°C,风速较小。
    Thought: 我观察到天气是多云,气温凉爽,风速小。这看起来很适合户外跑步。我可以直接给出最终答案了。
    Final Answer: 旧金山今天多云,气温18°C,风速较小。这样的天气条件非常适合跑步。
    
  2. 思维链(Chain-of-Thought)强化 :在 Thought 的指令中,要求模型进行更细致的推理。例如:“在Thought中,你必须:a) 复述当前任务;b) 总结已有信息;c) 分析下一步需要什么信息;d) 明确选择哪个工具以及为什么。”
  3. 使用更强的模型 :如果条件允许,在关键任务上使用更高级的模型(如GPT-4、Claude 3 Opus)。它们在复杂规划和遵循指令方面通常远优于小型或早期模型。

4.2 挑战二:工具调用的格式与可靠性问题

问题表现 :模型输出的 Action 格式不符合要求(如JSON格式错误、参数名拼写错误),或者调用了不存在的工具。

根优策略

  1. 严格的输出解析与错误处理 :像我们示例中的 parse_response 函数,需要使用健壮的正则表达式或更专业的解析库(如 Pydantic )。一旦解析失败,必须将错误信息作为 Observation 反馈给模型,让它有机会修正。例如: Observation: 你调用的格式不正确。请确保Action行是‘Action: 工具名’的格式,且参数是合法的JSON对象。
  2. 工具描述精细化 :在Prompt中描述工具时,不仅要写名字和功能,更要 严格定义输入输出的Schema 。最好能用JSON Schema或类似结构描述。
    工具:get_weather
    描述:查询指定城市的当前天气。
    参数:{"type": "object", "properties": {"location": {"type": "string", "description": "城市名称,如‘北京’、‘New York’"}}, "required": ["location"]}
    返回:一段描述天气的文本。
    
  3. 工具选择引导 :在Prompt中,可以根据任务类型对工具进行分组或排序,甚至提供简单的选择逻辑。例如:“如果问题涉及实时信息,优先使用 search_web 工具;如果涉及计算,使用 calculator 工具。”

4.3 挑战三:循环失控与冗余操作

问题表现 :智能体陷入无限循环(反复调用同一工具),或者进行不必要的重复操作,始终无法触发 Final Answer

调优策略

  1. 设置最大步数(Max Steps) :这是最基本的防护栏,如我们代码中的 max_steps=5 。防止资源被无限消耗。
  2. 在思考中引入“停止规则” :明确告诉模型在什么条件下应该停止。例如:“如果你认为已有的观察结果足以直接、准确地回答用户问题,则应该输出Final Answer,而不是继续调用工具。”
  3. 优化观察结果的摘要 :有时模型陷入循环是因为 Observation 内容太长或包含无关信息,干扰了后续思考。可以对工具返回的结果进行预处理和摘要,只提取关键信息喂给模型。
  4. 实现短期记忆去重 :在Agent的 history 中,可以检查最近N步内是否有完全相同的 Action Observation 组合,如果发现,则强制干预,返回一个特殊的 Observation ,如“你刚刚已经执行过完全相同的操作并得到了相同的结果,请尝试不同的策略或考虑是否已回答问题。”

4.4 挑战四:复杂任务下的上下文管理与长程依赖

问题表现 :任务需要很多步(超过10步),导致整个对话历史(所有Thought、Action、Observation)非常长,超出了模型上下文窗口。模型开始“遗忘”早期的关键信息,导致后续决策错误。

调优策略

  1. 关键信息摘要与压缩 :不要简单地将所有历史记录都塞进Prompt。可以设计一个“记忆管理器”,定期对之前的循环进行总结,用一段简短的文本替代冗长的原始记录。例如,将“查询了A、B、C三个数据,结果分别是X、Y、Z”总结为“已确认A为X,B为Y,C为Z”。
  2. 分层或链式任务分解 :对于极其复杂的任务,不要指望一个ReAct循环搞定。可以设计一个“主控Agent”,负责将大任务分解为多个子任务,然后为每个子任务启动一个独立的“子任务Agent”(使用ReAct模式)去完成。主控Agent负责协调和汇总结果。
  3. 利用向量数据库进行记忆 :将历史交互中的重要片段(如关键决策点、查询结果)转换成向量存储起来。在每一步思考时,从向量库中检索最相关的历史片段,作为上下文输入模型,而不是输入全部历史。这能有效突破上下文长度限制。

5. 超越基础ReAct:高级模式与架构演进

基础的ReAct循环解决了从“想”到“做”的问题,但在生产环境中,我们需要更鲁棒、更高效的架构。以下是几种重要的演进方向。

5.1 智能体(Agent)与工作流(Workflow)的融合

ReAct智能体擅长处理 目标明确但路径不确定 的任务(如“回答这个问题”)。而工作流引擎(如Airflow、Prefect)擅长处理 路径确定 的自动化流程(如“每天凌晨1点下载数据->清洗->生成报表->发送邮件”)。

融合模式 :将ReAct智能体作为工作流中的一个 智能决策节点 。例如,在一个客户服务自动化流程中,前几步是固定的(接收工单、提取信息),到了“判断问题类型并分派”这一步,则调用一个ReAct智能体。智能体分析工单内容,决定是分派给技术组、账单组还是普通客服,然后工作流引擎根据这个决策执行后续不同的固定分支。

这种模式结合了确定性的效率和不确定性的灵活性。

5.2 多智能体协作(Multi-Agent Collaboration)

对于超大型或涉及多领域知识的任务,可以部署多个具备不同专长和工具集的ReAct智能体,让它们通过通信进行协作。

常见模式

  • 主从模式 :一个“管理者”Agent负责分解任务和协调,多个“执行者”Agent负责具体子任务。
  • 平等辩论模式 :多个Agent对同一问题给出自己的推理过程和答案,然后由一个“评审”Agent或投票机制决定最终采纳哪个。
  • 黑板模式 :所有Agent共享一个公共的“黑板”工作区,从中读取信息,并将自己的产出写入,其他Agent可以基于此继续工作。

例如,一个“撰写行业分析报告”的任务,可以拆解为:一个“数据收集Agent”负责搜索和整理市场数据;一个“分析师Agent”负责解读数据并生成核心观点;一个“撰稿Agent”负责将观点润色成文。它们通过ReAct模式各自完成内部循环,并通过消息队列或共享状态进行交互。

5.3 与规划器(Planner)的结合:ReAct的“增强版”

在基础ReAct中,规划(下一步做什么)和执行(做)是交替进行的、短视的。这可能导致效率低下或陷入局部最优。

引入规划器 :在任务开始时,或每隔若干步,让一个专门的“规划模块”(可以是一个更强的LLM,或一个基于规则的引擎)先进行 全局性、前瞻性的规划 。这个规划器输出一个初步的步骤列表(如:1. 查天气;2. 根据天气搜索活动;3. 整合信息并回复)。然后,ReAct智能体再基于这个“蓝图”去执行每一步,同时保留根据实际情况(Observation)动态调整局部步骤的能力。

这相当于给了智能体一个粗略的“地图”,让它不至于在每一步都从头思考,提高了效率和任务完成的可靠性。

5.4 工具学习(Tool Learning)与智能体进化

一个智能体的能力上限受限于其工具集。如何让智能体自己发现或学习使用新工具?

工具学习 :让智能体能够理解自然语言描述的工具说明书,并在没有见过具体示例的情况下正确调用。例如,给智能体一段新API的文档,它就能在后续的思考中决定是否以及如何使用这个新API。这需要模型具备极强的泛化能力和代码理解能力。

智能体进化 :更进一步,智能体可以在运行过程中记录成功和失败的轨迹。这些轨迹可以用于微调模型本身,或者优化提示词策略,让智能体在类似任务上表现得越来越好,实现“从经验中学习”。

6. 评估一个ReAct智能体:不仅仅是看最终答案

开发完成后,如何判断你的ReAct智能体是好是坏?不能只看最终答案的对错。

1. 任务完成率 :在涵盖各种复杂度的测试用例集上,智能体能成功完成(输出合理Final Answer)的比例是多少? 2. 平均步数/效率 :完成一个任务平均需要多少次循环?步数越少,通常意味着规划越高效,成本也越低(因为每次循环都是一次LLM调用)。 3. 工具调用准确率 :模型选择的工具是否恰当?参数是否正确?错误调用会导致任务失败或额外开销。 4. 推理链的可解释性与合理性 :人工审查 Thought 记录,其逻辑是否清晰、合理?是否出现了明显的逻辑跳跃或荒谬的推理? 5. 鲁棒性 :当工具返回错误、网络超时或用户输入模糊时,智能体是否能妥善处理(如重试、切换工具、澄清问题)而不是直接崩溃? 6. 安全性 :智能体是否会尝试调用危险工具(如删除文件、发送敏感信息)?是否会对不可信的用户输入做出不当响应?必须建立严格的工具权限管理和输入输出过滤机制。

建立一个全面的评估体系,并持续进行测试和迭代,是打造一个真正可用、可靠的ReAct智能体的必经之路。

更多推荐