react - ReActAgent 配置与构建
2026年1月14日 下午2:55:28
ReActAgent 采用 “Reasoning + Acting(推理+行动)” 闭环模式。它能够根据用户目标,自主思考(Thought)、选择工具执行动作(Action)、观察结果(Observation),直至完成任务。
1、ReActAgent 配置参考(可参考 ReActAgentConfig 字段)
| 分类 | 参数名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
| 身份定义 | name | String | react_agent | 智能体唯一标识,决定了 Session 存储中的 TraceKey(__name)。 |
| title | String | / | 视觉标题,多用于可视化 UI 或日志报表的友好显示。 | |
| description | String | / | 核心字段。定义智能体职责,供模型识别角色任务。 | |
| 决策大脑 | chatModel | ChatModel | / | 充当大脑,负责理解需求、分派任务与总结。 |
| chatOptions | Consumer | / | 用于精细控制模型的参数(如调低 Temperature 以稳健决策)。 | |
| systemPrompt | ReActSystemPrompt | 中文模板 | 定义推理的提示词骨架,包含 Thought/Action/Observation 规范。 | |
| 执行控制 | maxSteps | int | 5 | 单次任务允许的最大推理步数,防止成员间无限“思考”导致死循环。 |
| retryConfig | int, long | 3, 1000L | 决策失败或解析异常时的自动重试次数及延迟。 | |
| finishMarker | String | 自动生成 | 任务完结标识。模型输出此标记代表任务整体终结。 | |
| 存储输出 | historyWindowSize | int | 10 | 记忆窗口大小。加载最近 N 条历史消息作为上下文。 |
| outputKey | String | / | 任务结束后的结果回填至 FlowContext 的键名。 | |
| outputSchema | String/Type | / | 约束输出格式(JSON Schema),确保结果符合业务预期。 | |
| 扩展定制 | graphAdjuster | Consumer | / | 进阶项。允许在生成的默认执行图基础上微调链路。 |
| defaultInterceptorAdd | ReActInterceptor | / | 生命周期拦截器,用于监控思考过程、工具调用等过程。 |
关键配置点补充说明
- 关于职责描述 (description):在 ReActAgent 中,描述不仅是给人看的,更是给“模型”看的。一个清晰的描述能让模型更准确地判断何时该调用什么工具。
- 关于终止标识 (finishMarker):系统会根据
name自动生成。当模型认为任务已达成,输出该标识后,Agent 将提取内容作为最终答复。 - 关于最大推理步数 (maxSteps):在推理协作中,模型可能会产生反复确认或死循环。该参数是“保险丝”,确保系统不会因为无限对话而耗尽 Token。
2、ReActAgent 构建
- 基础版:具备工具能力的智能体
适用于逻辑固定的线性任务。赋予智能体一组工具,让其自主调度解决问题。
// 创建一个具备数据库查询能力的智能体
ReActAgent dbAgent = ReActAgent.of(chatModel)
.name("data_helper")
.description("数据助手,负责查询用户信息及订单状态")
// 1. 注入工具(支持注解方法或 FunctionTool 实例)
.toolAdd(new MethodToolProvider(new MyUserTools()))
// 2. 限制步数防止死循环
.maxSteps(5)
.build();
// 执行:模型会根据问题判断是否需要调用工具
String result = dbAgent.prompt("帮我查一下用户 ID 为 1001 的最近一笔订单金额")
.call()
.getContent();
- 进阶版:精细化控制专家团队
这是一个包含重试策略、拦截监控及性能调优的复杂示例。
// 创建一个全能的技术支持专家
ReActAgent techAgent = ReActAgent.of(chatModel)
// --- 1. 身份与职责定义 ---
.name("tech_support_expert")
.title("技术支持专家")
.description("负责处理复杂的客户技术问题,包括查询数据库和排查日志")
// --- 2. 注入工具与重试策略 ---
.toolAdd(dbTool)
.toolAdd(logTool)
.retryConfig(3, 2000L) // 决策失败自动重试
.maxSteps(12) // 允许最多 12 步推理,处理深度问题
// --- 3. 配置决策大脑的运行策略 ---
.chatOptions(options -> {
options.setTemperature(0.1f); // 调低温度,让决策更严谨
})
// --- 4. 插入定制化逻辑 ---
.finishMarker("[TASK_SOLVED]") // 自定义任务完结标识
.defaultInterceptorAdd(new ReActInterceptor() {
@Override
public void onThought(ReActTrace trace, String thought) {
System.out.println("🤖 思考中: " + thought);
}
@Override
public void onAction(ReActTrace trace, String toolName, Map<String, Object> args) {
System.out.println("🛠️ 执行工具: " + toolName + ",参数: " + args);
}
})
// --- 5. 手动微调计算图(高级项) ---
.graphAdjuster(spec -> {
// 可以在此处对生成的 Graph 进行链路微调
})
.build();
// 执行调用:模型会分析问题,决定先查数据,再分析情况
String finalAnswer = techAgent.call("用户 ID 为 9527 的反馈登录失败,请排查原因并给出建议。");
3、ReActInterceptor 接口参考
package org.noear.solon.ai.agent.react;
import org.noear.solon.ai.chat.ChatRequestDesc;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.interceptor.ChatInterceptor;
import org.noear.solon.flow.intercept.FlowInterceptor;
import org.noear.solon.lang.Preview;
import java.util.Map;
/**
* ReAct 智能体拦截器
* <p>提供对智能体起止、模型推理、工具执行等全生命周期的监控与干预能力</p>
*
* @author noear
* @since 3.8.1
*/
@Preview("3.8.1")
public interface ReActInterceptor extends FlowInterceptor, ChatInterceptor {
/**
* 智能体生命周期:开始执行前
*/
default void onAgentStart(ReActTrace trace) {
}
/**
* 模型推理周期:发起 LLM 请求前
* <p>可用于动态修改请求参数、Stop 词或注入 Context</p>
*/
default void onModelStart(ReActTrace trace, ChatRequestDesc req) {
}
/**
* 模型推理周期:LLM 响应后
* <p>常用于死循环(复读)检测或原始响应审计</p>
*/
default void onModelEnd(ReActTrace trace, ChatResponse resp) {
}
/**
* 推理节点:解析出思考内容 (Thought) 时触发
*/
default void onThought(ReActTrace trace, String thought) {
}
/**
* 动作节点:调用功能工具 (Action) 前触发
* <p>可用于权限控制、参数合法性预检</p>
*/
default void onAction(ReActTrace trace, String toolName, Map<String, Object> args) {
}
/**
* 观察节点:工具执行返回结果 (Observation) 后触发
*/
default void onObservation(ReActTrace trace, String result) {
}
/**
* 智能体生命周期:任务结束(成功或异常中止)时触发
*/
default void onAgentEnd(ReActTrace trace) {
}
}
- FlowInterceptor
package org.noear.solon.flow.intercept;
import org.noear.solon.flow.*;
import org.noear.solon.lang.Preview;
/**
* 流拦截器
*
* @author noear
* @since 3.1
* @since 3.5
* @since 3.7
*/
@Preview("3.1")
public interface FlowInterceptor {
/**
* 拦截流程执行, eval(graph)
*
* @param invocation 调用者
* @see org.noear.solon.flow.FlowEngine#eval(Graph, FlowExchanger)
*/
default void interceptFlow(FlowInvocation invocation) throws FlowException {
invocation.invoke();
}
/**
* 节点运行开始时
*
* @since 3.4
*/
default void onNodeStart(FlowContext context, Node node) {
}
/**
* 节点运行结束时
*
* @since 3.4
*/
default void onNodeEnd(FlowContext context, Node node) {
}
}
- ChatInterceptor
package org.noear.solon.ai.chat.interceptor;
import org.noear.solon.ai.chat.ChatRequest;
import org.noear.solon.ai.chat.ChatResponse;
import org.reactivestreams.Publisher;
import java.io.IOException;
/**
* 聊天拦截器
*
* @author noear
* @since 3.3
*/
public interface ChatInterceptor extends ToolInterceptor {
/**
* 拦截 Call 请求
*
* @param req 请求
* @param chain 拦截链
*/
default ChatResponse interceptCall(ChatRequest req, CallChain chain) throws IOException {
return chain.doIntercept(req);
}
/**
* 拦截 Stream 请求
*
* @param req 请求
* @param chain 拦截链
*/
default Publisher<ChatResponse> interceptStream(ChatRequest req, StreamChain chain) {
return chain.doIntercept(req);
}
}