Solon AI 4.0的ReActAgent:构建生产级AI Agent,实现推理、行动与学习循环

发布时间:2026/7/5 18:11:01
Solon AI 4.0的ReActAgent:构建生产级AI Agent,实现推理、行动与学习循环 ReActAgent有何不同传统LLM擅长生成文本但在与现实世界交互如查数据库、拉取实时数据、做计算时就无能为力。ReActAgentReason Act打破了这一局限实现了一个认知循环思考 → 行动 → 观察 →重复或结束。Agent先思考下一步行动接着行动调用工具再观察结果最后决定继续还是交出最终答案。Solon AI的ReActAgent已在自动客服、智能数据分析、多步工作流自动化等生产场景中得到验证。1. 添加依赖首先在项目中添加 solon - ai - agent 模块dependencygroupIdorg.noear/groupIdartifactIdsolon-ai-agent/artifactId/dependency若使用了Solon的父POM版本会自动管理否则需指定最新的Solon版本。2. 构建ChatModelAgent的大脑每个Agent都需要一个负责推理的“大脑”——ChatModel。可以用Builder API快速构建import org.noear.solon.ai.chat.ChatModel;ChatModel chatModel ChatModel.of(https://api.moark.com/v1/chat/completions).apiKey(your-api-key-here).model(Qwen3-32B).build();也可通过YAML配置后注入solon.ai.chat:demo:apiUrl: http://127.0.0.1:11434/api/chatprovider: ollamamodel: llama3.2Inject(${solon.ai.chat.demo})ChatModel chatModel;3. Hello World你的第一个ReActAgent先从一个简单例子开始创建一个获取时间的工具和一个基础Agentimport org.noear.solon.ai.agent.react.ReActAgent;import org.noear.solon.ai.annotation.ToolMapping;import org.noear.solon.ai.annotation.Param;import org.noear.solon.ai.chat.tool.AbsToolProvider;import java.time.LocalDateTime;// 1. 定义工具public class TimeTool extends AbsToolProvider {ToolMapping(description 获取当前的日期和时间)public String getCurrentTime() {return LocalDateTime.now().toString();}}// 2. 构建并运行Agentpublic class HelloAgent {public static void main(String[] args) throws Throwable {ChatModel chatModel ChatModel.of(https://api.moark.com/v1/chat/completions).apiKey(***).model(Qwen3-32B).build();ReActAgent agent ReActAgent.of(chatModel).role(你是一个可以查询时间的助手。).defaultToolAdd(new TimeTool()).build();String response agent.prompt(现在几点了).call().getContent();System.out.println(response);}}运行时Agent会1. 思考“用户想知道时间我有一个 getCurrentTime 工具”2. 行动调用 getCurrentTime()3. 观察拿到时间戳4. 回答“当前时间是2026 - 07 - 04T14:30:22……”4. 实战客服支持Agent构建一个更实用的场景——支持查询订单和库存的客服Agent。#### 第1步定义工具import org.noear.solon.ai.chat.tool.AbsToolProvider;import org.noear.solon.ai.annotation.ToolMapping;import org.noear.solon.ai.annotation.Param;public class OrderTool extends AbsToolProvider {ToolMapping(description 根据订单ID查询订单状态)public String getOrderStatus(Param(description 订单ID) String orderId) {// 模拟数据库查询if (ORD-1001.equals(orderId)) {return 订单ORD-1001已发货预计7月7日送达;} else if (ORD-1002.equals(orderId)) {return 订单ORD-1002待处理付款未确认;}return 未找到订单 orderId;}ToolMapping(description 根据商品ID查询库存)public String checkInventory(Param(description 商品SKU) String sku) {if (SKU-A100.equals(sku)) {return 库存充足42件;} else if (SKU-B200.equals(sku)) {return 库存紧张仅剩3件;}return 未找到商品 sku;}}#### 第2步构建AgentReActAgent supportAgent ReActAgent.of(chatModel).name(customer_support).role(客服支持Agent----处理订单查询和库存检查。).defaultToolAdd(new OrderTool()).maxTurns(8) // 最大推理步数.autoRethink(true) // 卡住时自动重新思考.retryConfig(3, 1000L) // 重试3次间隔1秒.modelOptions(options - {options.temperature(0.1); // 低温度确定性决策}).build();String result supportAgent.prompt(客户ORD-1002想知道订单什么时候到能帮忙查一下吗).call().getContent();System.out.println(result);Agent会1. 意识到需要查 ORD-10022. 调用 getOrderStatus(ORD-1002)3. 读到结果“待处理付款未确认”4. 向客户解释付款尚未确认所以还未发货5. 添加拦截器可观测性生产环境中需要看到Agent的思考过程。ReActInterceptor提供了完整的生命周期钩子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;ReActAgent observableAgent ReActAgent.of(chatModel).name(observable_agent).role(我帮你处理各种任务。).defaultToolAdd(new OrderTool()).defaultInterceptorAdd(new ReActInterceptor() {Overridepublic void onAgentStart(ReActTrace trace) {System.out.println( Agent启动。提示词 trace.getOriginalPrompt().getUserContent());}Overridepublic void onThought(ReActTrace trace, String thoughtContent,AssistantMessage assistantMessage) {System.out.println( 思考 thoughtContent);}Overridepublic void onAction(ReActTrace trace, ToolExchanger toolExchanger) {System.out.println(️ 工具 toolExchanger.getToolName() 参数 toolExchanger.getArgs());}Overridepublic void onObservation(ReActTrace trace, ToolExchanger toolExchanger,ChatMessage observation, Throwable error,long durationMs) {if (error ! null) {System.err.println(❌ 工具调用失败 error.getMessage());} else {System.out.println(✅ 工具结果返回耗时 durationMs ms);}}Overridepublic void onAgentEnd(ReActTrace trace) {System.out.println(✅ Agent任务完成。);}}).build();这样就有了Agent每次决策的完整审计轨迹。6. 流式响应对于长时间运行的任务使用 stream() 获取实时输出agent.prompt(分析我们的Top 10商品给我一份销售摘要。).stream().doOnNext(resp - {System.out.print(resp.getMessage().getContent());}).doOnComplete(() - {System.out.println(\n✅ 分析完成);}).subscribe();7. 进阶单次调用选项通过 .options() 可以为单次调用调整行为agent.prompt(分析这个复杂数据集生成JSON报告。).session(mySession) // 复用已有会话.options(o - o.maxTurns(15) // 复杂任务给更多步数.planningMode(true) // 启用规划阶段.temperature(0.3) // 平衡创造性与精确性.outputSchema({\type\:\object\,\properties\:{...}} // 结构化输出.toolAdd(new ReportingTool()) // 临时添加一个工具).call();#### 选项一览| 分类 | 方法 | 说明 | 默认值 || --- | --- | --- | --- || 控制 | maxTurns(int) | 最大推理步数 | 8 || 控制 | autoRethink(boolean) | 自动重新思考 | false || 控制 | retryConfig(int, long) | 重试次数与间隔 | 3, 1000ms || 模型 | temperature(double) | 随机性0 - 2 | 0.5 || 模型 | max_tokens(long) | 最大生成Token | -- || 工具 | toolAdd(FunctionTool) | 临时添加工具 | -- || 工具 | talentAdd(Talent) | 添加技能模块 | -- || 扩展 | interceptorAdd(interceptor) | 添加拦截器 | -- |8. 会话与轨迹Sessions TracesReActAgent的会话支持带记忆的长时间对话import org.noear.solon.ai.agent.session.InMemoryAgentSession;import org.noear.solon.ai.agent.AgentSession;// 创建或复用会话AgentSession session InMemoryAgentSession.of(user-session-123);// 第一轮String r1 agent.prompt(帮我找找50元以下的商品).session(session).call().getContent();// 第二轮Agent记得上下文String r2 agent.prompt(最便宜的那个运费多少).session(session).call().getContent();// 查看轨迹ReActTrace trace agent.getTrace(session);System.out.println(总步数 trace.getStepCount());// 或获取格式化摘要System.out.println(trace.getFormattedHistory());Trace对象提供- 完整的思考/行动/观察历史getFormattedHistory()- 步数和指标getStepCount()、getMetrics()- 工具调用参数和结果- 原始提示词和会话getOriginalPrompt()、getSession()9. 轻量模型的STRUCTURED_TEXT模式不是所有模型都原生支持工具调用。ReActAgent支持 **Text ReAct模式**它通过正则从模型输出的文本中提取 Action: {json} 标签来执行工具这使得它兼容更小、更轻量的模型适合边缘部署和对成本敏感的场景。执行风格ReActStyle在构建时通过 ReActAgentConfig 配置可选择 ReActStyle.NATIVE_TOOL原生工具调用默认和轻量的 ReActStyle.STRUCTURED_TEXT结构化文本。使用STRUCTURED_TEXT模式时Agent从模型输出中解析 Action: {json} 标签并执行对应的工具。完整示例电商支持Agent可直接复制运行的完整代码import org.noear.solon.ai.agent.react.ReActAgent;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.annotation.ToolMapping;import org.noear.solon.ai.annotation.Param;import org.noear.solon.ai.chat.ChatModel;import org.noear.solon.ai.chat.tool.AbsToolProvider;import org.noear.solon.ai.chat.message.ChatMessage;public class ECommerceSupportApp {public static void main(String[] args) throws Throwable {// 1. 构建模型ChatModel model ChatModel.of(https://api.moark.com/v1/chat/completions).apiKey(${API_KEY}).model(Qwen3-32B).build();// 2. 构建AgentReActAgent agent ReActAgent.of(model).name(ecommerce_support).role(电商客服支持Agent).defaultToolAdd(new OrderTool()).defaultToolAdd(new InventoryTool()).defaultInterceptorAdd(new LoggingInterceptor()).defaultInterceptorAdd(new ContextCompressionInterceptor(...)) //【可选】如果轮数过多需要压缩上下文.maxTurns(10).autoRethink(true).build();// 3. 运行String answer agent.prompt(客户想下单SKU-A100但发现ORD-1001还没收到。查一下两个情况给客户解释。).call().getContent();System.out.println(answer);}}// 工具class OrderTool extends AbsToolProvider {ToolMapping(description 根据订单ID查询订单状态)public String getOrderStatus(Param(description 订单ID) String orderId) {return ORD-1001已发货;}}class InventoryTool extends AbsToolProvider {ToolMapping(description 根据SKU查询商品库存)public String checkStock(Param(description 商品SKU) String sku) {return SKU-A10042件库存充足;}}// 拦截器class LoggingInterceptor implements ReActInterceptor {Overridepublic void onThought(ReActTrace trace, String thought,AssistantMessage msg) {System.out.println( thought);}Overridepublic void onAction(ReActTrace trace, ToolExchanger tool) {System.out.println(️ tool.getToolName());}}要点总结1. **ReActAgent** 遵循 **思考 - 行动 - 观察** 循环可实现推理、行动、学习2. **工具** 通过 ToolMapping 和 Param 注解定义就是普通的POJO3. **拦截器** 让你对Agent的决策过程有完整的可观测性4. **单次调用选项** 让你在不重建Agent的前提下灵活调整行为5. **Text ReAct模式** 兼容不支持原生工具调用的轻量模型6. **会话和轨迹** 支持带完整审计日志的持久化对话