deepseek本地部署(在线、离线)、知识库搭建(个人、组织)与代码接入

本文主要介绍deepSeek本地化容器化部署,知识库搭建与springAI接入。因笔者工作内容原因,也会介绍内网部署方式。

一、deepSeek本地化部署

1.1 windows与mac部署

  • 首先我们访问ollama官方网站:
    ollama.com.
  • 下载相应版本安装包:

注意: 如果没有梯子,下载较慢,可以直接通过网盘链接下载:

windows

macOS

  • 点击models导航栏,并选择deepseek-r1

这里因为是测试服务器搭建,我们选择一个较小的模型,如果是本机部署,建议选择1.5b的蒸馏模型。具体模型配置可参考:

DeepSeek模型各版本硬件要求

参考量 显存需求 显卡推荐 命令
1.5B 通常4GB左右 GTX 1050 ollama run deepseek-r1:1.5b
8B 一般8-10GB GTX 1660 ollama run deepseek-r1:8b
14B 12GB以上,16GB以上运行流畅 RTX 3060 ollama run deepseek-r1:14b
32B 16GB以上,21GB以上运行流畅 RTX 3060 ollama run deepseek-r1:32b
70B 24GB以上,40GB以上运行流畅 RTX 3090、RTX 4090 ollama run deepseek-r1:70b
671B 1342GB 16张NVIDIA A100 80GB显卡 ollama run deepseek-r1:671b
  • 在本地命令行终端执行如下命令在ollma安装deepseek模型:
arduino 复制代码
ollama run deepseek-r1:${tag} // ollama run deepseek-r1:8b
  • 安装完成输出success后输入问题进行测试:

1.2 linux部署

1.2.1 容器化基础(有基础可跳过)

1.2.1.1 Docker安装

step 1:卸载已有资源 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine.

step 2:添加 Docker 安装源 yum-config-manager \ --add-repo \ <https://download.docker.com/linux/centos/docker-ce.repo>.

如果提示yum-config-manager不存在,执行yum -y install yum-utils.

step 3: 安装最新版本Docker yum install docker-ce docker-ce-cli containerd.io.

如果想要安装指定版本的Docker,可以使用以下命令:

yum list docker-ce --showduplicates | sort -r.

yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io.

step 4: 启动docker

systemctl start docker

启动完成后,运行hello world容器,检查是否安装正确,命令如下:

docker run hello-world

Docker 首先会检查本地是否有hello-world这个镜像,如果发现本地没有这个镜像,Docker 就会去 Docker Hub 官方仓库下载此镜像,然后运行它。最后输出 "Hello from Docker!" 并退出。

如需卸载docker,执行yum -y remove docker-engine,,如需删除镜像、容器、卷以及自定义文件,可执行以下命令:

rm -rf /var/lib/docker

1.2.1.2 Docker基础操作

拉取镜像,使用docker pull命令拉取远程仓库的镜像到本地 ;

命令格式:docker pull [Registry]/[Repository]/[Image]:[Tag]

重命名镜像,使用docker tag命令"重命名"镜像 ;

命令格式:docker tag [SOURCE_IMAGE](#) [TARGET_IMAGE](#)

查看镜像,使用docker image lsdocker images命令查看本地已经存在的镜像 ;

删除镜像,使用docker rmi命令删除镜像 ;

构建镜像,构建镜像有两种方式。第一种方式是使用docker build命令基于 Dockerfile 构建镜像,也是我比较推荐的镜像构建方式;第二种方式是使用docker commit命令基于已经运行的容器提交为镜像。

Dockerfile常用指令:

eg:

sql 复制代码
FROM centos:7
​
COPY nginx.repo /etc/yum.repos.d/nginx.repo
​
RUN yum install -y nginx
​
EXPOSE 80
​
ENV HOST=iotnginx
​
CMD ["nginx","-g","daemon off;"]

第一行表示基于 centos:7 这个镜像来构建自定义镜像。这里需要注意,每个 Dockerfile 的第一行除了注释都必须以 FROM 开头。

第二行表示拷贝本地文件 nginx.repo 文件到容器内的 /etc/yum.repos.d 目录下。这里拷贝 nginx.repo 文件是为了添加 nginx 的安装源。

第三行表示在容器内运行yum install -y nginx命令,安装 nginx 服务到容器内,执行完第三行命令,容器内的 nginx 已经安装完成。

第四行声明容器内业务(nginx)使用 80 端口对外提供服务。

第五行定义容器启动时的环境变量 HOST=iotnginx,容器启动后可以获取到环境变量 HOST 的值为 iotnginx。

第六行定义容器的启动命令,命令格式为 json 数组。这里设置了容器的启动命令为 nginx ,并且添加了 nginx 的启动参数 -g 'daemon off;' ,使得 nginx 以前台的方式启动。

1.2.2 单机服务编排入门

单机服务编排工具Docker-compose,这里我们介绍他的安装与基础命令。

bash 复制代码
curl -L "https://github.com/docker/compose/releases/download/${release_tag}/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose

替换release_tag为对应版本,这里我们使用最新的v2.6.0.

bash 复制代码
curl -L "https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose

常用命令:

  • 启动:docker-compose up -d 注意这里需要在yml配置文件路径执行,其他路径执行需要-f指定配置文件地址。
  • 查看日志:docker-compose logs -f ${compose-contatainer-name}
  • 停止:docker-compose stop
  • 停止并删除容器:docker-compose down
  • 其他命令帮助:docker-compose --help

深入学习容器化与服务编排,请查阅参考资料

1.2.3 部署deepseek

  • 运行如下代码:
bash 复制代码
sudo docker pull  swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ollama/ollama
sudo docker run -d -v ollama:/ollama -p 11434:11434 --name ollama swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ollama/ollama

这里因为没有梯子会比较慢,我们使用华为云的ollama镜像。

  • 等待执行完成后,使用如下命令进入容器:
arduino 复制代码
docker ps | grep ollama // 确认容器状态
docker exec -it ${containerId} /bin/bash // 进入容器
ollama run deepseek-r1:${tag} // ollama run deepseek-r1:7b 安装deepseek模型 
  • 测试deepseek服务

二、知识库搭建

2.1 个人知识库搭建

个人知识库的搭建,可以借助ChatboxanythingLLM等工具,这里我们介绍使用Chatbox进行个人知识库的搭建。

  • 进入Chatbox官网:

    chatboxai.app/zh

  • 下载客户端并安装

  • 安装完成后配置本地deepseek地址:

  • 测试个人知识库

2.2 组织知识库搭建

组织知识库的搭建,我们使用Open WebUI,提供一个简洁、好看的页面。

Open WebUI项目地址:Open WebUI.

  • 部署Open WebUI
kotlin 复制代码
docker run -d -p 3030:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.nju.edu.cn/open-webui/open-webui:main

这里我们不使用梯子,仍旧使用国内南京大学的镜像。

  • 访问Open WebUI

浏览器输入http://${webUI-deploy-ip}:3030/

首次进入,需要注册,这里我已经注册,直接进入:

  • 配置模型

进入管理员面板:

点击设置,配置外部链接:

  • 设置模型权限

点击设置->模型,便于测试,这里我们直接设置成public

  • 测试组织知识库
  • docker compose一键部署

前面我们使用docker部署了ollmaOpen WebUI,这里我们将两个容器通过docker compose编排,一键部署,也为后续离线部署降低工作量。 整合容器配置如下:

yaml 复制代码
version: '3' 
    services: 
        ollama: 
            image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ollama/ollama 
            container_name: ollama 
            restart: always 
            ports: - "11434:11434" 
            volumes: - ollama:/ollama 
            networks: - app-network 
        open-webui: 
            image: ghcr.nju.edu.cn/open-webui/open-webui:main 
            container_name: open-webui 
            restart: always ports: - "3030:8080" 
            volumes: - open-webui:/app/backend/data 
            depends_on: - ollama 
            extra_hosts: - "host.docker.internal:host-gateway" 
            networks: - app-network 
    volumes:
        ollama:
            name:ollama-ds
            external: true
       open-webui:
            name: webui-ds
            external: true
    networks:
        app-network:
            external: true
            name: ds-net

启动服务使用:

docker-compose up -d

关闭服务使用:

docker-compose down
  • 内网服务器离线部署
  1. 我们先转储镜像:
lua 复制代码
docker save -o ollama_image.tar swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ollama/ollama 
docker save -o open-webui_image.tar ghcr.nju.edu.cn/open-webui/open-webui:main
  1. 接下来我们备份数据卷:
bash 复制代码
sudo tar -czvf ollama-backup.tar.gz -C /var/lib/docker/volumes/ollama-ds/_data .
sudo tar -czvf webui-backup.tar.gz -C /var/lib/docker/volumes/webui-ds/_data .
  1. 将数据转移到内网服务器后,恢复数据:
kotlin 复制代码
// 恢复数据卷
sudo tar -xzvf ollama-backup.tar.gz -C /var/lib/docker/volumes/ollama-ds/_data
sudo tar -xzvf webui-backup.tar.gz -C /var/lib/docker/volumes/webui-ds/_data
// 加载镜像
docker load -i ollama.tar
docker load -i open-webui.tar
// 创建数据卷和网络
docker volume create --name=ollama-ds
docker volume create --name=webui-ds
docker network create ds-net
// 启动服务
docker-compose up -d
// 验证服务
docker ps

三、代码接入

  • 依赖配置
xml 复制代码
// 主pom
...
<properties>
        <spring-ai.version>1.0.0-SNAPSHOT</spring-ai.version>
</properties>
...
</dependencyManagement>
    </dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
... 
// ai模块
...
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
...
  • springAI接入
  1. 公共调用组件封装
scss 复制代码
@Component
public class Completion {

    @Resource
    private OllamaChatModel aiClient;

    /**
     * 最大消息记录数
     */
    private final static Integer MAX_SIZE = 10;

    /**
     * 消息记录
     */
    private List<Message> messages = new ArrayList<>();


    /**
     * 初始化存入系统消息
     */
    @PostConstruct
    private void addSystemMessage() {
        String message = "李白(701年2月28日---762年12月),字太白,号青莲居士,出生于蜀郡绵州昌隆县(今四川省绵阳市江油市青莲镇),一说出生于西域碎叶 ,祖籍陇西成纪(今甘肃省秦安县)。唐朝伟大的浪漫主义诗人,凉武昭王李暠九世孙 。" +
                "为人爽朗大方,乐于交友,爱好饮酒作诗,名列"酒中八仙" 。曾经得到唐玄宗李隆基赏识,担任翰林供奉,赐金放还后,游历全国,先后迎娶宰相许圉师、宗楚客的孙女。唐肃宗李亨即位后,卷入永王之乱,流放夜郎,辗转到达当涂县令李阳冰家。上元二年,去世,时年六十二 。" +
                "著有《李太白集》,代表作有《望庐山瀑布》《行路难》《蜀道难》《将进酒》《早发白帝城》《黄鹤楼送孟浩然之广陵》等。李白所作词赋,就其开创意义及艺术成就而言,享有极为崇高的地位,后世誉为"诗仙",与诗圣杜甫并称"李杜"。";
        Message systemMessage = new SystemMessage(message);
        messages.add(systemMessage);
    }

    /**
     * 存储用户发送的消息
     */
    private void addUserMessage(String message) {
        Message userMessage = new UserMessage(message);
        messages.add(userMessage);
    }

    /**
     * 存储AI回复的消息
     */
    private void addAssistantMessage(String message) {
        Message assistantMessage = new AssistantMessage(message);
        messages.add(assistantMessage);
    }

    /**
     * 聊天接口
     */
    public String chat(String message) {
        addUserMessage(message);
        String result = aiClient.call(new Prompt(messages)).getResult().getOutput().getText();
        addAssistantMessage(result);
        update();
        return result;
    }

    /**
     * 流式聊天接口
     */
    public Flux<String> chatStream(String message) {
        addUserMessage(message);

        StringBuffer fullReply = new StringBuffer();

        Flux<String> fluxResult = aiClient.stream(new Prompt(messages))
                .flatMap(response -> {
                    String reply = response.getResult().getOutput().getText();

                    //拼接回复内容
                    fullReply.append(reply);

                    return Flux.just(reply);
                })
                .doOnComplete(() -> {
                    //监听流式响应完成,完整回复存入消息记录
                    System.out.println(fullReply);
                    addAssistantMessage(String.valueOf(fullReply));
                });

        update();
        return fluxResult;
    }

    /**
     * 更新消息记录
     */
    private void update() {
        if (messages.size() > MAX_SIZE) {
            messages = messages.subList(messages.size() - MAX_SIZE, messages.size());
        }
    }
}
  1. 创建测试用controller:
ini 复制代码
@Slf4j
@RestController
@RequestMapping("/api")
public class OllamaTestController {
    @Autowired
    private OllamaChatModel ollamaChatClient;

    @RequestMapping("/chat")
    public String chat(){
        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));

        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        List<Generation> response = ollamaChatClient.call(prompt).getResults();

        String result = "";

        for (Generation generation : response){
            String content = generation.getOutput().getText();
            result += content;
        }

        return result;
    }


    @RequestMapping("/stream")
    public SseEmitter stream(HttpServletResponse response){
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");
        SseEmitter emitter = new SseEmitter();


        String systemPrompt = "{prompt}";
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);

        String userPrompt = "广州有什么特产?";
        Message userMessage = new UserMessage(userPrompt);

        Message systemMessage = systemPromptTemplate.createMessage(MapUtil.of("prompt", "you are a helpful AI assistant"));
        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));

        ollamaChatClient.stream(prompt).subscribe(x -> {
            try {
                log.info("response: {}",x);
                List<Generation> generations = x.getResults();
                if(CollUtil.isNotEmpty(generations)){
                    for(Generation generation:generations){
                        AssistantMessage assistantMessage =  generation.getOutput();
                        String content = assistantMessage.getText();
                        if(StringUtils.isNotEmpty(content)){
                            emitter.send(content);
                        }else{
                            if(StringUtils.equals(content,"null"))
                                emitter.complete(); // Complete the SSE connection
                        }
                    }
                }


            } catch (Exception e) {
                emitter.complete();
                log.error("流式返回结果异常",e);
            }
        });

        return emitter;
    }
}
  1. 测试

四、参考资料

相关推荐
陈老师还在写代码2 分钟前
介绍下SpringBoot常用的依赖项
java·spring boot·后端
yc_235 分钟前
语义分割文献阅读——SETR:使用Transformer从序列到序列的角度重新思考语义分割
人工智能·深度学习·transformer
深圳市快瞳科技有限公司8 分钟前
杜绝遛狗不牵绳,AI技术助力智慧城市宠物管理
人工智能·智慧城市·宠物
豆豆酱18 分钟前
强化学习到大模型训练理论概要(一)
人工智能·算法
山海青风19 分钟前
OpenAI 实战进阶教程 - 第十二节 : 多模态任务开发(文本、图像、音频)
图像处理·人工智能·python·ai作画·音视频·语音识别
007php00736 分钟前
Docker、Ollama、Dify 及 DeepSeek 安装配置与搭建企业级本地私有化知识库实践
运维·服务器·开发语言·后端·docker·容器·云计算
2501_9044477443 分钟前
荣耀已接入DeepSeek-R1,荣耀手机系统版本MagicOS8.0及以上用户可用
人工智能·智能手机·virtualenv·scikit-learn·tornado
LaughingZhu1 小时前
PH热榜 | 2025-02-10
人工智能·经验分享·产品运营
魏翾蒨1 小时前
VBA语言的数据可视化
开发语言·后端·golang
不爱原创的Yoga1 小时前
【AI】人工智能与搜索引擎知识了解
人工智能·搜索引擎