)
Spring AI Function Calling实战5分钟构建智能天气查询系统天气预报总是让人又爱又恨——我们依赖它却又常常质疑它的准确性。想象一下当你正在开发一个智能客服系统用户随口问道明天旧金山会下雨吗而你的AI助手不仅能理解问题还能实时查询天气数据给出精确回答。这就是Spring AI的Function Calling功能赋予我们的魔法。1. 环境准备与基础配置在开始编码之前我们需要确保开发环境准备就绪。与大多数Spring Boot项目类似我们需要先初始化项目基础结构。首先使用Spring Initializr创建项目添加以下关键依赖dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId version0.8.0/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency /dependencies对于IDE的选择我强烈推荐IntelliJ IDEA它对Spring Boot和AI相关开发有着出色的支持。在项目配置方面我们需要在application.properties中添加OpenAI的API密钥spring.ai.openai.api-keyyour-api-key-here提示实际开发中应该使用环境变量或配置中心来管理敏感信息避免将API密钥直接写入配置文件2. 核心架构设计我们的天气查询机器人需要三个核心组件协同工作AI模型交互层负责与大型语言模型通信函数调用层处理模型发起的函数调用请求数据服务层提供实际的天气数据查询能力这种分层架构设计带来了几个显著优势各层职责明确便于维护可以独立替换或升级某一层实现更容易编写单元测试让我们先定义数据服务层的接口public interface WeatherService { WeatherData getCurrentWeather(String location, TemperatureUnit unit); } public enum TemperatureUnit { CELSIUS, FAHRENHEIT } public record WeatherData(double temperature, TemperatureUnit unit, String condition) {}3. 实现Function CallingSpring AI使函数调用变得异常简单。我们只需要定义一个标准的Java函数然后通过注解告诉AI模型何时使用它。首先创建我们的Mock天气服务实现public class MockWeatherService implements FunctionWeatherRequest, WeatherResponse { public record WeatherRequest(String location, TemperatureUnit unit) {} public record WeatherResponse(double temp, TemperatureUnit unit, String condition) {} Override public WeatherResponse apply(WeatherRequest request) { // 模拟不同城市的天气数据 MapString, Double mockTemps Map.of( san francisco, 18.5, tokyo, 23.0, paris, 16.8 ); return new WeatherResponse( mockTemps.getOrDefault(request.location().toLowerCase(), 20.0), request.unit(), sunny ); } }接下来我们需要将这个函数注册为Spring Bean并添加必要的描述信息Configuration public class WeatherFunctionConfig { Bean Description(获取指定位置的当前天气信息包括温度、天气状况等) public FunctionWeatherRequest, WeatherResponse currentWeather() { return new MockWeatherService(); } }注意Description注解的内容非常重要它直接决定了AI模型是否能正确理解何时应该调用这个函数4. 集成与测试现在我们可以创建一个简单的REST控制器来测试整个流程RestController public class WeatherBotController { private final ChatClient chatClient; public WeatherBotController(ChatClient chatClient) { this.chatClient chatClient; } GetMapping(/ask) public String ask(RequestParam String question) { Prompt prompt new Prompt( new UserMessage(question), OpenAiChatOptions.builder() .withFunction(currentWeather) .build() ); ChatResponse response chatClient.call(prompt); return response.getResult().getOutput().getContent(); } }启动应用后我们可以通过curl进行测试curl http://localhost:8080/ask?questionWhats%20the%20weather%20like%20in%20San%20Francisco%20and%20Tokyo%3F预期会得到类似这样的响应 San Francisco目前天气晴朗温度18.5°C东京天气晴朗温度23.0°C。5. 生产环境优化虽然我们的基础版本已经可以工作但在生产环境中还需要考虑以下几个关键点性能优化建议为天气查询添加缓存层减少对API的调用使用异步处理提高并发能力对AI模型的响应进行限流错误处理策略Bean public FunctionWeatherRequest, WeatherResponse currentWeather() { return request - { try { // 实际业务逻辑 } catch (Exception e) { return new WeatherResponse( Double.NaN, request.unit(), service unavailable ); } }; }监控与日志建议添加以下监控指标函数调用成功率平均响应时间异常类型统计6. 扩展应用场景掌握了天气查询机器人的开发方法后我们可以轻松扩展更多实用功能股票查询功能Description(获取指定股票的实时价格信息) public FunctionStockRequest, StockResponse stockQuote() { // 实现股票查询逻辑 }日历集成Description(查询或添加日历事件) public FunctionCalendarRequest, CalendarResponse calendarManager() { // 实现日历集成逻辑 }多语言翻译Description(将文本翻译成指定语言) public FunctionTranslationRequest, TranslationResponse textTranslator() { // 实现翻译逻辑 }在实际项目中我发现最有效的做法是先从小而专的功能开始验证技术可行性后再逐步扩展。比如先做好天气查询再考虑添加空气质量指数等功能。