基于SpringBoot+Vue实现DeepSeek对话效果的详细步骤
目录
- Spring Boot + vue 实现 DeepSeek 对话效果详细步骤
- 一、整体架构设计
- 二、后端实现 (Spring Boot)
- 1. 创建 Spring Boot 项目
- 2. 设计 API 接口
- 3. 定义数据传输对象
- 4. 实现对话服务
- 5. 配置 CORS
- 三、前端实现 (Vue)
- 1. 创建 Vue 项目
- 2. 创建聊天组件
- 3. 在主应用中使用聊天组件
- 四、前后端集成与部署
- 1. 开发环境配置
- 2. 生产环境部署
- 五、进阶优化
- 1. WebSocket 实现实时通信
- 2. 使用 Redis 缓存会话历史
- 3. 前端连接 WebSocket
- 总结
Spring Boot + Vue 实现 DeepSeek 对话效果详细步骤
一、整体架构设计
我们需要构建一个前后端分离的应用:
- 后端:Spring Boot 提供 API 接口,处理与 AI 模型的交互
- 前端:Vue 实现聊天界面,展示对话内容并发送用户输入
二、后端实现 (Spring Boot)
1. 创建 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. 定义数据传输对象
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. 实现对话服务
@Service public class ChatService { // 可以使用 Map 临时存储会话,生产环境建议使用数据库 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) { // 这里实现与 DeepSeek API 的实际交互 // 可以使用 RestTemplate 或 WebClient // 示例代码: try { // 实际开发中替换为真实 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); } }
三、前端实现 (Vue)
1. 创建 Vue 项目
# 使用 npm npm create vue@latest my-chat-app cd my-chat-app npm install # 安装必要的依赖 npm install axIOS
2. 创建聊天组件
<!-- 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()"> 发送 </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: '抱歉,发生了错误,请稍后再试。' }); } 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 参数或本地存储获取 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: nojavascriptt-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> </templatehttp://www.devze.com> <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. 开发环境配置
启动后端服务
./mvnw spring-boot:run
启动前端开发服务器
npm run dev
2. 生产环境部署
构建前端应用
npm run build
配置后端服务提供静态文件
// 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"); } }); } }
将前端构建文件复制到后端资源目录
五、进阶优化
1. WebSocket 实现实时通信
// 后端 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 { @Aut编程客栈owired 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 { // ... 其他数据 ... 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; cojavascriptnst 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(); } }
总结
通过上述步骤,你可以实现一个基于 Spring Boot 和 Vue 的对话系统,类似 DeepSeek 的交互效果。这个实现包含了:
- 后端 API 设计与实现
- 前端聊天界面设计
- 会话管理与历史记录
- WebSocket 实现实时通信(可选)
- 部署配置
根据实际需求,你可以进一步扩展功能,如支持 Markdown 渲染、代码高亮、对话导出等高级特性。
以上就是基于SpringBoot+Vue实现DeepSeek对话效果的详细步骤的详细内容,更多关于SpringBoot Vue DeepSeek对话的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论