创建Spring AI项目

前置环境要求

  1. JDK 17+(SpringBoot3 强制最低 JDK17,不支持 JDK8/11)
  2. IDEA 2022.3+ 版本
  3. Maven 3.8.6+ / Gradle 7.5+

image

 

image

 

 

分模块推荐勾选(普通后端 Web 项目,按需复制)

Spring Boot 版本选 4.1.0(稳定正式版,不要选带 SNAPSHOT 快照版)

一、开发工具(Development,必选 3 个)

  1. ✅ Spring Boot DevTools:热部署,改代码不用手动重启服务
  2. ✅ Lombok:实体类自动生成 get/set、toString,简化代码
  3. ✅ Spring Configuration Processor:yaml 配置文件自动提示,无警告

二、Web 模块(Web,做接口必须选)

展开 Web 分组,勾选:
 
✅ Spring Web
 
内置 Tomcat,提供 Controller、Restful 接口能力,前后端交互核心依赖

三、SQL 数据库(有 MySQL/Oracle 才选,纯接口演示可跳过)

展开 SQL 分组:
  1. ✅ MySQL Driver:MySQL 数据库驱动
  2. 二选一持久层框架:
    • 传统 MyBatis 开发:MyBatis Framework
    • JPA 自动化 CRUD:Spring Data JPA

四、测试(Testing,默认必带,不用手动勾)

创建后自动引入 Spring Boot Test,写单元测试用

五、其他按需扩展(新手起步先不选)

  • Template Engines:Thymeleaf 模板(前后不分离页面才用,Vue 前端项目跳过)
  • Security:登录权限、OAuth2(需要登录验证再勾)
  • NoSQL:Redis/MongoDB(用到缓存 / 文档库再勾)
  • GraalVM Native Support:云原生编译,普通开发不用
  • Docker Compose Support:本地一键启动数据库容器,新手暂时不用

最简基础勾选清单(只做接口演示、无数据库)

Development:DevTools、Lombok、Configuration Processor
 
Web:Spring Web

带 MySQL+MyBatis 完整勾选清单(日常业务后端)

  1. Development:Spring Boot DevTools、Lombok、Spring Configuration Processor
  2. Web:Spring Web
  3. SQL:MySQL Driver、MyBatis Framework

 

image

 

 

application.yaml
spring:
  application:
    name: demo-springboot3
  ai:
    deepseek:
      api-key: 你的api_key
      # 可选:自定义接口地址(国内代理/私有化部署时填)
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-v4-flash   # 最新模型名,推荐

  

如果测试环境不需要数据库,则需要添加exclude过滤

@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class // 不用数据库,跳过数据源
})
public class DemoSpringboot3Application {

    public static void main(String[] args) {
        SpringApplication.run(DemoSpringboot3Application.class, args);
    }

}

  

创建测试的controller

import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.deepseek.DeepSeekChatOptions;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * DeepSeek 聊天控制器,提供同步问答、带参问答和流式输出三种接口。
 *
 * <p>基于 Spring AI 的 {@link DeepSeekChatModel} 封装,支持普通文本响应和 SSE 流式推送。
 */
@RestController
public class DeepSeekController {

    // SpringAI自动装配好Bean,直接注入
    private final DeepSeekChatModel deepSeekChatModel;
    // 全局自增序号,每条流式分片+1
    private final AtomicLong seqNum = new AtomicLong(0);
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss.SSS");

    /**
     * 构造方法,通过 Spring 自动注入 DeepSeek 聊天模型实例。
     *
     * @param deepSeekChatModel DeepSeek 聊天模型,由 Spring AI 自动装配
     */
    public DeepSeekController(DeepSeekChatModel deepSeekChatModel) {
        this.deepSeekChatModel = deepSeekChatModel;
    }

    /**
     * 简单问答接口,同步调用 DeepSeek 模型并返回完整回复。
     *
     * @param msg 用户发送的消息内容
     * @return DeepSeek 模型返回的完整文本响应
     */
    @GetMapping("/chat")
    public String chat(@RequestParam String msg) {
        // 简单问答
        String response = deepSeekChatModel.call(msg);
        return response;
    }

    /**
     * 带自定义参数的问答接口,支持指定模型、温度和最大 Token 数。
     *
     * @param msg 用户发送的消息内容
     * @return DeepSeek 模型返回的完整文本响应
     */
    @GetMapping("/chat/param")
    public String chatWithParam(@RequestParam String msg) {
//        自定义参数(模型、温度、最大长度)
        // 构建参数
        DeepSeekChatOptions options = DeepSeekChatOptions.builder()
                .model("deepseek-v4-flash") // 对话模型,deepseek-reasoner是深度思考
                .temperature(0.7) // 随机性0~1,越低回答越固定
                .maxTokens(1024)
                .build();

        Prompt prompt = new Prompt(msg, options);
        return deepSeekChatModel.call(prompt).getResult().getOutput().getText();
    }

    /**
     * 流式聊天接口,以 Server-Sent Events(SSE)格式向前推送 DeepSeek 模型的实时响应。
     *
     * <p>处理流程:
     * <ol>
     *     <li>调用 DeepSeek 流式 API 获取 ChatResponse 响应流</li>
     *     <li>过滤空响应,提取文本片段</li>
     *     <li>通过 bufferTimeout 将短时间内的多条片段合并为一批,减少推送频率</li>
     *     <li>封装为带序号和时间戳的 JSON 格式 SSE 事件</li>
     * </ol>
     *
     * @param msg 用户发送的消息内容
     * @return 以 SSE 格式推送的 Flux 字符串流,每条数据格式为 {@code data:{"seq":N,"timestamp":"HH:mm:ss.SSS","delta":"文本"}}
     */
    @GetMapping(value = "/stream/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChat(@RequestParam String msg) {
        return deepSeekChatModel.stream(new Prompt(msg))
                // 过滤无效响应,提取非空文本片段
                .filter(r -> r.getResult() != null && r.getResult().getOutput() != null)
                .mapNotNull(r -> r.getResult().getOutput().getText())
                .filter(text -> !text.isEmpty())
                // 规范SSE格式,前端EventSource兼容
                .bufferTimeout(12, Duration.ofMillis(80))
                .map(list -> String.join("", list))
                // 封装为带序号、时间戳的 SSE JSON 事件
                .map(chunk -> String.format("data:{\"seq\":%d,\"timestamp\":\"%s\",\"delta\":\"%s\"}\n\n",
                        seqNum.incrementAndGet(), LocalDateTime.now().format(FORMATTER), chunk))
                .onErrorResume(e -> Flux.just("data:【服务异常】\n\n"));
    }
}

  

posted @ 2026-07-15 13:35  show-code  阅读(17)  评论(0)    收藏  举报