Agent Scope Java 2.x 系列【3】从零构建 ReActAgent

文章目录

  • [1. 概述](#1. 概述)
  • [2. 环境准备](#2. 环境准备)
    • [2.1 Maven 依赖](#2.1 Maven 依赖)
    • [2.2 API Key](#2.2 API Key)
  • [3. ReActAgent 架构](#3. ReActAgent 架构)
    • [3.1 三种调用方式](#3.1 三种调用方式)
    • [3.2 Builder 核心参数](#3.2 Builder 核心参数)
  • [4. 第一步:创建模型](#4. 第一步:创建模型)
  • [5. 第二步:定义工具](#5. 第二步:定义工具)
    • [5.1 注解方式](#5.1 注解方式)
    • [5.2 接口方式](#5.2 接口方式)
  • [6. 第三步:注册工具到 Toolkit](#6. 第三步:注册工具到 Toolkit)
  • [7. 第四步:构建 ReActAgent](#7. 第四步:构建 ReActAgent)
  • [8. 第五步:调用 Agent](#8. 第五步:调用 Agent)
    • [8.1 同步调用](#8.1 同步调用)
    • [8.2 流式调用(2.0 新 API)](#8.2 流式调用(2.0 新 API))
    • [8.3 多轮对话(带 RuntimeContext)](#8.3 多轮对话(带 RuntimeContext))
  • [9. 完整 Spring Boot 示例](#9. 完整 Spring Boot 示例)
    • [9.1 配置类](#9.1 配置类)
    • [9.2 控制器](#9.2 控制器)

1. 概述

ReActAgentAgentScope 2.0 的核心推理引擎,实现 ReAct(Reasoning + Acting) 模式------交替进行推理和工具调用,直到得出最终答案。

智能体在每次调用时运行推理-行动循环,下图展示了主要控制流程:


2. 环境准备


2.1 Maven 依赖

xml 复制代码
<properties>
    <agentscope.version>2.0.0-RC2</agentscope.version>
</properties>

<dependencies>
    <!-- AgentScope 2.0 核心(含 ReActAgent + Model + Toolkit) -->
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-core</artifactId>
        <version>${agentscope.version}</version>
    </dependency>

    <!-- Spring Boot Web(提供 REST 端点) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.5.11</version>
    </dependency>
</dependencies>

2.2 API Key

bash 复制代码
export DASHSCOPE_API_KEY=sk-your-key-here

3. ReActAgent 架构

复制代码
                         ReActAgent
                             │
              ┌──────────────┼──────────────┐
              │              │              │
           Model         Toolkit      AgentStateStore
        (推理引擎)      (工具注册表)     (状态持久化,可选)
              │              │
    ┌─────────┼─────────┐    │
    │         │         │    │
  call()  stream()  streamEvents()    ← 三种调用方式
              │
    ┌─────────┴─────────┐
    │   doCall(msgs)    │    ← 核心推理循环
    │                    │
    │  while (未完成):     │
    │    1. reasoning()   │   → Model.stream()
    │    2. acting()      │   → Toolkit.callTools()
    │    3. summarizing() │   → 上下文压缩(可选)
    └────────────────────┘

3.1 三种调用方式

方法 返回类型 适用场景
call(List<Msg>) Mono<Msg> 同步等待完整结果
stream(List<Msg>, StreamOptions) Flux<Event> 流式观察(2.0 已废弃)
streamEvents(List<Msg>) Flux<AgentEvent> 2.0 新 API------27 种细粒度事件

3.2 Builder 核心参数

java 复制代码
ReActAgent agent = ReActAgent.builder()
    .name("my-agent")                    // Agent 名称(必填)
    .model(model)                        // 语言模型(必填)
    // 或字符串形式:.model("dashscope:qwen-max")
    .sysPrompt("你是一个有用的助手")      // 系统提示词
    .maxIters(10)                        // 最大推理轮次(默认 10)
    .toolkit(toolkit)                    // 工具注册表(可选)
    .middleware(myMiddleware)            // 中间件(可选,可多次调用)
    .hook(myHook)                        // Hook(可选,兼容 1.x)
    .stateStore(redisStore)              // 状态持久化(可选,默认内存)
    .defaultSessionId("default")         // 默认会话 ID
    .modelExecutionConfig(execConfig)    // 模型调用执行策略
    .toolExecutionConfig(toolExecConfig) // 工具执行策略
    .build();

4. 第一步:创建模型

java 复制代码
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.model.Model;

// 方式1:直接构造
Model model = DashScopeChatModel.builder()
    .apiKey(System.getenv("DASHSCOPE_API_KEY"))
    .modelName("qwen-plus")
    .build();

// 方式2:ModelRegistry 自动解析(自动读取环境变量)
Model model = ModelRegistry.resolve("dashscope:qwen-plus");

5. 第二步:定义工具

AgentScope 2.0 支持两种工具定义方式:


5.1 注解方式

java 复制代码
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;

public class WeatherTool {

    @Tool(name = "get_weather", description = "获取指定城市的天气信息")
    public String getWeather(
            @ToolParam(name = "city", description = "城市名称", required = true)
            String city) {
        return String.format("城市: %s, 温度: 22°C, 天气: 晴", city);
    }
}

5.2 接口方式

java 复制代码
import io.agentscope.core.tool.AgentTool;
import io.agentscope.core.tool.ToolCallParam;
import io.agentscope.core.message.ToolResultBlock;

public class CalculatorTool implements AgentTool {
    @Override
    public String getName() { return "calculator"; }

    @Override
    public String getDescription() { return "执行数学计算"; }

    @Override
    public ToolResultBlock call(ToolCallParam param) {
        String expr = param.getArguments().get("expression").asText();
        double result = eval(expr);
        return ToolResultBlock.builder()
            .toolUseId(param.getToolUseId())
            .content("计算结果: " + result)
            .build();
    }
}

6. 第三步:注册工具到 Toolkit

java 复制代码
import io.agentscope.core.tool.Toolkit;

WeatherTool weatherTool = new WeatherTool();
CalculatorTool calcTool = new CalculatorTool();

Toolkit toolkit = new Toolkit();
toolkit.registerTool(weatherTool);  // 自动扫描 @Tool 注解
toolkit.registerAgentTool(calcTool); // 手动注册 AgentTool

7. 第四步:构建 ReActAgent

java 复制代码
ReActAgent agent = ReActAgent.builder()
    .name("weather-assistant")
    .description("天气查询助手")
    .model(model)             // 或 .model("dashscope:qwen-plus")
    .toolkit(toolkit)
    .sysPrompt("你是一个天气助手,使用 get_weather 工具回答天气问题。用中文回复。")
    .maxIters(5)
    .build();

8. 第五步:调用 Agent


8.1 同步调用

java 复制代码
Msg userMsg = Msg.builder()
    .role(MsgRole.USER)
    .content(List.of(TextBlock.builder().text("北京今天天气怎么样?").build()))
    .build();

// 阻塞等待结果
Msg result = agent.call(List.of(userMsg)).block();
System.out.println(result.getTextContent());

8.2 流式调用(2.0 新 API)

java 复制代码
agent.streamEvents(List.of(userMsg))
    .subscribe(event -> {
        if (event instanceof TextBlockDeltaEvent e) {
            System.out.print(e.getDelta());       // 逐 token 打印
        } else if (event instanceof ToolCallStartEvent e) {
            System.out.println("\n[调用工具: " + e.getToolName() + "]");
        } else if (event instanceof ToolResultTextDeltaEvent e) {
            System.out.print(e.getDelta());
        }
    });

8.3 多轮对话(带 RuntimeContext)

java 复制代码
RuntimeContext ctx = RuntimeContext.builder()
    .sessionId("session-001")
    .userId("alice")
    .build();

// 第一轮
Msg msg1 = Msg.builder().role(MsgRole.USER)
    .content(List.of(TextBlock.builder().text("我叫张三").build())).build();
agent.call(List.of(msg1), ctx).block();

// 第二轮------Agent 记住了名字
Msg msg2 = Msg.builder().role(MsgRole.USER)
    .content(List.of(TextBlock.builder().text("我叫什么名字?").build())).build();
Msg reply = agent.call(List.of(msg2), ctx).block();
System.out.println(reply.getTextContent());  // "你叫张三"

9. 完整 Spring Boot 示例


9.1 配置类

java 复制代码
@Configuration
public class AgentConfig {

    @Value("${DASHSCOPE_API_KEY}")
    private String apiKey;

    @Bean
    public Model model() {
        return DashScopeChatModel.builder()
            .apiKey(apiKey).modelName("qwen-plus").build();
    }

    @Bean
    public Toolkit toolkit(WeatherTool weatherTool) {
        Toolkit tk = new Toolkit();
        tk.registerTool(weatherTool);
        return tk;
    }

    @Bean
    public ReActAgent agent(Model model, Toolkit toolkit) {
        return ReActAgent.builder()
            .name("demo-agent")
            .model(model)
            .toolkit(toolkit)
            .sysPrompt("你是一个有用的 AI 助手,用中文回答。")
            .maxIters(5)
            .build();
    }
}

9.2 控制器

java 复制代码
@RestController
public class AgentController {

    private final ReActAgent agent;

    // 同步
    @GetMapping("/call")
    public Mono<Map<String, Object>> call(@RequestParam String query) {
        Msg msg = Msg.builder().role(MsgRole.USER)
            .content(List.of(TextBlock.builder().text(query).build())).build();
        return agent.call(List.of(msg))
            .map(r -> Map.of("query", query, "response", r.getTextContent()));
    }

    // 流式
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream(@RequestParam String query) {
        Msg msg = Msg.builder().role(MsgRole.USER)
            .content(List.of(TextBlock.builder().text(query).build())).build();
        return agent.streamEvents(List.of(msg))
            .filter(e -> e instanceof TextBlockDeltaEvent)
            .map(e -> "data: " + ((TextBlockDeltaEvent) e).getDelta() + "\n\n");
    }
}

相关推荐
tedcloud1231 天前
taste-skill部署教程:打造个性化AI推荐工作流
服务器·前端·人工智能·系统架构·edge
碳基硅坊1 天前
把本地入口接上远端算力:读懂 LM Studio 的 LM Link
人工智能·lm studio·lm link
莱歌数字1 天前
换热器计算方法与步骤:从热平衡到性能校核
人工智能·科技·制造·cae·散热
小鹿研究点东西1 天前
AI直播工具实操:从直播录制、AI剪辑去重到直播伴侣开播完整流程
人工智能·自动化·音视频·语音识别
碳基硅坊1 天前
Spring AI:把大模型接进 Spring 应用
java·人工智能·spring ai
才兄说1 天前
机器人二次开发机器狗巡检?全环境稳定感知
人工智能·机器人
黄毛火烧雪下1 天前
Java 核心知识点总结(一)
java·开发语言
一一哥Sun1 天前
第06课:Transformer与注意力机制——大模型背后的秘密武器
人工智能·深度学习·transformer
landyjzlai1 天前
蓝迪哥玩转Ai(10)---Harness工程说透1。
人工智能·harness
onething3651 天前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 3 —— 消息表设计 + 级联删除 + 事务管理
人工智能·后端