作为 Java 开发者,想在本地搭建一个能理解代码、支持多轮对话的 AI 机器人?DeepSeek-R1 这款开源大模型绝对值得一试。今天就带大家用 Ollama+Java 实现本地化部署,全程实操,新手也能跟着做!

一、先搞懂:为什么选 DeepSeek-R1?

这款模型有三个核心优势,特别适合开发者:

  • 代码理解强:对 Java 语法、框架原理的解析准确率比同类模型高 15%+
  • 对话不 "失忆":支持 50 轮以上多轮对话,上下文连贯性远超基础模型
  • 本地能跑:7B 参数版在 16GB 内存的普通电脑上就能流畅运行,不用高配显卡

硬件要求放这里了,对照着看:

  • 最低配置:CPU 8 核 +,16GB 内存(纯 CPU 推理能跑,但响应稍慢)
  • 推荐配置:NVIDIA 显卡(8GB 显存以上),支持 CUDA 加速,响应速度提升 3 倍

二、环境搭建:3 步搞定 Ollama 和模型

1. 安装 Ollama

官网下载对应系统版本:Download Ollama on macOS
安装完成后打开终端,输入ollama --version,能看到版本号就说明成功了。

2. 拉取 DeepSeek-R1 模型

终端执行命令:

# 推荐先装7B参数版,平衡性能和资源
ollama pull deepseek-r1:7b

拉取过程可能需要几分钟(看网速),耐心等一下。

3. 测试模型是否能用

输入ollama run deepseek-r1:7b进入交互模式,试试问它:"用 Java 写个单例模式",能得到正确回复就没问题了。

三、Java 代码实战:从依赖到接口

1. 项目依赖(pom.xml)

先把必要的依赖加上,都是 Spring 生态常用的:

<dependencies><!-- Spring Web核心 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- HTTP客户端 --><dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.3</version></dependency><!-- JSON处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- Lombok简化代码 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

2. 数据模型:4 个类搞定请求响应

这些类是用来封装数据的,直接抄就行:

// 接收用户输入的模型
@Data
public class ChatRequest {private String message; // 用户输入的消息private String sessionId; // 会话ID,多轮对话用
}// 发给Ollama的请求参数
@Data
public class DeepSeekRequest {private String model = "deepseek-r1:7b"; // 模型名private List<Message> messages; // 对话历史private Float temperature = 0.6f; // 0.6适合对话,不生硬private Boolean stream = false; // 非流式响应@Datapublic static class Message {private String role; // "user"或"assistant"private String content; // 消息内容}
}// Ollama返回的响应
@Data
public class DeepSeekResponse {private String model;private List<ResponseMessage> messages;private Boolean done;@Datapublic static class ResponseMessage {private String role;private String content; // 模型回复的内容}
}// 给前端的最终响应
@Data
public class ChatResponse {private String reply; // 回复内容private String sessionId; // 会话IDprivate long timestamp; // 时间戳
}

3. 会话管理:让机器人记住上下文

这个服务用来存对话历史,不然每次对话都是新的:

@Service
public class SessionManager {// 用ConcurrentHashMap存会话,key是sessionIdprivate final Map<String, List<DeepSeekRequest.Message>> sessionHistory = new ConcurrentHashMap<>();// 获取某个会话的历史消息public List<DeepSeekRequest.Message> getHistory(String sessionId) {return sessionHistory.computeIfAbsent(sessionId, k -> new ArrayList<>());}// 添加用户消息到历史public void addUserMessage(String sessionId, String message) {DeepSeekRequest.Message msg = new DeepSeekRequest.Message();msg.setRole("user");msg.setContent(message);getHistory(sessionId).add(msg);}// 添加机器人回复到历史public void addAssistantMessage(String sessionId, String message) {DeepSeekRequest.Message msg = new DeepSeekRequest.Message();msg.setRole("assistant");msg.setContent(message);getHistory(sessionId).add(msg);}// 清理会话(可选)public void clearHistory(String sessionId) {sessionHistory.remove(sessionId);}
}

4. 核心服务:调用 Ollama 接口

这部分是关键,负责把用户消息发给模型,再把回复拿回来:

@Service
public class DeepSeekService {// Ollama的API地址,本地部署固定这个private static final String OLLAMA_API_URL = "http://localhost:11434/api/chat";private final CloseableHttpClient httpClient;private final ObjectMapper objectMapper;private final SessionManager sessionManager;// 构造函数注入依赖public DeepSeekService(SessionManager sessionManager) {this.httpClient = HttpClients.createDefault();this.objectMapper = new ObjectMapper();this.sessionManager = sessionManager;}// 处理用户消息,返回回复public ChatResponse processMessage(ChatRequest request) {// 生成或复用sessionIdString sessionId = request.getSessionId();if (sessionId == null || sessionId.isEmpty()) {sessionId = UUID.randomUUID().toString();}// 构建发给模型的请求DeepSeekRequest deepSeekRequest = new DeepSeekRequest();sessionManager.addUserMessage(sessionId, request.getMessage());deepSeekRequest.setMessages(sessionManager.getHistory(sessionId));try {// 发送POST请求到OllamaHttpPost httpPost = new HttpPost(OLLAMA_API_URL);httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(deepSeekRequest)));// 执行请求并解析响应try (CloseableHttpResponse response = httpClient.execute(httpPost)) {HttpEntity entity = response.getEntity();if (entity != null) {String responseBody = EntityUtils.toString(entity);DeepSeekResponse deepSeekResponse = objectMapper.readValue(responseBody, DeepSeekResponse.class);// 提取回复内容String reply = deepSeekResponse.getMessages().get(0).getContent();sessionManager.addAssistantMessage(sessionId, reply);// 构建返回结果ChatResponse chatResponse = new ChatResponse();chatResponse.setReply(reply);chatResponse.setSessionId(sessionId);chatResponse.setTimestamp(System.currentTimeMillis());return chatResponse;}}} catch (Exception e) {throw new RuntimeException("调用模型出错:" + e.getMessage());}return null;}
}

5. 控制器:提供 HTTP 接口

最后写个控制器,前端就能通过接口调用了:

@RestController
@RequestMapping("/chatbot")
public class ChatController {private final DeepSeekService deepSeekService;public ChatController(DeepSeekService deepSeekService) {this.deepSeekService = deepSeekService;}// 接收消息的接口@PostMapping("/message")public ResponseEntity<ChatResponse> sendMessage(@RequestBody ChatRequest request) {try {ChatResponse response = deepSeekService.processMessage(request);return ResponseEntity.ok(response);} catch (Exception e) {return ResponseEntity.status(500).body(null);}}// 清理会话的接口(可选)@PostMapping("/clear/{sessionId}")public ResponseEntity<Void> clearSession(@PathVariable String sessionId) {sessionManager.clearHistory(sessionId);return ResponseEntity.ok().build();}
}

四、测试运行:用 curl 或 Postman 调用

  1. 先启动 Ollama 服务:ollama serve(后台运行)
  2. 启动 Spring Boot 应用
  3. 用 curl 测试(也可以用 Postman):
# 第一次请求(没有sessionId,会自动生成)
curl -X POST http://localhost:8080/chatbot/message \-H "Content-Type: application/json" \-d '{"message":"什么是Spring Boot?"}'# 多轮对话(用第一次返回的sessionId)
curl -X POST http://localhost:8080/chatbot/message \-H "Content-Type: application/json" \-d '{"message":"它和Spring MVC有啥区别?", "sessionId":"第一次返回的ID"}'

返回的 JSON 里有reply字段,就是机器人的回复啦。

五、踩坑指南:这些问题要注意

1. 模型响应慢?

  • 检查显卡是否被用上:nvidia-smi看看有没有 Ollama 进程
  • 换小模型:用 7B 代替 33B 版本
  • 限制内存使用:export OLLAMA_MAX_MEMORY=12GB(根据自己内存调整)

2. 多轮对话记不住上下文?

  • 一定传对 sessionId,每次对话都要用同一个
  • 服务重启后,旧的 sessionId 会失效,需要重新获取

3. 中文乱码?

  • 请求头加上charset=UTF-8(代码里已经加了,注意别删)
  • 配置 Jackson:
    objectMapper.getFactory().configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
    

4. 内存溢出(OOM)?

  • 给 Java 加内存:启动参数加-Xmx4g
  • 清理不活跃的会话:加个定时任务,删除几小时没动静的 session

动手试试吧,有问题可以在评论区交流~

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

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

相关文章

Java Web项目Dump文件分析指南

目录 1. Dump文件的类型与作用 2. 生成Dump文件的方法 3. 分析Dump文件的工具 4. 分析步骤与常见问题解决 5. 最佳实践与预防 在Java Web项目中&#xff0c;dump文件是JVM&#xff08;Java虚拟机&#xff09;在发生崩溃、内存溢出或特定事件时生成的内存快照文件&#xff0…

Ubuntu网卡驱动无效,不能连接wifi上网

一、现象及临时网络准备 我的另一篇博客详细介绍了前期准备工作&#xff1a; 知乎&#xff1a;Ubuntu网卡驱动无效&#xff0c;不能连接wifi上网知乎&#xff1a;Ubuntu网卡驱动无效&#xff0c;不能连接wifi上网 在此基础上&#xff0c;还得给Ubuntu配好镜像源&#xff0c;…

LeetCode Hot 100 二叉搜索树中第 K 小的元素

给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 小的元素&#xff08;从 1 开始计数&#xff09;。示例 1&#xff1a;输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff1a;1示例 2&#xff1a;输入&#xff1a…

5-大语言模型—理论基础:注意力机制优化

目录 1、稀疏注意力机制&#xff08;Sparse Attention&#xff09; 1.1、核心问题&#xff1a;传统注意力的 “效率瓶颈” 1.2、具体稀疏策略&#xff08;详细计算逻辑&#xff09; 1.2.1、局部窗口稀疏&#xff08;Local Window Sparse&#xff09; 1.2.2、基于内容的稀疏…

轻松学习C++:基本语法解析

基本语法解析引言基本语法变量和数据类型运算符控制结构函数示例代码&#xff1a;计算圆的面积引言 C是一种功能强大的通用编程语言&#xff0c;由Bjarne Stroustrup于1979年创建。它在C语言的基础上进行了扩展&#xff0c;支持面向对象编程、泛型编程和过程式编程。C以其高性…

Python Pandas读取Excel表格中数据并根据时间字段筛选数据

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录Python Pandas读取Excel表格中数据并根据时间…

CS231n-2017 Lecture3线性分类器、最优化笔记

图片向量与标签得分向量&#xff1a;上节讲到&#xff0c;图片可以被展开成一个向量&#xff0c;对于这个向量&#xff0c;假设它有D维&#xff0c;那么它就是D维空间的一个点&#xff0c;又假设我们的标签集合总共有K种&#xff0c;我们可以定义一个K维标签得分向量&#xff0…

windows wsl ubuntu 如何安装 open-jdk8

安装步骤 jdk dhd:~$ java -version Command java not found, but can be installed with: sudo apt install openjdk-11-jre-headless # version 11.0.20.11-0ubuntu1~22.04, or sudo apt install default-jre # version 2:1.11-72build2 sudo apt install op…

Javascript进程和线程通信

JavaScript 中的进程通信&#xff08;IPC&#xff09;和线程通信是实现高性能、高并发应用的核心技术&#xff0c;尤其在处理 CPU 密集型任务或跨环境数据交互时至关重要。以下从底层机制到应用场景的详解&#xff1a;&#x1f9e9; ​​一、进程通信&#xff08;Inter-Process…

堆堆堆,咕咕咕

1.找TopK问题要找到最前面的k个元素void swap(int *a,int *b) {int temp*a;*a*b;*btemp; } //向下调整最小堆 void minheapify(int arr[],int n,int index) {int left2*index1;int right2*index2;int smallestindex;if(left<n&&arr[left]<arr[smallest]) smalles…

n8n教程分享,从Github读取.md文档内容

从上一篇我们了解到了如何安装 n8n 那么这节课我们尝试从github的个人仓库获取某个文件的内容 目标如下 content/business/1.how-to-use-money.mdx 总流程图 流程详解 第1步&#xff1a;申请 GitHub Personal Access Token (Classic) 在gitrhub 个人 设置选项 申请 GitHub P…

分布式ID与幂等性面试题整理

分布式ID与幂等性面试题整理 文章目录分布式ID与幂等性面试题整理一、分布式ID1. 为什么需要分布式ID&#xff1f;2. 分布式ID的核心要求3. 常见分布式ID方案(1) UUID(2) 数据库自增(3) Redis自增(4) 雪花算法(Snowflake)(5) 美团Leaf/百度UidGenerator4. 雪花算法详解二、幂等…

node.js学习笔记1

目录 Node.js是什么 Node.js下载与安装 Buffer缓冲区 一些计算机硬件基础 程序运行的基本流程 Node.js是什么 node.js是一个JavaScript运行环境&#xff0c;或者说&#xff0c;node.js是一个可以运行JavaScript的软件。 可以用于开发服务端、桌面端、工具类应用。 服务器…

游戏开发日志

我来为您逐行详细讲解这个 ViewMgr.cs 文件。这是一个Unity游戏中的视野管理系统&#xff0c;用于优化游戏性能。## 文件结构概览这个文件主要包含以下几个部分&#xff1a; 1. 数据结构和接口定义 2. 视野管理器 ViewMgr 类 3. 工具类 ViewTools让我逐行为您讲解&#xff1a;#…

使用 PlanetScope 卫星图像绘制水质参数:以莫干湖为例

1.数据采集 我使用ArcGIS Pro 中的Planet Imagery插件下载了 2023 年 6 月 25 日的安卡拉莫干湖卫星图像。 图 1&#xff1a;使用 Planet 插件下载卫星图像 图 2&#xff1a;下载图像的日期和传感器选择 我查阅的研究中指出&#xff0c;使用无降水时期的卫星图像对于水质测定…

Docker部署前后端分离项目——多项目共享环境部署

目录 一、简介 二、文件目录结构 三、前端部署流程&#xff08;多nginx&#xff09; 3.1 前端打包 3.2 编写部署文件——项目1&#xff08;consult-system&#xff09; 3.3 编写部署文件——项目2&#xff08;person-system&#xff09; 3.4 前端部署至linux服务器 3.5…

学习笔记(39):结合生活案例,介绍 10 种常见模型

学习笔记(39):结合生活案例&#xff0c;介绍 10 种常见模型线性回归只是机器学习的 “冰山一角”&#xff01;根据不同的任务场景&#xff08;分类、回归、聚类等&#xff09;&#xff0c;还有许多强大的模型可以选择。下面我用最通俗易懂的语言&#xff0c;结合生活案例&#…

BabyAGI 是一个用于自构建自主代理的实验框架

这个最新的 BabyAGI 是一个用于自构建自主代理的实验框架 核心是一个新的函数框架 &#xff08;functionz&#xff09;&#xff0c;用于存储、管理和执行数据库中的函数。它提供了一个基于图形的结构&#xff0c;用于跟踪导入、依赖函数和身份验证密钥&#xff0c;并具有自动加…

商业秘密视域下计算机软件的多重保护困境

作者&#xff1a;邱戈龙、柯坚豪重庆商业秘密律师广东长昊律师事务所引言&#xff1a;计算机软件保护的复杂性 在商业秘密保护的宏大版图中&#xff0c;计算机软件因其技术密集性和创新性占据着特殊地位。软件的真正价值不仅在于其代码本身&#xff0c;更在于其背后的流程、逻…

深入理解 Spring Boot 自动配置原理

Spring Boot 之所以能“开箱即用”&#xff0c;其核心就在于 自动配置机制&#xff08;Auto Configuration&#xff09;。本文将深入剖析 Spring Boot 自动配置的工作原理&#xff0c;从注解入手&#xff0c;再到底层的源码机制&#xff0c;揭开 Spring Boot 背后的“魔法”。 …