简介:这份资源面向希望在本地离线环境中搭建个人知识库的开发者与AI应用实践者,围绕 Dify、Ollama 与 DeepSeek 的组合,提供 Dify 平台的 GitHub 源码 zip 包,解决私有化部署与模型接入时的源码获取问题。压缩包共约2000个文件,以1605个 Python 源码文件和344个 YAML 配置为主,辅以32个 Markdown 文档、9个 HTML 邮件模板、5个 JSON 配置及少量 shell、SQL、XML 文件,整体约26.31MB,覆盖后端逻辑、服务编排、界面模板与数据库脚本等模块,目录结构完整,便于按功能检索与二次开发。已有3583人学习下载,适合需要研究 Dify 内部实现、配置 Ollama 本地模型地址并构建离线问答流程的读者参考,也可作为团队协同与插件化扩展的实践底本。
1. 断网也能跑的知识库:Dify + Ollama + DeepSeek 这套组合到底解决什么问题
上周有个做工业设备售后的朋友找我,说他手里攒了三百多份 PDF 维修手册,想做个能问答的内部工具,但现场车间根本没外网,云端 API 一个都调不通。这种场景其实很典型——不是不想用大模型,是网络条件不允许。Dify 加 Ollama 再挂 DeepSeek 模型,就是冲着这个痛点来的:Dify 负责知识库的切分、向量化和检索编排,Ollama 负责在本地把模型跑起来,DeepSeek 提供推理能力,三者串起来就是一套完全离线的 RAG 系统。这次拆的是 Dify 的 GitHub zip 包,解压即用,不用折腾 Docker 镜像拉取。适合谁?手里有私有文档、需要内网部署、又不想从零写检索链路的从业者。下面按我实际跑通的顺序讲,参数和坑都摆出来。
2. 环境准备与 Dify zip 包落地:从解压到服务起来的完整链路
2.1 为什么选 zip 包而不是镜像拉取
Dify 官方给了几种部署方式,Docker Compose 拉镜像是主流,但在内网或者网络受限的机器上,docker pull经常卡在拉取层。zip 包的好处是把编排文件、配置模板一次性拿到本地,镜像可以提前在有网的机器上导出成 tar 再导入,整个流程可控。我一般会先在能联网的开发机上把镜像docker save成文件,拷到目标机器docker load,再配合 zip 包里的docker-compose.yaml起服务。这样目标机器全程不需要访问外部仓库。
zip 包解压后目录结构大致是dify/docker/下放编排文件,dify/api/和dify/web/是源码,实际部署只用docker目录。先确认目标机器装了 Docker 和 Compose 插件:
docker --version docker compose version两个命令都要有输出,Compose 版本建议 2.x 以上,1.x 的docker-compose命令在部分新编排文件上会报字段不识别。确认完再进目录:
cd dify/docker cp .env.example .env.env是整套服务的配置中枢,数据库密码、端口、密钥都从这里读。复制完先别急着起,打开改几个关键项。
2.2 .env 里必须改的四个参数
很多人解压完直接docker compose up -d,结果服务起来但登录不了或者知识库建不了,八成是.env没动。下面这几个是我每次必改的:
| 参数 | 默认值 | 改成什么 | 不改的后果 |
|---|---|---|---|
SECRET_KEY | 空或示例值 | 随机长字符串 | 会话和加密不稳定 |
DB_PASSWORD | difyai | 自定义强密码 | 数据库裸奔 |
EXPOSE_NGINX_PORT | 80 | 空闲端口如 8080 | 端口冲突起不来 |
CONSOLE_API_URL | 空 | http://本机IP:端口 | 前端调接口 404 |
SECRET_KEY用openssl rand -base64 42生成就行。CONSOLE_API_URL和APP_WEB_URL这两个如果留空,本地localhost访问没问题,但换台机器用 IP 访问时前端会找不到后端,血泪经验是部署到内网服务器时一定填实际 IP。
改完执行:
docker compose up -d第一次起会初始化数据库、建表、跑迁移,耗时几分钟。用docker compose ps看容器状态,api、worker、db、redis、nginx几个都应该是running或healthy。api容器日志里出现Application startup complete才算真正就绪:
docker compose logs -f api看到这行再访问http://本机IP:8080,进初始化页面设管理员账号。这一步别跳过,账号密码记牢,后面知识库和应用都挂在这个账号下。
2.3 Ollama 的安装与模型拉取
Dify 服务起来只是空壳,模型还得靠 Ollama。Ollama 在 Linux 上一条脚本装完,装完确认服务在跑:
curl -fsSL https://ollama.com/install.sh | sh systemctl status ollama服务起来后拉 DeepSeek 模型。这里要注意,Ollama 仓库里的 DeepSeek 有多个尺寸,显存和内存决定你拉哪个。我一般先看机器资源:
nvidia-smi free -h有独立显卡且显存在 8G 以上,可以拉 7B 量化版;纯 CPU 或者显存小,拉更小的蒸馏版,否则加载就 OOM。拉取命令:
ollama pull deepseek-r1:7b拉完验证一下能不能正常推理:
ollama run deepseek-r1:7b "用一句话说明什么是向量检索"能出结果说明模型可用。Ollama 默认监听11434端口,Dify 的容器要访问它,得用宿主机 IP 而不是localhost——容器里的localhost是容器自己。这是新手最容易翻车的点之一,后面避坑章节细说。
3. 在 Dify 里接上 Ollama 与 DeepSeek:模型配置与知识库建库实操
3.1 模型供应商配置:把 Ollama 挂进 Dify
登录 Dify 后进「设置 → 模型供应商」,找到 Ollama 那一项。关键填两个东西:Base URL 和模型名称。Base URL 填http://宿主机IP:11434,注意不是127.0.0.1。填完点保存,如果报连接失败,先在宿主机上curl http://宿主机IP:11434/api/tags看能不能返回模型列表,返回不了就是 Ollama 没监听对外地址。
Ollama 默认只监听127.0.0.1,要让容器访问得改监听地址。编辑服务配置:
systemctl edit ollama在打开的编辑器里加:
[Service] Environment="OLLAMA_HOST=0.0.0.0:11434"保存后systemctl daemon-reload && systemctl restart ollama。再curl一次确认。这一步做完,Dify 里保存供应商配置就能通过。
模型名称填deepseek-r1:7b,要和ollama list里显示的一模一样,大小写、冒号都不能错。填完在供应商页面能看到模型出现在列表里,点「测试」能返回响应就通了。
3.2 知识库建库:切分参数怎么定
进「知识库 → 创建知识库」,上传 PDF 或 Word 文档。Dify 的切分有两种模式:自动切分和自定义。自动切分按固定字符数切,简单但容易把一段完整逻辑切断;自定义可以设分段标识符和最大长度。
我一般这么设:分段标识符用\n\n(段落分隔),最大分段长度 500 字符,分段重叠 50 字符。重叠的作用是防止一句话被切在两段之间导致检索丢上下文。500 这个值不是拍脑袋——中文技术文档一段通常 200 到 400 字,500 能容纳一个完整小节,再大检索精度会下降,因为向量把太多无关内容压进一个块。
索引方式选「高质量」,它用嵌入模型做向量化。嵌入模型也得在模型供应商里配好,Ollama 可以拉nomic-embed-text做嵌入:
ollama pull nomic-embed-text然后在 Dify 的嵌入模型设置里选它。如果选「经济」模式,用的是关键词检索,精度差一截,私有文档场景不建议省这一步。
上传完文档点「开始处理」,处理过程是异步的,看知识库文档状态从「排队中」变「可用」才算完。几百页的文档处理几分钟到十几分钟不等,取决于机器性能。
3.3 检索测试:验证召回质量
建完库别急着做应用,先在知识库的「召回测试」里验一下。输入一个你文档里明确有答案的问题,看返回的分段是不是相关。召回测试里有个「Top K」参数,控制返回几个分段,默认 4。调大召回多但噪声也多,调小精准但可能漏。我一般先设 4 看效果,如果答案分散在多个段落,加到 6。
如果召回结果完全不相关,先查嵌入模型有没有配对——建库时用的嵌入模型和查询时用的必须是同一个,换了模型向量空间对不上,检索就是玄学。这个坑我在一个项目里踩过,换嵌入模型后没重建索引,召回全是乱的,排查了半天才想起来。
4. 编排问答应用与离线验证:从对话链路到断网复测
4.1 创建聊天助手应用
知识库有了,进「工作室 → 创建应用 → 聊天助手」。在编排页面,把「上下文」节点接上刚建的知识库,模型选 Ollama 里的 DeepSeek。系统提示词里写清楚角色和约束,比如「你是设备维修助手,只根据检索到的文档内容回答,文档里没有的信息明确说不知道」。这句约束很关键,不加的话模型会自由发挥,私有知识库场景下胡编比不答更危险。
编排完在右侧调试窗口问几个问题,看回答是否引用了文档内容。Dify 的回答下方会显示引用的分段,点开能看原文,这是验证检索链路是否真的生效的直接手段。如果回答对但没引用,说明模型没走上下文,检查上下文节点有没有正确连线。
4.2 断网复测:确认真的离线可用
整套跑通后,把目标机器的外网断掉(拔网线或关网络接口),重启所有服务,再走一遍问答流程。这一步是很多人的盲区——开发时挂着网,模型和依赖都从网上拉,以为离线没问题,结果断网后 Ollama 拉不到模型、Dify 调不通嵌入接口,全挂。
断网复测要确认三件事:Ollama 模型已本地缓存(ollama list能看到)、Dify 所有容器正常起、问答链路能返回结果。三件都过,这套才算真正落地。我习惯在交付前把断网复测当固定动作走一遍,比事后救火省事得多。
4.3 性能调优的两个抓手
离线环境下性能瓶颈通常在推理速度。两个可调的点:一是模型尺寸,7B 在 CPU 上跑一个字要好几秒,能上 GPU 就上;二是 Dify 的检索 Top K 和分段长度,分段太长会拖慢嵌入和检索。我一般把分段控制在 500 以内,Top K 不超过 6,响应时间能压到可接受范围。
另外 Ollama 有个num_ctx参数控制上下文窗口,默认值偏小,长文档问答时可能截断。可以在模型配置里调大,但调大会吃显存,量力而行。
5. 避坑清单:这套离线组合最容易翻车的五个地方
5.1 容器访问不到宿主机 Ollama
现象:Dify 里配 Ollama 供应商时报连接超时,但宿主机curl localhost:11434正常。原因:容器网络里的localhost指向容器自身,不是宿主机。解决:Base URL 用宿主机实际 IP,同时把 Ollama 的OLLAMA_HOST改成0.0.0.0:11434让它监听对外地址。
5.2 嵌入模型和建库时不一致
现象:知识库召回结果完全不相关,问东答西。原因:建库用的嵌入模型和查询时用的不是同一个,向量空间不匹配。解决:确认模型供应商里嵌入模型唯一且固定,换模型后必须重建知识库索引,不能只改配置。
5.3 端口冲突导致 nginx 起不来
现象:docker compose ps里 nginx 反复重启,日志报bind: address already in use。原因:宿主机 80 端口被占用。解决:改.env里的EXPOSE_NGINX_PORT为 8080 或其他空闲端口,docker compose down再up -d。
5.4 模型拉取后 Dify 里看不到
现象:ollama list有模型,Dify 供应商配置里模型名填了却报不存在。原因:模型名拼写和列表不完全一致,或者 Ollama 服务重启后模型没加载。解决:从ollama list复制完整名称,确认 Ollama 服务状态,必要时ollama run一次触发加载。
5.5 断网后服务起不来
现象:联网时一切正常,断网重启后容器起不来或问答失败。原因:编排文件里有依赖外部镜像或在线资源的配置,或者模型没真正缓存到本地。解决:提前docker save所有镜像并docker load,确认ollama list有模型,断网复测作为交付前固定动作。
6. 进阶技巧:用 API 把离线知识库接进现有系统
Dify 编排好的应用不只是网页能用,它暴露了 API。进应用「访问 API」页面能拿到 API Key 和调用地址,这样就能把问答能力嵌进内部工单系统或者聊天工具,不用让人专门开网页。调用示例:
curl -X POST 'http://宿主机IP:8080/v1/chat-messages' \ -H 'Authorization: Bearer app-xxxxxxxx' \ -H 'Content-Type: application/json' \ -d '{ "inputs": {}, "query": "设备报错 E05 怎么处理", "response_mode": "blocking", "conversation_id": "", "user": "internal-user" }'response_mode选blocking是一次性返回完整回答,适合工单系统这种不需要流式的场景;要打字机效果就选streaming。conversation_id传空表示新会话,多轮对话时把上一轮返回的 id 带上就能保持上下文。user字段用来区分调用方,审计和限流都靠它。
API 调通后,可以在内部系统里做一个输入框加结果展示,后端转发这个请求就行。注意 API Key 别硬编码在前端,走后端代理。另外离线环境下这个接口只在局域网可达,外部访问不了,正好符合内网工具的定位。
验证 API 是否真的走了知识库,看返回体里的retriever_resources字段,里面有引用的分段和文档名。如果这个字段为空,说明检索没命中,回答是模型自由发挥的,得回头查知识库和检索参数。
从那以后我每次交付这类离线知识库,都会在断网状态下把网页问答和 API 调用各走一遍,确认retriever_resources有内容才敢交出去。这套组合的价值不在技术多新,而在每个环节都可控、可复现、断网不慌。希望帮到你。
本文还有配套的精品资源,点击获取