
今天带大家从零开始,用最简单的方式构建一个会说双关语的智能天气助手。不需要复杂的AI知识,跟着教程走,你也能做出来!
想象一下,你有个私人助理,不仅能回答问题,还能主动调用工具、查询数据、记住你们的对话历史。这就是Agent——比普通AI聊天机器人更强大的智能体。
今天我们要做的天气Agent有这些超能力:
听起来很酷吧?其实实现起来一点都不难!
在你的pom.xml文件中加入:
<!-- 如果用阿里云DashScope -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.1.0.0-RC2</version>
</dependency>
<!-- 如果用OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.1.0</version>
</dependency>就像给员工写岗位说明书,我们要告诉AI它是谁、能做什么:
String SYSTEM_PROMPT = """
你是一位资深气象专家,特别喜欢用双关语说话。
你可以使用两个工具:
• get_weather_for_location: 查询指定城市的天气
• get_user_location: 获取用户所在位置
当用户问天气时,一定要先确认位置。
如果用户说"这里"、"我这边"等模糊词,
就用get_user_location工具查询用户位置。
""";小贴士: System Prompt要写得具体明确,就像教小孩做事一样,越详细越好!
Agent之所以强大,就在于它会使用工具。我们给它准备两个工具:
工具1: 天气查询工具
public class WeatherForLocationTool implements BiFunction<String, ToolContext, String> {
@Override
public String apply(
@ToolParam(description = "城市名称") String city,
ToolContext toolContext) {
// 这里可以接入真实的天气API
// 现在先返回模拟数据
return city + "今天阳光明媚,气温25度!";
}
}工具2: 用户定位工具(这个厉害了,能读取运行时上下文!)
public class UserLocationTool implements BiFunction<String, ToolContext, String> {
@Override
public String apply(
@ToolParam(description = "用户查询") String query,
ToolContext toolContext) {
// 从上下文中获取用户ID
String userId = "";
if (toolContext != null && toolContext.getContext() != null) {
RunnableConfig config = (RunnableConfig)
toolContext.getContext().get(AGENT_CONFIG_CONTEXT_KEY);
Optional<Object> userIdObj = config.metadata("user_id");
if (userIdObj.isPresent()) {
userId = (String) userIdObj.get();
}
}
// 根据用户ID返回位置(实际应用中从数据库查询)
return "1".equals(userId) ? "深圳" : "北京";
}
}注册工具:
ToolCallback weatherTool = FunctionToolCallback
.builder("getWeatherForLocation", new WeatherForLocationTool())
.description("查询指定城市的天气情况")
.inputType(String.class)
.build();
ToolCallback locationTool = FunctionToolCallback
.builder("getUserLocation", new UserLocationTool())
.description("根据用户ID获取用户位置")
.inputType(String.class)
.build();关键点: 工具的名称、描述都会成为AI提示的一部分,写清楚能让AI更准确地判断何时使用!
// 以阿里云DashScope为例
DashScopeApi dashScopeApi = DashScopeApi.builder()
.apiKey(System.getenv("AI_DASHSCOPE_API_KEY")) // 从环境变量读取
.build();
ChatModel chatModel = DashScopeChatModel.builder()
.dashScopeApi(dashScopeApi)
.defaultOptions(DashScopeChatOptions.builder()
.withModel(DashScopeChatModel.DEFAULT_MODEL_NAME)
.withTemperature(0.5) // 控制回答的创造性,0-1之间
.withMaxToken(1000) // 限制回答长度
.build())
.build();参数解释:
temperature: 0接近精确,1更有创意。天气查询用0.5刚好maxToken: 防止回答太长,浪费成本让AI的回答结构化,方便前端展示:
public class ResponseFormat {
// 必须有的双关语回复
private String punnyResponse;
// 天气详情(如果有的话)
private String weatherConditions;
// Getters和Setters
public String getPunnyResponse() {
return punnyResponse;
}
public void setPunnyResponse(String punnyResponse) {
this.punnyResponse = punnyResponse;
}
public String getWeatherConditions() {
return weatherConditions;
}
public void setWeatherConditions(String weatherConditions) {
this.weatherConditions = weatherConditions;
}
}没有记忆的AI就像金鱼,聊完就忘。加上记忆后,它能记住你们的对话:
// 创建Agent时加入记忆组件
ReactAgent agent = ReactAgent.builder()
.name("weather_agent")
.saver(new MemorySaver()) // 内存存储,简单快速
.build();使用记忆的秘诀:
// 用同一个threadId,Agent就能记住之前的对话
String threadId = "user_123_chat";
RunnableConfig config = RunnableConfig.builder()
.threadId(threadId)
.build();
// 第一次问
agent.call("深圳今天天气怎么样?", config);
// 第二次问(注意用同一个threadId)
agent.call("明天呢?", config);
// Agent知道你问的是深圳明天的天气!生产环境提醒: MemorySaver只存在内存中,服务重启就没了。真实项目要用数据库持久化!
万事俱备,现在把所有组件组装起来:
// 创建你的智能天气助手
ReactAgent agent = ReactAgent.builder()
.name("weather_pun_agent") // 给Agent起个名字
.model(chatModel) // 配置的AI模型
.systemPrompt(SYSTEM_PROMPT) // Agent人设
.tools(locationTool, weatherTool) // 提供的工具
.outputType(ResponseFormat.class) // 输出格式
.saver(new MemorySaver()) // 记忆组件
.build();
// 开始对话!
String threadId = "chat_001";
RunnableConfig config = RunnableConfig.builder()
.threadId(threadId)
.addMetadata("user_id", "1") // 传入用户ID
.build();
// 第一轮对话
AssistantMessage response = agent.call("外面天气怎么样?", config);
System.out.println(response.getText());
// 可能输出: "深圳今天'晴'有独钟!阳光明媚25度,
// 简直是'天气晴郎'的好时'光'啊!"
// 继续对话
response = agent.call("谢谢!", config);
System.out.println(response.getText());
// 可能输出: "不'客气',能为您'预'报天气是我的'荣'幸!"看到双关语回复了吗?这就是你的AI Agent在工作:
除了用Java类,还可以直接定义JSON格式:
String customSchema = """
请按以下JSON格式输出:
{
"title": "标题",
"content": "内容",
"style": "风格"
}
""";
ReactAgent agent = ReactAgent.builder()
.outputSchema(customSchema)
.build();想看Agent内部发生了什么?用invoke方法:
Optional<OverAllState> result = agent.invoke("帮我查天气");
if (result.isPresent()) {
OverAllState state = result.get();
// 查看所有消息历史
List<Message> messages = state.value("messages", new ArrayList<>());
// 调试神器!
System.out.println("Agent内部状态: " + state);
}加个保险栓,限制最多调用次数:
ModelCallLimitHook hook = ModelCallLimitHook.builder()
.runLimit(5) // 最多调5次模型
.exitBehavior(ModelCallLimitHook.ExitBehavior.ERROR)
.build();
ReactAgent agent = ReactAgent.builder()
.hooks(hook)
.build();让重要操作需要人工确认:
Hook humanApproval = HumanInTheLoopHook.builder()
.approvalOn("getWeatherTool",
ToolConfig.builder()
.description("是否允许查询天气?")
.build())
.build();
ReactAgent agent = ReactAgent.builder()
.hooks(humanApproval)
.build();想看更多完整示例?访问阿里官方仓库: 👉 https://github.com/spring-ai-alibaba/examples
通过这个教程,你掌握了Agent开发的核心概念:
✅ System Prompt - 定义AI的角色和能力 ✅ 工具创建 - 让AI能调用外部功能 ✅ 模型配置 - 选择和调优AI模型 ✅ 结构化输出 - 让回答格式可控 ✅ 对话记忆 - 实现连续对话能力 ✅ 完整构建 - 从零到一搭建Agent
欢迎在评论区留言,我会第一时间回复!
觉得有用就点个赞吧! 👍 关注我,下期教你如何把Agent部署到生产环境!
#AI开发 #SpringAI #Agent #Java #人工智能