跳过正文
Dify 私有化部署与 RAG 应用构建实战

Dify 私有化部署与 RAG 应用构建实战

·665 字·4 分钟·
目录
AI 工程化实战 - 这篇文章属于一个选集。
§ : 本文

在做内部AI应用时,选型通常会在Dify和FastGPT之间纠结。Dify的定位更偏"平台"——它不只是知识库问答,还支持复杂的工作流编排、多种应用类型(聊天机器人、文本生成、Agent)。如果你的需求超出"问知识库"的范畴,Dify是更合适的选择。

这篇文章记录从零开始部署Dify并构建一个运维知识库问答应用的完整过程。


Docker Compose部署
#

Dify官方提供了Docker Compose配置,适合自托管场景。

系统要求
#

  • CPU:4核以上
  • 内存:8GB以上(跑embedding模型需要更多)
  • 磁盘:50GB以上(向量数据库 + 文档存储)
  • Docker 20.10+,Docker Compose 2.x

部署步骤
#

克隆仓库

git clone https://github.com/langgenius/dify.git
cd dify/docker

配置环境变量

cp .env.example .env

编辑.env,关键配置:

# 必须修改的配置
SECRET_KEY=your-random-secret-key-here  # 随机字符串,用于加密
INIT_PASSWORD=your-admin-password       # 初始管理员密码

# 数据库(默认用docker-compose里的postgres,生产建议用外部数据库)
DB_USERNAME=postgres
DB_PASSWORD=your-db-password
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password

# 向量数据库(默认weaviate,也支持pgvector/qdrant/milvus)
VECTOR_STORE=weaviate

# 存储(本地文件系统或S3)
STORAGE_TYPE=local
STORAGE_LOCAL_PATH=storage

# 如果用S3:
# STORAGE_TYPE=s3
# S3_ENDPOINT=https://s3.amazonaws.com
# S3_BUCKET_NAME=your-bucket
# S3_ACCESS_KEY=your-access-key
# S3_SECRET_KEY=your-secret-key
# S3_REGION=us-east-1

启动服务

docker compose up -d

第一次启动会拉取所有镜像(大约5-10分钟),启动后访问http://your-server-ip

验证服务

docker compose ps
# 应该看到以下服务都是 Up 状态:
# dify-api-1, dify-worker-1, dify-web-1
# dify-db-1, dify-redis-1, dify-weaviate-1, dify-nginx-1

生产部署注意事项
#

数据库外置:Docker Compose里的PostgreSQL不适合生产。建议用外部RDS,修改.env里的DB_HOST指向外部数据库。

持久化存储:确保docker-compose.yaml里的volume挂载点在有足够空间的磁盘上:

# 检查当前挂载
docker volume ls | grep dify
# dify_db_data
# dify_weaviate_data
# dify_app_data

反向代理:在Nginx前面加SSL终止,生产环境必须用HTTPS,涉及API Key等敏感信息。

资源限制:给各容器设置resource limits,避免单个服务耗尽宿主机资源:

# docker-compose.yaml
services:
  api:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G

配置LLM Provider
#

部署完成后,第一步是配置语言模型。Dify支持多种Provider。

进入设置
#

管理员登录后,右上角 → 设置 → 模型供应商。

配置OpenAI
#

点击OpenAI旁边的"设置":

  • API Key:sk-your-openai-api-key
  • 如果需要代理:设置Base URL为代理地址

添加后,点击"验证"确认连接正常。

配置Anthropic
#

  • API Key:sk-ant-your-anthropic-api-key
  • 支持Claude 3系列模型

配置本地模型(Ollama)
#

如果有GPU机器跑本地模型:

  1. 先在本地跑Ollama:ollama serve
  2. 拉取模型:ollama pull llama3
  3. 在Dify里选择"Ollama"Provider
  4. 设置Base URL:http://your-ollama-host:11434
  5. 填入模型名:llama3

配置Embedding模型
#

RAG知识库需要单独配置Embedding模型(用于向量化文档)。

进入设置 → 模型供应商 → 找到你的Provider → 配置Embedding模型。

推荐组合:

  • 高质量:OpenAI的text-embedding-3-large
  • 性价比:text-embedding-3-small
  • 本地:nomic-embed-text(通过Ollama)

重要:Embedding模型一旦用于知识库,不要随意更换。更换后所有文档需要重新向量化。


创建知识库
#

知识库是RAG应用的核心,这里重点讲切片配置对效果的影响。

新建知识库
#

主页 → 知识库 → 创建知识库

输入名称,选择使用的Embedding模型。

上传文档
#

支持格式:PDF、Markdown、TXT、HTML、CSV、Word。

上传方式三种:

  1. 本地上传:直接拖拽文件
  2. 同步网站:输入URL,Dify会爬取页面(适合文档站点)
  3. Notion集成:通过OAuth连接Notion,同步指定页面

切片配置
#

这是影响RAG效果最大的配置,值得认真调。

自动切分 vs 手动切分

对于结构良好的文档(有标题层级、段落清晰),用自动切分:

  • 按段落分割
  • 最大token数:500-1000
  • 重叠:50-100 token

对于日志、表格、代码等非结构化内容,建议手动切分(上传前处理好格式)。

切片大小的权衡

  • 切片太大:检索到的文本包含太多无关信息,影响LLM输出质量
  • 切片太小:单个切片上下文不足,答案可能不完整

经验值:

  • 普通文档:500-800 token每片
  • 技术文档/手册:800-1200 token(一个完整的操作步骤)
  • FAQ:按问题切割,每问一片

索引方式

  • 高质量(推荐):向量检索 + 关键词检索,效果最好,但需要配置LLM和Embedding模型
  • 经济:只用关键词检索(BM25),不消耗LLM token,效果一般

文档预处理技巧
#

上传前对文档做预处理,能显著提升效果:

# 预处理示例:去掉PDF导出时的页眉页脚
import re

def clean_pdf_text(text):
    # 去掉页码
    text = re.sub(r'\n\d+\n', '\n', text)
    # 去掉重复的页眉
    text = re.sub(r'公司内部文档 \d{4}-\d{2}-\d{2}\n', '', text)
    # 合并被换行打断的段落
    text = re.sub(r'(?<!\n)\n(?!\n)', ' ', text)
    return text

构建RAG对话应用
#

知识库准备好后,创建一个基于知识库的对话应用。

创建应用
#

主页 → 工作室 → 创建应用 → 聊天助手

配置提示词
#

系统提示词对最终效果影响很大。一个运维知识库问答的系统提示词示例:

你是一个运维技术助手,专门回答关于我们内部运维系统的问题。

**回答规范**:
1. 只基于提供的知识库内容回答,如果知识库里没有相关信息,明确说"我在知识库里没有找到相关信息"
2. 回答要具体、可操作,直接给出步骤或命令
3. 如果问题涉及风险操作(生产环境变更、数据删除等),要在回答里加上风险提醒
4. 引用具体的文档名称和章节,方便用户查找原文

**不要做的事**:
- 不要基于通用知识臆测,只用知识库内容
- 不要给出模糊的答案,如果不确定,说明不确定

关联知识库
#

在"上下文"区域,点击"添加",选择刚才创建的知识库。

关键配置:

  • 召回策略:N选一(多路召回效果更好)
  • 召回条数(TopK):默认3-5,运维文档通常5-8个片段
  • 相似度分数阈值:0.5-0.7,低于此分数的结果不返回

测试和调优
#

应用调试界面里,用真实问题测试:

  1. 问题覆盖面:核心场景都能正确回答
  2. 边界情况:知识库没有的问题,是否正确拒绝
  3. 引用准确性:答案里引用的文档是否真实存在

常见问题排查

Q:回答正确但没有引用来源

  • 检查提示词是否要求引用
  • 在变量设置里开启"引用与归因"

Q:相似问题答错了

  • 查看"召回测试"里,这类问题检索到了哪些片段
  • 可能是切片问题:关键信息和问题分布在不同切片了
  • 调整切片策略重新索引

Q:回答里有幻觉(编造了知识库没有的内容)

  • 强化提示词里的"只基于知识库回答"限制
  • 降低模型的temperature参数(在模型设置里)

工作流编排
#

Dify的工作流(Workflow)是比聊天机器人更强大的应用类型,支持条件分支、循环、多步骤处理。

创建工作流应用
#

创建应用 → 工作流

工作流是可视化节点图,支持拖拽连线。

核心节点类型
#

LLM节点:调用语言模型,可以配置提示词模板

知识检索节点:从知识库检索相关内容,输出召回的文本

代码节点:执行Python代码,适合数据处理、格式转换

# 代码节点示例:从日志中提取错误信息
def main(log_text: str) -> dict:
    import re
    errors = re.findall(r'ERROR.*', log_text)
    return {
        "error_count": len(errors),
        "errors": errors[:10]  # 最多返回10条
    }

条件分支节点:根据条件选择不同执行路径

HTTP请求节点:调用外部API,适合集成内部系统

迭代节点:对列表数据循环处理

实战:告警分析工作流
#

一个实用的工作流:接收告警信息,自动查询知识库给出处理建议。

节点连接:

开始(输入:告警内容)
  ↓
代码节点(提取关键字段:告警名、严重级别、涉及服务)
  ↓
知识检索节点(用提取的信息检索运维手册)
  ↓
LLM节点(综合告警信息和检索结果,生成处理建议)
  ↓
条件分支(判断严重级别)
  ├─ Critical → HTTP请求节点(发送紧急通知)
  └─ Warning  → LLM节点(生成工单摘要)
  ↓
结束(输出处理建议和通知状态)

代码节点示例(解析告警):

def main(alert_text: str) -> dict:
    import re
    
    # 解析Prometheus格式告警
    name_match = re.search(r'alertname="([^"]+)"', alert_text)
    severity_match = re.search(r'severity="([^"]+)"', alert_text)
    service_match = re.search(r'service="([^"]+)"', alert_text)
    
    return {
        "alert_name": name_match.group(1) if name_match else "unknown",
        "severity": severity_match.group(1) if severity_match else "unknown",
        "service": service_match.group(1) if service_match else "unknown",
        "search_query": f"{name_match.group(1) if name_match else ''} {service_match.group(1) if service_match else ''} 处理方法"
    }

API发布与集成
#

Dify应用可以通过API对外发布,集成到现有系统。

获取API Key
#

应用详情页 → API访问 → 创建API Key

API调用示例
#

发送消息

curl -X POST 'https://your-dify-domain/v1/chat-messages' \
  -H 'Authorization: Bearer app-your-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {},
    "query": "K8s节点NotReady怎么排查?",
    "response_mode": "streaming",
    "user": "ops-user-001"
  }'

Python集成

import requests
import json

class DifyClient:
    def __init__(self, api_key: str, base_url: str):
        self.api_key = api_key
        self.base_url = base_url
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
    
    def chat(self, query: str, user_id: str, conversation_id: str = "") -> str:
        payload = {
            "inputs": {},
            "query": query,
            "response_mode": "blocking",
            "user": user_id,
        }
        if conversation_id:
            payload["conversation_id"] = conversation_id
        
        response = requests.post(
            f"{self.base_url}/v1/chat-messages",
            headers=self.headers,
            json=payload,
            timeout=60
        )
        response.raise_for_status()
        result = response.json()
        return result["answer"]

# 使用
client = DifyClient(
    api_key="app-your-api-key-here",
    base_url="https://your-dify-domain"
)
answer = client.chat("Prometheus告警规则怎么写?", "user-123")
print(answer)

集成钉钉机器人
#

通过工作流的HTTP节点,在回答生成后自动推送到钉钉:

# 工作流里的代码节点:格式化钉钉消息
def main(answer: str, question: str) -> dict:
    message = {
        "msgtype": "markdown",
        "markdown": {
            "title": "运维知识库回答",
            "text": f"**问题**:{question}\n\n**回答**:\n{answer}"
        }
    }
    return {"dingtalk_payload": json.dumps(message)}

监控与日志
#

查看使用统计
#

主页 → 概览 可以看到:

  • API调用次数
  • Token消耗
  • 活跃用户数
  • 平均响应时间

查看对话日志
#

应用详情 → 日志 可以查看所有对话记录,包括:

  • 用户输入
  • 系统回答
  • 召回的文档片段
  • Token消耗
  • 响应时间

这是排查问题最重要的入口。

标注与优化
#

在日志里找到回答质量差的对话,点击"标注":

  • 可以写下正确答案
  • 这些标注可以用于微调(需要Pro版)
  • 也可以作为Few-shot示例加入提示词

监控关键指标
#

通过Dify的API可以拿到监控数据,接入Prometheus:

值得监控的指标:

  • 响应时间P99(超过10秒通常有问题)
  • Token消耗速率(成本控制)
  • 错误率(API调用失败率)
  • 知识库召回率(查询有没有召回到相关文档)

版本升级
#

Dify迭代很快,升级流程:

cd dify/docker

# 备份数据库
docker exec dify-db-1 pg_dump -U postgres dify > dify_backup_$(date +%Y%m%d).sql

# 拉取新版本
git pull
docker compose pull

# 重启服务
docker compose down
docker compose up -d

# 检查服务状态
docker compose ps
docker compose logs api --tail=50

升级后注意检查:数据库migration是否自动完成(看api日志),核心功能是否正常。

Wenzhuo Huang
作者
Wenzhuo Huang
搞运维的工程师,写代码的运维人。专注 Kubernetes、AWS、GitOps 与基础设施可靠性。这个博客既是我的技术笔记本,也是我踩过的坑的受害者档案。
AI 工程化实战 - 这篇文章属于一个选集。
§ : 本文

相关文章

LangChain 从入门到实战:构建 LLM 应用的工程框架

·1045 字·5 分钟
LangChain 是构建 LLM 应用最流行的框架,但也是踩坑最多的框架之一。本文从 LCEL 表达式、ReAct Agent、LangGraph 工作流到生产部署,梳理真正有用的部分,并指出哪些功能实际工程中应该避免。

RAG 评估体系:RAGAS 指标与幻觉检测实践

·1391 字·7 分钟
RAG 系统上线后,‘感觉回答质量还不错’不是一个可持续的评估方式。RAGAS 提供了一套可量化的评估框架,让你能追踪 Faithfulness、Answer Relevancy 等指标随时间的变化,并在每次改动后自动验证系统质量没有退化。