在腾讯云CodeBuddy上实现一个AI聊天助手

在腾讯云CodeBuddy上实现一个AI聊天助手项目

在当今数字化时代,AI聊天助手已经成为一种非常流行的应用,广泛应用于客户服务、智能助手等领域。今天,我们将通过腾讯云CodeBuddy平台,实现一个基于Spring Boot和OpenAI API的AI聊天助手项目。这个项目将帮助你快速搭建一个功能强大的聊天助手,同时展示腾讯云CodeBuddy的强大开发能力。

项目背景

我们选择的项目是 Spring AI 聊天助手,这是一个基于Spring Boot和OpenAI API的开源项目。它使用了DeepSeek-R1-Distill-Llama-8B模型,通过SiliconFlow API提供服务。这个项目具备以下功能特点:

  • 基于Spring AI框架实现的聊天功能
  • 使用OpenAI兼容的API接口
  • 响应式Web界面
  • 聊天历史记录管理
  • 支持代码高亮显示

环境准备

在开始之前,我们需要准备以下环境和工具:

  • 腾讯云CodeBuddy账号:用于开发和部署项目。
  • JDK 17或更高版本:用于运行Spring Boot项目。
  • Maven 3.6或更高版本:用于项目构建。
  • OpenAI API密钥或兼容的API密钥:用于接入AI服务。

项目搭建

1. 安装好CodeBuddy

首先,我们需要安装好CodeBuddy,可以参考我上一篇博客,然后在项目里给出命令,让AI创建代码,要加上技术栈和版本,比如本博客使用的版本是1.0.0-M5

API交互截图
这个过程比较长,需要一点引导AI创建修改代码

2. 配置项目

在腾讯云CodeBuddy中,找到项目的 application.yml 文件,进行以下配置:

spring:ai:openai:api-key: your-api-key-herebase-url: https://api.siliconflow.cnchat:options:model: deepseek-ai/DeepSeek-R1-Distill-Llama-8B

你也可以通过环境变量设置API密钥,例如:

export OPENAI_API_KEY=your-api-key-here

3. 构建和运行项目

在腾讯云CodeBuddy的终端中,运行以下命令构建项目:

mvn clean package

构建完成后,运行项目:

java -jar target/springboot-ai-chatbot-0.0.1-SNAPSHOT.jar

项目将在 http://localhost:8080 上运行。你可以通过浏览器访问该地址,开始使用AI聊天助手。

4. 使用Web界面与AI交互

打开浏览器,访问 http://localhost:8080。在输入框中输入你的问题,点击“发送”按钮或按Enter键,即可查看AI助手的回复。

5. 通过API与AI交互

你也可以通过API与AI进行交互。以下是几个常用的API端点:

  • 发送聊天消息

    curl -X POST http://localhost:8080/api/chat \-H "Content-Type: application/json" \-d '{"message":"你好,请介绍一下自己"}'
    
  • 获取聊天历史

    curl -X GET http://localhost:8080/api/chat/history
    
  • 清除聊天历史

    curl -X POST http://localhost:8080/api/chat/clear
    

代码说明

1. ChatService.java

ChatService.java 是项目的核心服务类,它负责与OpenAI API进行交互,处理聊天逻辑。以下是代码的关键部分:

package com.example.chatbot.service;import com.example.chatbot.exception.ChatException;
import com.example.chatbot.model.ChatMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;@Service
public class ChatService {private static final Logger log = LoggerFactory.getLogger(ChatService.class);private final ChatClient chatClient;private final String systemPrompt;private final int maxHistorySize;private final List<Message> chatHistory = new ArrayList<>();private final ReentrantLock historyLock = new ReentrantLock();public ChatService(ChatClient.Builder builder,@Value("${spring.ai.openai.system-prompt:你是一个友好、乐于助人的AI助手。请提供简洁、准确的回答。}") String systemPrompt,@Value("${spring.ai.chat.history.max-size:50}") int maxHistorySize) {this.chatClient = builder.defaultSystem(systemPrompt).build();this.systemPrompt = systemPrompt;this.maxHistorySize = maxHistorySize;initializeChatHistory();}/*** 初始化聊天历史,添加系统消息*/private void initializeChatHistory() {historyLock.lock();try {chatHistory.clear();chatHistory.add(new SystemMessage(systemPrompt));log.info("聊天历史已初始化,系统提示: {}", systemPrompt);} finally {historyLock.unlock();}}/*** 处理聊天请求* @param userInput 用户输入内容* @return AI响应内容*/public String chat(String userInput) {if (userInput == null || userInput.trim().isEmpty()) {throw new ChatException("输入内容不能为空");}try {String processedInput = userInput.trim();log.info("收到用户输入: {}", processedInput);// 添加用户消息到历史记录UserMessage userMessage = new UserMessage(processedInput);addToHistory(userMessage);// 检查历史记录大小,超过限制则清理trimHistoryIfNeeded();// 创建提示并获取响应(直接使用框架Message列表)Prompt prompt = new Prompt(new ArrayList<>(getFrameworkChatHistory()));log.info("发送请求到AI模型,历史消息数量: {}", prompt.getInstructions().size());String responseContent = chatClient.prompt(prompt).call().chatResponse().getResult().getOutput().getContent();// 处理空响应if (responseContent == null || responseContent.trim().isEmpty()) {responseContent = "抱歉,未能生成有效响应,请尝试重新提问。";log.warn("AI返回空响应,使用默认回复");}// 添加助手响应到历史记录addToHistory(new AssistantMessage(responseContent));log.info("AI响应处理完成,响应长度: {}", responseContent.length());return responseContent;} catch (Exception e) {log.error("处理聊天请求失败", e);throw new ChatException("处理聊天请求失败: " + e.getMessage(), e);}}/*** 获取前端需要的聊天历史(不含系统消息)* @return 聊天历史列表*/public List<ChatMessage> getChatHistory() {historyLock.lock();try {return chatHistory.stream().skip(1) // 跳过系统消息.map(message -> {String role = message instanceof UserMessage ? "user" : "assistant";return new ChatMessage(role, message.getContent());}).collect(Collectors.toList());} finally {historyLock.unlock();}}/*** 获取框架需要的完整聊天历史(包含系统消息)* @return 框架消息列表*/private List<Message> getFrameworkChatHistory() {historyLock.lock();try {return new ArrayList<>(chatHistory);} finally {historyLock.unlock();}}/*** 清除聊天历史*/public void clearHistory() {initializeChatHistory();log.info("聊天历史已清除");}/*** 添加消息到历史记录*/private void addToHistory(Message message) {historyLock.lock();try {chatHistory.add(message);log.debug("添加消息到历史,角色: {}, 内容长度: {}",message.getClass().getSimpleName(),message.getContent().length());} finally {historyLock.unlock();}}/*** 如果历史记录超过最大限制,清理部分历史*/private void trimHistoryIfNeeded() {historyLock.lock();try {// 保留系统消息,只清理用户和助手的消息if (chatHistory.size() > maxHistorySize) {int messagesToRemove = chatHistory.size() - maxHistorySize;for (int i = 0; i < messagesToRemove; i++) {chatHistory.remove(1); // 从索引1开始删除(保留系统消息)}log.info("聊天历史已修剪,移除了 {} 条消息,当前大小: {}",messagesToRemove, chatHistory.size());}} finally {historyLock.unlock();}}
}
  • OpenAIClient:这是Spring AI提供的客户端,用于与OpenAI API进行交互。
  • ChatRequest:这是发送给AI的请求对象,包含用户的消息。
  • ChatResponse:这是从AI返回的响应对象,包含AI的回复。

2. ChatController.java

ChatController.java 是项目的控制器类,负责处理HTTP请求和响应。以下是代码的关键部分:

package com.example.chatbot.controller;import com.example.chatbot.model.ChatMessage;
import com.example.chatbot.service.ChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/api/chat")
public class ChatController {private final ChatService chatService;@Autowiredpublic ChatController(ChatService chatService) {this.chatService = chatService;}@PostMappingpublic ResponseEntity<ChatMessage> chat(@RequestBody Map<String, String> request) {String userMessage = request.get("message");String response = chatService.chat(userMessage);return ResponseEntity.ok(new ChatMessage("assistant", response));}@GetMapping("/history")public ResponseEntity<List<ChatMessage>> getChatHistory() {return ResponseEntity.ok(chatService.getChatHistory());}@PostMapping("/clear")public ResponseEntity<Void> clearHistory() {chatService.clearHistory();return ResponseEntity.ok().build();}
}
  • @PostMapping:处理发送聊天消息的POST请求。
  • @GetMapping("/history"):处理获取聊天历史的GET请求。
  • @PostMapping("/clear"):处理清除聊天历史的POST请求。

3. index.html

index.html 是项目的前端页面,提供了一个响应式的Web界面,用户可以通过这个界面与AI进行交互。以下是代码的关键部分:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AI 聊天助手</title><!-- 引入Tailwind CSS --><script src="https://cdn.tailwindcss.com"></script><!-- 引入Font Awesome --><link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet"><!-- 配置Tailwind自定义颜色和字体 --><script>tailwind.config = {theme: {extend: {colors: {primary: '#3B82F6',secondary: '#10B981',neutral: '#F3F4F6',dark: '#1F2937',light: '#F9FAFB'},fontFamily: {inter: ['Inter', 'system-ui', 'sans-serif'],},}}}</script><style type="text/tailwindcss">@layer utilities {.content-auto {content-visibility: auto;}.message-appear {animation: fadeIn 0.3s ease-out forwards;}.typing-pulse span {animation: pulse 1.4s infinite ease-in-out both;}.typing-pulse span:nth-child(1) { animation-delay: -0.32s; }.typing-pulse span:nth-child(2) { animation-delay: -0.16s; }}@keyframes fadeIn {from { opacity: 0; transform: translateY(10px); }to { opacity: 1; transform: translateY(0); }}@keyframes pulse {0%, 80%, 100% { transform: scale(0); }40% { transform: scale(1); }}</style>
</head>
<body class="font-inter bg-gradient-to-br from-light to-neutral min-h-screen flex flex-col">
<!-- 顶部导航栏 -->
<header class="bg-white shadow-md py-4 px-6 sticky top-0 z-10"><div class="max-w-4xl mx-auto flex items-center justify-between"><div class="flex items-center gap-2"><i class="fa fa-comments text-primary text-2xl"></i><h1 class="text-[clamp(1.25rem,3vw,1.75rem)] font-bold text-dark">AI 聊天助手</h1></div><div class="text-sm text-gray-500"><span class="flex items-center gap-1"><span class="h-2 w-2 bg-green-500 rounded-full animate-pulse"></span>在线</span></div></div>
</header><!-- 主内容区 -->
<main class="flex-grow flex flex-col max-w-4xl w-full mx-auto w-full px-4 py-6 md:py-8"><!-- 聊天容器 --><div class="chat-container bg-white rounded-2xl shadow-lg p-4 md:p-6 h-[70vh] overflow-y-auto mb-6"><div th:each="message : ${chatHistory}"><div th:class="${message.role == 'user' ? 'message user-message' : 'message assistant-message'}"th:utext="${#strings.replace(#strings.escapeXml(message.content), '&#10;', '<br/>')}"></div></div><!-- 输入指示器 --><div class="message assistant-message typing opacity-0" id="typing-indicator"><div class="flex items-center gap-2"><div class="w-2 h-2 bg-gray-400 rounded-full typing-pulse"><span class="absolute w-2 h-2 bg-gray-400 rounded-full"></span><span class="absolute w-2 h-2 bg-gray-400 rounded-full ml-3"></span><span class="absolute w-2 h-2 bg-gray-400 rounded-full ml-6"></span></div><span>正在思考...</span></div></div></div><!-- 输入区域 --><div class="input-container bg-white rounded-2xl shadow-md p-3 flex gap-3"><inputtype="text"id="user-input"placeholder="输入你的问题..."autocomplete="off"class="flex-grow px-4 py-3 rounded-xl border border-gray-200 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"><button id="send-btn" class="bg-primary hover:bg-primary/90 text-white p-3 rounded-xl transition-all shadow-md hover:shadow-lg flex items-center justify-center"><i class="fa fa-paper-plane"></i></button><button id="clear-btn" class="bg-gray-200 hover:bg-gray-300 text-gray-700 p-3 rounded-xl transition-all shadow-sm hover:shadow"><i class="fa fa-trash"></i></button></div>
</main><!-- 页脚 -->
<footer class="py-4 px-6 text-center text-gray-500 text-sm"><p>© 2025 AI 聊天助手 | 提供智能对话服务</p>
</footer><script>document.addEventListener('DOMContentLoaded', function() {const chatContainer = document.querySelector('.chat-container');const userInput = document.getElementById('user-input');const sendBtn = document.getElementById('send-btn');const clearBtn = document.getElementById('clear-btn');const typingIndicator = document.getElementById('typing-indicator');// 滚动到底部function scrollToBottom() {chatContainer.scrollTop = chatContainer.scrollHeight;}// 初始滚动到底部scrollToBottom();// 添加消息到聊天界面function addMessage(content, isUser) {const messageDiv = document.createElement('div');messageDiv.className = `message message-appear ${isUser ? 'user-message' : 'assistant-message'} mb-4 opacity-0`;// 处理代码块格式if (content.includes('```')) {content = content.replace(/```([\s\S]*?)```/g,'<pre class="bg-gray-100 p-3 rounded-lg my-2 overflow-x-auto"><code>$1</code></pre>');}messageDiv.innerHTML = content.replace(/\n/g, '<br/>');chatContainer.appendChild(messageDiv);// 触发动画setTimeout(() => {messageDiv.classList.remove('opacity-0');}, 10);scrollToBottom();}// 发送消息function sendMessage() {const message = userInput.value.trim();if (message === '') return;// 添加用户消息addMessage(message, true);userInput.value = '';// 显示正在输入指示器typingIndicator.style.display = 'block';setTimeout(() => {typingIndicator.classList.remove('opacity-0');}, 10);scrollToBottom();// 发送请求到服务器fetch('/api/chat', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ message: message })}).then(response => response.json()).then(data => {// 隐藏正在输入指示器typingIndicator.classList.add('opacity-0');setTimeout(() => {typingIndicator.style.display = 'none';}, 300);// 添加AI响应addMessage(data.content, false);}).catch(error => {console.error('Error:', error);typingIndicator.classList.add('opacity-0');setTimeout(() => {typingIndicator.style.display = 'none';}, 300);addMessage('发生错误,请重试。', false);});}// 清除聊天历史function clearChat() {fetch('/api/chat/clear', {method: 'POST'}).then(() => {// 清除聊天界面const messages = chatContainer.querySelectorAll('.message:not(.typing)');messages.forEach(msg => {msg.classList.add('opacity-0');setTimeout(() => msg.remove(), 300);});}).catch(error => {console.error('Error:', error);});}// 事件监听器sendBtn.addEventListener('click', sendMessage);clearBtn.addEventListener('click', clearChat);userInput.addEventListener('keypress', function(e) {if (e.key === 'Enter') {sendMessage();}});// 样式定义const style = document.createElement('style');style.textContent = `.user-message {background-color: #3B82F6;color: white;margin-left: auto;border-radius: 18px 18px 4px 18px;padding: 12px 18px;max-width: 75%;word-wrap: break-word;box-shadow: 0 2px 4px rgba(59, 130, 246, 0.2);}.assistant-message {background-color: #F3F4F6;color: #1F2937;margin-right: auto;border-radius: 18px 18px 18px 4px;padding: 12px 18px;max-width: 75%;word-wrap: break-word;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);}pre {font-family: 'Consolas', 'Monaco', monospace;}.chat-container::-webkit-scrollbar {width: 6px;}.chat-container::-webkit-scrollbar-track {background: #f1f1f1;border-radius: 10px;}.chat-container::-webkit-scrollbar-thumb {background: #c1c1c1;border-radius: 10px;}.chat-container::-webkit-scrollbar-thumb:hover {background: #a8a8a8;}`;document.head.appendChild(style);});</script>
</body>
</html>
  • chat-container:聊天界面的容器。
  • chat-history:显示聊天历史的区域。
  • chat-input:用户输入消息的输入框。
  • send-button:发送消息的按钮。

4. scripts.js

scripts.js 是前端的JavaScript脚本,负责处理用户输入和与后端API的交互。以下是代码的关键部分:

document.getElementById('send-button').addEventListener('click', function() {const message = document.getElementById('chat-input').value;if (message) {fetch('/api/chat', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ message: message })}).then(response => response.json()).then(data => {const chatHistory = document.getElementById('chat-history');chatHistory.innerHTML += `<p><strong>User:</strong> ${message}</p>`;chatHistory.innerHTML += `<p><strong>AI:</strong> ${data.choices[0].message.content}</p>`;document.getElementById('chat-input').value = '';});}
});
  • fetch:发送POST请求到后端API。
  • response.json():解析返回的JSON数据。
  • innerHTML:将聊天内容动态显示到页面上。

自定义项目

你可以通过修改以下文件来自定义聊天助手的行为:

  • ChatService.java:修改系统提示信息和聊天逻辑。
  • index.html:自定义Web界面。
  • application.yml:调整模型参数和API设置。

项目截图

以下是项目运行的截图:

项目运行截图

总结

通过腾讯云CodeBuddy,我们快速搭建了一个基于Spring Boot和OpenAI API的AI聊天助手项目。这个项目不仅具备强大的功能,还提供了灵活的自定义选项。希望这篇文章能帮助你更好地理解和使用腾讯云CodeBuddy进行项目开发。

如果你有任何问题或建议,欢迎在评论区留言。让我们一起探索更多有趣的技术项目!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95551.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript Array.prototype.flatMap ():数组 “扁平化 + 映射” 的高效组合拳

在 JavaScript 数组处理中&#xff0c;我们经常需要先对每个元素进行转换&#xff08;映射&#xff09;&#xff0c;再将结果 “铺平”&#xff08;扁平化&#xff09;。比如将数组中的每个字符串按空格拆分&#xff0c;然后合并成一个新数组。传统做法是先用map()转换&#xf…

区块链与元宇宙:数字资产的守护者

1 区块链支撑元宇宙数字资产的底层逻辑1.1 不可篡改性构建信任基石区块链的不可篡改性为元宇宙数字资产提供了坚实的信任基础。其核心在于分布式账本技术&#xff0c;当一笔数字资产交易发生时&#xff0c;会被打包成区块并广播至网络中的所有节点。每个节点都会对这笔交易进行…

Linux软件编程:进程和线程(进程)

进程一、基本概念进程&#xff1a;是程序动态执行过程&#xff0c;包括创建、调度、消亡程序&#xff1a;存放在外存的一段数据的集合二、进程创建&#xff08;一&#xff09;进程空间分布每个进程运行起来后&#xff0c;操作系统开辟0-4G的虚拟空间进程空间&#xff1a;用户空…

Mybatis学习笔记(五)

分页插件与性能优化 分页插件配置 简要描述&#xff1a;MybatisPlus分页插件是基于物理分页实现的高性能分页解决方案&#xff0c;支持多种数据库的分页语法&#xff0c;能够自动识别数据库类型并生成对应的分页SQL。 核心概念&#xff1a; 物理分页&#xff1a;直接在SQL层面进…

企业可商用的conda:「Miniforge」+「conda-forge」

文章目录一、彻底卸载现有 Anaconda/Miniconda二、安装 Miniforge&#xff08;推荐&#xff09;macOS/Linux检查Windows检查三、将通道固定为 conda-forge&#xff08;严格优先&#xff09;四、验证是否仍引用 Anaconda 源五、常见问题&#xff08;FAQ&#xff09;六、参考命令…

Flutter ExpansionPanel组件(可收缩的列表)

可以展开或者收缩的面板组件&#xff0c;收缩面板组件效果由ExpansionPanelList组件和ExpansionPanel组件共同完成。 ExpansionPanelList属性说明属性说明children子元素expansionCallback设置回调事件ExpansionPanel属性说明headerBuilder收缩的标题body内容isExpanded设置内容…

C/C++ 进阶:深入解析 GCC:从源码到可执行程序的魔法四步曲

引言距离上一篇博客更新已经过去了大概一两周的时间&#xff0c;而对于 Linux 系统的基本指令以及 Shell 编程的学习其实基本讲解完毕&#xff0c;Linux基础一块的知识就将告一段落了&#xff0c;如果有细节性的知识&#xff0c;我也会及时分享给各位&#xff0c;作为一名正在攀…

云服务器运行持续强化学习COOM框架的问题

1 环境要求 下载地址&#xff1a;https://github.com/TTomilin/COOM tensorflow 2.11以上 python 3.9以上 tensorflow2.12.0&#xff0c;需要安装tensorflow-probability0.19 2 修改代码 COOM/wrappers/reward.py 将 from gym import RewardWrapper修改为 from gymnasium impor…

MyBatis Interceptor 深度解析与应用实践

MyBatis Interceptor 深度解析与应用实践 一、MyBatis Interceptor概述 1.1 什么是MyBatis Interceptor MyBatis Interceptor&#xff0c;也称为MyBatis 插件&#xff0c;是 MyBatis 提供的一种扩展机制&#xff0c;用于在 MyBatis 执行 SQL 的过程中插入自定义逻辑。它类似…

【自动化测试】Web自动化测试 Selenium

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 测试分类 了解各种各样的测试方法分类&#xff0c;不是为了墨守成规按照既定方法区测试&#xff0c;而是已了解思维为核心&#xff0c;并了解一些专业名词 根…

2025 电赛 C 题完整通关攻略:从单目标定到 2 cm 测距精度的全流程实战

摘要 2025 年全国大学生电子设计竞赛 C 题要求“仅用一颗固定摄像头”在 5 s 内完成 100 cm~200 cm 距离、误差 ≤2 cm 的单目测距&#xff0c;并实时显示功耗。本文整合国一选手方案、CSDN 高分博文、B 站实测视频及官方说明&#xff0c;给出从硬件选型→离线标定→在线算法→…

Day 10: Mini-GPT完整手写实战 - 从组件组装到文本生成的端到端实现

Day 10-2: Mini-GPT完整手写实战 - 从组件组装到文本生成的端到端实现 📚 今日学习目标 掌握GPT架构组装:将Transformer组件组装成完整的生成模型 理解生成式预训练:掌握自回归语言建模的核心机制 端到端代码实现:从数据预处理到模型训练的完整流程 文本生成实战:训练Mi…

深入解析Prompt缓存机制:原理、优化与实践经验

深入解析Prompt缓存机制&#xff1a;原理、优化与实践经验 概述 在大型语言模型应用中&#xff0c;API请求的延迟和成本始终是开发者关注的核心问题。Prompt缓存&#xff08;Prompt Caching&#xff09;技术通过智能地复用重复内容&#xff0c;有效减少了API响应时间和运行成本…

CV 医学影像分类、分割、目标检测,之【3D肝脏分割】项目拆解

CV 医学影像分类、分割、目标检测&#xff0c;之【3D肝脏分割】项目拆解第1行&#xff1a;from posixpath import join第2行&#xff1a;from torch.utils.data import DataLoader第3行&#xff1a;import os第4行&#xff1a;import sys第5行&#xff1a;import random第6行&a…

Mybatis学习笔记(七)

Spring Boot集成 简要描述&#xff1a;MyBatis-Plus与Spring Boot的深度集成&#xff0c;提供了自动配置、启动器等特性&#xff0c;大大简化了配置和使用。 核心概念&#xff1a; 自动配置&#xff1a;基于条件的自动配置机制启动器&#xff1a;简化依赖管理的starter配置属性…

机器人伴侣的智能升级:Deepoc具身智能模型如何重塑成人伴侣体验

引言&#xff1a;机器人伴侣市场的技术变革需求随着人工智能技术的飞速发展和人们情感需求的多元化&#xff0c;机器人成人伴侣市场正在经历前所未有的增长。传统机器人伴侣已经能够满足基础的交互需求&#xff0c;但在智能化、情感化和个性化方面仍存在明显不足。这正是深算纪…

metabase基础使用技巧 (dashboard, filter)

这是metabase系列分享文章的第2部分。本文将介绍metabase的基础概念和使用介绍 question question是metabase中提供的通过UI化操作就能实现简单的 快捷 直接的BI查询。 点击右侧的New -> Question即可创建Question&#xff0c;可以理解为一个格式化的查询&#xff1a; 这里…

机器人成人伴侣的智能化升级:Deepoc具身模型赋能沉浸式体验

引言&#xff1a;成人机器人市场的技术革新需求随着人工智能和机器人技术的快速发展&#xff0c;成人陪伴机器人行业正经历从简单机械运动到智能化交互的转型。据市场研究数据显示&#xff0c;全球成人机器人市场规模预计将在2026年突破100亿美元&#xff0c;年复合增长率保持在…

Go语言企业级权限管理系统设计与实现

最近跟着学长再写河南师范大学附属中学图书馆的项目&#xff0c;学长交给了我一个任务&#xff0c;把本项目的权限管理给吃透&#xff0c;然后应用到下一个项目上。 我当然是偷着乐呐&#xff0c;因为读代码的时候&#xff0c;总是莫名给我一种公费旅游的感觉。 本来就想去了解…

Java应用快速部署Tomcat指南

将Java应用部署到Apache Tomcat服务器是开发Web应用过程中常见的任务。Tomcat是一个免费且开源的Servlet容器,它为Java应用提供了运行环境。本文将介绍如何准备你的Java应用,并将其部署到Tomcat服务器上。 Java 应用部署 tomcat 的根目录结构 Tomcat中默认网站根目录是$CAT…