Dify工作流从0到1:可视化AI应用搭建完全指南
1. Dify是什么
- Dify( DIY + Verify ,意为"自己动手,验证想法")是一个开源的 LLM应用开发平台 ,其核心理念是让任何人都能通过可视化拖拽的方式搭建AI工作流,而无需编写大量胶水代码。它于2023年开源,支持接入 OpenAI、Anthropic Claude、国内通义千问/DeepSeek 等主流大模型。
官方定义:Dify是一个开源的LLM应用开发平台,提供可视化的工作流编排、知识库管理、模型接入、多端发布等能力。
对比传统开发方式,Dify 的核心价值在于:
- 0代码编排工作流:拖拽节点、连线、配置参数,三步完成一个AI流程
- 一键发布为API:任何工作流都可以暴露为 REST API,直接被其他系统调用
- 内置知识库:RAG(检索增强生成)开箱即用,无需自己搭向量数据库
- 可观测性:每个节点的输入输出实时可见,方便调试
2. 与同类工具横向对比
市场上主流的可视化AI工作流工具主要有四个:Dify、n8n、AutoGen 和 LangFlow。以下从多个维度做详细对比。
| 维度 | Dify | n8n | AutoGen | LangFlow |
|---|---|---|---|---|
| 定位 | LLM应用平台 | 通用工作流自动化 | 多智能体协作框架 | LangChain可视化 |
| 编程要求 | 零代码/低代码 | 低代码 | 需写Python | 需写Python |
| 工作流界面 | 拖拽画布(类Node-RED) | 拖拽画布+表达式 | 代码配置为主 | 图形节点图 |
| LLM接入 | 内置(直接填API Key) | 通过HTTP节点调用 | 灵活原生调用 | 通过LangChain接入 |
| RAG/知识库 | 内置,开箱即用 | 需自建或插件 | 需自行实现 | 通过LangChain组件 |
| API发布 | 一键生成,REST API | 自带Webhook | 需自行封装 | 需自行封装 |
| 社区活跃度 | 活跃(GitHub 40k+⭐) | 非常活跃 | 一般 | 较小 |
| 部署难度 | Docker一键 | Docker一键 | 需Python环境 | 需Python环境 |
| 适合人群 | 全栈/非程序员 | 自动化爱好者 | AI研究员 | LangChain用户 |
2.1 各工具适用场景
Dify — 首选推荐
- 快速搭建AI客服机器人
- 内容创作工作流(选题→写作→发布)
- 私有知识库问答系统
- 需要对外提供AI API的服务
n8n — 通用自动化
- 连接各种第三方SaaS(Slack/Gmail/Notion)
- 将AI能力嵌入到现有自动化流程中
- 定时任务+条件分支的复合流程
AutoGen — 多智能体
- 需要多个AI Agent互相协作完成复杂任务
- 学术研究/原型验证多Agent场景
- 需要精确控制Agent通信协议
LangFlow — LangChain用户
- 已在使用LangChain,想可视化调试Chain
- 需要灵活组合LangChain各种组件
- 作为LangChain的原型设计工具
3. Docker安装详解(逐行命令解释)
3.1 环境要求
| 项目 | 最低要求 | 推荐配置 |
|---|---|---|
| CPU | 2核 | 4核+ |
| 内存 | 4GB | 8GB+ |
| 磁盘 | 20GB | 50GB+ SSD |
| 系统 | Ubuntu 20.04+ / Debian 11+ | 同上 |
| Docker | v20.10+ | v24+ |
| Docker Compose | v2.0+ | v2.20+ |
docker --version 和 docker compose version 检查已安装版本。
3.2 安装步骤(Step by Step)
第一步:安装 Docker(如果未安装)
# 01 下载 Docker 官方安装脚本(适合 Ubuntu/Debian)
curl -fsSL https://get.docker.com -o get-docker.sh
# 02 以 root 权限执行安装脚本
# -s 支持台:让安装脚本输出安装过程
# --with-docker-compose-v2:同时安装 Docker Compose V2
sudo sh get-docker.sh --with-docker-compose-v2
# 03 将当前用户加入 docker 组(避免每次用 sudo)
# $USER 自动替换为当前用户名
sudo usermod -aG docker $USER
# 04 验证 Docker 是否安装成功
# 正常运行会输出 "Hello from Docker!"
docker run --rm hello-world
第二步:安装 Docker Compose V2
# 01 查看当前 Docker Compose 版本(如果是 V2 则已内置)
docker compose version
# 输出示例:Docker Compose version v2.24.0
# 02 如果是 V1 版本(docker-compose --version),升级到 V2
# V2 集成在 docker 主命令中,语法为 `docker compose`(空格)
# V1 语法为 `docker-compose`(横杠),新版已废弃
# 03 手动安装 Docker Compose V2(Ubuntu/Debian)
# 下载二进制文件到 /usr/local/bin/
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
# 04 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 05 创建符号链接,使 `docker compose` 全局可用
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 06 验证
docker compose version
第三步:下载 Dify
# 01 创建 Dify 工作目录(可自定义路径)
mkdir -p ~/dify && cd ~/dify
# 02 下载 Dify 官方 docker-compose 文件集合
# -O:保存为指定文件名(不覆盖本地已存在的 .env 文件)
# 官方提供三种版本:单机版 / 带宽优化版 / 社区开发版
wget https://q尊云.com/docker-compose.env.example -O .env 2>/dev/null \
|| wget https://raw.githubusercontent.com/langgenius/dify/main/docker/docker-compose.yaml \
-O docker-compose.yaml
# 03 下载 .env 配置文件模板
wget https://raw.githubusercontent.com/langgenius/dify/main/docker/.env.example \
-O .env
# 04 查看下载的文件
ls -la
SECRET_KEY 和 CONSOLE_WEB_URL 两项。
第四步:配置 .env 文件
# 01 编辑 .env 配置文件
nano .env # 或 vi .env / code .env
# 02 关键配置项说明(按需修改)
# ===== 必改项 =====
# 01 Dify 控制台初始管理员账号(请务必修改为强密码!)
CONSOLE_WEB_URL=http://localhost:80
# ^ 控制台访问地址,如果是远程服务器访问,改成本机IP或域名
CONSOLE_API_URL=http://localhost:80/api
# ^ API服务地址,通常与 WEB_URL 保持一致
SERVICE_API_URL=http://localhost:80/api/v1
# ^ 对外API地址,外部系统调用时使用
# 02 安全密钥(生产环境务必改掉!)
SECRET_KEY=尊云-请生成随机字符串-不要用这个默认值
# ^ 生成方法:openssl rand --base64 42
# 03 数据库配置(生产环境建议使用外部 PostgreSQL)
DB_USERNAME=dify
DB_PASSWORD=dify_password_change_me
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify
# 04 Redis 配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=dify_redis_change_me
# 05 模型接入(留空则使用 Dify 内置的模型配置页面)
# 如果你计划使用第三方模型(如 OpenAI),在此配置 API Key
#OPENAI_API_KEY=sk-your-key-here
#ANTHROPIC_API_KEY=sk-ant-your-key-here
第五步:启动 Dify(逐命令解释)
# 01 进入 Dify docker-compose 所在目录
cd ~/dify
# 02 拉取所有镜像(首次运行需要下载约 2-3GB)
# -p dify-net:创建名为 dify-net 的 Docker 网络
# --env-file .env:加载 .env 中的环境变量
docker network create dify-net 2>/dev/null || true
# ^ 创建网络(如果已存在则跳过)
# 03 使用 docker-compose 启动所有服务(后台运行)
# -f:指定使用的 docker-compose 文件
# --env-file:指定环境变量文件
# -d:detached mode,后台运行(不加 -d 会阻塞终端)
docker compose -f docker-compose.yaml --env-file .env up -d
# 04 等待服务启动(容器内部初始化需要约 30-60 秒)
# grep -E "Up|healthy" 检查各容器状态
docker compose -f docker-compose.yaml ps
# 05 查看日志(确认没有 Error)
# -f:follow,实时跟踪日志
# --tail=50:显示最近50行
docker compose -f docker-compose.yaml logs --tail=50 -f
# 06 检查容器健康状态
# 正常情况:api/web/db/redis/sandbox 状态均为 "Up"
docker compose -f docker-compose.yaml ps
http://服务器IP:80,首次访问会引导创建管理员账号。Dify Web 界面用于管理应用和工作流;http://服务器IP:80/api/v1 是对外 API 端点。
第六步:关闭与重启命令
# 关闭 Dify(保留数据卷,重启后数据不丢失)
docker compose -f docker-compose.yaml --env-file .env down
# 关闭并删除数据卷(⚠️ 彻底删除所有数据,无法恢复!)
docker compose -f docker-compose.yaml --env-file .env down -v
# 重启所有服务
docker compose -f docker-compose.yaml --env-file .env restart
# 更新 Dify 到最新版本
git -C ~/dify pull # 或重新下载 docker-compose.yaml
docker compose -f docker-compose.yaml --env-file .env pull
docker compose -f docker-compose.yaml --env-file .env up -d
4. 第一个工作流创建步骤
以下以"文章摘要提取"为例,完整走一遍工作流创建过程。这个工作流的逻辑是:输入一篇长文章 → 调用 LLM 提取摘要 → 输出结果。
4.1 操作序列(图解文字版)
浏览器打开 http://服务器IP:80,使用管理员账号登录。登录后在左侧导航栏找到 「工作流」 选项卡。
点击「创建工作流」→ 选择「空白工作流」→ 输入名称「文章摘要提取」→ 确认。此时进入工作流画布(Canvas)页面。
在左侧节点列表,找到「开始(Start)」节点,点击或拖拽到画布中央。配置内容:
- 变量名:
article_text - 类型:段落文本(Long Text)
- 必填:是
从节点列表拖拽「LLM」节点到画布,放置在「开始」节点右侧。用鼠标拖动连线(蓝色箭头),从「开始」的输出端口连接到「LLM」的输入端口。
LLM 节点配置:
- 模型选择:Claude 3.5 Sonnet / GPT-4o(根据你的 API Key 选择)
- 系统提示词:
你是一位专业的文字编辑。请在200字内提取这篇文章的核心观点和关键信息。 - 输入变量:点击「变量」,选择
article_text(来自开始节点的输出)
拖拽「直接回复(Direct Output)」节点到画布最右侧,连接「LLM」节点的输出端口到这个节点。这个节点代表工作流的最终输出。
点击画布右上角「发布」按钮。第一次发布会提示设置「发布描述」,填写如"v1.0 文章摘要提取"即可。
返回「应用」页面,创建「空白应用」→ 类型选择「工作流」→ 关联刚才的工作流。创建后会生成一个 API 访问地址。
Space + 鼠标拖拽 可以平移画布;滚轮缩放;双击节点名称可编辑;右键节点可复制/删除。
4.2 截图位置说明(文字描述)
| 步骤 | 对应截图位置 |
|---|---|
| 工作流列表 | 左侧导航「工作流」→ 右上「创建工作流」按钮 |
| 画布界面 | 顶部工具栏(保存/发布/设置)+ 左侧节点面板 + 中央画布 + 右侧属性面板 |
| 节点连线 | 节点右下角圆点(输出)拖拽到目标节点左下角圆点(输入) |
| LLM配置 | 右侧属性面板 → 模型选择下拉 → 系统提示词文本框 → 变量映射区 |
| 发布确认 | 右上角「发布」按钮 → 弹出「发布描述」输入框 → 确认按钮 |
5. 常用节点详解
5.1 LLM 节点(大型语言模型)
功能说明
LLM 节点是 Dify 工作流的核心,用于调用大语言模型(GPT/Claude/通义千问等)进行文本生成。是工作流中处理自然语言的主力节点。
核心配置参数
- 模型:从下拉列表选择已接入的模型(如 GPT-4o、claude-3-5-sonnet-20241022)
- 系统提示词(System Prompt):定义 AI 的角色和行为规则,支持变量引用
- 用户提示词(User Prompt):用户输入,可组合多个变量
- 温度(Temperature):0.0-1.0,越高越有创意,越低越确定。摘要类用 0.3,创作类用 0.7-0.9
- 最大令牌数(Max Tokens):限制单次输出长度,防止无限生成
- 上下文长度:控制输入的上下文窗口大小
配置示例:文章风格改写
# 系统提示词配置
你是一位资深的科技专栏作家,擅长将复杂的技术概念用通俗易懂的语言解释。
请根据用户提供的原始文章,用生动的语言进行改写,保持核心信息不变。
输出格式:先写一段引导语,然后分3点展开,每点不超过50字。
# 用户提示词配置(引用变量)
请将以下文章改写成适合公众号发布的风格:
{{article_text}}
# 参数设置
温度(Temperature):0.7
最大令牌数:800
停止序列:不填
{{变量名}} 引用上游节点的输出变量。注意变量名必须与上游节点输出的变量名完全一致。
5.2 条件分支节点(If / Switch)
功能说明
条件分支节点用于在工作流中引入逻辑判断,根据变量的值或表达式的结果,将流程路由到不同的分支路径。类似编程语言中的 if/switch 语句。
配置参数
- 分支数量:至少2个分支,支持添加更多
- 变量:选择要判断的变量(来自上游节点)
- 条件关系:AND(同时满足)/ OR(满足其一)
- 运算符:等于 / 不等于 / 包含 / 大于 / 小于 / 正则匹配 / 为空 / 不为空
- 比较值:与变量比较的目标值
配置示例:情绪分类路由
# 场景:用户输入一段文字,情绪分类后走不同处理流程
# 分支一:积极情绪
条件:sentiment(来自上游LLM的情绪分类结果)
运算符:等于
比较值:"positive"
# 分支二:消极情绪
条件:sentiment
运算符:等于
比较值:"negative"
# 分支三:中性/其他(兜底)
# 无需配置,作为 else 默认分支
# 后续各分支可挂载不同的处理 LLM 节点
# 分支一 → 鼓励回复 LLM
# 分支二 → 安慰回复 LLM
# 分支三 → 常规回复 LLM
5.3 代码执行节点(Code)
功能说明
代码执行节点运行一段 JavaScript / Python 代码(节点运行环境的 sandbox),用于数据转换、计算、格式处理等无法用可视化节点完成的任务。代码在隔离的沙箱环境中执行,无法访问网络和文件系统。
输入输出
- 输入:接收上游节点的任意变量(最多10个)
- 输出:定义输出变量名及类型(文本/数字/布尔/数组/对象)
配置示例:JSON 解析与字段提取
# 场景:上游节点返回了 JSON 格式的天气数据,需提取温度和天气状况
# 输入变量(来自上游节点):
# - weather_json_string: 类型「文本」,值为 '{"temp":22,"condition":"多云","humidity":65}'
# JavaScript 代码:
def main(weather_json_string):
# 将 JSON 字符串解析为对象
data = JSON.parse(weather_json_string)
# 提取所需字段
temperature = data.temp # 提取温度:22
condition = data.condition # 提取天气状况:多云
humidity = data.humidity # 提取湿度:65
# 组合成自然语言描述
description = f"今天天气{condition},气温{temperature}°C,湿度{humidity}%"
# 返回输出变量(必须在 outputs 中声明)
return {
"temperature": temperature,
"condition": condition,
"description": description
}
# 输出变量定义:
# - temperature: 类型「数字」
# - condition: 类型「文本」
# - description: 类型「文本」
require() 加载外部模块,无法访问网络,无法读写文件。只能做纯数据计算。如果需要复杂能力,考虑用「HTTP 请求」节点调用外部服务。
5.4 模板转换节点(Template)
功能说明
模板转换节点使用类似 Jinja2 的语法,将多个变量拼接/格式化为一段文本。适合生成格式化输出(如邮件模板、报告模板、消息模板等),无需写代码。
Jinja2 语法速查
{{变量名}}— 插入变量值{% if 条件 %}...{% endif %}— 条件判断{% for item in 列表 %}...{% endfor %}— 循环| length / | upper / | lower / | default(值)— 过滤器
配置示例:生成邮件报告模板
# 输入变量:
# - user_name: "张总"
# - date: "2026-05-23"
# - summary: "本季度收入增长20%,用户活跃度提升35%"
# - next_action: "下季度重点拓展海外市场"
# 模板内容:
尊敬的 {{ user_name }}:
您好!以下是 {{ date }} 的周报摘要:
📊 本期总结:
{{ summary }}
🎯 下期计划:
{{ next_action }}
如有任何问题,请随时联系。
此致
敬礼
# 输出:
# 尊敬的 张总:
#
# 您好!以下是 2026-05-23 的周报摘要:
#
# 📊 本期总结:
# 本季度收入增长20%,用户活跃度提升35%
#
# 🎯 下期计划:
# 下季度重点拓展海外市场
#
# 如有任何问题,请随时联系。
# ...
# (渲染后的结果会被传递到下游 LLM 节点做进一步处理)
5.5 HTTP 请求节点
功能说明
HTTP 请求节点用于向外部 API 发起 HTTP 调用,是 Dify 接入第三方服务的主要方式。支持的 method:GET / POST / PUT / DELETE / PATCH。
配置参数
- URL:目标 API 地址,支持变量插值
{{变量名}} - Method:HTTP 方法
- Headers:请求头(如 Authorization: Bearer xxx)
- URL Params / Body:查询参数或请求体
- 超时时间:默认30秒,可调
配置示例:调用高德天气API
# URL(变量插值):
https://restapi.amap.com/v3/weather/weatherInfo
# Method:GET
# URL Params:
key → your_amap_api_key
city → {{ city_code }} # 来自上游输入的城市编码
extensions → base # base=实时天气,all=完整天气
# Headers:
Content-Type → application/x-www-form-urlencoded
# 超时时间:10秒
# 输出变量映射:
response_body → $.weather[0] # JSONPath 提取第一个天气对象
6. API调用示例
Dify 的每个已发布应用都暴露了 REST API。以下以「文章摘要提取」工作流为例,分别用 curl 和 Python 两种方式演示完整调用。
6.1 API 基本信息
# 应用端点基础信息(来自 Dify 控制台 → 应用 → API访问)
BASE_URL=http://服务器IP:80/api/v1
APP_ID=your_app_id_here # 应用 ID
API_KEY=your_api_key_here # API 密钥(控制台 → API 密钥 获取)
# 调用地址(workflow inference endpoint)
INFER_URL=${BASE_URL}/workflows/run
6.2 curl 调用示例
# 01 调用文章摘要提取工作流
# -X POST:使用 HTTP POST 方法
# -H:添加 HTTP 请求头
# Authorization:Bearer Token 认证,API Key 填在这里
# Content-Type:application/json,声明请求体为 JSON
# -d:指定请求体(JSON 格式)
# inputs:工作流的输入变量,与「开始」节点定义的变量名对应
# response_mode:响应模式
# blocking:同步阻塞,等待工作流执行完成返回结果
# blocking_no_output:同上,但不返回中间节点输出
# streaming:流式响应(SSE),适合大模型输出场景
# conversation_id:会话ID(可选,用于多轮对话上下文)
curl -X POST '${INFER_URL}' \
-H 'Authorization: Bearer YOUR_API_KEY_HERE' \
-H 'Content-Type: application/json' \
-d '{
"inputs": {
"article_text": "人工智能技术的发展正在深刻改变各行各业的生产方式。从生成式AI到自动驾驶,从医疗诊断到金融风控,AI的应用场景越来越广泛。本文深入分析了当前AI技术的最新进展,探讨了大语言模型在自然语言处理领域的突破性应用,并展望了未来三到五年内AI技术的发展趋势。研究表明,融合多模态能力的AI系统将成为下一代人工智能的主流方向。"
},
"response_mode": "blocking",
"conversation_id": ""
}'
# 02 解释返回的 JSON 字段
# {
# "workflow_run_id": "run_xxxxx", # 本次运行的唯一ID,用于查询状态
# "task_id": "task_xxxxx", # 任务ID
# "status": "succeeded", # 运行状态:running/succeeded/failed
# "outputs": { # 工作流输出内容
# "summary": "AI技术正深刻改变各行业...融合多模态能力的AI系统将成为下一代主流方向。"
# },
# "latency": 2.345 # 耗时(秒)
# }
# 03 如果状态为 failed,查询错误详情
# 用 workflow_run_id 查询详细状态和错误日志
curl -X GET '${BASE_URL}/workflow-runs/{workflow_run_id}' \
-H 'Authorization: Bearer YOUR_API_KEY_HERE'
6.3 Python 调用示例(requests 库)
# Python 版本(建议 3.8+,使用 requests 库)
# 安装:pip install requests
import requests
import json
# ========== 配置区 ==========
# Dify 服务地址
BASE_URL = "http://服务器IP:80/api/v1"
# API 密钥(来自 Dify 控制台 → API 密钥)
API_KEY = "app-xxxxxxxxxxxxxxxx"
# 工作流调用地址
INFER_URL = f"{BASE_URL}/workflows/run"
# ========== 函数定义 ==========
def run_workflow(article_text: str, timeout: int = 60) -> dict:
"""
调用 Dify 工作流,提取文章摘要。
Args:
article_text: 要摘要的文章原文
timeout: 请求超时时间(秒),默认60秒
Returns:
dict: 工作流执行结果,包含 status 和 outputs
Raises:
requests.HTTPError: HTTP 请求失败时抛出
"""
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
# inputs:工作流的输入变量,必须与「开始」节点定义的变量名一致
"inputs": {
"article_text": article_text
},
# response_mode: blocking 同步等待,适合脚本调用
"response_mode": "blocking",
# conversation_id: 空字符串表示新建会话
"conversation_id": ""
}
# 发起 POST 请求
response = requests.post(
INFER_URL,
headers=headers,
json=payload,
timeout=timeout # 请求超时,防止 Dify 响应慢时程序卡死
)
# 4xx/5xx 响应码会抛出 HTTPError,做异常处理
response.raise_for_status()
result = response.json()
# 检查工作流执行状态
if result.get("status") == "succeeded":
return result
elif result.get("status") == "failed":
# 打印详细错误,供调试用
print(f"❌ 工作流执行失败:{result.get('error')}")
raise RuntimeError(f"Workflow failed: {result.get('error')}")
else:
print(f"⚠️ 工作流状态:{result.get('status')}")
return result
# ========== 调用示例 ==========
if __name__ == "__main__":
article = (
"人工智能技术的发展正在深刻改变各行各业的生产方式。"
"从生成式AI到自动驾驶,从医疗诊断到金融风控,AI的应用场景越来越广泛。"
"本文深入分析了当前AI技术的最新进展,探讨了大语言模型在自然语言处理领域的突破性应用,"
"并展望了未来三到五年内AI技术的发展趋势。研究表明,融合多模态能力的AI系统将成为下一代人工智能的主流方向。"
)
print("📤 正在调用 Dify 工作流...")
result = run_workflow(article, timeout=60)
print(f"✅ 调用成功!耗时:{result.get('latency', 'N/A')}s")
print(f"📋 摘要结果:{result['outputs']['summary']}")
# ========== 进阶:流式调用 ==========
# 适用于需要实时展示 AI 生成过程(如打字机效果)的场景
def run_workflow_stream(article_text: str):
"""流式调用(使用 SSE 协议实时获取输出片段)"""
payload = {
"inputs": {"article_text": article_text},
"response_mode": "streaming", # 关键区别:streaming 模式
"conversation_id": ""
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# stream=True 使 requests 返回一个迭代器
with requests.post(INFER_URL, headers=headers, json=payload,
stream=True, timeout=90) as resp:
resp.raise_for_status()
# SSE 流式数据,按 data: 分割行处理
for line in resp.iter_lines():
if line.startswith("data:"):
# 跳过 "data: " 前缀,解析 JSON
raw = line[5:].strip()
if raw == "[DONE]":
break
chunk = json.loads(raw)
# chunk 格式:{"event": "output", "data": {"text": "部分输出文字"}}
if chunk.get("event") == "output":
print(chunk["data"]["text"], end="", flush=True)
elif chunk.get("event") == "finished":
print("\n✅ 流式输出完成")
API_KEY = os.getenv("DIFY_API_KEY"),避免 Key 随代码提交到版本库。
7. 常见报错与解决
8.1 并发处理
当 Dify 工作流对外提供 API 后,可能会面临多个并发请求。以下是并发优化方案:
# 01 在 Dify 前加一层反向代理(Nginx),配置连接池和限流
# /etc/nginx/conf.d/dify.conf
upstream dify_backend {
# 01 使用 Unix Socket 连接(比 TCP 少一次网络开销)
server 127.0.0.1:80;
# 02 或者配置多个 Dify 实例做负载均衡
server 127.0.0.1:80 weight=1;
server 127.0.0.1:8081 weight=1; # 需要运行第二个 Dify 实例
}
server {
listen 80;
server_name your-domain.com;
# 03 限流:单个 IP 每秒最多 10 个请求
limit_req_zone $binary_remote_addr zone=dify_limit:10m rate=10r/s;
location / {
limit_req zone=dify_limit burst=20 nodelay;
proxy_pass http://dify_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 04 超时配置(避免长请求占用连接)
proxy_connect_timeout 60s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
# 05 WebSocket 支持(流式输出需要)
proxy_buffering off;
proxy_set_header Connection "upgrade";
}
}
# 06 测试 Nginx 配置语法
sudo nginx -t
# 07 重载 Nginx
sudo systemctl reload nginx
8.2 缓存策略
对于相同输入的重复请求(如 FAQ 类问答),加入缓存层可大幅降低延迟和 API 调用成本:
# 方案A:Nginx 层面缓存(适合 GET 请求)
# 适用于输入输出都相对固定的场景
server {
location /api/v1/ {
# 相同的 query string 缓存 10 分钟
proxy_cache_valid 200 10m;
# 缓存 Key:Host + 请求路径 + query string + API Key
proxy_cache_key "$host$request_uri$http_authorization";
# 缓存响应标记(命中 X-Cache-Key)
add_header X-Cache-Key $proxy_cache_key;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://dify_backend;
}
}
# 方案B:Redis 缓存(应用层,更灵活)
# 在工作流中加入代码执行节点,判断缓存是否命中
# JavaScript 代码执行节点(Redis 缓存判断)
def main(input_text):
# 注意:Dify 沙箱环境无法直接连 Redis
# 这个方案需要通过「HTTP 请求」节点调用外部缓存服务
# 以下是伪代码示例,实际需要配合外部 API 使用
cache_key = "summary:" + hash(input_text) # MD5(input_text)
# 调用外部缓存服务的示例:
# cached = http_get(f"http://cache-api/cache/{cache_key}")
# if cached:
# return {"result": cached, "from_cache": True}
return {
"cache_key": cache_key,
"need_generate": True
}
# 后续流程:先查缓存 → 命中则跳过 LLM → 未命中则调用 LLM 并写入缓存
8.3 监控与可观测性
# 01 容器健康检查脚本(可配置 cronjob 定期执行)
#!/bin/bash
# /opt/scripts/check-dify.sh
# 用法:*/5 * * * * /opt/scripts/check-dify.sh
# 解释:每5分钟检查一次 Dify 各容器状态,异常时发告警
CONTAINERS=$(docker compose -f ~/dify/docker-compose.yaml ps --format json)
FAILED=""
for container in api web db redis sandbox worker; do
STATUS=$(echo "$CONTAINERS" | jq -r ".[] | select(.Service==\"$container\") | .State")
if [ "$STATUS" != "running" ]; then
FAILED="$FAILED $container"
fi
done
if [ -n "$FAILED" ]; then
echo "$(date) Dify 容器异常:$FAILED" | tee /var/log/dify-alert.log
# 发送告警(可接入钉钉/飞书/Webhook)
curl -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"msgtype\":\"text\",\"text\":{\"content\":\"Dify容器异常:$FAILED\"}}"
fi
# 02 Nginx 访问日志分析(统计 API 调用量和响应时间)
# 分析最近 1 小时的 API 调用情况
tail -n 1000 /var/log/nginx/access.log | awk '
BEGIN { total=0; slow=0 }
{
total++
# 提取响应时间(nginx 日志格式需包含 $request_time)
if ($NF ~ /[0-9.]+/) {
rt = $NF + 0
if (rt > 5) slow++ # 响应时间超过5秒的请求
}
}
END {
print "总请求数:" total, "慢请求(>5s):" slow, "慢请求比例:" (slow/total*100) "%"
}'
# 03 Prometheus + Grafana 监控(可选进阶方案)
# 在 docker-compose.yaml 中加入 metrics 端点暴露
# Dify API 服务默认在 /metrics 端点暴露 Prometheus 格式指标
# 可用 Prometheus 采集后接入 Grafana 可视化
8.4 数据库和存储优化
# 01 将 Dify 的 PostgreSQL 和 Redis 从 Docker 改为独立部署(生产推荐)
# 独立部署可以获得更好的性能和可管理性
# PostgreSQL 独立部署(使用 Ubuntu/Debian apt 安装)
sudo apt install postgresql-16
sudo systemctl enable postgresql
sudo systemctl start postgresql
# 创建 Dify 专用数据库和用户
sudo -u postgres psql << 'EOF'
CREATE USER dify WITH PASSWORD 'your_secure_password';
CREATE DATABASE dify OWNER dify;
ALTER USER dify CREATEDB;
\q
EOF
# 02 修改 Dify .env 文件中的数据库连接
sed -i 's/^DB_HOST=.*/DB_HOST=127.0.0.1/' ~/dify/.env
sed -i 's/^DB_PASSWORD=.*/DB_PASSWORD=your_secure_password/' ~/dify/.env
# 03 配置 PostgreSQL 连接池(pgbouncer,降低连接数)
sudo apt install pgbouncer
# /etc/pgbouncer/pgbouncer.ini
[databases]
dify = host=127.0.0.1 port=5432 dbname=dify
[pgbouncer]
listen_port = 6432
listen_addr = 127.0.0.1
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
max_client_conn = 200
default_pool_size = 20 # 每个 PostgreSQL 连接池大小
sudo systemctl restart pgbouncer
SECRET_KEY 替换为随机字符串;数据库端口不要暴露到公网;启用防火墙,只允许必要的端口(如 80/443)入站。
总结
Dify 是一个功能完善、社区活跃的开源 LLM 应用开发平台,适合快速搭建 AI 工作流并对外提供 API 服务。本文从工具选型、Docker 安装、工作流创建、节点配置、API 调用、错误排查到生产优化,完整覆盖了 Dify 从入门到上线的全流程。
核心要点回顾:
- 选型:快速 AI 应用选 Dify,通用自动化选 n8n,多智能体研究选 AutoGen
- 安装:Docker 一键部署,.env 文件是关键,注意端口占用
- 工作流:开始节点定义输入 → 中间节点处理 → 结束节点输出,连线即逻辑
- 节点:LLM 是核心,条件分支做路由,代码节点补灵活性,模板节点做输出格式化
- API:Bearer Token 认证,blocking 同步调用,streaming 流式调用
- 错误:大多数问题来自未连接、变量类型不匹配、超时、配置错误
- 生产:Nginx 限流 + Redis 缓存 + 监控告警 + 独立数据库
遇到问题善用 GitHub Issues(github.com/langgenius/dify/issues)搜索,社区文档也比较完善。