基于SpringBoot+Vue實現(xiàn)DeepSeek對話效果的詳細步驟
Spring Boot + Vue 實現(xiàn) DeepSeek 對話效果詳細步驟
一、整體架構設計
我們需要構建一個前后端分離的應用:
- ??后端??:Spring Boot 提供 API 接口,處理與 AI 模型的交互
- ??前端??:Vue 實現(xiàn)聊天界面,展示對話內容并發(fā)送用戶輸入
二、后端實現(xiàn) (Spring Boot)
1. 創(chuàng)建 Spring Boot 項目
<!-- pom.xml 主要依賴 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 如果需要持久化存儲 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2. 設計 API 接口
// 對話控制器
@RestController
@RequestMapping("/api/chat")
public class ChatController {
@Autowired
private ChatService chatService;
@PostMapping("/message")
public ResponseEntity<ChatResponse> sendMessage(@RequestBody ChatRequest request) {
ChatResponse response = chatService.processMessage(request);
return ResponseEntity.ok(response);
}
@GetMapping("/history/{sessionId}")
public ResponseEntity<List<ChatMessage>> getHistory(@PathVariable String sessionId) {
List<ChatMessage> history = chatService.getChatHistory(sessionId);
return ResponseEntity.ok(history);
}
}
3. 定義數(shù)據(jù)傳輸對象
public class ChatRequest {
private String sessionId;
private String message;
// getter, setter
}
public class ChatResponse {
private String message;
private String sessionId;
// getter, setter
}
public class ChatMessage {
private String role; // "user" 或 "assistant"
private String content;
// getter, setter
}
4. 實現(xiàn)對話服務
@Service
public class ChatService {
// 可以使用 Map 臨時存儲會話,生產(chǎn)環(huán)境建議使用數(shù)據(jù)庫
private Map<String, List<ChatMessage>> chatSessions = new ConcurrentHashMap<>();
// 處理用戶消息
public ChatResponse processMessage(ChatRequest request) {
String sessionId = request.getSessionId();
if (sessionId == null || sessionId.isEmpty()) {
sessionId = UUID.randomUUID().toString();
}
String userMessage = request.getMessage();
// 保存用戶消息
ChatMessage userMsg = new ChatMessage("user", userMessage);
// 調用 AI 模型 API
String aiResponse = callAIApi(userMessage, sessionId);
// 保存 AI 回復
ChatMessage aiMsg = new ChatMessage("assistant", aiResponse);
// 更新會話歷史
chatSessions.computeIfAbsent(sessionId, k -> new ArrayList<>()).add(userMsg);
chatSessions.get(sessionId).add(aiMsg);
return new ChatResponse(aiResponse, sessionId);
}
// 獲取聊天歷史
public List<ChatMessage> getChatHistory(String sessionId) {
return chatSessions.getOrDefault(sessionId, Collections.emptyList());
}
// 調用 AI 模型 API 的方法
private String callAIApi(String message, String sessionId) {
// 這里實現(xiàn)與 DeepSeek API 的實際交互
// 可以使用 RestTemplate 或 WebClient
// 示例代碼:
try {
// 實際開發(fā)中替換為真實 API 調用
return "這是 AI 對 "" + message + "" 的回復";
} catch (Exception e) {
return "抱歉,我遇到了一些問題,請稍后再試。";
}
}
}
5. 配置 CORS
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:5173") // Vue 默認端口
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true);
}
}
三、前端實現(xiàn) (Vue)
1. 創(chuàng)建 Vue 項目
# 使用 npm npm create vue@latest my-chat-app cd my-chat-app npm install # 安裝必要的依賴 npm install axios
2. 創(chuàng)建聊天組件
<!-- ChatWindow.vue -->
<template>
<div class="chat-container">
<div class="chat-header">
<h2>AI 助手對話</h2>
</div>
<div class="chat-messages" ref="messageContainer">
<div v-for="(msg, index) in messages" :key="index"
:class="['message', msg.role === 'user' ? 'user-message' : 'assistant-message']">
<div class="message-content">
{{ msg.content }}
</div>
</div>
<div v-if="loading" class="message assistant-message">
<div class="message-content">
<span class="loading-dots">思考中<span>.</span><span>.</span><span>.</span></span>
</div>
</div>
</div>
<div class="chat-input">
<textarea
v-model="userInput"
placeholder="請輸入您的問題..."
@keyup.enter.ctrl="sendMessage"
></textarea>
<button @click="sendMessage" :disabled="loading || !userInput.trim()">
發(fā)送
</button>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'ChatWindow',
data() {
return {
messages: [],
userInput: '',
loading: false,
sessionId: this.generateSessionId(),
apiBaseUrl: 'http://localhost:8080/api/chat'
};
},
methods: {
generateSessionId() {
return Math.random().toString(36).substring(2, 15);
},
async sendMessage() {
if (!this.userInput.trim() || this.loading) return;
const userMessage = this.userInput.trim();
this.messages.push({ role: 'user', content: userMessage });
this.userInput = '';
this.loading = true;
// 滾動到底部
this.$nextTick(() => {
this.scrollToBottom();
});
try {
const response = await axios.post(`${this.apiBaseUrl}/message`, {
sessionId: this.sessionId,
message: userMessage
});
this.messages.push({ role: 'assistant', content: response.data.message });
this.sessionId = response.data.sessionId;
} catch (error) {
console.error('Error sending message:', error);
this.messages.push({
role: 'assistant',
content: '抱歉,發(fā)生了錯誤,請稍后再試。'
});
} finally {
this.loading = false;
this.$nextTick(() => {
this.scrollToBottom();
});
}
},
scrollToBottom() {
if (this.$refs.messageContainer) {
this.$refs.messageContainer.scrollTop = this.$refs.messageContainer.scrollHeight;
}
},
loadHistory() {
axios.get(`${this.apiBaseUrl}/history/${this.sessionId}`)
.then(response => {
this.messages = response.data;
this.$nextTick(() => {
this.scrollToBottom();
});
})
.catch(error => {
console.error('Error loading history:', error);
});
}
},
mounted() {
// 在實際應用中,可以從 URL 參數(shù)或本地存儲獲取 sessionId
// this.loadHistory();
}
}
</script>
<style scoped>
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
max-width: 800px;
margin: 0 auto;
padding: 1rem;
}
.chat-header {
text-align: center;
padding: 1rem 0;
border-bottom: 1px solid #eee;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 1rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.message {
max-width: 75%;
padding: 0.75rem;
border-radius: 0.5rem;
margin-bottom: 0.5rem;
}
.user-message {
align-self: flex-end;
background-color: #e1f5fe;
}
.assistant-message {
align-self: flex-start;
background-color: #f5f5f5;
}
.chat-input {
display: flex;
padding: 1rem 0;
gap: 0.5rem;
}
.chat-input textarea {
flex: 1;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 0.5rem;
resize: none;
min-height: 60px;
}
.chat-input button {
padding: 0.75rem 1.5rem;
background-color: #2196f3;
color: white;
border: none;
border-radius: 0.5rem;
cursor: pointer;
}
.chat-input button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.loading-dots span {
animation: loading 1.4s infinite;
display: inline-block;
}
.loading-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.loading-dots span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes loading {
0%, 100% { opacity: 0.3; }
50% { opacity: 1; }
}
</style>
3. 在主應用中使用聊天組件
<!-- App.vue -->
<template>
<div class="app">
<ChatWindow />
</div>
</template>
<script>
import ChatWindow from './components/ChatWindow.vue'
export default {
name: 'App',
components: {
ChatWindow
}
}
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
.app {
width: 100%;
height: 100vh;
}
</style>
四、前后端集成與部署
1. 開發(fā)環(huán)境配置
??啟動后端服務??
./mvnw spring-boot:run
??啟動前端開發(fā)服務器??
npm run dev
2. 生產(chǎn)環(huán)境部署
??構建前端應用??
npm run build
??配置后端服務提供靜態(tài)文件??
// Spring Boot 配置類
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${frontend.resources.path:${user.home}/my-chat-app/dist}")
private Resource frontendResources;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("file:" + frontendResources.getFile().getAbsolutePath() + "/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
??將前端構建文件復制到后端資源目錄??
五、進階優(yōu)化
1. WebSocket 實現(xiàn)實時通信
// 后端 WebSocket 配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOriginPatterns("*")
.withSockJS();
}
}
// WebSocket 控制器
@Controller
public class WebSocketController {
@Autowired
private ChatService chatService;
@MessageMapping("/chat.sendMessage")
@SendToUser("/queue/reply")
public ChatMessage sendMessage(@Payload ChatMessage chatMessage, Principal principal) {
return chatService.processWebSocketMessage(chatMessage);
}
}
2. 使用 Redis 緩存會話歷史
@Configuration
@EnableRedisHttpSession
public class SessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
}
3. 前端連接 WebSocket
// 在 ChatWindow.vue 中添加 WebSocket 連接
export default {
// ... 其他代碼 ...
data() {
return {
// ... 其他數(shù)據(jù) ...
stompClient: null
};
},
methods: {
// ... 其他方法 ...
connectWebSocket() {
const socket = new SockJS(this.apiBaseUrl.replace('/api', ''));
this.stompClient = Stomp.over(socket);
this.stompClient.connect({}, frame => {
console.log('Connected: ' + frame);
this.stompClient.subscribe(`/user/queue/reply`, response => {
const receivedMessage = JSON.parse(response.body);
this.messages.push(receivedMessage);
this.$nextTick(() => {
this.scrollToBottom();
});
});
}, error => {
console.error('WebSocket Error: ' + error);
// 重連邏輯
setTimeout(() => {
this.connectWebSocket();
}, 5000);
});
},
disconnectWebSocket() {
if (this.stompClient !== null) {
this.stompClient.disconnect();
}
},
sendWebSocketMessage() {
if (!this.userInput.trim() || this.loading) return;
const userMessage = this.userInput.trim();
this.stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
sessionId: this.sessionId,
message: userMessage
}));
this.messages.push({ role: 'user', content: userMessage });
this.userInput = '';
}
},
mounted() {
// ... 其他代碼 ...
this.connectWebSocket();
},
beforeUnmount() {
this.disconnectWebSocket();
}
}
總結
通過上述步驟,你可以實現(xiàn)一個基于 Spring Boot 和 Vue 的對話系統(tǒng),類似 DeepSeek 的交互效果。這個實現(xiàn)包含了:
- 后端 API 設計與實現(xiàn)
- 前端聊天界面設計
- 會話管理與歷史記錄
- WebSocket 實現(xiàn)實時通信(可選)
- 部署配置
根據(jù)實際需求,你可以進一步擴展功能,如支持 Markdown 渲染、代碼高亮、對話導出等高級特性。
以上就是基于SpringBoot+Vue實現(xiàn)DeepSeek對話效果的詳細步驟的詳細內容,更多關于SpringBoot Vue DeepSeek對話的資料請關注腳本之家其它相關文章!
相關文章
Java8并發(fā)新特性CompletableFuture
這篇文章主要介紹了Java8并發(fā)新特性CompletableFuture,CompletableFuture針對Future接口做了改進,相比Callable/Runnable接口它支持多任務進行鏈式調用、組合、多任務并發(fā)處理,下面文章更多相關內容得介紹,需要的小伙伴可以參考一下2022-06-06
Presto自定義函數(shù)@SqlNullable引發(fā)問題詳解
這篇文章主要為大家介紹了Presto自定義函數(shù)@SqlNullable引發(fā)問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
mybatis foreach批量插入數(shù)據(jù):Oracle與MySQL區(qū)別介紹
這篇文章主要介紹了,需要的朋友可以參考下2018-01-01
IDEA中將SpringBoot項目提交到git倉庫的方法步驟
本文主要介紹了IDEA中將SpringBoot項目提交到git倉庫的方法步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

