学习内容一览

  • Spring AI 2.0核心架构:ChatClient、ChatModel、Advisors API
  • 第一个Spring AI项目搭建:引入 spring-ai-starter,配置 API Key,完成 Hello World
  • Spring AI抽象设计理解:模型切换仅需修改配置,无需更改代码
  • 流式输出(Streaming)体验:借助 Spring WebFlux 实现“打字机”式输出

推荐资源


项目搭建与第一个接口

目标

创建 Spring AI 项目,配置 DeepSeek/通义千问,跑通第一个对话接口

步骤详解

1. 创建项目
方式一(推荐):使用 Spring Initializr 快速生成
  • 访问 Spring Initializr
  • 主要配置如下:
    • Project: Maven
    • Language: Java
    • Spring Boot: 4.1.1
    • Java: 21
    • Dependencies: Spring Web + Spring AI OpenAI
DeepSeek/通义千问兼容 OpenAI 接口,选这个 starter 即可
方式二:手动创建 Maven 项目
  • 参考核心 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>4.1.1</version>
        <relativePath/>
    </parent>
    <groupId>com.hejie</groupId>
    <artifactId>ai-study</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ai-study</name>

    <properties>
        <java.version>21</java.version>
        <spring-ai.version>2.0.1</spring-ai.version>
    </properties>
    <dependencies>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Spring AI -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-model-openai</artifactId>
        </dependency>
        <!-- Resilience4j -->
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot3</artifactId>
            <version>2.1.0</version>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </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>
</project>

2. 配置 application.yml
  • 重点:API Key 使用环境变量,不要写死在配置文件
  • 支持 DeepSeek 和通义千问(Qwen3.8-27b)模型切换
  • 集成 Resilience4j 实现熔断、限流、超时、舱壁等能力
server:
  port: 8080

spring:
  application:
    name: ai-study
  servlet:
    encoding:
      enabled: true
      force-response: true
      charset: UTF-8
  threads:
    virtual:
      enabled: true
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      # DeepSeek
#      base-url: https://api.deepseek.com
#      chat:
#        model: deepseek-chat
#        temperature: 0.7
      # 通义千问
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      chat:
        model: qwen3.8-27b
        temperature: 0.7

logging:
  level:
    org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor: DEBUG

resilience4j:
    circuitbreaker:
      configs:
        default:
          slidingWindowSize: 10
          failureRateThreshold: 50
          waitDurationInOpenState: 10000
          permittedNumberOfCallsInHalfOpenState: 5
          registerHealthIndicator: true
      instances:
        default:
          baseConfig: default
        chat-service:
          slidingWindowSize: 10
          failureRateThreshold: 50
          waitDurationInOpenState: 10000
          permittedNumberOfCallsInHalfOpenState: 5
          registerHealthIndicator: true
    ratelimiter:
      configs:
        default:
          limitForPeriod: 100
          limitRefreshPeriod: 1000ms
          timeoutDuration: 0ms
      instances:
        default:
          baseConfig: default
        chat-service:
          limitRefreshPeriod: 1000ms
          limitForPeriod: 5
          timeoutDuration: 0
    timelimiter:
      configs:
        default:
          timeoutDuration: 3000ms
      instances:
        default:
          baseConfig: default
        chat-service:
          timeoutDuration: 3000ms
    bulkhead:
      configs:
        default:
          maxConcurrentCalls: 50
          maxWaitDuration: 500ms
      instances:
        default:
          baseConfig: default
        chat-service:
          maxConcurrentCalls: 10

3. ChatClient 配置
3.1 通过提示词模板创建客户端
@Configuration
public class PromptClientConfiguration {
    @Bean
    public ChatClient conceptExplainChatClient(ChatModel chatModel) throws IOException {
        return ChatClient.builder(chatModel)
                .defaultSystem(new String(Files.readAllBytes(Paths.get("src/main/resources/templates/concept-explain-prompt.txt"))))
                .defaultUser("从以下内容中提取技术概念的名称、分类、一句话解释:\n")
                .build();
    }

    @Bean
    public ChatClient codeReviewChatClient(ChatModel chatModel) throws IOException {
        return ChatClient.builder(chatModel)
                .defaultSystem(new String(Files.readAllBytes(Paths.get("src/main/resources/templates/code-review-prompt.txt"))))
                .defaultUser("请审查以下代码:\n")
                .build();
    }
}
3.2 多模型客户端配置
  • 支持“快/深”两种模式,灵活应对不同场景
@Configuration
public class MultModelsClientConfiguration {
    @Bean("fastChatClient")
    public ChatClient fastChatClient(ChatClient.Builder builder) {
        return builder
                .defaultSystem("你是一个简洁的技术助手,回答控制在100字以内。")
                .defaultOptions(ChatOptions.builder()
                        .model("deepseek-chat")
                        .temperature(0.3))
                .build();
    }

    @Bean("deepChatClient")
    public ChatClient deepChatClient(ChatClient.Builder builder) {
        return builder
                .defaultSystem("你是一个资深架构师,回答要详细、有深度,先给框架再逐步分析。")
                .defaultOptions(ChatOptions.builder()
                        .model("qwen3.8-27b")
                        .temperature(0.7))
                .build();
    }
}

4. Controller 层接口设计
4.1 聊天相关接口
  • 纯文本对话:/chat/chat
  • 完整响应对象(含 token 消耗等元数据):/chat/detail
  • 结构化提取(返回 Java 对象):/chat/extract
  • 流式输出(打字机效果):/chat/stream
@RestController
@RequestMapping("/chat")
public class ChatController {

    @Resource
    private ChatClient conceptExplainChatClient;

    @GetMapping("/chat")
    @CircuitBreaker(name = "chat-service", fallbackMethod = "chatFallback")
    @RateLimiter(name = "chat-service")
    @TimeLimiter(name = "chat-service")
    @Bulkhead(name = "chat-service", type = Bulkhead.Type.SEMAPHORE)
    public String chat(@RequestParam String message) {
        return conceptExplainChatClient.prompt()
                .user(message)
                .call()
                .content();
    }

    public CompletableFuture<String> chatFallback(String message, Exception e) {
        return CompletableFuture.supplyAsync(() -> "服务繁忙,请稍后重试");
    }

    @GetMapping("/detail")
    public Map<String, Object> chatDetail(@RequestParam String message) {
        ChatResponse response = conceptExplainChatClient.prompt()
                .user(message)
                .call()
                .chatResponse();
        return Map.of(
                "content", response.getResult().getOutput().getText(),
                "model", response.getMetadata().getModel(),
                "usage", response.getMetadata().getUsage().toString()
        );
    }

    @GetMapping("/extract")
    public TechConceptVO extract(@RequestParam String text) {
        return conceptExplainChatClient.prompt()
                .user(text)
                .call()
                .entity(TechConceptVO.class);
    }

    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatStream(@RequestParam String message) {
        SimpleLoggerAdvisor customLogger = SimpleLoggerAdvisor.builder()
                .requestToString(request -> "【用户提问】: " + request.prompt().getUserMessage())
                .responseToString(response -> "【AI回复】: " + response.getResult().getOutput().getText())
                .build();
        return conceptExplainChatClient.prompt()
                .user(message)
                .advisors(customLogger)
                .stream()
                .content();
    }
}
  • 结构化输出对象示例:
@Data
public class TechConceptVO {
    String name;       // 概念名称
    String category;   // 分类
    String explanation;// 一句话解释
}

4.2 代码审核相关接口
@RestController
@RequestMapping("/code")
public class CodeReviewController {

    @Resource
    private ChatClient codeReviewChatClient;

    @GetMapping("/review")
    public String reviewCode(@RequestParam String code) {
        return codeReviewChatClient.prompt()
                .user(code)
                .call()
                .content();
    }
}

4.3 多模型相关接口
  • 支持快速模式(fast)与深度模式(deep)切换,满足不同对话需求
@RestController
@RequestMapping("/model")
public class MutiModelController {

    @Resource
    private ChatClient fastChatClient;

    @Resource
    private ChatClient deepChatClient;

    @GetMapping("/smart-chat")
    public String smartChat(@RequestParam String message, @RequestParam(defaultValue = "fast") String mode) {
        ChatClient client = "deep".equals(mode) ? deepChatClient : fastChatClient;
        return client.prompt()
                .user(message)
                .call()
                .content();
    }
}

5. 启动与测试
  • 设置环境变量,启动项目:
export OPENAI_API_KEY=你的key mvn spring-boot:run

以上为 Spring AI 2.0 项目搭建及核心接口整理,涵盖了从依赖配置、模型切换到流式输出的完整流程,适合快速入门和实战参考。如有疑问,欢迎留言交流!
Logo

一站式 AI 云服务平台

更多推荐