从零搭建Dify+DeepSeek RAG知识库:完整可跑代码
> 本文首发于 Agent评测站,一个独立AI智能体工具评测平台。
RAG(检索增强生成)是目前让大模型回答私有数据问题最实用的方案。这篇文章从零开始,带你在服务器上部署Dify,接入DeepSeek模型,导入文档,做成一个能直接用的知识库问答系统。
环境要求
服务器: Linux (Ubuntu 22.04 / CentOS 7+)
配置: 2核4G以上(推荐4核8G)
已安装: Docker + Docker Compose
没有Docker的先去装:
# Ubuntu
curl -fsSL https://get.docker.com | sh
sudo apt install docker-compose-plugin -y
# CentOS
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-compose-plugin
systemctl start docker
systemctl enable docker
第一步:部署Dify
Dify官方提供了Docker Compose一键部署:
git clone https://github.com/langgenius/dify.git
cd dify/docker
cp .env.example .env
docker compose up -d
等待镜像拉取和启动(第一次大约3-5分钟,取决于网络):
# 查看启动状态
docker compose ps
# 查看日志
docker compose logs -f
看到 api 和 worker 两个容器都正常运行后,访问 http://你的IP:80 进入设置页面。
踩坑记录
问题1:80端口被占
如果服务器上nginx已经在用80端口,改Dify的端口映射:
# 编辑 docker-compose.yml
# 把 nginx 的 80:80 改成 8080:80
sed -i 's/"80:80"/"8080:80"/g' docker-compose.yml
docker compose up -d
然后访问 http://IP:8080。
问题2:内存不够导致MySQL启动失败
Dify依赖MySQL 8.0,512M内存下经常启动不了。加swap:
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
问题3:容器重启后数据丢失
Dify的数据在docker volume里,正常情况下不会丢。但如果你 docker compose down -v(带-v参数)会把volume也删了。建议定期备份:
# 备份数据库
docker exec dify-db-1 pg_dump -U postgres dify > dify_backup_$(date +%Y%m%d).sql
第二步:配置模型
Dify支持多种模型。这里以DeepSeek为例(价格便宜,中文好,国内可直接访问):
进入Dify后台 → 右上角头像 → 设置 → 模型供应商 → 添加模型:
- 模型类型: LLM
- 供应商: OpenAI-API-compatible
- 模型名称: deepseek-chat
- API Key: 你的DeepSeek API Key(去 platform.deepseek.com 申请)
- API Base URL: https://api.deepseek.com/v1
- 上下文长度: 32768
配置Embedding模型(用于向量化文档):
- 模型类型: Embedding
- 供应商: OpenAI-API-compatible
- 模型名称: text-embedding-ada-002(也可以用DeepSeek的embedding接口)
> 注意:DeepSeek目前没有公开的Embedding API,所以这里用OpenAI的text-embedding-ada-002,或者用BAAI的bge-large-zh-v1.5(通过Ollama本地跑,免费但不限速)。
第三步:创建知识库
回到首页 → 知识库 → 创建知识库。
准备文档
把你的文档整理一下。Dify支持PDF、TXT、Markdown、HTML等格式。几点经验:
- 单文件不超过10MB,太大了处理时间长,还容易超时
- 按章节拆分,不要整个200页PDF扔进去。我一般按文档的章节拆成多个文件
- 表格多的文档,建议转成Markdown再传。Dify的PDF解析对复杂表格处理不好
分段设置
上传后进入分段设置页面,这里参数很关键:
分段模式: 父子分段
分段长度: 400 tokens
分段重叠: 40 tokens
索引方式: 高质量(向量检索)
Embedding模型: 选刚才配好的
检索策略: 混合检索(向量+关键词)
为什么用父子分段:简单说就是——把文档切成大块(父段)和小块(子段)。用户提问时用小段匹配,但回复时用大段上下文。这样既提高了检索准确率,又保证了回答的上下文完整性。
保存并索引
点"保存并处理",Dify会逐个文档做分段→向量化→索引。文档数量多的话需要几分钟。
完成后可以在知识库里测试搜索,输入一个问题看看检索到的段落是否相关。
第四步:创建问答应用
回到首页 → 工作室 → 创建应用 → 聊天助手。
关联知识库
在应用的提示词编辑器左侧,点"添加知识库",选刚才建的那个。
系统提示词
默认的提示词太啰嗦了,改成这样:
你是一个基于企业内部知识库的问答助手。
回答规则:
1. 只使用知识库中检索到的内容回答
2. 如果用户问的问题知识库中没有,直接说"知识库中暂时没有相关信息"
3. 不要编造信息
4. 保持回答简洁,控制在200字以内
5. 如果涉及具体数据,引用原文出处
调整LLM参数
模型: deepseek-chat
温度: 0.1(知识问答越精确越好)
最大Token: 2000
上下文限制: 最近5轮对话
温度设低一些,因为知识库问答需要精确性,不需要创造性。
第五步:优化检索效果
提高命中率
运行一段时间后,你会发现有些问题知识库回答不了。原因通常是:
问题1:分段太粗
用户问"上个月的销售数据",但知识库里的分段是按产品类型分的,没有按月。
解决:把文档按更多维度重新拆分。比如销售数据按"时间段"和"产品类型"两个维度各拆一份。
问题2:问题的用词和文档不一致
用户问"退货流程"但文档里写的是"退换货政策"。
解决:检索策略选"混合检索"。向量检索基于语义能理解"退货≈退换货",关键词检索能精确匹配"退货"。两种结合效果最好。
问题3:Top K设太少
默认Top K是3,但有时候相关段落分布比较散,3段不够覆盖。
解决:把Top K调到5,同时开启Rerank排序。Rerank会在5段候选里找出最相关的2-3段。
添加预查询
如果知识库文档结构固定(比如都是按"问题-答案"格式写的),可以加一个预查询步骤——用户提问时,先让LLM把问题改写成更匹配文档格式的表述,再用改写后的查询去检索。
# 伪代码:预查询改写
def preprocess_query(question):
prompt = f"""用户问:{question}
请将这个用户问题改写成知识库检索查询语句。
要求:保留核心关键词,补充同义词,去掉口语化表达。
直接返回改写后的查询语句,不要解释。"""
rewritten = llm_chat(prompt)
return rewritten
完整配置总结
┌────────────┐ ┌──────────────┐ ┌────────────────┐
│ 用户提问 │ → │ 意图识别 │ → │ 知识库检索 │
└────────────┘ └──────────────┘ └────────────────┘
│
↓
┌────────────┐ ┌──────────────┐ ┌────────────────┐
│ 最终回复 │ ← │ LLM生成 │ ← │ 上下文组装 │
└────────────┘ └──────────────┘ └────────────────┘
日常维护
- 定期更新知识库——业务文档变化后,及时替换知识库里的文件
- 关注检索质量——如果用户反复问同一个问题但回答不好,说明知识库里缺那部分内容
- 监控API费用——DeepSeek很便宜(¥1/1M tokens左右),但每天几千次查询也会积累。建议设一个日消耗上限
- 日志保留——Dify内置了对话日志,建议保留至少30天,用来分析哪些问题AI回答不好
---
代码和配置都可以直接用。如果你在部署过程中遇到具体问题,可以在评论区留言。