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

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

一、deepSeek本地化部署

本地部署方式我们采用ollama,简化部署、内网迁移流程。其他部署方式与对比,可参考:

7种大模型的部署方案汇总

需要提高模型推理效率,可参考:

KTransformers

1.1 windows与mac部署

  • 首先我们访问ollama官方网站:
    ollama.com.

  • 下载相应版本安装包:

4041d6c92c8198698d753c3906752ef6.jpeg


78029780ab6bca1240473658a71d6632.jpeg

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

windows

macOS

  • 配置环境变量

  1. 配置模型存储位置

Ollama会默认将模型存储到C:\Users%username%.ollama\models,防止影响性能,我们将模型路径修改到D盘:

222da067c55f621819526739130e4261.jpeg


  1. 配置跨域请求

Ollama 默认只允许来自127.0.0.10.0.0.0的跨域请求,这里因为笔者Open WebUI在内网其他服务器,配置OLLAMA_ORIGINS*

cafa65b9cf397152a80991beb3faca48.jpeg


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

0b804879c5e91a5ed7c1c55399e3566b.jpeg

这里因为是测试服务器搭建,我们选择一个较小的模型,如果是本机部署,没有显卡的情况下,建议选择「1.5b」(15亿参数)的蒸馏模型。具体模型配置可参考:

DeepSeek模型各版本硬件要求

参考量显存需求显卡推荐命令
1.5B通常4GB左右GTX 1050ollama run deepseek-r1:1.5b
8B一般8-10GBGTX 1660ollama run deepseek-r1:8b
14B12GB以上,16GB以上运行流畅RTX 3060ollama run deepseek-r1:14b
32B16GB以上,21GB以上运行流畅RTX 3060ollama run deepseek-r1:32b
70B24GB以上,40GB以上运行流畅RTX 3090、RTX 4090ollama run deepseek-r1:70b
671B1342GB16张NVIDIA A100 80GB显卡ollama run deepseek-r1:671b
  • 在本地命令行终端执行如下命令在ollma安装deepseek模型:

    我这里有一张英伟达4090卡,24G显存,选择了32b的模型。

ollama run deepseek-r1:${tag} // ollama run deepseek-r1:32b

61bebf79596e1ecc88c6ecfa0e2218b3.jpeg


  • windows内网迁移:

    在互联网机器模型下载成功后,打包ollama安装包与模型,模型我们之前是配置在D:\ollama\models,拷贝到内网后,安装ollama,特别注意要重启命令行工具与 ollama。这里因为我们需要查看具体的token速率,执行:

    ollama run deepseek-r1:32b --verbose // --verbose

    拍照后截图,图片比较模糊,请谅解。

  • b2f0802854d45b168d13751580035194.jpeg

  • 安装完成输出success后输入问题进行测试:

a99feddee67cb6288edd7b5922637e04.jpeg

可以看到成功返回,token rate38.46tokens/s

  • 查看显卡占用 这里我们是英伟达的显卡,输入nvidia-smi

0ea5a11ff716cfa0f4bcf24036f90685.jpeg

或者使用任务管理器->性能模块:

4c658a3b64079bb02f50bff2637697de.jpeg

可以看到GPU显存占用在22G左右。

1.2 linux部署

容器化基础可参考第四小节——「附录」

1.2.1 部署deepseek

  • 运行如下代码:

<!---->


    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镜像。

  • 等待执行完成后,使用如下命令进入容器:

<!---->


    docker ps | grep ollama // 确认容器状态
    docker exec -it ${containerId} /bin/bash // 进入容器
    ollama run deepseek-r1:${tag} // ollama run deepseek-r1:7b 安装deepseek模型
  • 测试deepseek服务

052e9f1dd72264d3578f51fbb497b5ba.jpeg


二、知识库搭建

用于内部涉密资料的检索,因为模型训练成本要求较高,这里我们搭建本地的个人与组织知识库,不过文档的解析、检索差强人意,对外提供服务可基于LlamaIndexLangChain进行开发。如需训练模型,可考虑全参数微调或者loRA等方式。

2.1 个人知识库搭建

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

  • 安装聊天客户端(也可以直接使用AnythingLLM

    进入Chatbox官网:

    chatboxai.app/zh[1]

  • 下载客户端并安装

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

58c6af09fd3da56540ac41704270efab.jpeg


  • 测试聊天工具

97449a8c8f7458c1387b351a4227bb1f.jpeg


  • 安装知识库工具

安装AnythingLLM

d49f6131dc0b1d27e3b49b448fcd1731.jpeg


  • 配置工作区

点击聊天设置,LLM提供者选择ollama

fda306e88d7895ed73ab55a2c12455af.jpeg

  • 设置模型地址 这里Ollama Base URL配置我们本地部署的模型地址:

  • 314864293bc115e26a46c39af1915ace.jpeg

  • 上传知识库文件

点击工作区文件上传按钮,添加知识库文件:

ed79f0de692588ebb35117e34a9ebf6e.jpeg

这里我们添加一个测试文件:

13933d65175f33fe23cb16eaa734256c.jpeg


添加完成后点击Move to Workspace,然后右下角点击Save and Embed进行向量化处理:

f22eac7123b8797b14a3b854347574f5.jpeg


  • 测试知识库 点击new thread,提问 「张三的原名是?」

02528f16be60abd486c7a73e91ff4b4b.jpeg

答案是「王五」,测试完成。

2.2 组织知识库搭建

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

Open WebUI项目地址:Open WebUI.

  • 部署Open WebUI

<!---->


    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/

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

a0d038ad6b9aa8d2b8bb9c88ffa77ca5.jpeg


  • 配置模型

进入管理员面板:

5eef28caf59c793c3ff558e6e72c64c8.jpeg

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

0b0c1739b9e6c9e1ab383c5135d51b16.jpeg

  • 设置模型权限

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

f06e668a280425addba6e7033c0cdd6d.jpeg


  • 测试对话

f58746ec4d4cb78b3c0d077584c6d8f9.jpeg


  • 测试知识库

依次点击工作空间 -> 知识库,即可构建组织知识库:

335a88594e0768880814a946925f0ce5.jpeg

2d149ccc43249818994f9881f4e604a1.jpeg

文档上传、使用过程按下不表,与「个人知识库」类似。

  • docker compose一键部署

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

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. 我们先转储镜像:

<!---->


    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

2.  接下来我们备份数据卷:

<!---->


    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 .

3.  将数据转移到内网服务器后,恢复数据:

<!---->


    // 恢复数据卷
    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

三、代码接入

  • 依赖配置

<!---->


    // 主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. 公共调用组件封装

<!---->


    @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());
            }
        }
    }

2.  创建测试用controller:

<!---->


    @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;
        }
    }

3.  测试

86a296c1c92e3ac8e81903d0b294d9f5.jpeg


四、附录

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

4.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

4.1.2 Docker基础操作

image-20210926111121750.png

拉取镜像,使用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常用指令:

image-20210926111823658.pngeg:

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 以前台的方式启动。

4.2 单机服务编排入门(有基础可跳过)

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

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.

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

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

五、参考资料

  • EdgeX Foundry第一弹 容器运行时docker与服务编排

  • springAI结合ollama简单实现

<think>好的,我需要帮助用户了解在本地部署DeepSeek后如何构建和配置知识库。根据用户提供的引用资料,首先应该整理出步骤流程。 首先,用户已经完成了DeepSeek本地部署,可能已经安装了Ollama并下载了模型文件,如引用1和2提到的。接下来需要搭建知识库,引用3和4提到了使用特定工具,比如AnythingLLM。因此,步骤可能包括安装知识库管理工具、导入文件、配置DeepSeek模型等。 接下来,需要详细说明每个步骤的具体操作。比如,安装AnythingLLM可能需要下载和配置,然后添加本地文件到知识库中。同时,需要确保DeepSeek模型正确接入,这可能涉及到在工具中选择Ollama作为模型源,并指定相应的模型名称。 还需要注意用户可能的疑问点,比如如何导入不同类型的文件,或者如何处理内网部署的情况。根据引用2和4,内网部署可能需要特别的配置,比如离线安装或路径设置。此外,测试知识库是否生效也是关键步骤,用户可能需要验证回答是否基于上传的资料。 最后,生成相关问题时要围绕知识库搭建的后续步骤、工具选择、优化方法等,帮助用户进一步探索。需要确保回答结构清晰,步骤明确,并正确引用提供的资料中的信息。</think>### 如何在本地部署后构建和配置DeepSeek知识库 #### 步骤一:完成DeepSeek本地部署 1. **安装Ollama** 访问[Ollama官网](https://ollama.com/)下载对应操作系统的安装包(Windows/Mac/Linux),完成基础环境配置[^1][^2]。 2. **下载DeepSeek模型** 在Ollama中通过命令行拉取DeepSeek模型(如`ollama pull deepseek-chat`)[^2]。 #### 步骤二:选择知识库管理工具 推荐使用**AnythingLLM**或**Cherry-Studio**: - **AnythingLLM**:支持本地文件解析和向量化存储,提供可视化界面管理知识库[^4]。 - **Cherry-Studio**:通过界面化操作直接关联Ollama模型和本地知识库[^1]。 #### 步骤三:配置知识库 以AnythingLLM为例: 1. **安装启动** 下载AnythingLLM并解压,运行启动脚本(如`docker-compose up`或直接启动可执行文件)[^4]。 2. **关联DeepSeek模型** - 在设置中选择“Ollama”作为模型供应商。 - 输入Ollama服务地址(如`http://localhost:11434`),选择已下载的DeepSeek模型名称[^4]。 3. **导入本地文件** - 进入知识库管理界面,上传文档(支持PDF、TXT、Markdown等格式)。 - 文件会被自动解析并向量化存储,生成知识库索引[^3]。 #### 步骤四:测试知识库功能 1. 创建对话助手,选择已配置的DeepSeek模型和对应的知识库。 2. 提问时,系统会优先从知识库中检索相关内容,再结合模型生成回答。 *示例问题*: - “根据知识库文档,DeepSeek的核心优势是什么?” - 验证回答是否引用了上传文件中的信息[^3]。 #### 步骤五:优化配置(可选) 1. **调整检索策略**:设置关键词权重、相似度阈值等参数。 2. **增量更新**:定期上传新文件,知识库支持动态扩展。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值