在这里插入图片描述

2027届的毕设季已经拉开序幕。如果你还在做一个"用户管理+增删改查+分页查询"的管理系统,答辩时大概率会被评委一句"创新点在哪里"问住。今年最大的变化是:大模型API的价格已经低到学生党也能承受,而Spring官方推出的Spring AI框架让接入过程缩短到了几十行代码。一个能对话、能理解上下文的智能问答模块,正在从"锦上添花"变成"毕设标配"。

这篇文章手把手带你用Spring Boot 3 + Spring AI 1.0接入DeepSeek大模型API,实现一个带流式输出(打字机效果)的智能问答模块。所有代码均可直接运行,看完就能动手。


一、为什么大模型API是今年毕设的最佳加分项

先看三组数据,理解今年的趋势变了什么。

2026年春节期间,国产AI大模型迎来史上最密集的发布潮,字节跳动推出豆包大模型2.0系列,DeepSeek V4系列也已完成多轮价格下调,API调用成本降至"白菜价"。具体到DeepSeek的定价:

模型版本 输入(缓存命中) 输入(缓存未命中) 输出
DeepSeek-V4-Pro 0.025元/百万tokens 3元/百万tokens 6元/百万tokens
DeepSeek-V3 2元/百万tokens 2元/百万tokens 8元/百万tokens

什么概念?一次普通问答大约消耗2000 tokens,用V3模型的成本不到0.02元。整个毕设开发期间调用量再大,总花费也很难超过10块钱。这意味着成本不再是接入AI的障碍

第二个变化在框架层面。Spring官方在2025年正式发布了Spring AI 1.0 GA版本,到2026年已迭代至1.0.2,提供了清晰的ChatClient和EmbeddingClient API,原生支持流式响应。以前自己拼HTTP请求、处理SSE解析的脏活累活,现在一个starter依赖就搞定了。

第三个变化在选题层面。各大高校的毕设选题指导中,"人工智能与机器学习"方向占比持续上升,深度学习、智能推荐、NLP情感分析等方向成为热门。但纯算法方向对数学和模型训练要求高,多数同学吃不消。而"业务系统+大模型API"这种组合,既保留了完整的工程开发量,又通过AI模块拿到了创新点,性价比最高。

一句话总结今年的选型逻辑:用工程能力搭骨架,用AI模块长灵魂


二、技术选型:为什么是Spring AI + DeepSeek

大模型接入方案不止一种,先做一轮横向对比,帮你避开选型阶段的纠结。

方案 优点 缺点 适合场景
Spring AI + DeepSeek API 官方框架、代码简洁、支持流式、成本极低 依赖网络、有API延迟 毕设首选,开发快、答辩好讲
直接HTTP调用大模型API 无额外依赖、灵活 需手动处理SSE、代码冗余 想展示底层原理的同学
Ollama本地部署DeepSeek-R1 无API费用、数据不出本地 需要GPU、部署复杂、答辩演示风险高 有显卡且想写"本地部署"亮点的同学
接入智谱清言/通义千问API 国产模型、中文能力强 API格式与OpenAI略有差异 对中文场景有特殊要求的项目

本文选择Spring AI + DeepSeek组合,理由有三:DeepSeek兼容OpenAI接口格式,Spring AI原生支持,零额外适配;价格全行业最低,学生无负担;模型效果在国产大模型中第一梯队,答辩时有说服力。


三、后端实战:Spring Boot 3接入DeepSeek流式问答

3.1 项目初始化

用Spring Initializr创建项目,选择JDK 21(LTS版本,也是当前推荐),勾选Spring Web和Lombok依赖。JDK 17也可以,但21的虚拟线程特性在毕设里也是个加分点。

3.2 添加Spring AI依赖

pom.xml中添加Spring AI的BOM和OpenAI starter。DeepSeek兼容OpenAI接口协议,所以直接用OpenAI的starter即可:

<properties>
    <java.version>21</java.version>
    <spring-ai.version>1.0.2</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>

<dependencies>
    <!-- Spring AI OpenAI starter,DeepSeek兼容此协议 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    <!-- Spring Web,提供REST接口 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- WebFlux,流式响应需要Reactor的Flux -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
</dependencies>

3.3 配置DeepSeek连接

application.yml中配置DeepSeek的API地址和密钥。先去DeepSeek开放平台注册账号,创建API Key,复制下来填入配置:

spring:
  ai:
    openai:
      api-key: sk-你的deepseek密钥
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat
          temperature: 0.7
          max-tokens: 2048

这里有个关键点:base-url必须改成DeepSeek的地址,默认值是OpenAI的官方地址,不改会报401。modeldeepseek-chat(对话模型)或deepseek-reasoner(推理模型,带思维链)。

3.4 编写流式问答Controller

Spring AI 1.0的核心入口是ChatClient,通过Builder模式构建请求,调用.stream()方法返回Flux<ChatResponse>,实现逐字输出:

package com.example.aidemo.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.Map;

@RestController
@RequestMapping("/api/ai")
public class ChatController {

    private final ChatClient chatClient;

    // 通过构造器注入,Spring AI会自动配置ChatClient.Builder
    public ChatController(ChatClient.Builder builder) {
        // 预设系统提示词,约束模型角色和回答风格
        this.chatClient = builder
                .defaultSystem("你是一个智能学习助手,用简洁清晰的中文回答问题。"
                        + "回答控制在300字以内,适当使用分点说明。")
                .build();
    }

    /**
     * 流式问答接口,前端通过SSE接收逐字输出
     * 返回 text/event-stream 格式,前端用EventSource对接
     */
    @GetMapping(value = "/chat/stream", produces = "text/event-stream;charset=UTF-8")
    public Flux<String> chatStream(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .stream()
                .content();
    }

    /**
     * 普通问答接口,一次性返回完整回答
     * 适合不需要打字机效果的后台接口
     */
    @PostMapping("/chat")
    public Map<String, String> chat(@RequestBody Map<String, String> body) {
        String message = body.get("message");
        String response = chatClient.prompt()
                .user(message)
                .call()
                .content();
        return Map.of("answer", response);
    }
}

上面这段代码包含两个接口:/api/ai/chat/stream是流式接口,用GET + SSE方式逐字返回;/api/ai/chat是普通接口,POST请求一次性返回完整回答。流式接口用了.stream().content(),返回的Flux<String>会被Spring WebFlux自动转成SSE事件流。

启动项目后可以直接用浏览器测试流式接口:

http://localhost:8080/api/ai/chat/stream?message=用一句话解释什么是RBAC权限控制

你会看到文字一个字一个字地出现,这就是流式输出的效果。

3.5 多轮对话上下文管理

单轮问答只能一问一答,缺乏上下文。毕设答辩时评委一定会问"能不能连续对话"。用Spring AI的Advisor机制可以实现多轮上下文:

package com.example.aidemo.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api/ai")
public class ChatController {

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        // 创建内存级对话记忆,保留最近20条消息
        InMemoryChatMemory memory = new InMemoryChatMemory();
        
        this.chatClient = builder
                .defaultSystem("你是一个智能学习助手,用简洁清晰的中文回答问题。")
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(memory).build())
                .build();
    }

    /**
     * 带会话ID的多轮流式对话
     * conversationId用于区分不同用户的对话
     */
    @GetMapping(value = "/chat/stream", produces = "text/event-stream;charset=UTF-8")
    public Flux<String> chatStream(
            @RequestParam String message,
            @RequestParam(defaultValue = "default") String conversationId) {
        
        return chatClient.prompt()
                .user(message)
                .advisors(a -> a.param("chat_memory_conversation_id", conversationId))
                .stream()
                .content();
    }
}

MessageChatMemoryAdvisor会自动把历史消息注入到请求中,conversationId用于区分不同用户的对话。前端每次请求带上同一个conversationId,模型就能"记住"之前的对话内容。注意InMemoryChatMemory是存内存的,重启就没了,如果毕设需要持久化对话记录,可以自己实现ChatMemory接口把记录存到MySQL。


四、前端对接:Vue 3实现打字机效果

后端有了SSE接口,前端用Vue 3 + EventSource对接,实现经典的"打字机"效果。

<template>
  <div class="chat-container">
    <!-- 消息列表 -->
    <div class="messages" ref="msgBox">
      <div v-for="(msg, i) in messages" :key="i" :class="['msg', msg.role]">
        <span class="role">{{ msg.role === 'user' ? '我' : 'AI' }}</span>
        <p>{{ msg.content }}</p>
      </div>
    </div>
    <!-- 输入框 -->
    <div class="input-area">
      <input
        v-model="input"
        @keyup.enter="send"
        placeholder="输入你的问题..."
        :disabled="loading"
      />
      <button @click="send" :disabled="loading || !input">
        {{ loading ? '回答中...' : '发送' }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, nextTick } from 'vue'

const input = ref('')
const loading = ref(false)
const messages = ref([])
const msgBox = ref(null)

const send = async () => {
  const text = input.value.trim()
  if (!text || loading.value) return

  // 添加用户消息
  messages.value.push({ role: 'user', content: text })
  input.value = ''
  loading.value = true

  // 添加AI消息占位,后续逐字填充
  const aiMsg = reactive({ role: 'assistant', content: '' })
  messages.value.push(aiMsg)

  // 用EventSource连接SSE流式接口
  const url = `/api/ai/chat/stream?message=${encodeURIComponent(text)}`
  const eventSource = new EventSource(url)

  eventSource.onmessage = (event) => {
    // 每收到一个字符片段,追加到AI消息中
    aiMsg.content += event.data
    scrollToBottom()
  }

  eventSource.onerror = () => {
    eventSource.close()
    loading.value = false
  }

  eventSource.addEventListener('complete', () => {
    eventSource.close()
    loading.value = false
  })
}

const scrollToBottom = async () => {
  await nextTick()
  if (msgBox.value) {
    msgBox.value.scrollTop = msgBox.value.scrollHeight
  }
}
</script>

<style scoped>
.chat-container { max-width: 680px; margin: 0 auto; padding: 20px; }
.messages { height: 400px; overflow-y: auto; border: 1px solid #e0e0e0; border-radius: 8px; padding: 16px; }
.msg { margin-bottom: 16px; }
.msg.user { text-align: right; }
.msg .role { font-weight: bold; color: #409eff; margin-right: 6px; }
.msg p { display: inline; line-height: 1.6; }
.input-area { display: flex; gap: 8px; margin-top: 12px; }
.input-area input { flex: 1; padding: 8px 12px; border: 1px solid #dcdfe6; border-radius: 4px; }
.input-area button { padding: 8px 20px; background: #409eff; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
</style>

注意前端用Vite开发时需要配置代理,把/api转发到后端localhost:8080,否则会有跨域问题。在vite.config.js中添加:

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  }
})

五、进阶:从单轮问答到知识库问答(RAG)

如果只做一个大模型对话接口,答辩时可能被问"你的模型知道你们学校的信息吗"。大模型的训练数据有截止日期,对特定领域知识一无所知。这时候就需要RAG(检索增强生成)——先从你的知识库中检索相关内容,再喂给大模型让它基于这些内容回答。

Spring AI提供了VectorStore接口和EmbeddingClient,整套RAG流程可以这样搭:

// 1. 文档向量化并存入向量库
@Configuration
public class RagConfig {
    
    @Bean
    public VectorStore vectorStore(EmbeddingModel embeddingModel) {
        return PgVectorStore.builder(jdbcTemplate, embeddingModel)
                .dimensions(1536)
                .build();
    }
}

// 2. 检索增强问答Controller
@RestController
@RequestMapping("/api/ai")
public class RagController {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public RagController(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder.build();
        this.vectorStore = vectorStore;
    }

    @PostMapping("/rag")
    public Map<String, String> ragChat(@RequestBody Map<String, String> body) {
        String question = body.get("question");
        
        String answer = chatClient.prompt()
                .user(question)
                // 从向量库检索相关文档,自动注入上下文
                .advisors(new QuestionAnswerAdvisor(vectorStore))
                .call()
                .content();
        
        return Map.of("answer", answer);
    }
}

这段代码的原理是:QuestionAnswerAdvisor在请求发出前,先用EmbeddingModel把用户问题转成向量,在向量库中检索最相似的文档片段,然后把这些片段拼接到用户的提问中,大模型就能"看着"你的资料来回答了。

毕设中可以这样做:把学校的规章制度、课程大纲、常见问题FAQ整理成文档,导入向量库,系统就能回答"怎么选课""毕业学分要求"这类特定问题。这个功能在答辩时的杀伤力远超普通问答。


六、答辩加分话术:如何讲好AI模块的故事

技术做完了,答辩讲不好等于白做。下面是三个高频问题的应答思路。

问题一:“你的AI模块和直接用ChatGPT有什么区别?”

回答重点放在"工程化封装"上:你做的是把大模型能力集成到了具体业务系统中,包括多轮对话上下文管理、会话持久化、业务数据联动、前端流式交互体验优化。大模型是原材料,你的系统是加工厂,价值在于加工过程而非原材料本身。如果做了RAG,再加一句"我解决了大模型对垂直领域知识不了解的问题"。

问题二:“大模型的回答不准确怎么办?”

展示你的工程思考:通过系统提示词约束回答范围和风格,通过temperature参数控制创造性(事实类问题调低到0.3,创意类问题调高到0.8),通过RAG引入领域知识保证回答有据可查,通过对话历史记录方便人工审核和纠错。这些都是在"调API"之外做的工程工作。

问题三:“这个模块的成本怎么控制?”

用数据说话:展示DeepSeek的定价表,说明开发期间总调用成本不到10元;提到错峰优惠时段(00:30-08:30)价格再降50%-75%;说明生产环境可以加缓存层,对高频问题直接返回缓存结果,避免重复调用。


七、动手清单与时间安排

把上面的内容拆成可执行的步骤,按以下节奏推进,两周内就能完成AI模块开发。

阶段 任务 预计耗时 产出
第1天 注册DeepSeek账号、获取API Key、创建Spring Boot项目 半天 项目骨架
第2-3天 接入Spring AI、实现单轮问答接口、Postman测试 1天 可调用的API
第4-5天 实现流式输出、Vue前端对接打字机效果 1.5天 前后端联调完成
第6-7天 实现多轮对话、上下文持久化到MySQL 1天 对话记录功能
第8-10天 RAG知识库搭建、文档导入、检索问答 2-3天 知识库问答
第11-12天 联调测试、异常处理、界面美化 1-2天 可演示的完整模块

有几个容易踩的坑提前提醒:第一,API Key不要硬编码在代码里,用环境变量或配置文件管理,提交Git时加入.gitignore;第二,流式接口在Nginx反代时需要关闭缓冲,加proxy_buffering off配置,否则前端收不到逐字输出;第三,DeepSeek的免费额度有限,开发时先用简单问题测试,避免烧完额度。


结语

今年毕设的竞争逻辑已经变了。评委看过太多千篇一律的CRUD管理系统,一个能流式对话、能理解上下文、能基于知识库回答问题的AI模块,足以让你的项目在答辩现场脱颖而出。更重要的是,这套技术栈——Spring AI + 大模型API + 向量检索——正是当前企业级AI应用开发的主流方案,做完这个毕设,你对AI工程化的理解会超过大多数同龄人。

代码已经给你了,接下来就是动手。遇到问题可以到公众号留言,我会逐条回复。


关注博主,每日推送选题指导、技术栈教学、AI模块接入、论文写作和答辩技巧。


参考来源:
参考来源
2025-2026年计算机毕业设计选题推荐 -计算机专业毕业设计题目大全,CSDN
计算机专业毕设选题清单:开题指导与选题建议,CSDN
【保姆级教程】2026届计算机毕业设计实现流程,看这篇就够了(1.2w字超详细流程),CSDN
2026届Java毕业设计选题推荐,1000道创新创意Java毕业设计题目推荐,避免踩坑,CSDN
两万字计算机毕设答辩相关问题汇总附赠350套ppt

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐