第2章 环境搭建与第一个智能体
本章目标:搭建开发环境,运行第一个智能体,理解基本代码结构
2.1 环境准备
2.1.1 JDK 安装
AgentScope-Java 需要 JDK 17 或更高版本。推荐使用以下发行版:
| 发行版 | 推荐指数 | 下载地址 |
|---|---|---|
| Eclipse Temurin | ⭐⭐⭐⭐⭐ | https://adoptium.net/ |
| Amazon Corretto | ⭐⭐⭐⭐⭐ | https://aws.amazon.com/corretto/ |
| Oracle JDK | ⭐⭐⭐⭐ | https://www.oracle.com/java/ |
| GraalVM | ⭐⭐⭐⭐ | https://www.graalvm.org/ |
验证安装:
# 检查 Java 版本
$ java -version
openjdk version "17.0.9" 2023-10-17
OpenJDK Runtime Environment Temurin-17.0.9+9 (build 17.0.9+9)
OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode)
# 确保版本号 >= 17
注意:如果你的系统安装了多个 JDK 版本,请确保
JAVA_HOME指向 JDK 17+。
2.1.2 构建工具
确保安装了 Maven 或 Gradle:
Maven(推荐):
$ mvn -v
Apache Maven 3.9.6
Maven home: /usr/local/maven
Java version: 17.0.9, vendor: Eclipse Adoptium
Gradle:
$ gradle -v
Gradle 8.5
Build time: 2023-11-29 14:08:57 UTC
Kotlin: 1.9.20
2.1.3 获取 API Key
AgentScope 支持多种 LLM 提供商。本教程主要使用 DashScope(阿里云百炼),因为:
- 免费试用额度充足
- 国内访问速度快
- 中文能力优秀
获取 DashScope API Key:
- 访问 阿里云百炼控制台
- 登录或注册阿里云账号
- 进入「API-KEY」页面
- 创建并复制 API Key
设置环境变量:
# Linux/macOS
export DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Windows PowerShell
$env:DASHSCOPE_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Windows CMD
set DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
安全提示:永远不要将 API Key 硬编码在代码中或提交到版本控制系统。
其他提供商的 API Key:
| 提供商 | 环境变量 | 获取地址 |
|---|---|---|
| OpenAI | OPENAIAPIKEY | https://platform.openai.com/api-keys |
| Anthropic | ANTHROPICAPIKEY | https://console.anthropic.com/ |
GOOGLEAPIKEY | https://aistudio.google.com/app/apikey |
2.2 项目配置
2.2.1 创建 Maven 项目
方式一:命令行创建
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=agentscope-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
cd agentscope-demo
方式二:IDE 创建
在 IntelliJ IDEA 或 Eclipse 中创建新的 Maven 项目。
2.2.2 添加依赖
编辑 pom.xml,添加 AgentScope 依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>agentscope-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- ========================================
【JDK 版本配置】
AgentScope 需要 JDK 17+
======================================== -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- ========================================
【AgentScope 核心依赖】
all-in-one 包含:
- agentscope-core: 核心功能
- DashScope SDK: 阿里云模型
- MCP SDK: MCP 协议支持
======================================== -->
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope</artifactId>
<version>1.0.7</version>
</dependency>
<!-- ========================================
【可选:其他模型提供商】
如果需要使用 OpenAI、Anthropic 等
======================================== -->
<!-- OpenAI -->
<!--
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>0.8.0</version>
</dependency>
-->
<!-- ========================================
【日志实现】
AgentScope 使用 SLF4J,需要提供实现
======================================== -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- ========================================
【编译器插件】
启用 -parameters 保留方法参数名
(虽然 AgentScope 不强制要求,但推荐开启)
======================================== -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2.3 Gradle 配置(可选)
如果使用 Gradle,在 build.gradle 中添加:
plugins {
id 'java'
}
group = 'com.example'
version = '1.0-SNAPSHOT'
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
// AgentScope 核心
implementation 'io.agentscope:agentscope:1.0.7'
// 日志实现
implementation 'ch.qos.logback:logback-classic:1.4.14'
}
// 保留方法参数名
tasks.withType(JavaCompile) {
options.compilerArgs += ['-parameters']
}
2.3 Hello World:第一个智能体
2.3.1 最简示例
创建 src/main/java/com/example/HelloAgent.java:
package com.example;
// ========================================
// 【导入说明】
// ========================================
import io.agentscope.core.ReActAgent; // 核心智能体类
import io.agentscope.core.message.Msg; // 消息类
import io.agentscope.core.message.MsgRole; // 消息角色枚举
import io.agentscope.core.message.TextBlock; // 文本内容块
import io.agentscope.core.model.DashScopeChatModel; // DashScope 模型
import java.util.List;
/**
* AgentScope Hello World 示例
*
* 这是最简单的智能体示例,展示了:
* 1. 如何创建模型
* 2. 如何创建智能体
* 3. 如何发送消息并获取响应
*/
public class HelloAgent {
public static void main(String[] args) {
// ========================================
// 【步骤 1】获取 API Key
// ========================================
// 从环境变量读取 API Key,避免硬编码
String apiKey = System.getenv("DASHSCOPE_API_KEY");
// 安全检查:确保 API Key 已设置
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("错误:请设置环境变量 DASHSCOPE_API_KEY");
System.err.println("示例:export DASHSCOPE_API_KEY=sk-xxx");
System.exit(1);
}
// ========================================
// 【步骤 2】创建 LLM 模型
// ========================================
// DashScopeChatModel 是连接阿里云百炼的模型实现
// 使用 Builder 模式配置各项参数
DashScopeChatModel model = DashScopeChatModel.builder()
.apiKey(apiKey) // API 密钥
.modelName("qwen-max") // 模型名称:qwen-max 是通义千问的旗舰模型
.stream(true) // 启用流式输出(可选,提升用户体验)
.build();
// 可选的模型:
// - qwen-max: 最强能力,适合复杂任务
// - qwen-plus: 平衡性能和成本
// - qwen-turbo: 速度最快,成本最低
// ========================================
// 【步骤 3】创建智能体
// ========================================
// ReActAgent 是框架提供的主要智能体实现
// 使用 ReAct 算法:推理(Reasoning) + 行动(Acting) 循环
ReActAgent agent = ReActAgent.builder()
.name("Assistant") // 智能体名称
// - 用于日志和多智能体场景的身份识别
.sysPrompt("你是一个友好的 AI 助手。请用简洁清晰的语言回答问题。")
// 系统提示词
// - 定义智能体的角色和行为
// - 会作为第一条 system 消息发送给 LLM
.model(model) // 关联 LLM 模型
// - 智能体的"大脑"
.build();
// ========================================
// 【步骤 4】构建用户消息
// ========================================
// Msg 是 AgentScope 的核心消息类
// 使用 Builder 模式构建消息内容
Msg userMessage = Msg.builder()
.name("user") // 发送者名称(可选)
.role(MsgRole.USER) // 消息角色:用户消息
.content(List.of( // 消息内容:ContentBlock 列表
TextBlock.builder()
.text("你好!请用一句话介绍一下你自己。")
.build()
))
.build();
// 简化写法:使用 textContent() 快捷方法
// Msg userMessage = Msg.builder()
// .textContent("你好!请用一句话介绍一下你自己。")
// .build();
// ========================================
// 【步骤 5】调用智能体
// ========================================
System.out.println("发送消息: " + userMessage.getTextContent());
System.out.println("等待响应...\n");
// agent.call() 返回 Mono<Msg>(响应式类型)
// .block() 阻塞等待结果(同步调用)
Msg response = agent.call(userMessage).block();
// ========================================
// 【步骤 6】处理响应
// ========================================
if (response != null) {
// getTextContent() 提取所有 TextBlock 的文本内容
String textContent = response.getTextContent();
System.out.println("智能体回复: " + textContent);
// 可选:查看更多响应信息
System.out.println("\n--- 响应详情 ---");
System.out.println("生成原因: " + response.getGenerateReason());
// 如果有 Token 用量信息
if (response.getChatUsage() != null) {
System.out.println("输入 Token: " + response.getChatUsage().getInputTokens());
System.out.println("输出 Token: " + response.getChatUsage().getOutputTokens());
}
} else {
System.err.println("错误:未收到响应");
}
}
}
2.3.2 运行示例
命令行运行:
# 确保设置了环境变量
export DASHSCOPE_API_KEY=sk-xxx
# 编译
mvn compile
# 运行
mvn exec:java -Dexec.mainClass="com.example.HelloAgent"
IDE 运行:
在 IntelliJ IDEA 或 Eclipse 中,右键点击 HelloAgent.java,选择「Run」。
预期输出:
发送消息: 你好!请用一句话介绍一下你自己。
等待响应...
智能体回复: 你好!我是通义千问,一个由阿里云开发的 AI 助手,
随时准备为你解答问题、提供帮助。
--- 响应详情 ---
生成原因: MODEL_STOP
输入 Token: 42
输出 Token: 35
2.4 添加工具能力
仅仅能对话的智能体是不够的。让我们给智能体添加工具调用能力。
2.4.1 定义工具类
创建 src/main/java/com/example/TimeTools.java:
package com.example;
// ========================================
// 【导入说明】
// ========================================
import io.agentscope.core.tool.annotation.Tool;
import io.agentscope.core.tool.annotation.ToolParam;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/**
* 时间相关工具类
*
* 工具类是普通的 Java 类,通过注解声明为工具。
* 智能体可以根据用户需求自动调用这些工具。
*/
public class TimeTools {
// ========================================
// 【工具定义】获取当前时间
// ========================================
@Tool(
name = "get_current_time", // 工具名称:LLM 看到的名称
description = "获取指定时区的当前时间" // 工具描述:帮助 LLM 理解何时使用
)
public String getCurrentTime(
// ========================================
// 【参数定义】
// @ToolParam 的 name 属性是必需的!
// Java 运行时默认不保留参数名,必须显式指定
// ========================================
@ToolParam(
name = "timezone", // 参数名:必须指定
description = "时区,如:Asia/Shanghai, America/New_York, Europe/London",
required = false // 是否必需,默认 true
)
String timezone
) {
// 默认使用上海时区
if (timezone == null || timezone.isEmpty()) {
timezone = "Asia/Shanghai";
}
try {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(timezone));
return now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"));
} catch (Exception e) {
return "无法识别的时区: " + timezone + ",请使用标准时区格式";
}
}
// ========================================
// 【工具定义】计算时间差
// ========================================
@Tool(
name = "get_days_until",
description = "计算从今天到指定日期还有多少天"
)
public String getDaysUntil(
@ToolParam(
name = "target_date",
description = "目标日期,格式:yyyy-MM-dd,如:2024-12-31"
)
String targetDate
) {
try {
var target = java.time.LocalDate.parse(targetDate);
var today = java.time.LocalDate.now();
long days = java.time.temporal.ChronoUnit.DAYS.between(today, target);
if (days > 0) {
return "距离 " + targetDate + " 还有 " + days + " 天";
} else if (days < 0) {
return targetDate + " 已经过去了 " + (-days) + " 天";
} else {
return "今天就是 " + targetDate + "!";
}
} catch (Exception e) {
return "日期格式错误,请使用 yyyy-MM-dd 格式";
}
}
}
2.4.2 创建带工具的智能体
创建 src/main/java/com/example/ToolAgent.java:
package com.example;
import io.agentscope.core.ReActAgent;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.tool.Toolkit;
import java.util.Scanner;
/**
* 带工具能力的智能体示例
*
* 展示了:
* 1. 如何定义和注册工具
* 2. 智能体如何自动选择和调用工具
* 3. 交互式对话
*/
public class ToolAgent {
public static void main(String[] args) {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("请设置环境变量 DASHSCOPE_API_KEY");
System.exit(1);
}
// ========================================
// 【步骤 1】创建模型
// ========================================
DashScopeChatModel model = DashScopeChatModel.builder()
.apiKey(apiKey)
.modelName("qwen-max")
.stream(true)
.build();
// ========================================
// 【步骤 2】创建工具包并注册工具
// ========================================
// Toolkit 是工具的容器,管理所有可用工具
Toolkit toolkit = new Toolkit();
// registerTool() 扫描类中的 @Tool 注解方法
// 自动注册为可用工具
toolkit.registerTool(new TimeTools());
// 可以注册多个工具类
// toolkit.registerTool(new CalculatorTools());
// toolkit.registerTool(new SearchTools());
// ========================================
// 【步骤 3】创建带工具的智能体
// ========================================
ReActAgent agent = ReActAgent.builder()
.name("TimeAssistant")
.sysPrompt("""
你是一个时间助手,可以:
1. 查询世界各地的当前时间
2. 计算距离某个日期还有多少天
当用户询问时间相关问题时,请使用提供的工具获取准确信息。
回答要简洁明了。
""")
.model(model)
.toolkit(toolkit) // 关联工具包
.maxIters(5) // 最大迭代次数(防止无限循环)
.build();
// ========================================
// 【步骤 4】交互式对话
// ========================================
System.out.println("=".repeat(50));
System.out.println("时间助手已启动!");
System.out.println("示例问题:");
System.out.println(" - 现在北京时间几点?");
System.out.println(" - 纽约现在几点?");
System.out.println(" - 距离2025年还有多少天?");
System.out.println("输入 'exit' 退出");
System.out.println("=".repeat(50));
System.out.println();
try (Scanner scanner = new Scanner(System.in)) {
while (true) {
System.out.print("你: ");
String input = scanner.nextLine().trim();
if (input.isEmpty()) {
continue;
}
if ("exit".equalsIgnoreCase(input)) {
System.out.println("再见!");
break;
}
try {
// 发送消息并获取响应
Msg response = agent.call(
Msg.builder().textContent(input).build()
).block();
if (response != null) {
System.out.println("助手: " + response.getTextContent());
}
} catch (Exception e) {
System.err.println("错误: " + e.getMessage());
}
System.out.println();
}
}
}
}
2.4.3 运行测试
mvn exec:java -Dexec.mainClass="com.example.ToolAgent"
对话示例:
==================================================
时间助手已启动!
示例问题:
- 现在北京时间几点?
- 纽约现在几点?
- 距离2025年还有多少天?
输入 'exit' 退出
==================================================
你: 现在北京时间几点?
助手: 北京时间现在是 2024-03-15 14:30:25 CST。
你: 纽约现在是几点?
助手: 纽约现在是 2024-03-15 02:30:30 EDT。
你: 距离今年国庆节还有多少天?
助手: 距离 2024-10-01 还有 200 天。
你: exit
再见!
2.5 理解 ReAct 循环
2.5.1 什么是 ReAct
ReAct(Reasoning + Acting)是当前最流行的智能体设计模式。它的核心思想是:
观察(Observation) → 思考(Reasoning) → 行动(Acting) → 循环
在 AgentScope 中,ReAct 循环的工作流程是:
┌─────────────────────────────────────────────────────────────┐
│ ReAct 循环 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户输入 │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 推理阶段 │ LLM 分析: │
│ │ (Reasoning) │ - 理解用户意图 │
│ │ │ - 决定是否需要调用工具 │
│ │ │ - 选择合适的工具和参数 │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ 需要工具? │ │
│ └────┬─────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ │ │ │
│ 是 否 │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 行动阶段 │ │ 生成回复 │ │
│ │ (Acting) │ │ │ │
│ │ │ │ 返回给 │ │
│ │ 执行工具 │ │ 用户 │ │
│ └────┬─────┘ └──────────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ 工具结果 │ │
│ │ 存入记忆 │ │
│ └────┬─────┘ │
│ │ │
│ └───────────────────┐ │
│ ▼ │
│ 返回推理阶段 │
│ │
└─────────────────────────────────────────────────────────────┘
2.5.2 观察 ReAct 过程
添加一个简单的日志 Hook 来观察 ReAct 过程:
import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import io.agentscope.core.hook.PreReasoningEvent;
import io.agentscope.core.hook.PostReasoningEvent;
import io.agentscope.core.hook.PreActingEvent;
import io.agentscope.core.hook.PostActingEvent;
import io.agentscope.core.message.ToolUseBlock;
import reactor.core.publisher.Mono;
import java.util.List;
/**
* 日志 Hook:观察 ReAct 循环过程
*/
public class LoggingHook implements Hook {
@Override
public <T extends HookEvent> Mono<T> onEvent(T event) {
// ========================================
// 【推理阶段开始】
// ========================================
if (event instanceof PreReasoningEvent e) {
System.out.println("\n[推理开始] 输入消息数: " +
e.getInputMessages().size());
}
// ========================================
// 【推理阶段结束】
// ========================================
if (event instanceof PostReasoningEvent e) {
var msg = e.getReasoningMessage();
List<ToolUseBlock> tools = msg.getContentBlocks(ToolUseBlock.class);
if (tools.isEmpty()) {
System.out.println("[推理完成] 直接生成回复");
} else {
System.out.println("[推理完成] 决定调用 " + tools.size() + " 个工具:");
for (ToolUseBlock tool : tools) {
System.out.println(" - " + tool.getName() +
"(" + tool.getInput() + ")");
}
}
}
// ========================================
// 【行动阶段开始】
// ========================================
if (event instanceof PreActingEvent e) {
System.out.println("[执行工具] " + e.getToolUse().getName());
}
// ========================================
// 【行动阶段结束】
// ========================================
if (event instanceof PostActingEvent e) {
System.out.println("[工具结果] " +
e.getToolResult().getTextContent().substring(0,
Math.min(50, e.getToolResult().getTextContent().length())) +
"...");
}
return Mono.just(event);
}
}
在创建智能体时添加 Hook:
ReActAgent agent = ReActAgent.builder()
.name("TimeAssistant")
.sysPrompt("...")
.model(model)
.toolkit(toolkit)
.hooks(List.of(new LoggingHook())) // 添加 Hook
.build();
输出示例:
你: 纽约现在几点?
[推理开始] 输入消息数: 2
[推理完成] 决定调用 1 个工具:
- get_current_time({"timezone":"America/New_York"})
[执行工具] get_current_time
[工具结果] 2024-03-15 02:30:30 EDT...
[推理开始] 输入消息数: 4
[推理完成] 直接生成回复
助手: 纽约现在是凌晨 2:30(东部时间)。
2.6 本章小结
本章我们完成了:
- 环境搭建
- 安装 JDK 17+ - 配置 Maven/Gradle - 获取 API Key
- 项目配置
- 添加 AgentScope 依赖 - 配置编译选项
- 第一个智能体
- 创建模型和智能体 - 发送消息获取响应 - 理解基本代码结构
- 添加工具能力
- 使用 @Tool 和 @ToolParam 注解 - 注册工具到 Toolkit - 交互式对话
- 理解 ReAct 循环
- 推理 + 行动的循环模式 - 使用 Hook 观察执行过程
练习
- 修改系统提示:尝试修改 sysPrompt,观察智能体行为变化
- 添加新工具:实现一个计算器工具,支持加减乘除
- 尝试其他模型:将
qwen-max改为qwen-plus,比较响应速度 - 观察 Token 用量:记录不同对话的 Token 消耗
常见问题
Q: 运行时报错 "DASHSCOPEAPIKEY not found"
A: 确保正确设置了环境变量。在 IDE 中可能需要在运行配置中单独设置。
Q: 工具没有被调用
A: 检查:
- @ToolParam 的 name 是否正确设置
- 工具描述是否清晰,让 LLM 知道何时使用
- 用户问题是否与工具相关
Q: 响应很慢
A:
- 首次调用可能较慢(建立连接)
- 尝试使用
qwen-turbo模型 - 检查网络连接
下一章 → 第3章 消息系统