Spring AI 快速开始

学习目标

  • 理解 Spring AI 框架的核心价值和应用场景
  • 掌握 Spring AI 的快速上手方法
  • 能够在 5 分钟内创建第一个 AI 应用
  • 了解 Spring AI 的学习路线和资源
  • 建立对 AI 应用开发的整体认知

知识结构

Spring AI 快速开始

为什么选择 Spring AI

Spring 生态集成

简化 AI 开发

统一抽象接口

企业级特性

核心概念

ChatClient

Prompt

Model

Response

快速上手

创建项目

添加依赖

配置模型

编写代码

学习路线

基础入门

模型集成

核心功能

高级特性

实战项目

一、项目场景引入

1.1 实际项目需求

在现代企业应用中,AI 能力正在成为标配:

场景 1:智能客服系统

需求:电商平台需要 7x24 小时回答用户咨询
传统方案:雇佣大量客服人员,成本高、响应慢
AI 方案:使用 AI 自动回答常见问题,人工处理复杂问题

场景 2:文档问答系统

需求:企业内部有大量技术文档,员工查找困难
传统方案:手动搜索文档,效率低下
AI 方案:基于企业知识库的智能问答系统

场景 3:代码助手

需求:帮助开发者快速生成代码、审查代码
传统方案:手动编写、人工审查
AI 方案:AI 辅助代码生成和审查

1.2 技术挑战

直接使用 AI 模型 API 面临的问题:

  1. API 调用复杂

    • 不同模型提供商的 API 格式不同
    • 需要处理 HTTP 请求、认证、错误处理
    • 代码重复度高
  2. 缺乏统一抽象

    • OpenAI、Azure、本地模型接口各不相同
    • 切换模型需要大量代码修改
    • 难以维护
  3. 缺少企业级特性

    • 没有现成的缓存机制
    • 没有统一的异常处理
    • 没有监控和日志
  4. 与 Spring 生态集成困难

    • 需要手动管理 Bean
    • 配置管理不统一
    • 难以利用 Spring 的依赖注入

1.3 Spring AI 的解决方案

Spring AI 提供了统一的抽象层:

传统方式:
应用代码 → OpenAI API
应用代码 → Azure API
应用代码 → Ollama API
(每个都需要不同的代码)

Spring AI 方式:
应用代码 → Spring AI 抽象层 → 各种 AI 模型
(统一的接口,配置切换)

核心优势:

  • ✅ 统一的编程接口
  • ✅ 配置化的模型切换
  • ✅ Spring Boot 自动配置
  • ✅ 企业级特性支持
  • ✅ 完善的文档和社区

二、Spring AI 核心思想

2.1 一句话总结

Spring AI = Spring Boot + AI 模型的统一抽象
让 Java 开发者像使用 Spring Data 一样简单地使用 AI

2.2 设计理念

1. 可移植性(Portability)

// 同样的代码,只需修改配置就能切换模型
ChatClient chatClient;  // 可以是 OpenAI、Azure、Ollama...
String response = chatClient.call("你好");

2. 模块化(Modularity)

spring-ai-core          # 核心抽象
spring-ai-openai        # OpenAI 实现
spring-ai-azure-openai  # Azure 实现
spring-ai-ollama        # Ollama 实现

3. Spring 原生(Spring Native)

@Service
public class AIService {
    @Autowired
    private ChatClient chatClient;  // 自动注入
    
    public String chat(String message) {
        return chatClient.call(message);
    }
}

2.3 核心组件

应用代码

ChatClient

EmbeddingClient

ImageClient

ChatModel

EmbeddingModel

ImageModel

OpenAI

Azure OpenAI

Ollama

组件说明:

组件 作用 示例
ChatClient 对话交互 聊天机器人、问答系统
EmbeddingClient 文本向量化 语义搜索、文档检索
ImageClient 图像生成 AI 绘画、图像处理
VectorStore 向量存储 知识库、RAG 应用

三、5 分钟快速上手

3.1 前置准备

环境要求:

  • JDK 17 或更高版本
  • Maven 3.6+ 或 Gradle 7.5+
  • IDE(推荐 IntelliJ IDEA)
  • OpenAI API Key(或其他模型的访问凭证)

获取 API Key:

  1. 访问 https://platform.openai.com/
  2. 注册账号并登录
  3. 进入 API Keys 页面
  4. 创建新的 API Key
  5. 保存 Key(只显示一次)

3.2 创建 Spring Boot 项目

方式 1:使用 Spring Initializr

访问 https://start.spring.io/,配置如下:

Project: Maven
Language: Java
Spring Boot: 3.2.0 或更高
Group: com.example
Artifact: spring-ai-demo
Name: spring-ai-demo
Package name: com.example.springai
Packaging: Jar
Java: 17

方式 2:使用 IDEA 创建

File → New → Project → Spring Initializr
填写项目信息
选择 Spring Boot 版本 3.2.0+

3.3 添加依赖

编辑 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>
    
    <groupId>com.example</groupId>
    <artifactId>spring-ai-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-ai-demo</name>
    <description>Spring AI Demo Project</description>
    
    <properties>
        <java.version>17</java.version>
        <spring-ai.version>0.8.1</spring-ai.version>
    </properties>
    
    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- Spring AI OpenAI -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
        </dependency>
        
        <!-- Lombok(可选,简化代码) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        
        <!-- Spring Boot Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <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>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
    <!-- Spring Milestone 仓库 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

3.4 配置 API Key

创建 src/main/resources/application.yml

spring:
  application:
    name: spring-ai-demo
  
  ai:
    openai:
      # OpenAI API Key
      api-key: ${OPENAI_API_KEY}
      
      # 聊天模型配置
      chat:
        options:
          model: gpt-3.5-turbo
          temperature: 0.7
          max-tokens: 1000

# 服务器配置
server:
  port: 8080

# 日志配置
logging:
  level:
    org.springframework.ai: DEBUG

配置说明:

配置项 说明 默认值
api-key OpenAI API 密钥 必填
model 使用的模型 gpt-3.5-turbo
temperature 创造性(0-2) 0.7
max-tokens 最大输出长度 无限制

环境变量设置:

Windows:

set OPENAI_API_KEY=sk-your-api-key-here

Linux/Mac:

export OPENAI_API_KEY=sk-your-api-key-here

或者在 IDEA 中配置:

Run → Edit Configurations → Environment Variables
添加:OPENAI_API_KEY=sk-your-api-key-here

3.5 编写第一个 AI 应用

项目结构:

src/main/java/com/example/springai/
├── SpringAiDemoApplication.java    # 启动类
├── controller/
│   └── ChatController.java         # 控制器
├── service/
│   └── ChatService.java            # 服务层
└── dto/
    ├── ChatRequest.java            # 请求对象
    └── ChatResponse.java           # 响应对象

1. 创建 DTO 类

ChatRequest.java:

package com.example.springai.dto;

import lombok.Data;

/**
 * 聊天请求对象
 */
@Data
public class ChatRequest {
    /**
     * 用户消息
     */
    private String message;
}

ChatResponse.java:

package com.example.springai.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 聊天响应对象
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatResponse {
    /**
     * AI 回复
     */
    private String reply;
    
    /**
     * 响应时间(毫秒)
     */
    private Long responseTime;
}

2. 创建服务层

ChatService.java:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

/**
 * AI 聊天服务
 * 项目场景:智能客服系统的核心服务
 */
@Service
public class ChatService {
    
    private final ChatClient chatClient;
    
    /**
     * 构造函数注入 ChatClient
     * Spring AI 会自动配置并注入 ChatClient Bean
     */
    public ChatService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 简单对话
     * 
     * @param userMessage 用户消息
     * @return AI 回复
     */
    public String simpleChat(String userMessage) {
        // 直接调用 call 方法,传入字符串
        return chatClient.call(userMessage);
    }
    
    /**
     * 标准对话(推荐方式)
     * 
     * @param userMessage 用户消息
     * @return ChatResponse 包含完整的响应信息
     */
    public ChatResponse chat(String userMessage) {
        // 1. 创建用户消息对象
        Message message = new UserMessage(userMessage);
        
        // 2. 创建 Prompt(提示词)
        Prompt prompt = new Prompt(message);
        
        // 3. 调用 AI 模型
        ChatResponse response = chatClient.call(prompt);
        
        // 4. 返回响应
        return response;
    }
    
    /**
     * 获取 AI 回复文本
     * 
     * @param userMessage 用户消息
     * @return AI 回复文本
     */
    public String getChatReply(String userMessage) {
        ChatResponse response = chat(userMessage);
        return response.getResult().getOutput().getContent();
    }
}

3. 创建控制器

ChatController.java:

package com.example.springai.controller;

import com.example.springai.dto.ChatRequest;
import com.example.springai.dto.ChatResponse;
import com.example.springai.service.ChatService;
import org.springframework.web.bind.annotation.*;

/**
 * AI 聊天控制器
 * 提供 RESTful API 接口
 */
@RestController
@RequestMapping("/api/chat")
public class ChatController {
    
    private final ChatService chatService;
    
    public ChatController(ChatService chatService) {
        this.chatService = chatService;
    }
    
    /**
     * 简单聊天接口
     * GET /api/chat/simple?message=你好
     * 
     * @param message 用户消息
     * @return AI 回复
     */
    @GetMapping("/simple")
    public String simpleChat(@RequestParam String message) {
        return chatService.simpleChat(message);
    }
    
    /**
     * 标准聊天接口
     * POST /api/chat
     * Body: {"message": "你好"}
     * 
     * @param request 聊天请求
     * @return 聊天响应
     */
    @PostMapping
    public ChatResponse chat(@RequestBody ChatRequest request) {
        long startTime = System.currentTimeMillis();
        
        // 调用服务层
        String reply = chatService.getChatReply(request.getMessage());
        
        long responseTime = System.currentTimeMillis() - startTime;
        
        // 返回响应
        return new ChatResponse(reply, responseTime);
    }
    
    /**
     * 健康检查接口
     * GET /api/chat/health
     * 
     * @return 健康状态
     */
    @GetMapping("/health")
    public String health() {
        return "Spring AI is running!";
    }
}

4. 启动类

SpringAiDemoApplication.java:

package com.example.springai;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Spring AI 演示应用
 */
@SpringBootApplication
public class SpringAiDemoApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SpringAiDemoApplication.class, args);
    }
}

3.6 运行和测试

1. 启动应用

# 方式 1:使用 Maven
mvn spring-boot:run

# 方式 2:使用 IDEA
右键 SpringAiDemoApplication → Run

# 方式 3:打包后运行
mvn clean package
java -jar target/spring-ai-demo-0.0.1-SNAPSHOT.jar

2. 测试接口

使用 curl 测试:

# 测试健康检查
curl http://localhost:8080/api/chat/health

# 测试简单聊天(GET)
curl "http://localhost:8080/api/chat/simple?message=你好"

# 测试标准聊天(POST)
curl -X POST http://localhost:8080/api/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "介绍一下 Spring AI"}'

使用 Postman 测试:

1. 创建 POST 请求
2. URL: http://localhost:8080/api/chat
3. Headers: Content-Type: application/json
4. Body (raw JSON):
{
  "message": "你好,请介绍一下自己"
}
5. 点击 Send

3. 预期响应

{
  "reply": "你好!我是一个 AI 助手,基于 Spring AI 框架开发。我可以回答各种问题,提供信息和建议。有什么我可以帮助你的吗?",
  "responseTime": 1523
}

3.7 代码执行流程

OpenAI API ChatClient ChatService ChatController 客户端 OpenAI API ChatClient ChatService ChatController 客户端 {"message": "你好"} API Key 认证 AI 生成的回复 {"reply": "...", "responseTime": 1523} POST /api/chat getChatReply("你好") 创建 UserMessage 创建 Prompt call(prompt) HTTP Request HTTP Response ChatResponse 提取回复文本 String reply 计算响应时间 ChatResponse JSON

四、核心概念速览

4.1 ChatClient

作用: 与 AI 模型进行对话交互的客户端

核心方法:

// 方法 1:简单调用
String reply = chatClient.call("你好");

// 方法 2:使用 Prompt
Prompt prompt = new Prompt("你好");
ChatResponse response = chatClient.call(prompt);

// 方法 3:流式响应
Flux<ChatResponse> stream = chatClient.stream(prompt);

自动配置:

// Spring AI 自动配置,无需手动创建
@Autowired
private ChatClient chatClient;

4.2 Prompt(提示词)

作用: 封装发送给 AI 模型的消息和参数

组成部分:

Prompt = Messages + Options
         ↓           ↓
      消息内容    模型参数

示例:

// 1. 简单 Prompt
Prompt prompt = new Prompt("你好");

// 2. 带消息的 Prompt
Message message = new UserMessage("你好");
Prompt prompt = new Prompt(message);

// 3. 带参数的 Prompt
OpenAiChatOptions options = OpenAiChatOptions.builder()
    .withModel("gpt-4")
    .withTemperature(0.8)
    .build();
Prompt prompt = new Prompt("你好", options);

4.3 Message(消息)

消息类型:

类型 类名 作用 示例
用户消息 UserMessage 用户输入 “你好”
系统消息 SystemMessage 设定角色 “你是一个专业的客服”
助手消息 AssistantMessage AI 回复 “你好,有什么可以帮助你的?”

示例:

// 用户消息
Message userMsg = new UserMessage("介绍一下 Spring AI");

// 系统消息(设定角色)
Message systemMsg = new SystemMessage("你是一个 Java 技术专家");

// 多轮对话
List<Message> messages = List.of(
    new SystemMessage("你是一个友好的助手"),
    new UserMessage("你好"),
    new AssistantMessage("你好!有什么可以帮助你的?"),
    new UserMessage("介绍一下 Spring AI")
);
Prompt prompt = new Prompt(messages);

4.4 ChatResponse(响应)

响应结构:

ChatResponse
├── Result                    # 主要结果
│   ├── Output               # 输出内容
│   │   └── Content          # 文本内容
│   └── Metadata             # 元数据
│       ├── FinishReason     # 结束原因
│       └── ContentFilter    # 内容过滤
└── Metadata                 # 响应元数据
    ├── Usage                # Token 使用情况
    │   ├── PromptTokens     # 输入 Token 数
    │   ├── GenerationTokens # 输出 Token 数
    │   └── TotalTokens      # 总 Token 数
    └── RateLimit            # 速率限制

获取响应内容:

ChatResponse response = chatClient.call(prompt);

// 获取回复文本
String content = response.getResult().getOutput().getContent();

// 获取 Token 使用情况
Usage usage = response.getMetadata().getUsage();
Long promptTokens = usage.getPromptTokens();
Long generationTokens = usage.getGenerationTokens();
Long totalTokens = usage.getTotalTokens();

// 获取结束原因
String finishReason = response.getResult().getMetadata().getFinishReason();

4.5 自动配置原理

Spring AI 的自动配置流程:

spring-ai-openai

spring-ai-azure

spring-ai-ollama

应用启动

检测依赖

加载 OpenAI 自动配置

加载 Azure 自动配置

加载 Ollama 自动配置

读取配置文件

创建 ChatClient Bean

创建 EmbeddingClient Bean

注入到应用

应用可以使用

配置类示例:

// Spring AI 自动配置(无需手动编写)
@Configuration
@ConditionalOnClass(OpenAiApi.class)
@EnableConfigurationProperties(OpenAiChatProperties.class)
public class OpenAiAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public ChatClient chatClient(OpenAiChatProperties properties) {
        return new OpenAiChatClient(
            new OpenAiApi(properties.getApiKey()),
            properties.getOptions()
        );
    }
}

五、实战应用场景

5.1 场景一:智能问答机器人

需求: 创建一个能回答技术问题的机器人

实现:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 技术问答服务
 */
@Service
public class TechQAService {
    
    private final ChatClient chatClient;
    
    // 系统提示词:设定 AI 的角色和行为
    private static final String SYSTEM_PROMPT = """
        你是一个专业的 Java 技术专家,擅长 Spring 框架和微服务架构。
        请用简洁、专业的语言回答技术问题。
        如果问题超出你的知识范围,请诚实地说明。
        """;
    
    public TechQAService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 回答技术问题
     * 
     * @param question 技术问题
     * @return 答案
     */
    public String answerQuestion(String question) {
        // 创建消息列表
        List<org.springframework.ai.chat.messages.Message> messages = List.of(
            new SystemMessage(SYSTEM_PROMPT),
            new UserMessage(question)
        );
        
        // 创建 Prompt
        Prompt prompt = new Prompt(messages);
        
        // 调用 AI
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
}

控制器:

package com.example.springai.controller;

import com.example.springai.service.TechQAService;
import org.springframework.web.bind.annotation.*;

/**
 * 技术问答控制器
 */
@RestController
@RequestMapping("/api/qa")
public class TechQAController {
    
    private final TechQAService qaService;
    
    public TechQAController(TechQAService qaService) {
        this.qaService = qaService;
    }
    
    /**
     * 提问接口
     * POST /api/qa/ask
     * Body: {"question": "什么是 Spring Boot?"}
     */
    @PostMapping("/ask")
    public String ask(@RequestBody QuestionRequest request) {
        return qaService.answerQuestion(request.getQuestion());
    }
    
    // 请求对象
    public record QuestionRequest(String question) {}
}

测试:

curl -X POST http://localhost:8080/api/qa/ask \
  -H "Content-Type: application/json" \
  -d '{"question": "什么是 Spring Boot 自动配置?"}'

5.2 场景二:文本摘要生成器

需求: 自动生成文章摘要

实现:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

/**
 * 文本摘要服务
 */
@Service
public class SummaryService {
    
    private final ChatClient chatClient;
    
    public SummaryService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 生成文本摘要
     * 
     * @param text 原文
     * @param maxWords 摘要最大字数
     * @return 摘要
     */
    public String generateSummary(String text, int maxWords) {
        // 构建提示词
        String promptText = String.format("""
            请为以下文本生成一个不超过 %d 字的摘要。
            要求:
            1. 保留核心信息
            2. 语言简洁明了
            3. 不要添加原文没有的内容
            
            原文:
            %s
            
            摘要:
            """, maxWords, text);
        
        // 创建 Prompt
        Prompt prompt = new Prompt(new UserMessage(promptText));
        
        // 调用 AI
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
    
    /**
     * 生成多语言摘要
     * 
     * @param text 原文
     * @param language 目标语言
     * @return 摘要
     */
    public String generateSummaryInLanguage(String text, String language) {
        String promptText = String.format("""
            请为以下文本生成一个 %s 语言的摘要,不超过 100 字。
            
            原文:
            %s
            
            %s 摘要:
            """, language, text, language);
        
        Prompt prompt = new Prompt(new UserMessage(promptText));
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
}

控制器:

package com.example.springai.controller;

import com.example.springai.service.SummaryService;
import lombok.Data;
import org.springframework.web.bind.annotation.*;

/**
 * 摘要生成控制器
 */
@RestController
@RequestMapping("/api/summary")
public class SummaryController {
    
    private final SummaryService summaryService;
    
    public SummaryController(SummaryService summaryService) {
        this.summaryService = summaryService;
    }
    
    /**
     * 生成摘要
     * POST /api/summary/generate
     */
    @PostMapping("/generate")
    public SummaryResponse generate(@RequestBody SummaryRequest request) {
        String summary = summaryService.generateSummary(
            request.getText(),
            request.getMaxWords()
        );
        return new SummaryResponse(summary);
    }
    
    /**
     * 生成多语言摘要
     * POST /api/summary/translate
     */
    @PostMapping("/translate")
    public SummaryResponse translateSummary(@RequestBody TranslateSummaryRequest request) {
        String summary = summaryService.generateSummaryInLanguage(
            request.getText(),
            request.getLanguage()
        );
        return new SummaryResponse(summary);
    }
    
    @Data
    public static class SummaryRequest {
        private String text;
        private int maxWords = 100;
    }
    
    @Data
    public static class TranslateSummaryRequest {
        private String text;
        private String language = "English";
    }
    
    public record SummaryResponse(String summary) {}
}

测试:

# 生成中文摘要
curl -X POST http://localhost:8080/api/summary/generate \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Spring AI 是 Spring 生态系统中用于构建 AI 应用的框架...",
    "maxWords": 50
  }'

# 生成英文摘要
curl -X POST http://localhost:8080/api/summary/translate \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Spring AI 是 Spring 生态系统中用于构建 AI 应用的框架...",
    "language": "English"
  }'

5.3 场景三:代码解释器

需求: 解释代码的功能和原理

实现:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 代码解释服务
 */
@Service
public class CodeExplainerService {
    
    private final ChatClient chatClient;
    
    private static final String SYSTEM_PROMPT = """
        你是一个专业的代码解释器。
        请用清晰、易懂的语言解释代码的功能和原理。
        解释应该包括:
        1. 代码的整体功能
        2. 关键代码的作用
        3. 使用的技术和模式
        4. 可能的优化建议
        """;
    
    public CodeExplainerService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 解释代码
     * 
     * @param code 代码
     * @param language 编程语言
     * @return 解释
     */
    public String explainCode(String code, String language) {
        String userPrompt = String.format("""
            请解释以下 %s 代码:
            
            ```%s
            %s
            ```
            """, language, language, code);
        
        List<org.springframework.ai.chat.messages.Message> messages = List.of(
            new SystemMessage(SYSTEM_PROMPT),
            new UserMessage(userPrompt)
        );
        
        Prompt prompt = new Prompt(messages);
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
    
    /**
     * 代码审查
     * 
     * @param code 代码
     * @return 审查意见
     */
    public String reviewCode(String code) {
        String userPrompt = String.format("""
            请审查以下代码,指出潜在的问题和改进建议:
            
            ```java
            %s
            ```
            
            请从以下方面进行审查:
            1. 代码规范
            2. 性能问题
            3. 安全隐患
            4. 可维护性
            5. 最佳实践
            """, code);
        
        Prompt prompt = new Prompt(new UserMessage(userPrompt));
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
}

控制器:

package com.example.springai.controller;

import com.example.springai.service.CodeExplainerService;
import lombok.Data;
import org.springframework.web.bind.annotation.*;

/**
 * 代码解释控制器
 */
@RestController
@RequestMapping("/api/code")
public class CodeExplainerController {
    
    private final CodeExplainerService codeExplainerService;
    
    public CodeExplainerController(CodeExplainerService codeExplainerService) {
        this.codeExplainerService = codeExplainerService;
    }
    
    /**
     * 解释代码
     * POST /api/code/explain
     */
    @PostMapping("/explain")
    public ExplanationResponse explain(@RequestBody CodeRequest request) {
        String explanation = codeExplainerService.explainCode(
            request.getCode(),
            request.getLanguage()
        );
        return new ExplanationResponse(explanation);
    }
    
    /**
     * 审查代码
     * POST /api/code/review
     */
    @PostMapping("/review")
    public ExplanationResponse review(@RequestBody ReviewRequest request) {
        String review = codeExplainerService.reviewCode(request.getCode());
        return new ExplanationResponse(review);
    }
    
    @Data
    public static class CodeRequest {
        private String code;
        private String language = "Java";
    }
    
    @Data
    public static class ReviewRequest {
        private String code;
    }
    
    public record ExplanationResponse(String explanation) {}
}

测试:

# 解释代码
curl -X POST http://localhost:8080/api/code/explain \
  -H "Content-Type: application/json" \
  -d '{
    "code": "@Service\npublic class UserService {\n    @Autowired\n    private UserRepository userRepository;\n}",
    "language": "Java"
  }'

# 审查代码
curl -X POST http://localhost:8080/api/code/review \
  -H "Content-Type: application/json" \
  -d '{
    "code": "public String getUser(String id) {\n    return userRepository.findById(id).get();\n}"
  }'

六、Spring AI 学习路线

6.1 学习路径图

开始学习

第一阶段:基础入门

第二阶段:模型集成

第三阶段:核心功能

第四阶段:高级特性

第五阶段:实战项目

第六阶段:生产部署

快速开始

核心概念

环境搭建

OpenAI 集成

Azure OpenAI

Ollama 本地模型

模型切换

Chat Client

Prompt Engineering

Function Calling

Embedding

向量检索

RAG 应用

智能客服

文档问答

代码助手

性能优化

监控告警

成本控制

6.2 学习时间规划

阶段 内容 建议时间 学习目标
第一阶段 基础入门 1-2 天 能够创建简单的 AI 应用
第二阶段 模型集成 2-3 天 掌握多种模型的集成方法
第三阶段 核心功能 3-5 天 掌握对话、提示词、函数调用
第四阶段 高级特性 5-7 天 掌握 RAG、向量检索等高级功能
第五阶段 实战项目 7-10 天 完成完整的 AI 应用项目
第六阶段 生产部署 3-5 天 掌握生产环境部署和优化

总计: 约 3-4 周完成完整学习

6.3 学习建议

1. 循序渐进

  • 不要跳过基础章节
  • 每个知识点都要动手实践
  • 理解原理比记忆 API 更重要

2. 项目驱动

  • 边学边做项目
  • 从简单项目开始
  • 逐步增加复杂度

3. 多看源码

  • 阅读 Spring AI 源码
  • 理解自动配置原理
  • 学习设计模式

4. 关注社区

  • 关注 Spring AI 官方文档
  • 参与 GitHub 讨论
  • 学习优秀的开源项目

6.4 学习资源

官方资源:

推荐博客:

  • Spring 官方博客
  • Baeldung Spring AI 教程
  • DZone Spring AI 文章

视频教程:

  • Spring I/O 大会视频
  • YouTube Spring AI 教程
  • B站 Spring AI 中文教程

开源项目:

  • spring-ai-examples
  • awesome-spring-ai
  • spring-ai-demos

七、最佳实践

7.1 配置管理

使用环境变量管理敏感信息:

# application.yml
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}  # ✓ 使用环境变量
      # api-key: sk-xxx            # ✗ 不要硬编码

多环境配置:

# application-dev.yml(开发环境)
spring:
  ai:
    openai:
      chat:
        options:
          model: gpt-3.5-turbo
          temperature: 0.7

# application-prod.yml(生产环境)
spring:
  ai:
    openai:
      chat:
        options:
          model: gpt-4
          temperature: 0.5

7.2 异常处理

统一异常处理:

package com.example.springai.exception;

import org.springframework.ai.retry.RetryUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    /**
     * 处理 AI 调用异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleAIException(Exception e) {
        // 记录日志
        log.error("AI 调用失败", e);
        
        // 返回友好的错误信息
        ErrorResponse error = new ErrorResponse(
            "AI_ERROR",
            "AI 服务暂时不可用,请稍后重试",
            System.currentTimeMillis()
        );
        
        return ResponseEntity
            .status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(error);
    }
    
    public record ErrorResponse(
        String code,
        String message,
        Long timestamp
    ) {}
}

7.3 日志记录

添加详细的日志:

package com.example.springai.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

/**
 * 带日志的聊天服务
 */
@Slf4j
@Service
public class LoggingChatService {
    
    private final ChatClient chatClient;
    
    public LoggingChatService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    public String chat(String message) {
        log.info("收到用户消息: {}", message);
        
        long startTime = System.currentTimeMillis();
        
        try {
            Prompt prompt = new Prompt(message);
            ChatResponse response = chatClient.call(prompt);
            
            String reply = response.getResult().getOutput().getContent();
            long duration = System.currentTimeMillis() - startTime;
            
            // 记录 Token 使用情况
            var usage = response.getMetadata().getUsage();
            log.info("AI 响应成功 - 耗时: {}ms, Token: {}/{}/{}", 
                duration,
                usage.getPromptTokens(),
                usage.getGenerationTokens(),
                usage.getTotalTokens()
            );
            
            return reply;
            
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("AI 调用失败 - 耗时: {}ms", duration, e);
            throw e;
        }
    }
}

7.4 性能优化

使用缓存减少 API 调用:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * 带缓存的聊天服务
 */
@Service
public class CachedChatService {
    
    private final ChatClient chatClient;
    
    public CachedChatService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 缓存相同问题的答案
     * 
     * @param message 用户消息
     * @return AI 回复
     */
    @Cacheable(value = "chatResponses", key = "#message")
    public String chat(String message) {
        return chatClient.call(message);
    }
}

配置缓存:

package com.example.springai.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;

import java.time.Duration;

/**
 * 缓存配置
 */
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofHours(1))  // 缓存 1 小时
            .disableCachingNullValues();
        
        return RedisCacheManager.builder(connectionFactory)
            .cacheDefaults(config)
            .build();
    }
}

7.5 成本控制

限制 Token 使用:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

/**
 * 成本控制服务
 */
@Service
public class CostControlService {
    
    private final ChatClient chatClient;
    
    public CostControlService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 限制 Token 数量的对话
     * 
     * @param message 用户消息
     * @param maxTokens 最大 Token 数
     * @return AI 回复
     */
    public String chatWithLimit(String message, int maxTokens) {
        // 设置 Token 限制
        OpenAiChatOptions options = OpenAiChatOptions.builder()
            .withMaxTokens(maxTokens)
            .build();
        
        Prompt prompt = new Prompt(message, options);
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
    
    /**
     * 使用更便宜的模型
     * 
     * @param message 用户消息
     * @return AI 回复
     */
    public String chatWithCheapModel(String message) {
        // 使用 gpt-3.5-turbo 而不是 gpt-4
        OpenAiChatOptions options = OpenAiChatOptions.builder()
            .withModel("gpt-3.5-turbo")
            .build();
        
        Prompt prompt = new Prompt(message, options);
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
}

八、常见问题

Q1: 如何获取 OpenAI API Key?

A:

  1. 访问 https://platform.openai.com/
  2. 注册并登录账号
  3. 进入 API Keys 页面
  4. 点击 “Create new secret key”
  5. 复制并保存 Key(只显示一次)
  6. 设置环境变量或配置文件

注意事项:

  • API Key 只显示一次,请妥善保存
  • 不要将 API Key 提交到代码仓库
  • 定期更换 API Key
  • 监控 API 使用量和费用

Q2: 为什么调用 AI 很慢?

A: 可能的原因和解决方案:

原因 1:网络问题

问题:国内访问 OpenAI API 可能较慢
解决:使用代理或选择国内的 AI 服务商

原因 2:模型选择

问题:gpt-4 比 gpt-3.5-turbo 慢
解决:根据需求选择合适的模型

原因 3:Token 数量过多

问题:生成的内容太长
解决:限制 max-tokens 参数

原因 4:没有使用缓存

问题:相同问题重复调用 API
解决:使用 Redis 缓存结果

Q3: 如何处理 API 调用失败?

A: 实现重试机制:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

/**
 * 带重试的聊天服务
 */
@Service
public class RetryableChatService {
    
    private final ChatClient chatClient;
    
    public RetryableChatService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 自动重试的对话方法
     * 最多重试 3 次,每次间隔 2 秒
     */
    @Retryable(
        maxAttempts = 3,
        backoff = @Backoff(delay = 2000)
    )
    public String chatWithRetry(String message) {
        return chatClient.call(message);
    }
}

启用重试:

package com.example.springai.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;

@Configuration
@EnableRetry
public class RetryConfig {
}

Q4: 如何切换到其他 AI 模型?

A: 只需修改依赖和配置:

切换到 Azure OpenAI:

<!-- 替换依赖 -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
</dependency>
# 修改配置
spring:
  ai:
    azure:
      openai:
        api-key: ${AZURE_OPENAI_API_KEY}
        endpoint: ${AZURE_OPENAI_ENDPOINT}

切换到 Ollama(本地模型):

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: llama2

代码无需修改!

Q5: 如何控制 AI 的回复风格?

A: 使用 System Message 和 Temperature 参数:

package com.example.springai.service;

import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 风格控制服务
 */
@Service
public class StyleControlService {
    
    private final ChatClient chatClient;
    
    public StyleControlService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 专业风格回复
     */
    public String professionalChat(String message) {
        SystemMessage systemMsg = new SystemMessage(
            "你是一个专业的技术顾问,回答要准确、简洁、专业。"
        );
        UserMessage userMsg = new UserMessage(message);
        
        // 低 temperature = 更确定性的回复
        OpenAiChatOptions options = OpenAiChatOptions.builder()
            .withTemperature(0.3)
            .build();
        
        Prompt prompt = new Prompt(List.of(systemMsg, userMsg), options);
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
    
    /**
     * 创意风格回复
     */
    public String creativeChat(String message) {
        SystemMessage systemMsg = new SystemMessage(
            "你是一个富有创意的助手,回答要生动、有趣、富有想象力。"
        );
        UserMessage userMsg = new UserMessage(message);
        
        // 高 temperature = 更有创造性的回复
        OpenAiChatOptions options = OpenAiChatOptions.builder()
            .withTemperature(1.5)
            .build();
        
        Prompt prompt = new Prompt(List.of(systemMsg, userMsg), options);
        
        return chatClient.call(prompt)
            .getResult()
            .getOutput()
            .getContent();
    }
}

Q6: 如何监控 API 使用情况?

A: 记录和统计 Token 使用:

package com.example.springai.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

/**
 * 使用监控服务
 */
@Slf4j
@Service
public class UsageMonitorService {
    
    private final ChatClient chatClient;
    
    // 统计信息
    private long totalRequests = 0;
    private long totalPromptTokens = 0;
    private long totalGenerationTokens = 0;
    private long totalTokens = 0;
    
    public UsageMonitorService(ChatClient chatClient) {
        this.chatClient = chatClient;
    }
    
    /**
     * 带监控的对话
     */
    public String chatWithMonitoring(String message) {
        Prompt prompt = new Prompt(message);
        ChatResponse response = chatClient.call(prompt);
        
        // 更新统计信息
        var usage = response.getMetadata().getUsage();
        totalRequests++;
        totalPromptTokens += usage.getPromptTokens();
        totalGenerationTokens += usage.getGenerationTokens();
        totalTokens += usage.getTotalTokens();
        
        // 记录日志
        log.info("API 调用统计 - 总请求: {}, 总 Token: {}", 
            totalRequests, totalTokens);
        
        return response.getResult().getOutput().getContent();
    }
    
    /**
     * 获取使用统计
     */
    public UsageStats getUsageStats() {
        return new UsageStats(
            totalRequests,
            totalPromptTokens,
            totalGenerationTokens,
            totalTokens
        );
    }
    
    public record UsageStats(
        long totalRequests,
        long totalPromptTokens,
        long totalGenerationTokens,
        long totalTokens
    ) {}
}

九、练习题

基础练习

练习 1:创建简单的翻译服务

要求:

  • 创建一个翻译服务,支持中英互译
  • 提供 REST API 接口
  • 返回翻译结果和耗时

提示:

@Service
public class TranslationService {
    public String translate(String text, String targetLanguage) {
        // TODO: 实现翻译逻辑
    }
}

练习 2:实现情感分析服务

要求:

  • 分析文本的情感倾向(正面/负面/中性)
  • 返回情感分类和置信度
  • 提供批量分析接口

提示:

public record SentimentResult(
    String sentiment,  // POSITIVE, NEGATIVE, NEUTRAL
    double confidence
) {}

练习 3:创建关键词提取服务

要求:

  • 从文本中提取关键词
  • 支持指定提取数量
  • 返回关键词和权重

进阶练习

练习 4:实现多轮对话

要求:

  • 支持上下文记忆
  • 每个用户独立的对话历史
  • 提供清除历史的接口

提示:

@Service
public class ConversationService {
    // 存储对话历史
    private Map<String, List<Message>> conversationHistory = new ConcurrentHashMap<>();
    
    public String chat(String userId, String message) {
        // TODO: 实现多轮对话
    }
}

练习 5:实现智能客服路由

要求:

  • 根据用户问题类型自动路由
  • 技术问题 → 技术客服
  • 售后问题 → 售后客服
  • 其他问题 → 通用客服

提示:

public enum QuestionType {
    TECHNICAL, AFTER_SALES, GENERAL
}

public QuestionType classifyQuestion(String question) {
    // TODO: 使用 AI 分类问题
}

练习 6:实现内容审核服务

要求:

  • 检测文本中的敏感内容
  • 返回审核结果和原因
  • 支持自定义审核规则

综合练习

练习 7:构建完整的智能问答系统

要求:

  1. 用户管理(注册、登录)
  2. 问答功能(提问、回答)
  3. 历史记录(查看、删除)
  4. 统计分析(使用量、Token 消耗)
  5. 管理后台(用户管理、数据统计)

技术栈:

  • Spring Boot 3.2+
  • Spring AI
  • MySQL(用户和历史数据)
  • Redis(缓存和会话)
  • Spring Security(认证授权)

项目结构:

intelligent-qa-system/
├── src/main/java/
│   ├── controller/
│   │   ├── AuthController.java
│   │   ├── QAController.java
│   │   └── AdminController.java
│   ├── service/
│   │   ├── UserService.java
│   │   ├── QAService.java
│   │   └── StatisticsService.java
│   ├── repository/
│   │   ├── UserRepository.java
│   │   └── QAHistoryRepository.java
│   ├── entity/
│   │   ├── User.java
│   │   └── QAHistory.java
│   └── config/
│       ├── SecurityConfig.java
│       └── AIConfig.java
└── src/main/resources/
    ├── application.yml
    └── schema.sql

十、学习检查清单

完成以下检查项,确保你已经掌握了 Spring AI 快速开始的内容:

基础知识

  • 理解 Spring AI 的核心价值和应用场景
  • 了解 Spring AI 的设计理念和核心组件
  • 掌握 Spring AI 与传统 AI API 调用的区别
  • 理解 Spring AI 的自动配置原理

环境搭建

  • 能够创建 Spring Boot 项目
  • 能够正确添加 Spring AI 依赖
  • 能够配置 API Key 和模型参数
  • 能够成功启动 Spring AI 应用

核心概念

  • 理解 ChatClient 的作用和使用方法
  • 掌握 Prompt 的创建和配置
  • 了解 Message 的类型和用途
  • 能够解析 ChatResponse 获取所需信息

代码实践

  • 能够编写简单的对话服务
  • 能够创建 REST API 接口
  • 能够处理用户请求和 AI 响应
  • 能够添加日志和异常处理

实战应用

  • 完成至少 1 个实战案例
  • 能够根据需求设计 AI 应用
  • 能够优化 Prompt 提高回复质量
  • 能够测试和调试 AI 应用

最佳实践

  • 掌握配置管理的最佳实践
  • 了解异常处理和重试机制
  • 能够添加缓存优化性能
  • 了解成本控制的方法

问题解决

  • 能够解决常见的配置问题
  • 能够处理 API 调用失败
  • 能够优化响应速度
  • 能够监控 API 使用情况

十一、下一步学习

完成快速开始后,建议按以下顺序继续学习:

1. Spring AI 概述与核心概念

  • 深入理解 Spring AI 架构
  • 学习核心接口和抽象
  • 掌握设计模式和最佳实践

2. 环境搭建与第一个 AI 应用

  • 详细的环境配置
  • 完整的项目开发流程
  • 生产环境部署指南

3. 模型集成

  • OpenAI 模型集成
  • Azure OpenAI 集成
  • Ollama 本地模型集成
  • 模型切换和配置管理

4. 核心功能

  • Chat Client 深入使用
  • Prompt Engineering 技巧
  • Function Calling 实战
  • 流式响应处理

5. 高级特性

  • Embedding 和向量化
  • 向量数据库集成
  • RAG 应用开发
  • 异步处理和缓存

6. 实战项目

  • 智能客服系统
  • 文档问答系统
  • AI 代码助手
  • 内容生成系统

十二、扩展阅读

官方文档

技术博客

视频教程

开源项目

相关技术

总结

恭喜你完成了 Spring AI 快速开始的学习!

你现在已经:

  • ✅ 了解了 Spring AI 的核心价值
  • ✅ 掌握了快速创建 AI 应用的方法
  • ✅ 理解了 Spring AI 的核心概念
  • ✅ 完成了多个实战案例
  • ✅ 学习了最佳实践和常见问题

下一步:
继续学习 Spring AI 的深入内容,完成更多实战项目,成为 AI 应用开发专家!

记住:

  • 实践是最好的学习方法
  • 不要害怕犯错,从错误中学习
  • 保持好奇心,持续探索新技术
  • 分享你的学习成果,帮助他人

祝你学习愉快!🎉

Logo

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

更多推荐