大模型应用技术之 Spring AI 2.0 变更说明

概述

Spring AI 2.0.0-M1 是 Spring AI 框架的一个重要里程碑版本,在 Spring AI 1.x 的基础上进行了重大升级和改进。该版本基于 Spring Boot 4.0 和 Spring Framework 7.0 构建,提供了更强大的 AI 应用开发能力,增强了与各种 AI 模型和服务的集成,并引入了多项新功能和性能优化。

版本信息

  • 当前版本: 2.0.0-M1 (里程碑版本)
  • 最低 Java 版本: Java 21
  • Spring Boot 版本: 4.0
  • Spring Framework 版本: 7.0

平台升级要求

Java 版本要求

Spring AI 2.x 必须 使用 Java 21 或更高版本。这是与 Spring Boot 4.0 和 Spring Framework 7.0 对齐的要求。

xml 复制代码
<properties>
    <java.version>21</java.version>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
</properties>

Spring 生态系统版本

  • Spring Boot: 4.0+
  • Spring Framework: 7.0+
  • Jakarta EE: 11

Maven 依赖配置

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-bom</artifactId>
    <version>2.0.0-M1</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

核心新功能

1. Redis Chat Memory Repository(Redis 聊天记忆存储)

Spring AI 2.x 引入了基于 Redis 的聊天记忆实现,支持持久化会话存储。

主要特性
  • 持久化会话存储: 跨会话保存对话历史
  • 文本搜索能力: 集成文本搜索功能,高效检索对话数据
  • 范围查询支持: 支持基于范围的查询,实现更精确的数据检索
  • HNSW 索引调优: 可调整 HNSW 索引参数(M、efConstruction、efRuntime)以优化性能
使用示例
xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-redis</artifactId>
</dependency>
java 复制代码
@Configuration
public class RedisChatMemoryConfig {
    
    @Bean
    public RedisChatMemoryRepository chatMemoryRepository(RedisConnectionFactory connectionFactory) {
        return new RedisChatMemoryRepository(connectionFactory);
    }
    
    @Bean
    public ChatMemory chatMemory(RedisChatMemoryRepository repository) {
        return new SimpleChatMemory(repository);
    }
}

2. Redis Vector Store 增强

Redis 向量存储功能得到显著增强,提供更强大的向量搜索能力。

新增功能
  • 文本搜索集成: 向量存储现在包含文本搜索功能
  • 基于范围的向量查询: 支持范围查询,提高搜索灵活性
  • HNSW 索引参数调优: 可自定义 HNSW 索引参数以优化相似度搜索性能
  • 元数据过滤: 支持元数据过滤,实现更精确的数据检索
  • 原生 Redis 客户端访问 : 通过 getNativeClient() 方法访问底层 Redis 客户端
配置示例
java 复制代码
@Configuration
public class RedisVectorStoreConfig {
    
    @Bean
    public RedisVectorStore vectorStore(RedisConnectionFactory connectionFactory) {
        RedisVectorStore.RedisVectorStoreConfig config = 
            RedisVectorStore.RedisVectorStoreConfig.builder()
                .withIndexName("vector-index")
                .withHnswM(16)  // HNSW 参数 M
                .withHnswEfConstruction(200)  // efConstruction
                .withHnswEfRuntime(50)  // efRuntime
                .build();
        
        return new RedisVectorStore(config, connectionFactory);
    }
}

3. OpenAI Java SDK 原生集成

Spring AI 2.x 集成了官方的 OpenAI Java SDK,提供更好的性能和功能支持。

主要改进
  • 原生 SDK 支持: 使用官方 OpenAI Java SDK 替代之前的实现
  • 默认模型更新 : 默认聊天模型更新为 gpt-5-mini
  • 更好的错误处理: 改进的错误处理和重试机制
  • 流式响应优化: 优化的流式响应处理
使用示例
java 复制代码
@Configuration
public class OpenAIConfig {
    
    @Bean
    public OpenAiChatModel chatModel(OpenAiApi openAiApi) {
        return new OpenAiChatModel(openAiApi, 
            OpenAiChatOptions.builder()
                .withModel("gpt-5-mini")
                .withTemperature(0.7f)
                .build());
    }
}

4. Anthropic Claude 增强

对 Claude 集成进行了全面更新,支持最新的 Claude 模型和功能。

新增功能
  • Claude 4.5 模型支持: 支持最新的 Claude 4.5 系列模型
  • Citations API: 支持引用 API,提供更准确的引用信息
  • Claude Skills with Files API: 支持文件 API 的 Claude Skills
  • Tool Choice 支持: 增强的工具选择功能
配置示例
java 复制代码
@Bean
public AnthropicChatModel claudeChatModel(AnthropicApi anthropicApi) {
    return new AnthropicChatModel(anthropicApi,
        AnthropicChatOptions.builder()
            .withModel("claude-4-5-sonnet-20241022")
            .withTemperature(0.7f)
            .withMaxTokens(4096)
            .build());
}

5. Google GenAI 和 Gemini 增强

新功能
  • ThinkingLevel 支持: 在 ThinkingConfig 中添加了 ThinkingLevel 支持
  • Google GenAI SDK 更新: 更新到 1.30.0 版本
  • 增强的 Gemini 模型支持: 更好的 Gemini 模型集成
使用示例
java 复制代码
@Bean
public GeminiChatModel geminiChatModel(GoogleGenerativeAiApi api) {
    return new GeminiChatModel(api,
        GeminiChatOptions.builder()
            .withModel("gemini-pro")
            .withThinkingConfig(ThinkingConfig.builder()
                .withThinkingLevel(ThinkingLevel.MEDIUM)
                .build())
            .build());
}

6. Azure Cosmos DB Chat Memory

新增了 Azure Cosmos DB 聊天记忆存储的 Spring Boot Starter。

特性
  • 持久化存储: 使用 Azure Cosmos DB 存储对话历史
  • 自动配置: 提供 Spring Boot 自动配置
  • 高可用性: 利用 Cosmos DB 的高可用性特性
依赖配置
xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-azure-cosmosdb</artifactId>
</dependency>

7. Model Context Protocol (MCP) 更新

改进内容
  • 自动配置增强: 改进了 MCP 客户端的自动配置
  • 可选处理器注册表支持: 支持可选的处理器注册表
  • 类型兼容性改进: 改进了对具有不可解析类型的 Bean 的兼容性

8. GemFire Vector Store 认证

为 GemFire Vector Store 添加了用户名和密码认证支持。

java 复制代码
@Bean
public GemFireVectorStore gemFireVectorStore() {
    GemFireVectorStore.GemFireVectorStoreConfig config = 
        GemFireVectorStore.GemFireVectorStoreConfig.builder()
            .withHost("localhost")
            .withPort(7070)
            .withUsername("admin")
            .withPassword("password")
            .build();
    
    return new GemFireVectorStore(config);
}

与 Spring AI 1.x 的对比

功能对比表

功能特性 Spring AI 1.x Spring AI 2.x 说明
Java 版本要求 Java 17+ Java 21+ 必须升级
Spring Boot 版本 3.x 4.0+ 重大升级
Spring Framework 6.x 7.0+ 重大升级
Redis Chat Memory ❌ 不支持 ✅ 支持 新增功能
Redis Vector Store 文本搜索 ❌ 不支持 ✅ 支持 新增功能
OpenAI 官方 SDK ❌ 不支持 ✅ 支持 新增功能
Claude 4.5 支持 ❌ 不支持 ✅ 支持 新增功能
Claude Citations API ❌ 不支持 ✅ 支持 新增功能
Azure Cosmos DB Memory ❌ 不支持 ✅ 支持 新增功能
Gemini ThinkingLevel ❌ 不支持 ✅ 支持 新增功能
GemFire 认证 ❌ 不支持 ✅ 支持 新增功能
默认 Temperature 配置 ✅ 自动配置 ❌ 需显式配置 破坏性变更
默认 OpenAI 模型 gpt-4 gpt-5-mini 变更
FunctionCallback API ✅ 支持 ⚠️ 已弃用 建议迁移到 ToolCallback

性能对比

  • 向量搜索性能: Redis Vector Store 的 HNSW 索引调优可提升 20-30% 的搜索性能
  • 内存使用: 优化的内存管理,减少约 15% 的内存占用
  • 响应时间: 原生 SDK 集成减少了约 10-15% 的 API 响应时间

破坏性变更

1. Java 版本要求

变更: 最低 Java 版本从 17 升级到 21

影响: 所有使用 Spring AI 2.x 的项目必须使用 Java 21 或更高版本

迁移步骤:

xml 复制代码
<!-- 更新 pom.xml -->
<properties>
    <java.version>21</java.version>
</properties>

2. 默认 Temperature 配置移除

变更: 模型实现中移除了默认的 temperature 配置

影响: 应用程序必须显式配置 temperature 设置

迁移示例:

java 复制代码
// Spring AI 1.x (自动配置 temperature)
@Bean
public ChatModel chatModel() {
    return new OpenAiChatModel(api);
}

// Spring AI 2.x (必须显式配置)
@Bean
public ChatModel chatModel() {
    return new OpenAiChatModel(api,
        OpenAiChatOptions.builder()
            .withTemperature(0.7f)  // 必须显式设置
            .build());
}

3. OpenAI 默认模型变更

变更 : 默认聊天模型从 gpt-4 更新为 gpt-5-mini

影响: 如果依赖默认模型,行为会发生变化

迁移步骤:

java 复制代码
// 显式指定模型以保持原有行为
OpenAiChatOptions.builder()
    .withModel("gpt-4")  // 或使用 gpt-5-mini
    .build()

4. FunctionCallback 到 ToolCallback 迁移

变更 : FunctionCallback API 已弃用,推荐使用 ToolCallback API

影响: 使用 FunctionCallback 的代码需要迁移

迁移示例:

java 复制代码
// Spring AI 1.x (已弃用)
@Bean
public FunctionCallback weatherFunction() {
    return FunctionCallback.builder()
        .withName("getWeather")
        .withDescription("Get weather information")
        .withFunction((location) -> getWeatherData(location))
        .build();
}

// Spring AI 2.x (推荐)
@Bean
public ToolCallback weatherTool() {
    return FunctionToolCallback.builder()
        .withName("getWeather")
        .withDescription("Get weather information")
        .withFunction((location) -> getWeatherData(location))
        .build();
}

5. API 方法重命名

变更: 多个 API 方法进行了重命名

主要变更:

  • ChatClient.builder().defaultFunctions()ChatClient.builder().defaultTools()
  • ChatClient.functions()ChatClient.tools()
  • FunctionCallingOptionsToolCallingChatOptions
  • UserMessage.propertiesUserMessage.metadata

6. OpenAI ChatOptions 参数变更

变更 : maxTokensmaxCompletionTokens 参数现在互斥

影响: 只能选择其中一个参数

迁移示例:

java 复制代码
// ❌ 错误:不能同时使用
OpenAiChatOptions.builder()
    .withMaxTokens(1000)
    .withMaxCompletionTokens(500)  // 错误
    .build();

// ✅ 正确:只使用一个
OpenAiChatOptions.builder()
    .withMaxTokens(1000)  // 或使用 withMaxCompletionTokens
    .build();

7. VectorStore 接口变更

变更 : 从 VectorStore 中提取了新的 VectorStoreRetriever 接口

影响: 自定义 VectorStore 实现可能需要更新

迁移示例:

java 复制代码
// Spring AI 2.x
public class CustomVectorStore implements VectorStore, VectorStoreRetriever {
    // 实现两个接口
}

8. MCP 自动配置类重命名

变更: MCP 自动配置类添加了 'Mcp' 前缀

影响: 如果直接引用自动配置类,需要更新引用


迁移指南

迁移步骤概览

  1. 升级 Java 版本到 21
  2. 更新 Spring Boot 到 4.0+
  3. 更新 Spring AI 依赖到 2.0.0-M1
  4. 修复破坏性变更
  5. 迁移到新的 API
  6. 测试和验证

详细迁移步骤

步骤 1: 更新项目配置
xml 复制代码
<!-- pom.xml -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.0</version>
</parent>

<properties>
    <java.version>21</java.version>
    <spring-ai.version>2.0.0-M1</spring-ai.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
步骤 2: 更新 ChatModel 配置
java 复制代码
// 迁移前 (1.x)
@Bean
public ChatModel chatModel(OpenAiApi api) {
    return new OpenAiChatModel(api);
}

// 迁移后 (2.x)
@Bean
public ChatModel chatModel(OpenAiApi api) {
    return new OpenAiChatModel(api,
        OpenAiChatOptions.builder()
            .withModel("gpt-4")  // 显式指定模型
            .withTemperature(0.7f)  // 显式设置 temperature
            .build());
}
步骤 3: 迁移 FunctionCallback 到 ToolCallback
java 复制代码
// 迁移前 (1.x)
@Bean
public FunctionCallback weatherFunction() {
    return FunctionCallback.builder()
        .withName("getWeather")
        .withDescription("Get weather")
        .withFunction((location) -> getWeather(location))
        .build();
}

// 迁移后 (2.x)
@Bean
public ToolCallback weatherTool() {
    return FunctionToolCallback.builder()
        .withName("getWeather")
        .withDescription("Get weather")
        .withFunction((location) -> getWeather(location))
        .build();
}
步骤 4: 更新 ChatClient 配置
java 复制代码
// 迁移前 (1.x)
ChatClient chatClient = ChatClient.builder()
    .defaultFunctions(weatherFunction)
    .build();

// 迁移后 (2.x)
ChatClient chatClient = ChatClient.builder()
    .defaultTools(weatherTool)
    .build();
步骤 5: 更新 UserMessage 使用
java 复制代码
// 迁移前 (1.x)
UserMessage message = new UserMessage("Hello", Map.of("key", "value"));

// 迁移后 (2.x)
UserMessage message = new UserMessage("Hello", 
    MessageMetadata.builder()
        .withMetadata("key", "value")
        .build());

代码示例

示例 1: 使用 Redis Chat Memory

java 复制代码
@SpringBootApplication
public class ChatApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ChatApplication.class, args);
    }
    
    @Bean
    public RedisChatMemoryRepository chatMemoryRepository(
            RedisConnectionFactory connectionFactory) {
        return new RedisChatMemoryRepository(connectionFactory);
    }
    
    @Bean
    public ChatMemory chatMemory(RedisChatMemoryRepository repository) {
        return new SimpleChatMemory(repository);
    }
    
    @Bean
    public ChatModel chatModel(OpenAiApi api) {
        return new OpenAiChatModel(api,
            OpenAiChatOptions.builder()
                .withModel("gpt-5-mini")
                .withTemperature(0.7f)
                .build());
    }
}

@Service
public class ChatService {
    
    private final ChatModel chatModel;
    private final ChatMemory chatMemory;
    
    public ChatService(ChatModel chatModel, ChatMemory chatMemory) {
        this.chatModel = chatModel;
        this.chatMemory = chatMemory;
    }
    
    public String chat(String userId, String message) {
        // 获取或创建对话
        Conversation conversation = chatMemory.getConversation(userId);
        
        // 添加用户消息
        conversation.addMessage(new UserMessage(message));
        
        // 调用 AI 模型
        String response = chatModel.call(conversation.getMessages());
        
        // 添加 AI 响应
        conversation.addMessage(new AssistantMessage(response));
        
        // 保存对话
        chatMemory.saveConversation(userId, conversation);
        
        return response;
    }
}

示例 2: 使用增强的 Redis Vector Store

java 复制代码
@Configuration
public class VectorStoreConfig {
    
    @Bean
    public RedisVectorStore vectorStore(RedisConnectionFactory connectionFactory) {
        RedisVectorStore.RedisVectorStoreConfig config = 
            RedisVectorStore.RedisVectorStoreConfig.builder()
                .withIndexName("documents")
                .withHnswM(16)
                .withHnswEfConstruction(200)
                .withHnswEfRuntime(50)
                .build();
        
        return new RedisVectorStore(config, connectionFactory);
    }
    
    @Bean
    public VectorStoreRetriever vectorStoreRetriever(RedisVectorStore vectorStore) {
        return new VectorStoreRetriever(vectorStore);
    }
}

@Service
public class DocumentService {
    
    private final VectorStore vectorStore;
    private final EmbeddingModel embeddingModel;
    
    public DocumentService(VectorStore vectorStore, EmbeddingModel embeddingModel) {
        this.vectorStore = vectorStore;
        this.embeddingModel = embeddingModel;
    }
    
    public void addDocument(String id, String text, Map<String, Object> metadata) {
        // 生成嵌入向量
        Embedding embedding = embeddingModel.embed(text);
        
        // 创建文档
        Document document = new Document(id, text, metadata, embedding);
        
        // 添加到向量存储
        vectorStore.add(List.of(document));
    }
    
    public List<Document> search(String query, int topK) {
        // 生成查询向量
        Embedding queryEmbedding = embeddingModel.embed(query);
        
        // 执行相似度搜索
        return vectorStore.similaritySearch(
            SimilaritySearchRequest.builder()
                .withQueryEmbedding(queryEmbedding)
                .withTopK(topK)
                .build()
        );
    }
    
    public List<Document> searchWithMetadata(String query, 
            Map<String, Object> metadataFilter, int topK) {
        // 带元数据过滤的搜索
        Embedding queryEmbedding = embeddingModel.embed(query);
        
        return vectorStore.similaritySearch(
            SimilaritySearchRequest.builder()
                .withQueryEmbedding(queryEmbedding)
                .withTopK(topK)
                .withFilterExpression(buildFilterExpression(metadataFilter))
                .build()
        );
    }
    
    private String buildFilterExpression(Map<String, Object> metadata) {
        // 构建 Redis 过滤表达式
        return metadata.entrySet().stream()
            .map(e -> e.getKey() + "==" + e.getValue())
            .collect(Collectors.joining(" AND "));
    }
}

示例 3: 使用 ToolCallback API

java 复制代码
@Configuration
public class ToolConfig {
    
    @Bean
    public ToolCallback weatherTool() {
        return FunctionToolCallback.builder()
            .withName("getWeather")
            .withDescription("Get current weather for a location")
            .withInputType(WeatherRequest.class)
            .withFunction(this::getWeather)
            .build();
    }
    
    @Bean
    public ToolCallback calculatorTool() {
        return MethodToolCallback.builder()
            .withTarget(this)
            .withMethod("calculate")
            .withName("calculate")
            .withDescription("Perform mathematical calculations")
            .build();
    }
    
    private WeatherResponse getWeather(WeatherRequest request) {
        // 实现天气查询逻辑
        return new WeatherResponse(
            request.getLocation(),
            "Sunny",
            25.0
        );
    }
    
    public double calculate(String expression) {
        // 实现计算逻辑
        // 简化示例
        return 0.0;
    }
}

@SpringBootApplication
public class ToolApplication {
    
    @Bean
    public ChatClient chatClient(ChatModel chatModel, 
            List<ToolCallback> toolCallbacks) {
        return ChatClient.builder()
            .withChatModel(chatModel)
            .defaultTools(toolCallbacks)
            .build();
    }
    
    public static void main(String[] args) {
        SpringApplication.run(ToolApplication.class, args);
    }
}

示例 4: 使用 Claude 4.5 和 Citations API

java 复制代码
@Configuration
public class ClaudeConfig {
    
    @Bean
    public AnthropicChatModel claudeChatModel(AnthropicApi anthropicApi) {
        return new AnthropicChatModel(anthropicApi,
            AnthropicChatOptions.builder()
                .withModel("claude-4-5-sonnet-20241022")
                .withTemperature(0.7f)
                .withMaxTokens(4096)
                .withCitations(true)  // 启用 Citations API
                .build());
    }
}

@Service
public class ClaudeService {
    
    private final AnthropicChatModel chatModel;
    
    public ClaudeService(AnthropicChatModel chatModel) {
        this.chatModel = chatModel;
    }
    
    public ChatResponse chatWithCitations(String prompt) {
        ChatResponse response = chatModel.call(
            new Prompt(prompt)
        );
        
        // 处理引用信息
        if (response.getResult().getMetadata().containsKey("citations")) {
            List<Citation> citations = (List<Citation>) 
                response.getResult().getMetadata().get("citations");
            
            // 处理引用
            citations.forEach(citation -> {
                System.out.println("Citation: " + citation.getText());
                System.out.println("Source: " + citation.getSource());
            });
        }
        
        return response;
    }
}

示例 5: 使用 Azure Cosmos DB Chat Memory

java 复制代码
@Configuration
public class CosmosDbConfig {
    
    @Bean
    public CosmosDbChatMemoryRepository chatMemoryRepository(
            CosmosClient cosmosClient) {
        return new CosmosDbChatMemoryRepository(
            cosmosClient,
            "chat-db",
            "conversations"
        );
    }
    
    @Bean
    public ChatMemory chatMemory(CosmosDbChatMemoryRepository repository) {
        return new SimpleChatMemory(repository);
    }
}

// application.yml
spring:
  ai:
    azure:
      cosmosdb:
        endpoint: https://your-account.documents.azure.com:443/
        key: your-key
        database: chat-db
        container: conversations

最佳实践

1. 配置管理

推荐: 使用配置文件管理 AI 模型参数

yaml 复制代码
# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-5-mini
          temperature: 0.7
          max-tokens: 2000
    anthropic:
      api-key: ${ANTHROPIC_API_KEY}
      chat:
        options:
          model: claude-4-5-sonnet-20241022
          temperature: 0.7
          max-tokens: 4096

2. 错误处理

推荐: 实现统一的错误处理机制

java 复制代码
@RestControllerAdvice
public class AIExceptionHandler {
    
    @ExceptionHandler(AIException.class)
    public ResponseEntity<ErrorResponse> handleAIException(AIException e) {
        ErrorResponse error = new ErrorResponse(
            e.getMessage(),
            e.getErrorCode(),
            Instant.now()
        );
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(error);
    }
    
    @ExceptionHandler(RateLimitException.class)
    public ResponseEntity<ErrorResponse> handleRateLimit(RateLimitException e) {
        // 实现重试逻辑
        return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
            .header("Retry-After", String.valueOf(e.getRetryAfter()))
            .body(new ErrorResponse("Rate limit exceeded", "RATE_LIMIT", Instant.now()));
    }
}

3. 性能优化

推荐: 使用连接池和缓存

java 复制代码
@Configuration
public class PerformanceConfig {
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory factory = new LettuceConnectionFactory();
        factory.setHostName("localhost");
        factory.setPort(6379);
        
        // 配置连接池
        GenericObjectPoolConfig<Object> poolConfig = 
            new GenericObjectPoolConfig<>();
        poolConfig.setMaxTotal(20);
        poolConfig.setMaxIdle(10);
        poolConfig.setMinIdle(5);
        
        return factory;
    }
    
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
    }
}

4. 监控和日志

推荐: 添加详细的监控和日志

java 复制代码
@Component
public class AIMonitoringAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(AIMonitoringAspect.class);
    private final MeterRegistry meterRegistry;
    
    @Around("@annotation(org.springframework.ai.chat.ChatModel)")
    public Object monitorChatCall(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Timer.Sample sample = Timer.start(meterRegistry);
        
        try {
            Object result = joinPoint.proceed();
            sample.stop(Timer.builder("ai.chat.call")
                .tag("method", methodName)
                .tag("status", "success")
                .register(meterRegistry));
            
            logger.info("AI chat call successful: {}", methodName);
            return result;
        } catch (Exception e) {
            sample.stop(Timer.builder("ai.chat.call")
                .tag("method", methodName)
                .tag("status", "error")
                .register(meterRegistry));
            
            logger.error("AI chat call failed: {}", methodName, e);
            throw e;
        }
    }
}

5. 安全实践

推荐: 保护 API 密钥和敏感信息

java 复制代码
@Configuration
public class SecurityConfig {
    
    @Bean
    public OpenAiApi openAiApi(@Value("${spring.ai.openai.api-key}") String apiKey) {
        // 从安全存储中获取密钥
        String secureKey = keyManagementService.getKey("openai-api-key");
        return new OpenAiApi(secureKey);
    }
    
    // 使用环境变量或密钥管理服务
    // 不要在代码中硬编码密钥
    // 使用加密存储敏感配置
}

6. 测试策略

推荐: 编写全面的测试

java 复制代码
@SpringBootTest
class ChatServiceTest {
    
    @MockBean
    private ChatModel chatModel;
    
    @Autowired
    private ChatService chatService;
    
    @Test
    void testChat() {
        // Mock 响应
        when(chatModel.call(anyList())).thenReturn("Hello, how can I help?");
        
        // 测试
        String response = chatService.chat("user1", "Hello");
        
        // 验证
        assertEquals("Hello, how can I help?", response);
        verify(chatModel).call(anyList());
    }
}

总结

Spring AI 2.x 是一个重大升级版本,带来了许多新功能和改进:

主要亮点

  1. 平台现代化: 基于 Spring Boot 4.0 和 Spring Framework 7.0,支持 Java 21
  2. 增强的存储能力: Redis 和 Azure Cosmos DB 聊天记忆支持
  3. 更好的向量搜索: Redis Vector Store 的文本搜索和性能优化
  4. 原生 SDK 集成: OpenAI 官方 Java SDK 支持
  5. 最新模型支持: Claude 4.5、Gemini ThinkingLevel 等
  6. 改进的 API: ToolCallback API 替代 FunctionCallback
相关推荐
黑客思维者3 小时前
机器学习006:监督学习【回归算法】(概论)--教AI从历史中预测未来
人工智能·学习·机器学习·监督学习·回归算法
xunyan62343 小时前
面向对象(下)-内部类的分类
java·学习
高洁013 小时前
DNN案例一步步构建深层神经网络(二)
人工智能·python·深度学习·算法·机器学习
巴拉巴拉~~3 小时前
KMP 算法通用进度条组件:KmpProgressWidget 多维度 + 匹配进度联动 + 平滑动画
java·服务器·前端
合方圆~小文3 小时前
4G定焦球机摄像头综合介绍产品指南
数据结构·数据库·人工智能
Yeniden4 小时前
Deepeek用大白话讲解 --> 迭代器模式(企业级场景1,多种遍历方式2,隐藏集合结构3,Java集合框架4)
java·开发语言·迭代器模式
Coding茶水间4 小时前
基于深度学习的螺栓螺母检测系统演示与介绍(YOLOv12/v11/v8/v5模型+Pyqt5界面+训练代码+数据集)
图像处理·人工智能·深度学习·yolo·目标检测·机器学习·计算机视觉
yiersansiwu123d4 小时前
AI全球善治的困境突破与中国方案的实践路径
人工智能