Solon v4.0.5

react - ReActTrace 思考记忆与轨迹

</> markdown
2026年7月30日 下午5:26:34

在 ReAct(Reasoning and Acting)模式下,智能体不再是简单的"问答机",而是一个具备"思考-行动-观察"循环的逻辑引擎。ReActTrace 正是记录这一循环过程的核心载体。它充当了智能体的运行时记忆和状态机,确保在复杂的推理过程中逻辑不丢失、状态可回溯。

1、核心职责:不仅是记录,更是驱动

ReActTrace 在一个典型的推理周期中承担了四种关键角色:

  • 逻辑状态机:维护 REASON(推理)、ACTION(行动)、END(结束)的流转状态。
  • 工作记忆 (Working Memory):实时存储当前任务的所有上下文、模型思考内容、工具调用参数及其返回结果(Observation)。
  • 度量审计:自动统计推理轮次(Turn Count)、工具调用次数以及 Token 消耗。
  • 计划中枢:如果启用了 Planning 能力,它还负责动态维护执行计划及其进度。

2、获取方式

从会话中提取"当前" ReActTrace

ReActTrace.getCurrent(session.getSnapshot());

从同步调用结果中获取

ReActResponse resp = agent.prompt("...").call();
ReActTrace trace = resp.getTrace();

从流式响应事件中获取

agent.prompt("...").stream()
    .doOnNext(event -> {
        if (event instanceof ReasonDeltaEvent) {
            ReasonDeltaEvent reasonEvent = (ReasonDeltaEvent) event;
            reasonEvent.getTrace();
        }
    })
    .subscribe();

从拦截器中获取。具体参考拦截器资料。

3、常用 API 快速查阅

分类方法返回类型功能描述
基础上下文getOriginalPrompt()Prompt获取用户最初输入的任务指令。
getSession()AgentSession获取当前会话上下文(持有对话历史)。
getContext()FlowContext获取流程快照,用于跨节点数据共享。
状态控制getRoute() / setRoute()String获取或更新当前的路由逻辑标识。
getTurnCount()int获取当前已进行的推理轮次
nextTurn()int轮次递增(通常由引擎在每一轮 Reason 前自动调用)。
执行计划setPlans(Collection)void注入或更新智能体生成的执行计划列表。
getFormattedPlans()String获取 Markdown 格式的计划列表,用于增强模型感知的有序性。
getPlanProgress()String获取当前进度描述(如:总步数与当前进度的对比)。
结果与度量getFinalAnswer()String获取最终生成的结论。
getMetrics()Metrics获取性能度量指标(耗时、Token 消耗等)。
getFormattedHistory()String获取人性化的对话与行动历史记录(Markdown 格式)。

注意:旧方法 getStepCount() / nextStep() 已在 4.0 版本标记为 @Deprecated,请统一使用 getTurnCount() / nextTurn()

4、自定义拦截器中的应用示例

这个示例展示了如何通过拦截器实现两个最常用的功能:实时监控推理过程以及防止模型死循环的"轮次熔断"。

场景:推理过程监控与安全熔断


import org.noear.solon.ai.agent.react.ReActInterceptor;
import org.noear.solon.ai.agent.react.ReActTrace;
import org.noear.solon.ai.agent.react.task.ToolExchanger;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.message.AssistantMessage;
import org.noear.solon.ai.chat.message.ChatMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 一个利用 ReActInterceptor 新 API 的监控拦截器
 * 职责:1. 打印推理过程;2. 监控工具调用;3. 轮次安全熔断
 */
public class MyReActInterceptor implements ReActInterceptor {
    private static final Logger log = LoggerFactory.getLogger(MyReActInterceptor.class);
    private static final int MAX_TURNS = 20;

    @Override
    public void onAgentStart(ReActTrace trace) {
        log.info("--- 智能体任务开始 [{}] ---", trace.getOriginalPrompt().getUserContent());
    }

    @Override
    public void onReasonStart(ReActTrace trace, StringBuilder systemPromptBuf) {
        // 轮次熔断:在每次推理前检查是否超过最大轮次
        if (trace.getTurnCount() > MAX_TURNS) {
            systemPromptBuf.append("\n\n[系统提示] 已超过最大推理轮次(")
                    .append(MAX_TURNS).append("),请尽快给出最终结论并结束。");
        }
    }

    @Override
    public void onReasonEnd(ReActTrace trace, ChatResponse resp, AssistantMessage message, long durationMs) {
        // 实时输出 AI 的推理结果(替代已废弃的 onThought)
        System.out.println("🤔 推理完成(耗时 " + durationMs + "ms): " + message.getContent());
        if (message.isThinking()) {
            System.out.println("🧠 深度思考中...");
        }
    }

    @Override
    public void onToolCallStart(ReActTrace trace, ToolExchanger toolExchanger) {
        // 工具调用前的审计或记录(替代已废弃的 onAction)
        log.info("🛠️ 准备调用工具: {},参数: {}", toolExchanger.getToolName(), toolExchanger.getArgs());
    }

    @Override
    public void onAgentEnd(ReActTrace trace) {
        log.info("--- 任务结束,总轮次: {},总耗时: {}ms ---",
                trace.getTurnCount(),
                trace.getMetrics().getTotalDuration());
    }
}

向后兼容指引:如果您在 4.0.4 之前的版本中使用了 onThoughtonActiononObservation 三个方法,它们依然可用但已被 @Deprecated 标记。推荐迁移到新的 API: - onThoughtonReasonEnd(ReActTrace, ChatResponse, AssistantMessage, long),额外获取 ChatResponse 和耗时参数 - onActiononToolCallStart(ReActTrace, ToolExchanger),语义更明确 - onObservationonToolCallEnd(ReActTrace, ToolExchanger, ChatMessage, Throwable, long),额外获取错误和耗时参数 新的拦截器还额外支持 onReasonStart(推理开始前,可修改 systemPrompt)、onReasonRetry(推理重试)、onActionStart / onActionEnd(整个动作阶段前后)等精细化钩子。

5、技术特性解析

5.1 协议工具注入 (Protocol Tooling)

当智能体处于 TeamAgent 协作模式下,协作协议(TeamProtocol)可能会动态注入一些特殊工具(如 transfer_to)。这些工具被存储在 protocolToolMap 中,优先级高于智能体的默认工具。

5.2 结构化历史记录

getFormattedHistory() 会将复杂的消息列表转换为易于阅读的日志格式:

  • [User]: 原始指令
  • [Assistant]: 模型的思考(Thought)
  • [Action]: 调用的工具名及参数
  • [Observation]: 工具返回的结果

5.3 动态计划管理

如果开启了 options.planningMode(true),智能体会先在 ReActTrace 中生成一份 plans。每一轮推理时,系统会自动将这份计划和当前进度(getPlanProgress())注入提示词,显著提升 Agent 处理复杂长任务的成功率。

6、使用建议

调试神器:在开发阶段,打印 getFormattedHistory() 是排查智能体为什么"跑偏"的最快方式。

内存注意:对于长任务,workingMemory 会持续增长。在极高并发场景下,建议通过拦截器监控 turnCount 以防止内存异常增长。

结果提取:如果需要将 AI 的结果转换为 Java 对象,通常在 finalAnswer 产出后,配合 toBean(Class) 使用。