在生成式AI技术蓬勃发展的今天,大语言模型已成为企业智能化转型和个人效率提升的核心驱动力。作为国产大模型的优秀代表,DeepSeek凭借其卓越的中文语义理解能力和开发者友好的API生态,正在成为构建本土化AI应用的首选平台。本文将以Spring Boot3+Vue2全栈技术为基础,手把手带你打造一个具备以下特性的AI对话系统:
<?xml version="1.0" encoding="UTF-8"?>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.8</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<groupId>cn.com.codingce</groupId>
<artifactId>deepseek</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>deepseek</name>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-ai.version>1.0.0-M5</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server:
port: 8080
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: deepseek-r1:8b
application:
name: codingce-deepspeek
webflux:
base-path: /
codec:
max-in-memory-size: 10MB
logging:
level:
cn.com.codingce.deepseek: DEBUG
org.springframework.web: INFO
DeepSeekService
是一个核心服务类,主要负责处理与 Ollama 的通信和数据处理。整个服务采用响应式编程模式(Flux
),实现非阻塞式处理,提高系统性能。同时通过日志记录,确保服务的可靠性和稳定性。
package cn.com.codingce.deepseek.service;
import cn.com.codingce.deepseek.model.Message;
import cn.com.codingce.deepseek.model.MessageType;
import cn.com.codingce.deepseek.model.OllamaResponse;
import cn.com.codingce.deepseek.model.StreamResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.ollama.OllamaClient;
import org.springframework.ai.ollama.OllamaException;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Service
@AllArgsConstructor
@Slf4j
public class DeepSeekService {
private final OllamaClient ollamaClient;
private final ObjectMapper objectMapper;
public Flux<Message> generateResponse(String prompt) {
return Flux.create(sink -> {
List<String> messages = new ArrayList<>();
messages.add(prompt);
try {
ollamaClient.chat("deepseek-r1:8b", messages, response -> {
try {
OllamaResponse ollamaResponse = objectMapper.readValue(response, OllamaResponse.class);
String content = ollamaResponse.getContent();
if (content != null && !content.isEmpty()) {
sink.next(new Message(MessageType.ASSISTANT, content));
}
} catch (IOException e) {
log.error("Error processing Ollama response", e);
sink.error(e);
}
}, error -> {
log.error("Error from Ollama", error);
sink.error(new RuntimeException("Error from Ollama", error));
}, () -> {
log.info("Ollama chat completed");
sink.complete();
});
} catch (OllamaException e) {
log.error("Error initiating Ollama chat", e);
sink.error(e);
}
});
}
}
WebSocketController
是一个 WebSocket 控制器,用于处理前端与后端之间的实时通信。它支持消息的接收和发送,并将用户的消息传递给 DeepSeekService
,然后将 AI 的响应实时推送给前端。
package cn.com.codingce.deepseek.controller;
import cn.com.codingce.deepseek.model.Message;
import cn.com.codingce.deepseek.service.DeepSeekService;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import reactor.core.publisher.FluxSink;
import java.util.concurrent.ConcurrentHashMap;
@Controller
public class WebSocketController {
private final DeepSeekService deepSeekService;
private final ConcurrentHashMap<String, FluxSink<Message>> sinks = new ConcurrentHashMap<>();
public WebSocketController(DeepSeekService deepSeekService) {
this.deepSeekService = deepSeekService;
}
@MessageMapping("/chat")
public void receiveMessage(String sessionId, String message) {
sinks.putIfAbsent(sessionId, Flux.sink());
FluxSink<Message> sink = sinks.get(sessionId);
deepSeekService.generateResponse(message)
.subscribe(sink::next, sink::error, sink::complete);
}
@SendTo("/topic/messages/{sessionId}")
public Flux<Message> sendMessage(String sessionId) {
return Flux.create(sinks.get(sessionId));
}
}
前端项目基于 Vue2 构建,主要包含以下目录结构:
src/
├── assets/
├── components/
│ └── ChatWindow.vue
├── App.vue
├── main.js
在项目根目录下运行以下命令安装依赖:
npm install
App.vue
是主组件,用于加载聊天窗口组件。
<template>
<div id="app">
<ChatWindow />
</div>
</template>
<script>
import ChatWindow from './components/ChatWindow.vue';
export default {
name: 'App',
components: {
ChatWindow
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
ChatWindow.vue
是聊天窗口组件,负责显示消息和处理用户输入。
<template>
<div class="chat-window">
<div class="messages">
<div v-for="message in messages" :key="message.id" class="message">
<div :class="['message-content', { 'assistant': message.type === 'assistant' }]">
<div v-html="message.content"></div>
</div>
</div>
</div>
<input v-model="inputMessage" @keyup.enter="sendMessage" placeholder="Type a message..." />
</div>
</template>
<script>
import { WebSocketSubject } from 'rxjs/webSocket';
import DOMPurify from 'dompurify';
export default {
name: 'ChatWindow',
data() {
return {
messages: [],
inputMessage: '',
sessionId: Date.now().toString(),
ws: null
};
},
mounted() {
this.connectWebSocket();
},
methods: {
connectWebSocket() {
this.ws = new WebSocketSubject(`ws://localhost:8080/ws/chat/${this.sessionId}`);
this.ws.subscribe(
(message) => {
const sanitizedMessage = DOMPurify.sanitize(message.content);
this.messages.push({ ...message, content: sanitizedMessage });
},
(error) => console.error('WebSocket error:', error),
() => console.log('WebSocket closed')
);
},
sendMessage() {
if (this.inputMessage.trim()) {
this.ws.next(this.inputMessage);
this.messages.push({ id: Date.now(), type: 'user', content: this.inputMessage });
this.inputMessage = '';
}
}
},
beforeDestroy() {
if (this.ws) {
this.ws.complete();
}
}
};
</script>
<style scoped>
.chat-window {
width: 100%;
max-width: 600px;
margin: 0 auto;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
}
.messages {
height: 400px;
overflow-y: scroll;
margin-bottom: 10px;
}
.message {
margin-bottom: 10px;
}
.message-content {
padding: 5px;
border-radius: 5px;
}
.message-content.assistant {
background-color: #f0f0f0;
}
input {
width: 100%;
padding: 10px;
box-sizing: border-box;
}
</style>
在后端项目启动 Spring Boot 应用
在前端项目根目录下运行以下命令启动 Vue 项目:
npm run serve
打开浏览器,访问 http://localhost:8080,即可看到聊天窗口。输入消息后,即可与 AI 进行实时对话。
希望这篇文章能帮助你快速上手 DeepSeek 开发,开启你的 AI 应用构建之旅!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有