1. Function Calling 核心原理:大模型自动调用本地业务接口

Function Calling 的核心原理是让大语言模型(LLM)能够理解并自动调用开发者定义的本地业务函数/接口 ,从而将 LLM 的通用能力与特定业务逻辑和数据无缝结合。


核心思想:将函数/工具作为“扩展能力”暴露给 LLM

传统 LLM 只能基于训练数据进行文本生成。Function Calling 机制允许 LLM 在对话过程中,识别用户意图是否需要调用外部工具 ,并生成结构化请求 来调用这些工具,最后将工具执行结果融入回复中。

Spring AI 在此过程中扮演 “桥梁” 角色:

  1. 定义工具 :将本地 Java 方法(或 REST API)包装成 LLM 可识别的“函数”。
  2. 对话管理 :在上下文中告知 LLM 可用的函数列表及其描述。
  3. 解析与执行 :当 LLM 返回“调用请求”时,Spring AI 解析并反射调用对应的 Java 方法。
  4. 结果整合 :将方法返回值返回给 LLM,由 LLM 生成最终用户回复。

技术实现流程(以 OpenAI 函数调用为例)
步骤 1:定义业务函数(Java 方法)
@Bean
public Function<WeatherRequest, WeatherResponse> weatherFunction() {
    return request -> {
        // 实际业务逻辑:查询数据库或调用外部 API
        return new WeatherResponse(request.location(), 22, "Sunny");
    };
}
步骤 2:向 LLM 声明函数元数据

Spring AI 会将 Java 函数转换为 LLM 所需的 JSON Schema 格式:

{
  "name": "getWeather",
  "description": "获取指定城市的天气",
  "parameters": {
    "type": "object",
    "properties": {
      "location": {
        "type": "string",
        "description": "城市名称"
      }
    },
    "required": ["location"]
  }
}

关键点 :LLM 只接收函数描述,而非具体代码。

步骤 3:对话触发函数调用

用户提问:

“北京天气怎么样?”

LLM 分析后可能返回:

{
  "role": "assistant",
  "content": null,
  "function_call": {
    "name": "getWeather",
    "arguments": "{\"location\": \"北京\"}"
  }
}

注意:LLM 只生成调用请求,并不实际执行 。

步骤 4:Spring AI 执行函数
// Spring AI 内部处理流程
if (response.hasFunctionCall()) {
    String functionName = response.getFunctionCall().getName();
    Map<String, Object> args = parseArguments(response);
    
    // 查找注册的 Function 并执行
    Function<?, ?> function = functionRegistry.get(functionName);
    Object result = function.apply(args);
    
    // 将结果封装为新的消息放入对话上下文
    ChatMessage functionMessage = new FunctionMessage(result);
    chatContext.add(functionMessage);
}
步骤 5:LLM 生成最终回复

Spring AI 将函数执行结果(如 ​​{"temperature": 22, "condition": "Sunny"}​​)发送给 LLM,LLM 将其转化为自然语言:

“北京目前天气晴朗,气温 22 度。”


Spring AI 的关键抽象与组件
  1. ​FunctionCallback​​ :函数调用的核心接口
  1. 提供函数名称、描述、参数 Schema
  2. 包含实际执行逻辑
  1. ​FunctionCallbackRegistry​​ :函数注册中心
  1. 管理所有可用函数
  2. 支持按名称查找
  1. ​ChatClient​​ 的扩展 :
chatClient.prompt()
    .functions("getWeather", "searchProducts") // 声明可用函数
    .call();
  1. 消息类型扩展 :
  1. ​SystemMessage​​:可包含函数定义
  2. ​FunctionCallMessage​​:LLM 的调用请求
  3. ​FunctionResponseMessage​​:函数执行结果

与其他技术方案的对比

表格 还在加载中,请等待加载完成后再尝试复制


最佳实践与注意事项
  1. 函数设计原则 :
  1. 单一职责:一个函数完成一个明确任务
  2. 描述清晰:函数名和参数描述要准确,帮助 LLM 正确选择
  3. 安全边界:函数应进行权限验证和输入清理
  1. 错误处理 :
try {
    return function.apply(request);
} catch (Exception e) {
    // 返回结构化错误信息,让 LLM 告知用户
    return Map.of("error", "查询失败,请稍后重试");
}
  1. 性能优化 :
  1. 函数调用有额外 token 开销,避免定义过多函数
  2. 对耗时函数进行异步处理
  1. 安全考虑 :
  1. 限制可调用函数范围
  2. 验证 LLM 生成的参数,防止注入攻击

典型应用场景
  1. 数据查询 :数据库、API 查询
  2. 业务操作 :下单、预订、状态更新
  3. 计算服务 :汇率换算、单位转换
  4. 系统交互 :发送邮件、生成报表

代码示例(简化版)
@SpringBootApplication
public class FunctionCallApp {
    
    @Bean
    public Function<WeatherRequest, WeatherResponse> weatherFunction() {
        return request -> {
            // 实际业务逻辑
            return weatherService.getWeather(request.location());
        };
    }
    
    @Bean
    public ChatClient chatClient(OpenAiChatClient client, 
                                 FunctionCallbackRegistry registry) {
        return ChatClient.builder(client)
            .functionCallbacks(registry)
            .build();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(FunctionCallApp.class, args);
    }
}
总结

Spring AI Function Calling 的核心价值在于:

  1. 扩展性 :让 LLM 突破训练数据限制,接入实时数据和业务逻辑
  2. 解耦 :LLM 负责意图识别,本地代码负责具体执行
  3. 可控性 :开发者完全控制可调用的函数范围和权限

这种模式正在成为构建 AI 应用的标准范式,而 Spring AI 通过熟悉的 Spring 编程模型,为 Java 开发者提供了高效、安全的实现路径。

2. 自定义函数注册、参数自动解析、结果回传

函数定义与注册

1.1 定义函数类
@Service
public class WeatherService {
    
    @Function(name = "getCurrentWeather", description = "获取指定城市的当前天气")
    public Weather getCurrentWeather(
            @Parameter(description = "城市名称,例如:北京、上海") String city,
            @Parameter(description = "温度单位,celsius 或 fahrenheit", required = false) 
            @DefaultValue("celsius") String unit) {
        
        // 模拟天气数据
        Weather weather = new Weather();
        weather.setCity(city);
        weather.setTemperature(unit.equals("celsius") ? 25.0 : 77.0);
        weather.setUnit(unit);
        weather.setCondition("晴朗");
        weather.setHumidity(65);
        
        return weather;
    }
    
    @Function(name = "getWeatherForecast", description = "获取天气预报")
    public List<Weather> getWeatherForecast(
            @Parameter(description = "城市名称") String city,
            @Parameter(description = "天数,1-7") int days) {
        
        List<Weather> forecast = new ArrayList<>();
        for (int i = 0; i < days; i++) {
            Weather weather = new Weather();
            weather.setCity(city);
            weather.setTemperature(20 + i * 2);
            weather.setCondition(i % 2 == 0 ? "晴朗" : "多云");
            weather.setDate(LocalDate.now().plusDays(i));
            forecast.add(weather);
        }
        return forecast;
    }
}

// 数据类
@Data
public class Weather {
    private String city;
    private double temperature;
    private String unit;
    private String condition;
    private int humidity;
    private LocalDate date;
}
1.2 注册函数到 AI 模型
@Configuration
public class FunctionConfiguration {
    
    @Bean
    public FunctionCallback weatherFunctionCallback(WeatherService weatherService) {
        return FunctionCallbackWrapper.builder(weatherService)
                .withName("weatherService")
                .withDescription("天气服务")
                .build();
    }
    
    @Bean
    public ChatClient chatClient(
            ChatModel chatModel,
            List<FunctionCallback> functionCallbacks) {
        
        return ChatClient.builder(chatModel)
                .defaultFunctions(functionCallbacks.stream()
                        .map(FunctionCallback::getName)
                        .toArray(String[]::new))
                .build();
    }
}

参数自动解析机制

2.1 参数类型支持

Spring AI 支持多种参数类型自动解析:

@Service
public class MultiTypeService {
    
    @Function(name = "calculate", description = "数学计算")
    public Result calculate(
            // 基本类型
            @Parameter(description = "操作数A") double a,
            @Parameter(description = "操作数B") double b,
            
            // 枚举类型
            @Parameter(description = "操作类型") Operation operation,
            
            // 复杂对象(需要 JSON 解析)
            @Parameter(description = "计算选项") Options options,
            
            // 可选参数
            @Parameter(description = "精度", required = false) 
            @DefaultValue("2") int precision) {
        
        double result = switch (operation) {
            case ADD -> a + b;
            case SUBTRACT -> a - b;
            case MULTIPLY -> a * b;
            case DIVIDE -> a / b;
        };
        
        return new Result(result, precision);
    }
    
    @Function(name = "searchProducts", description = "搜索商品")
    public List<Product> searchProducts(
            @Parameter(description = "搜索条件") SearchCriteria criteria) {
        // 复杂对象参数会自动从 JSON 解析
        return productRepository.search(criteria);
    }
}

// 枚举
public enum Operation {
    ADD, SUBTRACT, MULTIPLY, DIVIDE
}

// 复杂参数对象
@Data
public class SearchCriteria {
    private String keyword;
    private Double minPrice;
    private Double maxPrice;
    private List<String> categories;
    private SortOrder sortBy;
}
2.2 自定义参数解析器
@Component
public class CustomArgumentResolver implements FunctionArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 支持自定义类型的参数解析
        return parameter.getParameterType().equals(CustomDate.class);
    }
    
    @Override
    public Object resolveArgument(
            MethodParameter parameter, 
            Message message, 
            ConversionService conversionService) {
        
        // 从 AI 返回的 JSON 中提取并转换
        String dateStr = extractDateFromMessage(message);
        return CustomDate.fromString(dateStr);
    }
    
    private String extractDateFromMessage(Message message) {
        // 解析消息内容获取日期参数
        // 实际实现根据消息格式而定
        return message.getContent();
    }
}

// 注册自定义解析器
@Configuration
public class ResolverConfig {
    
    @Bean
    public FunctionArgumentResolver customDateResolver() {
        return new CustomArgumentResolver();
    }
}

结果回传与处理

3.1 基本结果回传
@Service
public class ResultHandlingService {
    
    @Function(name = "getUserInfo", description = "获取用户信息")
    public UserInfo getUserInfo(
            @Parameter(description = "用户ID") String userId) {
        
        UserInfo user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        // 结果会自动转换为 JSON 返回给 AI
        return user;
    }
    
    @Function(name = "batchProcess", description = "批量处理")
    public BatchResult batchProcess(
            @Parameter(description = "处理项列表") List<ProcessItem> items) {
        
        BatchResult result = new BatchResult();
        for (ProcessItem item : items) {
            ProcessResult processResult = processItem(item);
            result.addResult(processResult);
        }
        
        // 复杂嵌套对象也会被正确序列化
        return result;
    }
}

// 支持复杂嵌套结果
@Data
public class BatchResult {
    private int total;
    private int success;
    private int failed;
    private List<ProcessResult> results;
    private Statistics statistics;
    
    @Data
    public static class Statistics {
        private double averageTime;
        private double successRate;
        private Map<String, Integer> statusCount;
    }
}
3.2 结果后处理
@Component
public class ResultPostProcessor {
    
    @Autowired
    private ObjectMapper objectMapper;
    
    public String processFunctionResult(Object result) {
        // 1. 转换为 JSON
        String jsonResult = objectMapper.writeValueAsString(result);
        
        // 2. 添加额外信息
        Map<String, Object> enhancedResult = new HashMap<>();
        enhancedResult.put("data", result);
        enhancedResult.put("timestamp", Instant.now());
        enhancedResult.put("success", true);
        
        // 3. 格式化输出(可选)
        return formatForAI(enhancedResult);
    }
    
    private String formatForAI(Map<String, Object> result) {
        // 根据 AI 模型的要求格式化结果
        StringBuilder sb = new StringBuilder();
        sb.append("执行结果:\n");
        
        if (result.get("data") instanceof List) {
            sb.append("找到 ").append(((List<?>) result.get("data")).size()).append(" 条记录");
        } else {
            sb.append("操作成功完成");
        }
        
        return sb.toString();
    }
}

完整示例:电商助手

@RestController
@RequestMapping("/api/ai")
public class ECommerceAssistantController {
    
    @Autowired
    private ChatClient chatClient;
    
    @Autowired
    private ProductService productService;
    
    @Autowired
    private OrderService orderService;
    
    @PostMapping("/chat")
    public ResponseEntity<ChatResponse> chat(@RequestBody UserMessage request) {
        
        // 注册多个功能
        List<FunctionCallback> callbacks = Arrays.asList(
                FunctionCallbackWrapper.builder(productService)
                        .withName("productService")
                        .build(),
                FunctionCallbackWrapper.builder(orderService)
                        .withName("orderService")
                        .build()
        );
        
        // 创建聊天客户端
        ChatClient client = ChatClient.builder(chatClient.getChatModel())
                .defaultFunctions(callbacks.stream()
                        .map(FunctionCallback::getName)
                        .toArray(String[]::new))
                .defaultSystem("""
                    你是一个电商助手,可以:
                    1. 搜索商品 (使用 productService.searchProducts)
                    2. 查询订单 (使用 orderService.getOrderDetails)
                    3. 推荐商品 (使用 productService.getRecommendations)
                    4. 检查库存 (使用 productService.checkStock)
                    """)
                .build();
        
        // 执行对话
        AssistantMessage response = client.prompt()
                .user(request.getMessage())
                .call()
                .chatResponse()
                .getResult();
        
        return ResponseEntity.ok(new ChatResponse(response.getContent()));
    }
}

// 商品服务
@Service
public class ProductService {
    
    @Function(name = "searchProducts", description = "搜索商品")
    public SearchResult searchProducts(
            @Parameter(description = "搜索关键词") String keyword,
            @Parameter(description = "分类", required = false) String category,
            @Parameter(description = "最低价格", required = false) Double minPrice,
            @Parameter(description = "最高价格", required = false) Double maxPrice,
            @Parameter(description = "排序方式", required = false) 
            @DefaultValue("relevance") String sortBy) {
        
        // 执行搜索逻辑
        List<Product> products = productRepository.search(
                keyword, category, minPrice, maxPrice, sortBy);
        
        SearchResult result = new SearchResult();
        result.setProducts(products);
        result.setTotal(products.size());
        result.setKeyword(keyword);
        
        // 添加建议
        if (products.isEmpty()) {
            result.setSuggestions(getSuggestions(keyword));
        }
        
        return result;
    }
    
    @Function(name = "getRecommendations", description = "获取商品推荐")
    public List<Product> getRecommendations(
            @Parameter(description = "用户ID,用于个性化推荐") String userId,
            @Parameter(description = "推荐数量", required = false) 
            @DefaultValue("5") int count) {
        
        return recommendationEngine.getRecommendations(userId, count);
    }
}

// 订单服务
@Service
public class OrderService {
    
    @Function(name = "getOrderDetails", description = "获取订单详情")
    public OrderDetails getOrderDetails(
            @Parameter(description = "订单号") String orderId) {
        
        Order order = orderRepository.findByOrderId(orderId);
        
        OrderDetails details = new OrderDetails();
        details.setOrderId(orderId);
        details.setStatus(order.getStatus());
        details.setItems(order.getItems());
        details.setTotalAmount(order.getTotalAmount());
        details.setShippingAddress(order.getShippingAddress());
        details.setEstimatedDelivery(order.getEstimatedDelivery());
        
        return details;
    }
    
    @Function(name = "trackOrder", description = "订单物流跟踪")
    public TrackingInfo trackOrder(
            @Parameter(description = "订单号") String orderId) {
        
        return logisticsService.trackOrder(orderId);
    }
}

高级配置

5.1 函数调用策略配置
@Configuration
public class AdvancedFunctionConfig {
    
    @Bean
    public FunctionCallingOptions functionCallingOptions() {
        return FunctionCallingOptions.builder()
                .withFunctionCall(FunctionCallingOptions.FunctionCall.AUTO)
                .withFunctions("weatherService", "calculatorService")
                .withTemperature(0.2)  // 降低随机性,使函数调用更稳定
                .build();
    }
    
    @Bean
    public ChatClient chatClient(
            ChatModel chatModel,
            FunctionCallingOptions options) {
        
        return ChatClient.builder(chatModel)
                .defaultOptions(options)
                .defaultSystem("""
                    请根据用户需求选择合适的函数调用。
                    如果需要精确数据,请调用相应函数。
                    """)
                .build();
    }
}
5.2 错误处理
@ControllerAdvice
public class FunctionExceptionHandler {
    
    @ExceptionHandler(FunctionCallException.class)
    @ResponseBody
    public ErrorResponse handleFunctionError(FunctionCallException e) {
        
        ErrorResponse error = new ErrorResponse();
        error.setErrorCode("FUNCTION_ERROR");
        error.setMessage("函数调用失败: " + e.getMessage());
        error.setTimestamp(Instant.now());
        
        // 提供修复建议
        if (e.getCause() instanceof IllegalArgumentException) {
            error.setSuggestion("请检查参数是否正确");
        }
        
        return error;
    }
    
    @ExceptionHandler(JsonProcessingException.class)
    @ResponseBody
    public ErrorResponse handleJsonError(JsonProcessingException e) {
        return new ErrorResponse(
            "JSON_PARSE_ERROR",
            "参数解析失败,请检查参数格式",
            Instant.now()
        );
    }
}

测试函数调用

@SpringBootTest
class FunctionCallingTest {
    
    @Autowired
    private ChatClient chatClient;
    
    @Test
    void testWeatherFunction() {
        AssistantMessage response = chatClient.prompt()
                .user("北京现在的天气怎么样?")
                .call()
                .chatResponse()
                .getResult();
        
        assertThat(response.getContent()).contains("天气");
        assertThat(response.getContent()).contains("北京");
    }
    
    @Test
    void testComplexFunctionChain() {
        // 测试多个函数链式调用
        AssistantMessage response = chatClient.prompt()
                .system("""
                    用户想买一件商品,请先搜索商品,
                    然后检查库存,最后给出购买建议。
                    """)
                .user("我想买一台笔记本电脑,预算8000左右")
                .call()
                .chatResponse()
                .getResult();
        
        // 验证响应包含函数调用结果
        assertThat(response.getContent())
                .containsPattern("搜索到.*笔记本")
                .contains("库存")
                .contains("建议");
    }
}

关键要点总结

  1. 函数注册 :使用 @Function 注解标记方法,通过 FunctionCallbackWrapper 注册
  2. 参数解析 :Spring AI 自动处理基本类型、枚举、复杂对象的 JSON 解析
  3. 结果回传 :函数返回值自动序列化为 JSON 返回给 AI 模型
  4. 链式调用 :支持多个函数的链式调用和结果传递
  5. 错误处理 :完善的异常处理和错误信息反馈机制
  6. 类型安全 :强类型参数和返回值,减少运行时错误

这种设计让 Spring AI 的函数调用既灵活又类型安全,能够很好地处理复杂的业务逻辑。

3. 实战开发:AI查询业务数据、AI自动生成报表、AI接口查询

我来分享一个完整的Spring AI实战开发方案,涵盖AI查询业务数据、自动生成报表和接口查询三大场景。

一、项目架构设计

技术栈选择
# pom.xml 关键依赖
dependencies:
  - spring-boot-starter-web
  - spring-ai-openai-spring-boot-starter  # 或Azure OpenAI、Ollama
  - spring-ai-pgvector-store  # 向量数据库
  - spring-data-jpa
  - mysql-connector-java
  - lombok
  - springdoc-openapi-starter-webmvc-ui  # API文档
项目结构
src/main/java/com/example/aiassistant/
├── config/
│   ├── AiConfig.java          # AI配置
│   └── VectorStoreConfig.java # 向量存储
├── domain/
│   ├── entity/               # 业务实体
│   ├── repository/           # 数据访问
│   └── dto/                 # 数据传输对象
├── service/
│   ├── DataQueryService.java    # 数据查询服务
│   ├── ReportService.java       # 报表服务
│   ├── AiQueryService.java      # AI查询服务
│   └── EmbeddingService.java    # 嵌入服务
├── controller/
│   ├── AiQueryController.java
│   └── ReportController.java
└── Application.java

二、核心功能实现

AI查询业务数据
@Service
@Slf4j
public class AiQueryService {
    
    @Autowired
    private ChatClient chatClient;
    
    @Autowired
    private DataQueryService dataQueryService;
    
    /**
     * 自然语言查询业务数据
     */
    public String queryBusinessData(String naturalLanguageQuery) {
        // 1. 解析查询意图
        String sqlQuery = parseQueryToSQL(naturalLanguageQuery);
        
        // 2. 执行SQL查询
        List<Map<String, Object>> results = dataQueryService.executeQuery(sqlQuery);
        
        // 3. 使用AI格式化结果
        String formattedResult = formatResultsWithAI(results, naturalLanguageQuery);
        
        return formattedResult;
    }
    
    private String parseQueryToSQL(String naturalQuery) {
        String prompt = """
            请将以下自然语言查询转换为SQL语句:
            用户查询:"%s"
            
            数据库表结构:
            1. sales_order表:id, customer_name, product_name, quantity, amount, order_date
            2. customer表:id, name, region, customer_level
            3. product表:id, name, category, price
            
            转换规则:
            - 只生成SQL语句,不要解释
            - 使用中文字段别名
            - 考虑性能优化
            """.formatted(naturalQuery);
        
        return chatClient.call(prompt);
    }
    
    private String formatResultsWithAI(List<Map<String, Object>> results, String originalQuery) {
        String dataJson = convertToJson(results);
        
        String prompt = """
            根据以下数据回答用户查询:
            用户问题:%s
            
            查询结果数据:%s
            
            请以清晰、专业的方式呈现结果,包含:
            1. 数据总结
            2. 关键洞察
            3. 建议(如果需要)
            使用中文回复。
            """.formatted(originalQuery, dataJson);
        
        return chatClient.call(prompt);
    }
}
AI自动生成报表
@Service
public class ReportGenerationService {
    
    @Autowired
    private ChatClient chatClient;
    
    @Autowired
    private VectorStore vectorStore;
    
    /**
     * 生成智能报表
     */
    public ReportDTO generateReport(ReportRequest request) {
        // 1. 收集相关数据
        List<BusinessData> data = collectReportData(request);
        
        // 2. AI分析数据并生成洞察
        String analysis = analyzeDataWithAI(data, request.getReportType());
        
        // 3. 生成报表内容(文本+图表建议)
        ReportContent content = generateReportContent(analysis, data);
        
        // 4. 格式化为多种格式
        return formatReport(content, request.getFormat());
    }
    
    private String analyzeDataWithAI(List<BusinessData> data, String reportType) {
        String dataSummary = summarizeData(data);
        
        String prompt = """
            作为数据分析专家,请分析以下业务数据并生成%s报告:
            
            数据概览:%s
            
            请提供:
            1. 关键趋势分析
            2. 异常点识别
            3. 业务建议
            4. 可视化图表建议(如:折线图、柱状图、饼图)
            
            使用专业但易于理解的商业语言。
            """.formatted(reportType, dataSummary);
        
        return chatClient.call(prompt);
    }
    
    private ReportContent generateReportContent(String aiAnalysis, List<BusinessData> data) {
        // 解析AI建议的图表类型
        List<ChartConfig> charts = extractChartSuggestions(aiAnalysis);
        
        // 生成数据表格
        String dataTable = generateDataTable(data);
        
        // 生成执行摘要
        String executiveSummary = generateExecutiveSummary(aiAnalysis);
        
        return ReportContent.builder()
                .title("智能业务分析报告")
                .executiveSummary(executiveSummary)
                .detailedAnalysis(aiAnalysis)
                .dataTables(dataTable)
                .chartConfigs(charts)
                .recommendations(extractRecommendations(aiAnalysis))
                .build();
    }
    
    /**
     * 导出多种格式
     */
    public byte[] exportReport(ReportDTO report, ExportFormat format) {
        switch (format) {
            case PDF:
                return generatePdfReport(report);
            case EXCEL:
                return generateExcelReport(report);
            case HTML:
                return generateHtmlReport(report);
            case MARKDOWN:
                return generateMarkdownReport(report);
            default:
                throw new IllegalArgumentException("不支持的格式");
        }
    }
}
AI接口查询系统
@RestController
@RequestMapping("/api/ai-query")
public class AiQueryController {
    
    @Autowired
    private AiQueryService aiQueryService;
    
    /**
     * 自然语言查询接口
     */
    @PostMapping("/natural-query")
    public ApiResponse<String> naturalLanguageQuery(
            @RequestBody NaturalQueryRequest request) {
        
        String result = aiQueryService.queryBusinessData(request.getQuery());
        
        return ApiResponse.success(result);
    }
    
    /**
     * 流式响应查询
     */
    @GetMapping("/stream-query")
    public Flux<String> streamQuery(@RequestParam String query) {
        return aiQueryService.streamQuery(query);
    }
    
    /**
     * 带上下文的查询
     */
    @PostMapping("/contextual-query")
    public ApiResponse<QueryResult> contextualQuery(
            @RequestBody ContextualQueryRequest request) {
        
        // 获取历史上下文
        List<ChatMessage> history = getQueryHistory(request.getSessionId());
        
        // 执行带上下文的查询
        QueryResult result = aiQueryService.queryWithContext(
            request.getQuery(), 
            history
        );
        
        return ApiResponse.success(result);
    }
}

/**
 * 智能API查询服务
 */
@Service
public class IntelligentApiService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private ChatClient chatClient;
    
    /**
     * AI辅助API查询
     */
    public Object queryApi(String naturalLanguageRequest) {
        // 1. AI解析用户意图
        ApiRequest parsedRequest = parseApiRequest(naturalLanguageRequest);
        
        // 2. 构建API请求
        HttpEntity<?> requestEntity = buildRequestEntity(parsedRequest);
        
        // 3. 执行请求
        ResponseEntity<String> response = restTemplate.exchange(
            parsedRequest.getUrl(),
            parsedRequest.getMethod(),
            requestEntity,
            String.class
        );
        
        // 4. AI处理响应
        return processApiResponse(response.getBody(), naturalLanguageRequest);
    }
    
    private ApiRequest parseApiRequest(String naturalLanguage) {
        String prompt = """
            请将以下用户请求解析为API调用参数:
            用户请求:%s
            
            可用API列表:
            1. 用户查询:GET /api/users?department={dept}
            2. 订单查询:GET /api/orders?startDate={start}&endDate={end}
            3. 销售统计:GET /api/sales/stats?region={region}
            4. 产品列表:GET /api/products?category={category}
            
            请返回JSON格式,包含:
            - url: API地址
            - method: HTTP方法
            - parameters: 参数Map
            - headers: 请求头
            """.formatted(naturalLanguage);
        
        String jsonResponse = chatClient.call(prompt);
        return parseJsonToApiRequest(jsonResponse);
    }
}

三、高级功能实现

RAG增强查询
@Service
public class RagEnhancedService {
    
    @Autowired
    private VectorStore vectorStore;
    
    /**
     * RAG增强的业务查询
     */
    public String ragQuery(String question) {
        // 1. 从向量库检索相关文档
        List<Document> relevantDocs = vectorStore.similaritySearch(question);
        
        // 2. 构建增强的Prompt
        String context = buildContextFromDocs(relevantDocs);
        
        String prompt = """
            基于以下业务文档回答问题:
            
            相关业务文档:
            %s
            
            用户问题:%s
            
            要求:
            1. 基于文档内容回答
            2. 如果文档中没有相关信息,请明确说明
            3. 引用相关文档片段
            4. 用中文回答
            """.formatted(context, question);
        
        return chatClient.call(prompt);
    }
    
    /**
     * 文档向量化存储
     */
    public void storeBusinessDocuments(List<BusinessDocument> docs) {
        List<Document> documents = docs.stream()
            .map(doc -> new Document(doc.getContent(), doc.getMetadata()))
            .collect(Collectors.toList());
        
        vectorStore.add(documents);
    }
}
智能数据可视化
@Service
public class VisualizationService {
    
    @Autowired
    private ChatClient chatClient;
    
    /**
     * AI建议的数据可视化
     */
    public VisualizationConfig suggestVisualization(List<Map<String, Object>> data) {
        String dataSample = data.stream()
            .limit(10)
            .map(Object::toString)
            .collect(Collectors.joining("\n"));
        
        String prompt = """
            分析以下数据,建议最适合的可视化方案:
            
            数据样例:
            %s
            
            请建议:
            1. 图表类型(折线图、柱状图、散点图等)
            2. X轴和Y轴字段
            3. 颜色方案建议
            4. 是否需要分组
            5. 交互建议
            
            以JSON格式返回配置。
            """.formatted(dataSample);
        
        String configJson = chatClient.call(prompt);
        return parseVisualizationConfig(configJson);
    }
    
    /**
     * 生成ECharts配置
     */
    public String generateEChartsConfig(VisualizationConfig config) {
        String prompt = """
            根据以下配置生成ECharts选项JSON:
            
            配置:%s
            
            要求:
            1. 生成完整的ECharts option配置
            2. 包含标题、图例、工具提示
            3. 美观的颜色方案
            4. 响应式设计
            5. 返回纯JSON,不要解释
            """.formatted(config.toString());
        
        return chatClient.call(prompt);
    }
}

四、配置示例

Spring AI配置
# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4
          temperature: 0.3
          max-tokens: 2000
    
    vectorstore:
      pgvector:
        enabled: true
        index-type: HNSW
        dimensions: 1536

  datasource:
    url: jdbc:mysql://localhost:3306/business_db
    username: root
    password: password
业务数据实体
@Entity
@Table(name = "sales_data")
@Data
public class SalesData {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String region;
    private String productCategory;
    private BigDecimal salesAmount;
    private Integer quantity;
    private LocalDate saleDate;
    private String customerSegment;
    
    @Column(columnDefinition = "json")
    private String additionalMetrics;
}

五、最佳实践建议

性能优化
@Configuration
public class AiPerformanceConfig {
    
    @Bean
    public CachingChatClient cachingChatClient(ChatClient chatClient) {
        return new CachingChatClient(chatClient);
    }
    
    @Bean
    public RetryTemplate aiRetryTemplate() {
        return RetryTemplate.builder()
                .maxAttempts(3)
                .exponentialBackoff(1000, 2, 5000)
                .retryOn(OpenAiApiException.class)
                .build();
    }
}
安全考虑
@Service
public class AiSecurityService {
    
    /**
     * 输入验证和防护
     */
    public String sanitizeInput(String userInput) {
        // 1. 检查注入攻击
        if (containsSqlInjection(userInput)) {
            throw new SecurityException("检测到可疑输入");
        }
        
        // 2. 敏感信息过滤
        String filtered = filterSensitiveInfo(userInput);
        
        // 3. 长度限制
        if (filtered.length() > 1000) {
            filtered = filtered.substring(0, 1000);
        }
        
        return filtered;
    }
    
    /**
     * 输出内容审查
     */
    public boolean validateOutput(String aiOutput) {
        // 检查有害内容
        return !containsHarmfulContent(aiOutput);
    }
}
监控和日志
@Aspect
@Component
@Slf4j
public class AiServiceMonitor {
    
    @Around("@within(org.springframework.stereotype.Service)")
    public Object monitorAiCalls(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();
        
        try {
            Object result = joinPoint.proceed();
            long duration = System.currentTimeMillis() - start;
            
            log.info("AI服务调用成功 - 方法: {}, 耗时: {}ms", 
                    methodName, duration);
            
            // 记录到监控系统
            metricsService.recordAiCall(methodName, duration, true);
            
            return result;
        } catch (Exception e) {
            metricsService.recordAiCall(methodName, 
                System.currentTimeMillis() - start, false);
            throw e;
        }
    }
}

六、完整示例:销售分析系统

@RestController
@RequestMapping("/api/sales-ai")
public class SalesAiController {
    
    @PostMapping("/analyze")
    public SalesAnalysis analyzeSales(@RequestBody AnalysisRequest request) {
        // 1. 查询销售数据
        List<SalesData> salesData = salesService.getSalesData(request);
        
        // 2. AI分析趋势
        String trendAnalysis = aiAnalyzer.analyzeSalesTrend(salesData);
        
        // 3. 生成建议
        String recommendations = aiAdvisor.generateRecommendations(salesData);
        
        // 4. 创建可视化配置
        VisualizationConfig charts = visualizationService.suggestCharts(salesData);
        
        return SalesAnalysis.builder()
                .period(request.getPeriod())
                .summary(generateSummary(salesData))
                .trendAnalysis(trendAnalysis)
                .keyInsights(extractInsights(trendAnalysis))
                .recommendations(recommendations)
                .visualizationConfig(charts)
                .generatedAt(LocalDateTime.now())
                .build();
    }
    
    @PostMapping(value = "/export-report", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public ResponseEntity<byte[]> exportReport(@RequestBody ReportRequest request) {
        SalesAnalysis analysis = analyzeSales(request.getAnalysisRequest());
        
        byte[] reportBytes = reportService.exportToPdf(analysis);
        
        return ResponseEntity.ok()
                .header("Content-Disposition", 
                        "attachment; filename=\"sales-report.pdf\"")
                .body(reportBytes);
    }
}

关键点总结

  1. 分层架构 :清晰的Controller-Service-Repository分层
  2. 错误处理 :完善的异常处理和重试机制
  3. 性能优化 :缓存、流式响应、异步处理
  4. 安全性 :输入验证、输出审查、API防护
  5. 可扩展性 :支持多AI模型、多数据源
  6. 可观测性 :完整的日志和监控

这个方案提供了完整的Spring AI实战开发框架,你可以根据具体业务需求进行调整和扩展。

4. 函数调用异常处理、参数校验、重试机制

Spring AI 的函数调用(Function Calling)提供了强大的工具调用能力,但在实际应用中需要完善的异常处理、参数校验和重试机制。以下是完整的实现方案:

异常处理机制

1.1 全局异常处理器

@RestControllerAdvice
public class SpringAIExceptionHandler {
    
    @ExceptionHandler(ApiClientException.class)
    public ResponseEntity<ErrorResponse> handleApiClientException(ApiClientException ex) {
        log.error("AI API调用异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
            .body(ErrorResponse.of("AI服务暂时不可用", ex.getMessage()));
    }
    
    @ExceptionHandler(FunctionCallException.class)
    public ResponseEntity<ErrorResponse> handleFunctionCallException(FunctionCallException ex) {
        log.error("函数调用异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(ErrorResponse.of("函数调用失败", ex.getMessage()));
    }
    
    @ExceptionHandler(InvalidFunctionParameterException.class)
    public ResponseEntity<ErrorResponse> handleInvalidParameterException(
            InvalidFunctionParameterException ex) {
        log.error("函数参数异常: {}", ex.getMessage(), ex);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(ErrorResponse.of("参数校验失败", ex.getValidationErrors()));
    }
}

// 自定义异常类
public class FunctionCallException extends RuntimeException {
    public FunctionCallException(String message) {
        super(message);
    }
    
    public FunctionCallException(String message, Throwable cause) {
        super(message, cause);
    }
}

public class InvalidFunctionParameterException extends RuntimeException {
    private final Map<String, String> validationErrors;
    
    public InvalidFunctionParameterException(Map<String, String> errors) {
        super("函数参数校验失败");
        this.validationErrors = errors;
    }
}

1.2 函数调用包装器

@Component
public class FunctionCallWrapper {
    
    @Autowired
    private FunctionCallingOptions functionCallingOptions;
    
    public <T> T executeWithExceptionHandling(
            Supplier<T> functionCall, 
            String functionName) {
        try {
            return functionCall.get();
        } catch (ApiClientException e) {
            log.error("AI API调用失败 - 函数: {}", functionName, e);
            throw new FunctionCallException(
                String.format("调用函数%s时AI服务异常", functionName), e);
        } catch (IllegalArgumentException e) {
            log.error("参数异常 - 函数: {}", functionName, e);
            throw new InvalidFunctionParameterException(
                Map.of("error", e.getMessage()));
        } catch (Exception e) {
            log.error("未知异常 - 函数: {}", functionName, e);
            throw new FunctionCallException(
                String.format("调用函数%s时发生未知错误", functionName), e);
        }
    }
}

参数校验机制

2.1 基于注解的校验

import jakarta.validation.Valid;
import jakarta.validation.constraints.*;

public class WeatherRequest {
    
    @NotBlank(message = "城市名称不能为空")
    @Size(max = 50, message = "城市名称长度不能超过50")
    private String city;
    
    @NotBlank(message = "国家代码不能为空")
    @Pattern(regexp = "^[A-Z]{2}$", message = "国家代码必须是2位大写字母")
    private String countryCode;
    
    @NotNull(message = "日期不能为空")
    @FutureOrPresent(message = "日期不能是过去时间")
    private LocalDate date;
    
    @Min(value = -50, message = "温度不能低于-50℃")
    @Max(value = 60, message = "温度不能高于60℃")
    private Integer temperature;
    
    // getters and setters
}

2.2 函数参数校验器

@Component
public class FunctionParameterValidator {
    
    private final Validator validator;
    
    public FunctionParameterValidator() {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        this.validator = factory.getValidator();
    }
    
    public <T> void validate(T request) {
        Set<ConstraintViolation<T>> violations = validator.validate(request);
        
        if (!violations.isEmpty()) {
            Map<String, String> errors = violations.stream()
                .collect(Collectors.toMap(
                    v -> v.getPropertyPath().toString(),
                    ConstraintViolation::getMessage
                ));
            throw new InvalidFunctionParameterException(errors);
        }
    }
    
    public void validateString(String value, 
                              @Nullable Integer maxLength,
                              @Nullable Pattern pattern,
                              String fieldName) {
        if (value == null || value.trim().isEmpty()) {
            throw new InvalidFunctionParameterException(
                Map.of(fieldName, "不能为空"));
        }
        
        if (maxLength != null && value.length() > maxLength) {
            throw new InvalidFunctionParameterException(
                Map.of(fieldName, String.format("长度不能超过%d", maxLength)));
        }
        
        if (pattern != null && !pattern.matcher(value).matches()) {
            throw new InvalidFunctionParameterException(
                Map.of(fieldName, "格式不正确"));
        }
    }
}

2.3 带校验的函数实现

@Component
public class WeatherFunction implements Function<WeatherRequest, WeatherResponse> {
    
    @Autowired
    private FunctionParameterValidator validator;
    
    @Autowired
    private WeatherService weatherService;
    
    @Override
    public WeatherResponse apply(WeatherRequest request) {
        // 参数校验
        validator.validate(request);
        
        // 业务逻辑校验
        validateBusinessLogic(request);
        
        // 执行业务逻辑
        return weatherService.getWeather(request);
    }
    
    private void validateBusinessLogic(WeatherRequest request) {
        // 示例:检查城市是否支持
        if (!weatherService.isCitySupported(request.getCity(), request.getCountryCode())) {
            throw new InvalidFunctionParameterException(
                Map.of("city", "不支持的城市: " + request.getCity()));
        }
        
        // 示例:检查日期范围
        if (request.getDate().isAfter(LocalDate.now().plusDays(14))) {
            throw new InvalidFunctionParameterException(
                Map.of("date", "只能查询未来14天的天气"));
        }
    }
    
    @Bean
    public Function<Message, WeatherResponse> weatherFunction() {
        return message -> {
            WeatherRequest request = convertMessageToRequest(message);
            return apply(request);
        };
    }
}

重试机制

3.1 基于Spring Retry的配置

@Configuration
@EnableRetry
public class RetryConfig {
    
    @Bean
    public RetryTemplate aiFunctionRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();
        
        // 重试策略:最多重试3次,指数退避
        ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
        backOffPolicy.setInitialInterval(1000);
        backOffPolicy.setMultiplier(2.0);
        backOffPolicy.setMaxInterval(10000);
        
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
        retryPolicy.setMaxAttempts(3);
        
        retryTemplate.setRetryPolicy(retryPolicy);
        retryTemplate.setBackOffPolicy(backOffPolicy);
        
        return retryTemplate;
    }
    
    @Bean
    public RetryTemplate circuitBreakerRetryTemplate() {
        CircuitBreakerRetryPolicy circuitBreakerPolicy = 
            new CircuitBreakerRetryPolicy(new SimpleRetryPolicy(3));
        circuitBreakerPolicy.setOpenTimeout(5000);
        circuitBreakerPolicy.setResetTimeout(10000);
        
        RetryTemplate retryTemplate = new RetryTemplate();
        retryTemplate.setRetryPolicy(circuitBreakerPolicy);
        
        return retryTemplate;
    }
}

3.2 带重试的函数调用器

@Component
public class ResilientFunctionCaller {
    
    @Autowired
    private RetryTemplate aiFunctionRetryTemplate;
    
    @Autowired
    private CircuitBreakerFactory circuitBreakerFactory;
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    private final Counter successCounter;
    private final Counter failureCounter;
    private final Timer executionTimer;
    
    public ResilientFunctionCaller(MeterRegistry meterRegistry) {
        this.successCounter = meterRegistry.counter("function.call.success");
        this.failureCounter = meterRegistry.counter("function.call.failure");
        this.executionTimer = meterRegistry.timer("function.execution.time");
    }
    
    public <T> T callWithRetry(Supplier<T> function, 
                               String functionName,
                               Map<String, Object> context) {
        return executionTimer.record(() -> {
            try {
                T result = aiFunctionRetryTemplate.execute(context -> {
                    try {
                        return function.get();
                    } catch (ApiClientException e) {
                        if (shouldRetry(e)) {
                            throw e; // 触发重试
                        }
                        throw new NonRetryableException("不可重试的异常", e);
                    } catch (InvalidFunctionParameterException e) {
                        throw new NonRetryableException("参数错误,不重试", e);
                    }
                });
                
                successCounter.increment();
                return result;
                
            } catch (Exception e) {
                failureCounter.increment();
                log.error("函数调用失败,已重试: {}", functionName, e);
                throw new FunctionCallException(
                    String.format("调用%s失败,已重试多次", functionName), e);
            }
        });
    }
    
    private boolean shouldRetry(ApiClientException e) {
        // 根据异常类型决定是否重试
        return e.getStatusCode() != null &&
               e.getStatusCode().is5xxServerError() &&
               e.getStatusCode().value() != 501; // 不重试501错误
    }
    
    // 使用熔断器
    public <T> T callWithCircuitBreaker(Supplier<T> function, 
                                        String functionName) {
        CircuitBreaker circuitBreaker = circuitBreakerFactory.create(functionName);
        
        return circuitBreaker.run(() -> {
            try {
                return callWithRetry(function, functionName, Map.of());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }, throwable -> {
            // 降级逻辑
            log.warn("熔断器触发,使用降级逻辑: {}", functionName);
            return getFallbackResult(functionName);
        });
    }
    
    private <T> T getFallbackResult(String functionName) {
        // 返回默认值或缓存值
        if ("getWeather".equals(functionName)) {
            return (T) new WeatherResponse("服务暂时不可用", null, null);
        }
        return null;
    }
}

3.3 注解式重试

@Service
public class WeatherService {
    
    @Retryable(
        value = {ApiClientException.class, TimeoutException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    @Recover
    public WeatherResponse recover(ApiClientException e, WeatherRequest request) {
        log.warn("天气服务调用失败,使用缓存数据: {}", request.getCity());
        return getCachedWeather(request);
    }
    
    @CircuitBreaker(
        name = "weatherService",
        fallbackMethod = "getWeatherFallback"
    )
    @RateLimiter(name = "weatherService", limit = 10)
    @TimeLimiter(name = "weatherService")
    public CompletableFuture<WeatherResponse> getWeatherAsync(WeatherRequest request) {
        return CompletableFuture.supplyAsync(() -> getWeather(request));
    }
    
    public WeatherResponse getWeatherFallback(WeatherRequest request, Exception e) {
        return new WeatherResponse("降级响应", null, null);
    }
}

完整集成示例

4.1 配置类

@Configuration
public class SpringAIFunctionConfig {
    
    @Bean
    public FunctionCallingOptions functionCallingOptions() {
        return FunctionCallingOptions.builder()
            .withFunctionCallbacks(List.of(
                FunctionCallback.builder()
                    .withName("getWeather")
                    .withDescription("获取天气信息")
                    .withInputType(WeatherRequest.class)
                    .withOutputType(WeatherResponse.class)
                    .build()
            ))
            .build();
    }
    
    @Bean
    public ChatClient chatClient(
            ChatModel chatModel,
            FunctionCallingOptions options,
            ResilientFunctionCaller resilientCaller) {
        
        return ChatClient.builder(chatModel)
            .defaultOptions(options)
            .defaultSystem("""
                你是一个天气助手。请根据用户需求调用适当的函数。
                如果参数不完整,请询问用户补充信息。
                """)
            .build();
    }
}

4.2 服务层整合

@Service
@Slf4j
public class AIChatService {
    
    @Autowired
    private ChatClient chatClient;
    
    @Autowired
    private ResilientFunctionCaller resilientCaller;
    
    @Autowired
    private FunctionParameterValidator validator;
    
    @Autowired
    private WeatherFunction weatherFunction;
    
    public String chatWithFunctions(String userMessage) {
        return resilientCaller.callWithCircuitBreaker(() -> {
            // 执行AI对话,包含函数调用
            ChatResponse response = chatClient.prompt()
                .user(userMessage)
                .call()
                .chatResponse();
            
            // 处理函数调用结果
            return processFunctionCalls(response);
            
        }, "aiChatFunction");
    }
    
    private String processFunctionCalls(ChatResponse response) {
        if (response.getToolCalls() != null && !response.getToolCalls().isEmpty()) {
            for (ToolCall toolCall : response.getToolCalls()) {
                if ("getWeather".equals(toolCall.function().name())) {
                    WeatherRequest request = parseWeatherRequest(toolCall);
                    
                    // 执行带校验和异常处理的函数调用
                    WeatherResponse weatherResponse = resilientCaller.callWithRetry(
                        () -> weatherFunction.apply(request),
                        "getWeather",
                        Map.of("request", request)
                    );
                    
                    // 将结果返回给AI
                    return chatClient.prompt()
                        .tools(ToollCallResponse.from(weatherResponse))
                        .call()
                        .content();
                }
            }
        }
        return response.content();
    }
    
    private WeatherRequest parseWeatherRequest(ToolCall toolCall) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(
                toolCall.function().arguments(), 
                WeatherRequest.class
            );
        } catch (Exception e) {
            throw new FunctionCallException("解析函数参数失败", e);
        }
    }
}

4.3 监控和日志

@Component
@Aspect
@Slf4j
public class FunctionCallMonitor {
    
    @Around("@annotation(MonitorFunctionCall)")
    public Object monitorFunctionCall(ProceedingJoinPoint joinPoint) throws Throwable {
        String functionName = joinPoint.getSignature().getName();
        long startTime = System.currentTimeMillis();
        
        MDC.put("functionName", functionName);
        log.info("开始执行函数: {}", functionName);
        
        try {
            Object result = joinPoint.proceed();
            long duration = System.currentTimeMillis() - startTime;
            
            log.info("函数执行成功: {}, 耗时: {}ms", functionName, duration);
            return result;
            
        } catch (Exception e) {
            log.error("函数执行失败: {}", functionName, e);
            throw e;
        } finally {
            MDC.remove("functionName");
        }
    }
    
    @EventListener
    public void handleFunctionCallEvent(FunctionCallEvent event) {
        log.info("函数调用事件: {}, 状态: {}", 
            event.getFunctionName(), 
            event.getStatus());
        
        // 发送到监控系统
        Metrics.counter("function.call.event")
            .tag("function", event.getFunctionName())
            .tag("status", event.getStatus().name())
            .increment();
    }
}

最佳实践建议

  1. 分层处理 :将参数校验、业务逻辑、异常处理分层实现
  2. 优雅降级 :为关键函数提供降级逻辑
  3. 监控告警 :对函数调用成功率、耗时等关键指标进行监控
  4. 配置化 :将重试策略、超时时间等配置化,便于调整
  5. 幂等性 :确保可重试的函数具有幂等性
  6. 超时控制 :为每个函数设置合理的超时时间
  7. 限流保护 :对高频函数进行限流,防止系统过载

这套方案提供了完整的异常处理、参数校验和重试机制,能够确保Spring AI函数调用的稳定性和可靠性。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐