Spring AI Alibaba智能体Agent实战教程
前言
大语言模型(LLM)技术这几年突飞猛进,构建一个能干活儿的智能Agent应用,门槛已经低了很多。今天就用两个真实的代码实例,来拆解如何用Spring AI Alibaba框架打造一个能查天气的Agent——从最基础的测试版本,一路演进到生产级别的完整应用。
技术栈概述
- Spring AI Alibaba:阿里巴巴开源的一套AI应用开发框架,把模型调用、工具编排这些事儿都封装好了。
- DashScope:阿里云的AI模型服务平台,负责给Agent提供推理能力。
- React Agent:基于ReAct(Reasoning and Acting)范式的智能袋里,边思考边行动,很实用。
示例一:SimpleTest - 快速入门
添加核心依赖
先把依赖加上,Ma ven里加这么几行就行:
com.alibaba.cloud.ai spring-ai-alibaba-agent-framework 1.1.2.0 com.alibaba.cloud.ai spring-ai-alibaba-starter-dashscope 1.1.2.0
代码结构分析
来看一段最精简的单元测试代码,感受一下整个流程是怎么串起来的:
@Test
void agentTest() throws GraphRunnerException {
// 1. 初始化 DashScope API
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AliQwen_API"))
.build();
// 2. 创建 ChatModel
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.build();
// 3. 定义天气工具
ToolCallback weatherTool = FunctionToolCallback.builder("get_weather", new WeatherTool())
.description("获取某个城市的天气")
.inputType(String.class)
.build();
// 4. 构建React Agent
ReactAgent agent = ReactAgent.builder()
.name("weather_agent")
.model(chatModel)
.tools(weatherTool)
.systemPrompt("你是一个非常有帮助的助手")
.sa ver(new MemorySa ver())
.build();
// 5. 调用Agent
AssistantMessage response = agent.call("上海今天天气怎么样?");
System.out.println(response.getText());
}
这段代码虽然简单,但核心流程一个没少:初始化模型 → 定义工具 → 组装Agent → 调用。Builder模式用得很舒服,代码可读性很高。
核心特性
- 简洁的配置:Builder模式一气呵成,不用写一堆XML或者配置类。
- 工具集成:
FunctionToolCallback把普通的Ja va函数包装成Agent可以调用的工具,设计很优雅。 - 内存存储:
MemorySa ver负责保存对话历史,保证多轮对话的连贯性。 - 中文支持:提示词和工具描述可以直接用中文,省去了翻译的麻烦。
自定义工具实现
那这个WeatherTool长什么样?其实就是一个实现了BiFunction接口的简单类:
class WeatherTool implements BiFunction {
@Override
public String apply(String city, ToolContext toolContext) {
return city + "今天天气非常好!";
}
}
这个工具类目前只是返回一句固定的话,但已经能看出业务逻辑如何被封装成Agent可调用的函数了。后面换成真实API调用,就是一个完整的能力。
示例二:RealAgent - 真实的智能体
如果说SimpleTest是上手指南,那RealAgent就是实战练兵。它展示了几个生产环境才用得到的特性:精细的模型配置、多工具协同、结构化输出、对话上下文管理。
系统提示词设计
先说提示词,这是Agent的“人设”和“行为准则”:
String SYSTEM_PROMPT = """
你是一位擅长说**天气冷笑话/谐音梗**的专业天气预报员。
你可以使用两个工具:
- **get_weather_for_location**:用于获取指定地点的天气
- **get_user_location**:用于获取用户当前所在位置
如果用户询问天气,**必须先确认地点**。如果从问题中能判断出他们指的是**自己所在的地方**,就使用 **get_user_location** 工具获取他们的位置。
""";
这里面有几个设计要点值得注意:
- 角色定位:给Agent一个鲜明的身份(天气预报员+冷幽默),输出会更有趣。
- 工具说明:两句话就把两个工具的区别说清楚了。
- 行为约束:规定先确认地点、再调用工具的顺序,避免了Agent胡乱猜测。
模型参数优化
生产环境不能什么参数都用默认值。这里是一个实用的配置示例:
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
.model(DashScopeChatModel.DEFAULT_MODEL_NAME)
.temperature(0.5) // 平衡创造性和准确性
.maxToken(1000) // 控制响应长度
.build())
.build();
temperature设为0.5,既不会太死板,也不会天马行空;maxToken定在1000,响应长度足够又不会浪费token。
多工具协同
这个Agent有两个工具,一个查天气,一个获取用户位置:
// 天气查询工具
ToolCallback getWeatherTool = FunctionToolCallback.builder("getWeatherForLocation", new WeatherForLocationTool())
.description("获取一个给定城市的天气")
.inputType(String.class)
.build();
// 用户定位工具
ToolCallback getUserLocationTool = FunctionToolCallback.builder("getUserLocation", new UserLocationTool())
.description("根据User Id获取用户位置")
.inputType(String.class)
.build();
两个工具配合使用,用户说“帮我查查天气”,Agent会先调用定位工具拿到城市,再调用天气工具获取数据,整个流程自动完成。
结构化输出配置
为了让Agent的返回更规范,可以指定输出格式:
ReactAgent agent = ReactAgent.builder()
// ... 其他配置
.outputType(ResponseFormat.class) // 指定输出格式
.hooks(humanInTheLoopHook)
.build();
这样Agent返回的内容就会按照ResponseFormat的结构来,方便下游程序解析。
对话上下文管理
多轮对话怎么保持“记忆”?这里通过RunnableConfig的threadId来做:
RunnableConfig runnableConfig = RunnableConfig.builder()
.threadId(Thread.currentThread().getId() + "")
.build();
// 第一次调用
AssistantMessage response1 = agent.call("上海今天天气怎么样", runnableConfig);
// 第二次调用(保持上下文)
AssistantMessage response2 = agent.call("明天天气怎么样", runnableConfig);
同一个threadId意味着Agent知道之前的对话历史,第二次问“明天天气怎么样”,它能自动理解指的是上海的明天。
总结
两个示例,两种视角。SimpleTest像是“第一块积木”,五步搭建一个能跑的Agent,适合快速验证想法或者入门学习;RealAgent则更像是“工具箱”,把模型调参、多工具编排、结构化输出、上下文管理这些生产级特性都整合在了一起。
如果你已经跑通了这两个例子,接下来可以尝试:
- 集成更多的工具(比如数据库查询、消息推送)
- 换用不同的Checkpoint实现来持久化对话(比如Redis或者数据库)
- 利用Hooks扩展Agent行为(比如日志、限流、人工审核)
- 构建多Agent协作系统——一个负责规划,一个负责执行,一个负责校验
参考资料
- Spring AI Alibaba官方文档
- DashScope平台
