本文主要是介绍JAVA集成本地部署的DeepSeek的图文教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《JAVA集成本地部署的DeepSeek的图文教程》本文主要介绍了JAVA集成本地部署的DeepSeek的图文教程,包含配置环境变量及下载DeepSeek-R1模型并启动,具有一定的参考价值,感兴趣的...
一、下载部署DeepSeek
1.下载ollama
前往 Ollama 主页。

点击下载,选择对应操作系统,点击下载。

下载完成后打开直接无脑下一步就行。
安装完成之后打开CMD页面,输入ollama,如果有输出就代表安装成功,如果显示"不是内部命令"就需要配置一下环境变量。

###配置环境变量以及更改ollama模型路径###
win10系统为例,右键此电脑>高级系统设置>高级>环境变量
ollama 默认会安装到 C:\Users\XX\AppData\Local\Programs\ollama 下,将此文件全部移到其他盘。
选择系统变量Path>编辑>新建>输入移动后的ollama地址

在系统变量中点击新建,输入变量名OLLAMA_MODELS,变量值D:\ollama\models(希望ollama模型放入哪个位置)

配置完成后重启电脑,打开CMD页面再次输入ollama,查看是否有输出
2.下载DeepSeek-R1模型并启动
打开 Ollama 首页,点击 DeepSeek-R1

在这里有模型各种参数大小

DeepSeek-R1模型有1.5b、7b、8b、14b、32b、70b和671b的参数量区别,B代表十亿的意思,1.5b代表15亿参数量的意思。671B是基础大模型,1.5B、7B、8B、14B、32B、70B是蒸馏后的小模型,它们的区别主要体现在参数规模、模型容量、性能表现、准确性、训练成本、推理成本和不同使用场景:
| DeepSeek模型版本 | 参数量 | 特点 | 适用场景 | 硬件配置 |
| DeepSeek-R1-1.5B | 1.5B | 轻量级模型,参数量少,模型规模小 | 适用于轻量级任务,如短文本生成、基础问答等 | 4核处理器、8G内存,无需显卡 |
| DeepSeek-R1-7B | 7B | 平衡型模型,性能较好,硬件需求适中 | 适合中等复杂度任务,如文案撰写、表格处理、统计分析等 | 8核处理器、16G内存,Ryzen7或更高,RTX 3060(12GB)或更高 |
| DeepSeek-R1-8B | 8B | 性能略强于7B模型,适合更高精度需求 | 适合需要更高精度的轻量级任务,比如代码生成、逻辑推理等 | 8核处理器、16G内存,Ryzen7或更高,RTX 3060(12GB)或4060 |
| DeepSeek-R1-14B | 14B | 高性能模型,擅长复杂的任务,如数学推理、代码生成 | 可处理复杂任务,如长文本生成、数据分析等 | i9-13900K或更高、32G内存,RTX 4090(24GB)或A5000 |
| DeepSeek-R1-32B | 32B | 专业级模型,性能强大,适合高精度任务 | 适合超大规模任务,如语言建模、大规模训练、金融预测等 | Xeon 8核、128GB内存或更高,2-4张A100(80GB)或更高 |
| DeepSeek-R1-70B | 70B | 顶级模型,性能最强,适合大规模计算和高复杂任务 | 适合高精度专业领域任务,比如多模态任务预处理。这些任务对硬件要求非常高,需要高端的 CPU 和显卡,适合预算充足的企业或研究机构使用 | Xeon 8核、128GB内存或更高,8张A100/H100(80GB)或更高 |
| DeepSeek-R1-671B | 671B | 超大规模模型,性能卓越,推理速度快,适合极高精度需求 | 适合国家级 / 超大规模 AI 研究,如气候建模、基因组分析等,以及通用人工智能探索 | 64核、512GB或更高,8张A100/H100 |
根据自己电脑的配置选择对应大小的模型,复制安装命令,在cmd中执行命令


等待安装完成后会自己启动。

退出 DeepSeek 输入 /bye 或者 Ctrl+D
ollama 常用命令
ollama list :查看已安装的模型
ollama ps:正在运行的模型
ollama run 模型名称:启动模型
ollama rm 模型名称:卸载模型
下次启动 DeepSeek 只需要先 ollama list 查看已安装的模型,ollama run 模型名称启动即可。
二、JAVA项目接入DeepSeek
创建一个是 Springboot 项目引入 okhttp,lombok 等依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.10.0</version>
</dependency>配置文件中配置好本地 DeepSeek 的访问URL,ollama启动的 DeepSeek 端口默认为 11434
deepseek:
api:
url: "http://127.0.0.1:11434/api/generate"
model: "deepseek-r1:1.5b"编写 DeepSeekController
@RestController
@RequestMapping("/deepSeek")
public class DeepSeekController {
@Autowired
private DeepSeekService deepSeekService;
@GetMapping
@RequestMapping("/chat")
public String chat(String question) {
try {
return deepSeekService.chat(question);
} catch (IOException e) {
return "服务器繁忙,请稍后重试!";
}
}
}编写DeepSeekRequest实体类
@Data
@Builder
public class DeepSeekRequest {
/**
* 消息列表,包含对话中的消息对象
*/
private String prompt;
/**
* 模型名称,指定要使用的模型
*/
private String model;
}请求参数有很多,只列举最主要的两个参数
编写DeepSeekResponse实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("deepseek_response")
public class DeepSeekResponse {
private String id;
private String questionId;
//模型名称
private String model;
//创建时间
@jsONField(name = "created_at")
private String createdAt;
//响应内容
private String response;
//
private boolean done;
//
@JSONField(name = "done_reason")
private String doneReason;
//
@TableField(typeHandler = JacksonTypeHandler.class)
private Integer[] context;
//
@JSONField(name = "total_duration")
private Long totalDuration;
//
@JSONField(name = "load_duration")
private Long loadDuration;
//
@JSONField(name = "prompt_eval_count")
private Long promptEvalCount;
//
@JSONField(name = "prompt_eval_duration")
private Long promptEvalDuration;
//
@JSONField(name = "eval_count")
private Long evalCount;
//
@JSONField(name = "eval_duration")
private Long evalDuration;
}编写DeepSeekService
@Service
public class DeepSeekService {
@Value("${deepseek.api.url}")
private String url;
@Value("${deepseek.api.model}")
private String model;
private final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
public String chat(String question) throws IOException {
DeepSeekRequest requestBody = DeepSeekRequest.builder()
.model(model)
.prompt(question)
.build();
// 创建HTTP请求
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(JSON.toJSONString(requestBody), MediaType.get("application/json")))
.build();
// 发送请求并处理响应
try {
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);http://www.chinasem.cn
}
DeepSeekResponse deepSeekResponse = JSON.parseobject(response.body().string(), DeepSeekResponse.class);
return deepSeekResponse.getResponse();
} catch (IOException e) {
e.printStackTrace();
}
return "服务器繁忙!";
}随便写一个前端页面使用axIOS访问刚才暴露出来的接口就可以啦
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>智能 AI</title> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow" > <link rel="stylesheet" href="/css/self.css" rel="external nofollow" > </head> <body> <div id="app"> <div class="chat-container"> <div v-if="showTitle" class="welcome-title">你好!我是CloseAI,有什么可以帮助你的吗?</div> <div class="chat-messages"> <transition-group name="list"> <div v-for="message in messages" :key="message.id" class="message-wrapper" :class="{'user-message-wrapper': message.sender === 'user', 'ai-message-wrapper': message.sender === 'ai'}"> <img :src="message.sender === 'user' ? '/images/user.png' : '/images/ai.png'" class="avatar"/> <div class="message" :class="{'user-message': message.sender === 'user', 'ai-message': message.sender === 'ai'}"> <span v-if="message.sender === 'user'">{{ message.text }}</span> <div v-else v-html="message.formattedText || message.text"></div> <div v-if="message.sender === 'ai' && message.isLoading" class="loading-icon"></div> <!-- 调整停止按钮容器位置 --> <div v-if="(isThinking || animationFrameId) && message.sender === 'ai' && message.isActive" class="stop-container"> <button @click="stopThinking" class="stop-btn" title="JAVA集成本地部署的DeepSeek的图文教程"> <svg width="24" height="24" viewBox="0 0 24 24"> <rect x="6" y="4" width="4" height="16" rx="1"/> <rect x="14" y="4" width="4" height="16" rx="1"/> </svg> </button> </div> </div> </div> </transition-group> </div> <div class="chat-input"> <input type="text" v-model="userInput" @keyup.enter="sendMessage" placeholder="给 CloseAI 发送消息..."/> <button @click="sendMessage">Send</button> </div> </div> </div> <script src="/js/vue.js"></script> <script src="/js/axios.min.js"></script> <script src="/js/method.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <script src="https://cdnjs.cloudflare.com/AJAX/libs/dompurify/3.0.5/purify.min.js"></script> <script> function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } new Vue({ el: '#app', data: { userInput: '', messages: [], showTitle: true, // 添加一个新属性来控制标题的显示 performanceConfig: { maxMessageLength: 1000, // 超过该长度启用优化 chunkSize: window.innerWidth < 768 ? 3 : 5 // 响应式分段 }, // 新增控制变量 isThinking: false, currentController: null, // 请求中止控制器 animationFrameId: null // 动画帧ID }, methods: { sendMessage() { if (this.userInput.trim() !== '') { this.showTitle = false; // 用户开始提问时隐藏标题 const userMessage = { id: Date.now(), sender: 'user', text: this.userInput }; this.messages.push(userMessage); this.userInput = ''; // 停用所有旧消息 this.messages.forEach(msg => { if (msg.sender === 'ai') { this.$set(msg, 'isActive', false); } }); const aiMessage = { id: Date.now() + 1, sender: 'ai', text: '思考中 ', isLoading: true, isThinking: true, // 新增状态字段 isActive: true // 新增激活状态字段 }; this.messages.push(aiMessage); // 在请求前重置状态 tChina编程his.isThinking = true; // 使用 axios 的取消令牌 const controller = new AbortController(); this.currentController = controller; axios.get('/deepSeek/chat?question=' + userMessage.text, { signal: controller.signal }).then(response => { aiMessage.isLoading = false; aiMessage.text = '' aiMessage.rawContent = response.data; // 新增原始内容存储 let index = 0; let chunk = ''; const chunkSize = this.performanceConfig.chunkSize; let lastUpdate = 0; let lastFullRender = 0; const processChunk = () => { // 分块处理逻辑 const remaining = response.data.length - index; const step = remaining > chunkSize * 5 ? chunkSize * 5 : 1; chunk += response.data.slice(index, index + step); index += step; // 增量更新文本 aiMessage.text = chunk; this.safeParseMarkdown(aiMessage, true); // 实时解析 this.scrollToBottom(); }; const animate = (timestamp) => { // 时间片控制逻辑 if (timestamp - lastUpdate > 16) { // 约60fps processChunk(); lastUpdate = timestamp; } // 完整渲染控制(每100ms强制更新一次) if (timestamp - lastFullRender > 100) { this.$forceUpdate(); lastFullRender = timestamp; } if (timestamp - lastUpdate > 20) { const remainingChars = response.data.length - index; const step = remainingChars > chunkSize ? chunkSize : 1; aiMessage.text += response.data.substr(index, step); index += step; this.safeParseMarkdown(aiMessage); this.scrollToBottom(); lastUpdate = timestamp; } if (index < response.data.length) { this.animationFrameId = requestAnimationFrame(animate); } else { this.$set(aiMessage, 'isActive', false); // 关闭激活状态 this.$set(aiMessage, 'formattedText', DOMPurify.sanitize(marked.parse(aiMessage.text)) ); this.animationFrameId = null; // 新增重置 this.isThinking = false; // 在此处更新状态 this.finalizeMessage(aiMessage); } }; // 修改动画启动方式 this.animationFrameId = requestAnimationFrame(animate); }).catch(error => { if (error.name !== 'CanceledError') { console.error('Error:', error); } }).finally(() => { this.animationFrameId = null; // 新增消息状态更新 this.messages.forEach(msg => { if (msg.sender === 'ai') { msg.isLoading = false; msg.isThinking = false; } }); }); } }, // 新增滚动方法 scrollToBottom() { const container = this.$el.querySelector('.chat-messages'); container.scrollTop = container.scrollHeight; }, // 优化的Markdown解析方法 safeParseMarkdown: debounce(function (aiMessage, immediate = false) { if (immediate) { // // 快速解析基础格式(粗体、斜体等) // const quickFormatted = aiMessage.text // .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // .replace(/\*(.*?)\*/g, '<em>$1</em>'); // 完整Markdown解析 this.$set(aiMessage, 'formattedText', DOMPurify.sanitize(marked.parse(aiMessage.text)) ); } else { // 完整Markdown解析 this.$set(aiMessage, 'formattedText', DOMPurify.sanitize(marked.parse(aiMessage.text)) ); } }, 50), // 完整解析保持50ms防抖 stopThinking() { // 只停止当前活动消息 const activeMessage = this.messages.find(msg => msg.sender === 'ai' && msg.isActive ); if (activeMessage) { // 更新消息状态 this.$set(activeMessage, 'text', activeMessage.text + '\n(响应已停止)'); this.$set(activeMessage, 'isLoading', false); this.$set(activeMessage, 'isActive', false); this.safeParseMarkdown(activeMessage); } // 取消网络请求 if (this.currentController) { this.currentController.abort() } // 停止打印渲染 if (this.animationFrameId) { cancelAnimationFrame(this.animationFrameId); this.animationFrameId = null; } // 更新所有相关消息状态 this.messages.forEach(msg => { if (msg.sender === 'ai' && (msg.isLoading || msg.isThinking)) { msg.text += '\n(响应已停止)'; msg.isLoading = false; msg.isThinking = false; this.safeParseMarkdown(msg); } }); this.isThinking = false; this.animationFrameId = null; // 确保重置 }, // 新增最终处理函数 finalizeMessage(aiMessage) { this.$set(aiMessage, 'formattedText', DOMPurify.sanitize(marked.parse(aiMessage.text)) ); this.$set(aiMessage, 'isActive', false); this.animationFrameId = null; this.isThinking = false; this.$forceUpdate(); }, } }); </script> </body> </html>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
display: Flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.chat-container {
width: 100%;
/*max-width: 800px;*/
background-color: #fff;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
display: flex;
flex-direction: column;
}
.welcome-title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
font-size: 24px;
font-weight: bold;
}
/* 新增停止按钮样式 */
.stop-btn {
background-color: #ff4d4f;
color: white;
margin-left: 8px;
transition: all 0.3s;
}
.stop-btn:hover {
background-color: #f5f7fa;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
vertical-align: middle;
}
.chat-messages {
/*flex: 1;*/
overflow-y: auto;
padding: 20px;
/*display: flex;*/
flex-direction: column-reverse;
height: 70vh;
width: 500px;
scrollbar-width: none;
scroll-behavior: smooth; /* 平滑滚动效果 */
contain: strict; /* 限制浏览器重排范围 */
transform: translateZ(0);
}
.message {
margin-bottom: 15px;
padding: 12px;
border-radius: 12px;
max-width: 70%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
/*align-self: flex-end; !* 默认消息靠右对齐 *!*/
display: table;
}
.message-wrapper {
display: flex;
max-width: 80%;
margin: 10px;
align-items: flex-start;
will-change: transform, opacity; /* 启用GPU加速 */
}
/*.user-message-wrapper {*/
/* justify-content: flex-end;*/
/*}*/
.ai-message-wrapper {
justify-content: flex-start;
position: relative; /* 为绝对定位的停止按钮提供参考系 */
margin-bottom: 50px; /* 给停止按钮留出空间 */
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
vertical-align: middle;
}
.message {
margin-bottom: 0;
}
.user-message {
background-color: #007bff;
color: #fff;
margin-left: auto; /* 用户消息靠右对齐 */
}
.ai-message {
background-color: #f0f2f5; /* AI消息背景色 */
margin-right: auto; /* 消息内容靠左 */
position: relative; /* 添加相对定位 */
padding-bottom: 40px; /* 为按钮预留空间 */
}
/* 在self.css中添加 */
.user-message-wrapper {
flex-direction: row-reverse; /* 反转排列方向 */
margin-left: auto; /* 让用户消息靠右 */
}
.user-message-wrapper .avatar {
margin: 0 0 0 15px; /* 调整头像右边距 */
}
.chat-input {
display: flex;
align-items: center;
padding: 15px;
background-color: #f8f9fa;
}
.chat-input input {
flex: 1;
padding: 12px;
border: 1px solid #ccc;
border-radius: 6px;
margin-right: 15px;
transition: border-color 0.3s ease;
}
.chat-input input:focus {
border-color: #007bff;
}
.chat-input button {
padding: 12px 24px;
border: none;
border-radius: 6px;
background-color: #007bff;
color: #fff;
cursor: pointer;
transition: background-color 0.3s ease;
}
.message {
display: flex;
align-items: center;
}
/* 调整停止按钮定位 */
.stop-container {
position: absolute;
bottom: 10px;
right: 10px;
z-index: 10;
}CSBARwMYp
.stop-btn {
background: #ff4757;
border: none;
border-radius: 50%;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: transform 0.2s;
}
.stop-btn:hover {
transform: scale(1.1);
}
.stop-btn svg {
fill: white;
width: 16px;
height: 16px;
}
.ai-message pre {
background: #f5f7fa;
padding: 15px;
border-radius: 6px;
http://www.chinasem.cn overflow-x: auto;
}
.ai-message code {
font-family: 'Courier New', monospace;
font-size: 14px;
}
.ai-message table {
border-collapse: collapse;
margin: 10px 0;
}
.ai-message td, .ai-message th {
border: 1px solid #ddd;
padding: 8px;
}
.loading-icon {
width: 20px;
height: 20px;
border: 2px solid #ccc;
border-top-color: #007bff;
border-radius: 50%;
/*animation: spin 1s linear infinite;*/
margin-left: 10px;
/* 替换为CSS动画实现的加载效果 */
/*background: linear-gradient(90deg, #eee 25%, #ddd 50%, #eee 75%);*/
animation: spin 1s infinite linear;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.chat-input button:hover {
background-color: #0056b3;
}
.list-enter-active, .list-leave-active {
transition: all 0.5s ease;
}
.list-enter, .list-leave-to /* .list-leave-active in <2.1.8 */ {
opacity: 0;
www.chinasem.cn transform: translateY(30px);
}
我的这个页面有bug,只供参考!!!


到此这篇关于JAVA集成本地部署的DeepSeek的图文教程的文章就介绍到这了,更多相关JAVA集成本地部署DeepSeek内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于JAVA集成本地部署的DeepSeek的图文教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!