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");
    }
}

相关推荐
怕浪猫1 天前
第1章:认识 DeepSeek Harness——一个插件化的 Agent Runtime 平台
agent·natural language toolkit·deepseek
Henry-SAP1 天前
SAP引领ERP智能化转型
人工智能·云原生·sap·erp
峥嵘life1 天前
Android16 311Y3 EAP-TLS 网络连接失败分析与修复总结
android·开发语言·人工智能·php
M-Robots echo1 天前
轻量化裁剪方案解析:M-Robots 模块化构建,适配高低端各类机器人硬件平台
java·机器人·ros·开源社区·atomgit·m-robots
特立独行的猫a1 天前
一切皆插件:DeepSeek Harness 的架构哲学,以及与主流 Agent 的对比
人工智能·架构·agent·deepseek·harness
电商API_180079052471 天前
京东商品详情API技术文章
大数据·运维·人工智能·网络爬虫
不可求~1 天前
多模型路由怎么落地:把任务分流写进项目的最小实现
java·前端·数据库
fīɡЙtīиɡ ℡1 天前
AI Agent 记忆系统
人工智能
mldong1 天前
用 DDD 设计工作流引擎:聚合根与充血模型
java·架构
企鹅的企1 天前
2027北京AI数字健康与智慧医疗展官方:超两成展品亚洲首秀
人工智能·科技·机器人