SpringAI 完全指南:为Java应用注入生成式AI能力

1. SpringAI 框架概述

SpringAI是Spring官方推出的AI应用开发框架,它将大模型能力封装成Spring Boot风格,让Java开发者能够像使用其他Spring组件一样轻松集成AI功能。SpringAI的核心价值在于提供统一API抽象层,支持多种主流AI模型和服务,同时保持Spring生态的简洁性和一致性。

核心定位与优势

  • 标准化接入:提供类似JdbcTemplate的模板方法调用LLM(大语言模型),降低学习成本
  • 多模型支持:统一接口支持OpenAI、Azure OpenAI、Ollama(本地模型)、Hugging Face等20+种AI服务
  • 企业级特性:内置重试机制、限流策略、监控指标等生产就绪功能
  • Spring生态集成:完美继承Spring Boot的自动配置特性,配置驱动,开箱即用

与Python生态的LangChain相对应,SpringAI为Java开发者提供了同等级别的AI应用开发体验,支持从简单的文本生成到复杂的RAG(检索增强生成)应用场景。

2. 环境准备与项目配置

2.1 开发环境要求

在开始使用SpringAI前,需确保您的开发环境满足以下要求:

  • JDK版本:JDK 17或更高版本(推荐JDK 21)
  • Spring Boot:3.0.0或更高版本(推荐3.2.x)
  • 构建工具:Maven 3.6+ 或 Gradle 8.5+
  • IDE:IntelliJ IDEA、Eclipse或VS Code等

2.2 项目初始化与依赖配置

使用Spring Initializr创建项目时,选择以下依赖:

  • Spring Web
  • Spring AI Starter(根据需要的模型选择具体starter)
  • Lombok(可选,简化代码)

Maven依赖配置(以OpenAI为例):

xml 复制代码
<dependencyManagement>
    <dependencies>
        <!-- Spring AI BOM -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0-M2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- Spring Boot BOM -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.2.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- Spring AI OpenAI Starter -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

如需使用本地模型(如通过Ollama),可替换为:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
    <version>1.0.0-M2</version>
</dependency>

由于Spring AI版本迭代较快,可能需要添加相应的仓库配置:

xml 复制代码
<repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>https://repo.spring.io/milestone</url>
        <snapshots><enabled>false</enabled></snapshots>
    </repository>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>https://repo.spring.io/snapshot</url>
        <releases><enabled>false</enabled></releases>
    </repository>
</repositories>

2.3 应用配置

application.yml中配置模型参数(以OpenAI为例):

yaml 复制代码
spring:
  ai:
    openai:
      api-key: sk-your-api-key-here  # 替换为您的API密钥
      base-url: https://api.openai.com/v1
      chat:
        options:
          model: gpt-4  # 或 gpt-3.5-turbo
          temperature: 0.7
          timeout: 60s

如果使用本地Ollama模型,配置如下:

yaml 复制代码
spring:
  ai:
    ollama:
      base-url: http://localhost:11434  # Ollama服务地址
      chat:
        model: qwen2.5:7b  # 本地部署的模型名称

3. 基础功能与快速入门

3.1 创建第一个AI接口

SpringAI的核心入口是ChatClient接口,它提供了简化的大模型调用方法。

基础控制器实现

java 复制代码
@RestController
@RequiredArgsConstructor
public class ChatController {
    
    private final ChatClient chatClient;
    
    @GetMapping("/chat")
    public String chat(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

启动应用后,访问http://localhost:8080/chat?message=介绍一下Spring Boot即可获得AI响应。

3.2 使用专用模型客户端

除了通用的ChatClient,SpringAI还为不同模型提供了专用客户端,如OpenAIChatModelOllamaChatModel等,这些客户端提供更丰富的模型特定功能。

使用专用客户端的示例

java 复制代码
@RestController
public class TextGenerationController {
    
    private final OllamaChatModel ollamaChatModel;
    
    public TextGenerationController(OllamaChatModel ollamaChatModel) {
        this.ollamaChatModel = ollamaChatModel;
    }
    
    // 普通输出
    @GetMapping("/generate")
    public String generate(@RequestParam String prompt) {
        return ollamaChatModel.call(prompt);
    }
    
    // 流式输出(SSE)
    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> generateStream(@RequestParam String prompt) {
        return ollamaChatModel.stream(prompt);
    }
}

3.3 流式响应与实时输出

对于生成较长内容的场景,流式响应可以显著提升用户体验,避免长时间等待:

java 复制代码
@GetMapping(value = "/stream-chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String prompt) {
    return chatClient.prompt()
            .user(prompt)
            .stream()
            .content();
}

前端可通过Server-Sent Events (SSE)或WebSocket接收流式响应,实现打字机效果。

4. 核心功能深入解析

4.1 提示工程与模板化

Prompt工程是AI应用的核心,SpringAI通过PromptTemplate支持模板化提示,提升输出质量与一致性。

基础提示模板使用

java 复制代码
@GetMapping("/summary")
public String summarize(@RequestParam String text) {
    String template = "请用一句话总结以下文本: {input}";
    
    return chatClient.prompt()
            .user(template, Map.of("input", text))
            .call()
            .content();
}

多角色提示模板: 对于复杂场景,可以定义系统角色和用户角色,实现更精确的控制:

java 复制代码
@GetMapping("/translation")
public String translation(@RequestParam String text) {
    String systemPrompt = """
            你是一名专业的翻译专家,擅长技术文档翻译。
            你的名字是TranslatePro,翻译时应保持专业性和准确性。
            """;
    
    String userPrompt = "将以下英文技术文档翻译成中文: {query}";
    
    // 系统提示词
    SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);
    Message systemMessage = systemPromptTemplate.createMessage();
    
    // 用户提示词
    PromptTemplate userPromptTemplate = new PromptTemplate(userPrompt);
    Message userMessage = userPromptTemplate.createMessage(Map.of("query", text));
    
    // 组合提示词
    Prompt prompt = new Prompt(Arrays.asList(systemMessage, userMessage));
    
    return chatClient.generate(prompt).content();
}

4.2 结构化输出

SpringAI支持将AI输出自动转换为Java对象,极大简化了数据处理流程:

定义数据结构

java 复制代码
@Data
public class WeatherInfo {
    private String location;
    private String forecast;
    private int temperature;
    private String advice;
}

获取结构化响应

java 复制代码
@GetMapping("/weather")
public WeatherInfo getWeather(@RequestParam String place) {
    return chatClient.prompt()
            .user("请提供{place}的天气情况,并返回结构化数据", 
                  Map.of("place", place))
            .call()
            .entity(WeatherInfo.class);
}

4.3 上下文管理与多轮对话

实现多轮对话需要维护对话历史,SpringAI提供了ChatMemory组件来管理对话上下文。

配置对话记忆

java 复制代码
@Configuration
public class AiConfig {
    
    @Bean
    public ChatMemory chatMemory() {
        return new InMemoryChatMemory(50); // 保留最近50轮对话
    }
}

使用记忆功能的对话服务

java 复制代码
@Service
public class AIService {
    
    private final ChatClient chatClient;
    private final ChatMemory chatMemory;
    
    public AIService(ChatClient chatClient, ChatMemory chatMemory) {
        this.chatClient = chatClient;
        this.chatMemory = chatMemory;
    }
    
    public String chatWithMemory(String userInput, String sessionId) {
        // 获取当前会话的对话历史
        List<Message> history = chatMemory.get(sessionId);
        
        // 构建新消息
        Message userMessage = new UserMessage(userInput);
        List<Message> messages = new ArrayList<>();
        
        // 添加历史对话
        if (history != null) {
            messages.addAll(history);
        }
        messages.add(userMessage);
        
        // 调用AI
        Prompt prompt = new Prompt(messages);
        ChatResponse response = chatClient.generate(prompt);
        Message aiMessage = response.getResult().getOutput();
        
        // 更新对话历史
        messages.add(aiMessage);
        chatMemory.put(sessionId, messages);
        
        return aiMessage.getContent();
    }
}

5. 高级应用场景

5.1 RAG(检索增强生成)

RAG技术结合本地知识库与大模型能力,实现基于私有数据的智能问答。SpringAI内置了向量数据库支持,可轻松实现RAG应用。

向量存储与检索配置

java 复制代码
@Configuration
public class RagConfig {
    
    @Bean
    public VectorStore vectorStore(EmbeddingModel embeddingModel) {
        // 可使用多种向量存储:Milvus、PgVector、Redis等
        InMemoryVectorStore vectorStore = new InMemoryVectorStore(embeddingModel);
        return vectorStore;
    }
    
    @Bean
    @DependsOn("vectorStore")
    public VectorStoreRetriever vectorStoreRetriever(VectorStore vectorStore) {
        return new VectorStoreRetriever(vectorStore);
    }
}

知识库初始化与RAG查询

java 复制代码
@Service
public class KnowledgeBaseService {
    
    private final VectorStore vectorStore;
    private final ChatClient chatClient;
    private final VectorStoreRetriever retriever;
    
    public KnowledgeBaseService(VectorStore vectorStore, ChatClient chatClient, 
                               VectorStoreRetriever retriever) {
        this.vectorStore = vectorStore;
        this.chatClient = chatClient;
        this.retriever = retriever;
    }
    
    @PostConstruct
    public void initKnowledgeBase() {
        // 初始化知识库文档
        List<Document> documents = List.of(
            new Document("Spring是一个流行的Java开发框架,提供了依赖注入功能。"),
            new Document("Spring AI支持OpenAI、Ollama等多种大语言模型。"),
            new Document("Spring Boot简化了Spring应用的初始搭建和开发过程。")
        );
        
        vectorStore.add(documents);
    }
    
    public String askQuestion(String question) {
        // 1. 检索相关文档
        List<Document> relatedDocs = retriever.retrieve(question);
        
        // 2. 构建增强提示
        String context = relatedDocs.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n\n"));
        
        String enhancedPrompt = """
                请根据以下上下文信息回答问题。如果上下文没有提供足够信息,请说明。
                
                上下文:
                {context}
                
                问题:{question}
                """;
        
        return chatClient.prompt()
                .user(enhancedPrompt, 
                      Map.of("context", context, "question", question))
                .call()
                .content();
    }
}

5.2 文档处理与ETL

SpringAI支持处理多种格式的文档(PDF、Word、HTML等),可提取文本内容供AI分析。

文档读取示例

java 复制代码
@Service
public class DocumentService {
    
    public List<Document> processPdf(String filePath) {
        // 使用Tika解析PDF文档
        DocumentReader reader = new TikaDocumentReader();
        return reader.read("file://" + filePath);
    }
    
    public String analyzeDocument(String filePath, String question) {
        // 读取文档
        List<Document> docs = processPdf(filePath);
        
        // 组合文档内容
        String content = docs.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n"));
        
        // 基于文档内容提问
        return chatClient.prompt()
                .user("根据以下文档内容回答问题:{question}\n\n文档内容:{content}", 
                      Map.of("question", question, "content", content))
                .call()
                .content();
    }
}

5.3 多模型混合调用

在企业级应用中,可能需要根据场景切换不同模型,SpringAI通过@Qualifier注解支持多模型配置。

多模型配置

yaml 复制代码
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4
    azure:
      openai:
        api-key: ${AZURE_OPENAI_KEY}
        endpoint: ${AZURE_OPENAI_ENDPOINT}
        chat:
          options:
            model: gpt-35-turbo
    ollama:
      base-url: http://localhost:11434
      chat:
        model: qwen2.5:7b

模型路由服务

java 复制代码
@Service
public class ModelRouterService {
    
    private final ChatClient openAIClient;
    private final ChatClient azureClient;
    private final ChatClient ollamaClient;
    
    public ModelRouterService(@Qualifier("openAiChatClient") ChatClient openAIClient,
                             @Qualifier("azureChatClient") ChatClient azureClient,
                             @Qualifier("ollamaChatClient") ChatClient ollamaClient) {
        this.openAIClient = openAIClient;
        this.azureClient = azureClient;
        this.ollamaClient = ollamaClient;
    }
    
    public String routeRequest(String query, ModelType modelType) {
        ChatClient targetClient = switch (modelType) {
            case OPENAI -> openAIClient;
            case AZURE -> azureClient;
            case OLLAMA -> ollamaClient;
        };
        
        return targetClient.prompt()
                .user(query)
                .call()
                .content();
    }
    
    public enum ModelType {
        OPENAI, AZURE, OLLAMA
    }
}

6. 生产环境最佳实践

6.1 性能优化与监控

超时与重试配置

yaml 复制代码
spring:
  ai:
    openai:
      chat:
        options:
          timeout: 30s
          
# 重试配置
spring:
  cloud:
    circuitbreaker:
      retry:
        instances:
          ai-service:
            maxAttempts: 3
            backoff:
              delay: 1000
              multiplier: 2

监控与日志

yaml 复制代码
logging:
  level:
    org.springframework.ai: DEBUG
    com.example.ai: INFO

6.2 异常处理与容错

java 复制代码
@RestControllerAdvice
public class AiExceptionHandler {
    
    @ExceptionHandler(AiClientException.class)
    public ResponseEntity<ErrorResponse> handleAiException(AiClientException ex) {
        ErrorResponse error = new ErrorResponse("AI_SERVICE_ERROR", 
                "AI服务暂时不可用,请稍后重试");
        return ResponseEntity.status(503).body(error);
    }
    
    @ExceptionHandler(TimeoutException.class)
    public ResponseEntity<ErrorResponse> handleTimeoutException(TimeoutException ex) {
        ErrorResponse error = new ErrorResponse("REQUEST_TIMEOUT", 
                "请求超时,请稍后重试");
        return ResponseEntity.status(504).body(error);
    }
}

6.3 安全与隐私考虑

  • API密钥管理:使用Vault或Kubernetes Secrets管理敏感信息
  • 数据脱敏:在处理用户数据前进行脱敏处理
  • 访问控制:实现基于角色的AI服务访问权限控制
  • 审计日志:记录所有AI调用详情以满足合规要求

7. 总结与展望

SpringAI为Java开发者提供了强大而灵活的AI集成能力,大大降低了在Spring应用中添加智能功能的门槛。通过本文的介绍,您应该已经掌握了:

  1. 环境配置:如何正确配置SpringAI依赖和模型参数
  2. 基础用法:使用ChatClient进行简单的AI对话
  3. 高级特性:提示工程、结构化输出、上下文管理等核心功能
  4. 企业级应用:RAG、文档处理、多模型路由等实战场景
相关推荐
间彧2 小时前
Logback、Log4j与SLF4J的区别与选型指南
后端
间彧2 小时前
Logback详解与Spring Boot项目实战指南
后端
ezl1fe2 小时前
RAG 每日一技(二十一):让证据“会算账”——差异对照与可核验公式的最小闭环
人工智能·后端·程序员
开心猴爷2 小时前
FTP 抓包分析实战,命令、被动主动模式要点、FTPS 与 SFTP 区别及真机取证流程
后端
本当迷ya3 小时前
最新2025年SpringBoot集成PowerJob分布式任务调度
后端
骈拇3 小时前
ConcurrentHashMap细节分析
后端
不爱编程的小九九3 小时前
小九源码-springboot082-java旅游攻略平台
java·开发语言·旅游
只是懒得想了3 小时前
用C++实现一个高效可扩展的行为树(Behavior Tree)框架
java·开发语言·c++·design-patterns
码农阿树3 小时前
Java 离线视频目标检测性能优化:从 Graphics2D 到 OpenCV 原生绘图的 20 倍性能提升实战
java·yolo·目标检测·音视频