react - ReActTrace 思考记忆与轨迹
2026年2月2日 下午9:46:19
在 ReAct(Reasoning and Acting)模式下,智能体不再是简单的“问答机”,而是一个具备“思考-行动-观察”循环的逻辑引擎。ReActTrace 正是记录这一循环过程的核心载体。它充当了智能体的运行时记忆和状态机,确保在复杂的推理过程中逻辑不丢失、状态可回溯。
1、核心职责:不仅是记录,更是驱动
ReActTrace 在一个典型的推理周期中承担了四种关键角色:
- 逻辑状态机:维护 REASON(推理)、ACTION(行动)、END(结束)的流转状态。
- 工作记忆 (Working Memory):实时存储当前任务的所有上下文、模型思考内容、工具调用参数及其返回结果(Observation)。
- 度量审计:自动统计推理步数(Step Count)、工具调用次数以及 Token 消耗。
- 计划中枢:如果启用了 Planning 能力,它还负责动态维护执行计划及其进度。
2、常用 API 快速查阅
| 分类 | 方法 | 返回类型 | 功能描述 |
|---|---|---|---|
| 基础上下文 | getOriginalPrompt() | Prompt | 获取用户最初输入的任务指令。 |
getSession() | AgentSession | 获取当前会话上下文(持有对话历史)。 | |
getContext() | FlowContext | 获取流程快照,用于跨节点数据共享。 | |
| 状态控制 | getRoute() / setRoute() | String | 获取或更新当前的路由逻辑标识。 |
getStepCount() | int | 获取当前已进行的推理轮次。 | |
nextStep() | int | 步数递增(通常由引擎在每一轮 Reason 前自动调用)。 | |
| 执行计划 | setPlans(Collection) | void | 注入或更新智能体生成的执行计划列表。 |
getFormattedPlans() | String | 获取 Markdown 格式的计划列表,用于增强模型感知的有序性。 | |
getPlanProgress() | String | 获取当前进度描述(如:总步数与当前进度的对比)。 | |
| 结果与度量 | getFinalAnswer() | String | 获取最终生成的结论。 |
getMetrics() | Metrics | 获取性能度量指标(耗时、Token 消耗等)。 | |
getFormattedHistory() | String | 获取人性化的对话与行动历史记录(Markdown 格式)。 |
3、自定义拦截器中的应用示例
这个示例展示了如何通过拦截器实现两个最常用的功能:实时监控思考过程 以及 防止模型死循环的“步数熔断”。
场景:推理过程监控与安全熔断
import org.noear.solon.ai.agent.react.ReActInterceptor;
import org.noear.solon.ai.agent.react.ReActTrace;
import org.noear.solon.ai.chat.message.AssistantMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 一个简单的 ReAct 监控拦截器
* 职责:1. 打印思考过程;2. 监控工具调用;3. 步数安全熔断
*/
public class MyReActInterceptor implements ReActInterceptor {
private static final Logger log = LoggerFactory.getLogger(MyReActInterceptor.class);
@Override
public void onAgentStart(ReActTrace trace) {
log.info("--- 智能体任务开始 [{}] ---", trace.getOriginalPrompt().getQuestion());
}
@Override
public void onThought(ReActTrace trace, String thought) {
// 实时输出 AI 的内心独白,常用于前端“思考中...”的展示
System.out.println("🤔 思考中: " + thought);
}
@Override
public void onAction(ReActTrace trace, String toolName, Map<String, Object> args) {
// 工具调用前的审计或记录
log.info("🛠️ 准备调用工具: {} , 参数: {}", toolName, args);
}
@Override
public void onModelEnd(ReActTrace trace, ChatResponse resp) {
// 安全熔断:如果推理步数超过 5 步,强制中止,防止 LLM 陷入无限 Tool Call 循环
if (trace.getStepCount() > 5) {
log.warn("检测到异常长路径推理,触发步数熔断!");
trace.setFinalAnswer("抱歉,该任务过于复杂,为了安全已中止推理。");
// 提示:拦截器可以利用底层 FlowInterceptor 能力直接中止流程
throw new RuntimeException();
}
}
@Override
public void onAgentEnd(ReActTrace trace) {
log.info("--- 任务结束,总步数: {},总耗时: {}ms ---",
trace.getStepCount(),
trace.getMetrics().getDuration());
}
}
4、技术特性解析
4.1 协议工具注入 (Protocol Tooling)
当智能体处于 TeamAgent 协作模式下,协作协议(TeamProtocol)可能会动态注入一些特殊工具(如 transfer_to)。这些工具被存储在 protocolToolMap 中,优先级高于智能体的默认工具。
4.2 结构化历史记录
getFormattedHistory() 会将复杂的消息列表转换为易于阅读的日志格式:
[User]: 原始指令[Assistant]: 模型的思考(Thought)[Action]: 调用的工具名及参数[Observation]: 工具返回的结果
4.3 动态计划管理
如果开启了 options.planningMode(true),智能体会先在 ReActTrace 中生成一份 plans。每一轮推理时,系统会自动将这份计划和当前进度(getPlanProgress())注入提示词,显著提升 Agent 处理复杂长任务的成功率。
5、使用建议
调试神器:在开发阶段,打印 getFormattedHistory() 是排查智能体为什么“跑偏”的最快方式。
内存注意:对于长任务,workingMemory 会持续增长。在极高并发场景下,建议通过拦截器监控 stepCount 以防止内存异常增长。
结果提取:如果需要将 AI 的结果转换为 Java 对象,通常在 finalAnswer 产出后,配合 toBean(Class