
简介这是一份Dify平台全流程学习文档面向具备一定编程基础、希望快速上手基于大语言模型应用开发的工程师与技术爱好者。文档从Dify的核心特性与适用场景切入系统梳理了从入门到高级的开发路径既包含Docker Compose、Kubernetes集群部署与高可用配置也涵盖可视化工作流设计、提示词工程、复杂条件分支与并行处理等进阶技巧并延伸到插件开发、模型微调与企业级最佳实践能够帮助读者独立搭建并交付可用的AI应用。资源为1个docx文档整体仅30KB内容密度较高适合按章节循序渐进阅读。文内配有部署命令、环境变量示例、工作流节点说明及提示词模板等实操细节便于边读边练。目前已有497人学习适合希望系统掌握Dify平台、快速验证LLM应用落地方案的开发者参考。1. Dify 到底是什么你需要它解决的不只是“一个聊天框”如果你第一次打开 Dify 平台大概率会先被左侧那一排可视化节点吸引然后在十分钟内搭出一个能对话的机器人。但 Dify 的价值远不止“做个聊天框”。它真正解决的是 AI 应用从原型到可维护交付之间的那段空白模型路由、知识库接入、工作流编排、日志追踪、权限隔离这些在传统开发里至少要两三个后端模块才能串起来的事情现在都集中在一个平台上完成。适合谁用正在做 RAG 问答、需要把多个模型和工具串成一条业务流水线、或者想给团队交付一套可复用 AI 应用的算法工程师和全栈开发者。不适合谁只想简单调模型 API 的选手用它会觉得重。2. 部署与初始化Docker Compose 是默认答案含 Windows 与 CentOS7 两条路2.1 部署方式选型先定场景再选路径Dify 的部署方式大致有三条路Docker Compose、源码运行、Kubernetes。我第一次部署时图省事直接选了 Docker Compose后来发现这个选择在绝大多数场景下都是最优解。源码运行适合要二次改造平台的团队但你需要自己维护前端、后端、worker 三套进程还要处理 Celery 任务队列和 PostgreSQL 连接部署成本明显高于容器方式。Kubernetes 则是为多租户生产环境准备的社区版默认不带 Helm Chart需要你自己封装没有专职运维的话不建议一上来就碰。Docker Compose 的另一个好处是升级路径清晰。社区版发版频繁小版本迭代基本是拉新镜像、重启容器两步就能完成。官方仓库里维护了一份完整的 docker-compose.yml包含 api、worker、web、db、redis、sandbox、ssrf_proxy 等核心服务你只需要准备一台至少 4 核 8G 的机器磁盘留 40G 以上。git clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env docker compose up -d代码说明第一句拉取 Dify 仓库第二句进入 docker 编排目录第三句复制环境变量模板最后一句启动全部容器。这里要强调一下 cp 复制 .env 是必做的因为 compose 文件里几乎所有敏感配置都从 .env 读取不复制模板直接启动会因缺少环境变量而报错。启动之后用 docker compose ps 看容器状态等 api 和 worker 都显示 healthy再访问 http://localhost 就能看到初始化页面。首次打开会让你设置管理员邮箱和密码这一步设置的账号就是后续所有工作区的超级管理员。2.2 Windows 与 CentOS7 两条实操路线Windows 上装 Dify最省事的方式是 WSL2 加 Docker Desktop。要注意三点第一WSL2 需要开启 Hyper-V 虚拟机平台在 PowerShell 里执行wsl --install会自动完成第二Docker Desktop 的 WSL Integrated 设置里务必勾选你使用的发行版第三把项目放在 WSL 文件系统内而不是 /mnt/c 下否则文件监听和磁盘 IO 会慢到让你怀疑人生。CentOS7 则是另一套剧本。这台机器的系统内核通常比较老直接装新版 Docker Engine 经常会遇到依赖冲突。我一般会先检查内核版本低于 3.10 的建议先用yum update kernel升内核再装 Docker。另外 CentOS7 默认的 iptables 规则有时会拦截容器端口映射启动后从外部访问不到页面先执行systemctl stop firewalld排查确认能访问后再收敛防火墙规则。docker --version free -h df -h /var/lib/docker这三条命令分别验证 Docker 客户端版本、可用内存、磁盘空间。Dify 的 api 和 worker 服务对内存比较敏感8G 的机器跑起来已经有点紧如果同时开多个模型供应商的 Embedding 计算内存不足会触发 OOM现象是容器反复重启。2.3 初始化配置模型供应商与默认管理员平台跑起来之后第一件正事是配置模型供应商。进入「设置 → 模型供应商」选 OpenAI 兼容或者你实际使用的服务商填入 API Key。这里要注意Dify 的每个模型类型是独立配置的LLM 和 Embedding 模型分开填缺了 Embedding 模型会导致后面知识库向量化直接失败。我踩过的坑是只配了对话模型就急着建知识库结果上传文档后一直卡在“等待索引”日志里报 embedding model not configured。配置完模型立刻把默认管理员的密码换掉。社区版的初始管理员虽然是你自己设置的但很多团队习惯用统一弱密码一旦暴露到公网别人可以直接登录后台查看所有工作区的知识库和 API 密钥。顺带在 .env 里改掉默认的 SECRET_KEY这个值用于会话加密和 API 签名默认值在公网仓库里是公开的。docker compose exec api flask db upgrade docker compose restart api worker这两条在初始化后执行确保数据库迁移到与当前镜像匹配的版本。注意不要跳过 flask db upgrade 直接重启否则 api 服务起来后会报数据库表结构不匹配症状是登录页能打开但一点登录就 500。3. 可视化工作流与知识库把 RAG 流水线搭成一张图3.1 先选流模式Chatflow 还是 WorkflowDify 把应用分成 Chatflow 和 Workflow 两种形态这个选择直接决定后续编排的自由度。Chatflow 面向对话场景内置了对话记忆、用户会话管理等能力适合客服机器人、知识库问答这类需要多轮上下文的交互。Workflow 则更像一个后端服务输入输出都是结构化数据适合文档分类、内容提取、自动摘要这类批处理任务没有会话状态也没必要有。维度ChatflowWorkflow典型入口网页对话 / 嵌入组件API 调用 / 定时任务对话记忆原生支持不提供节点自由度受限必须走对话链路自由编排任意节点适用场景客服、知识库问答内容处理、数据清洗我的习惯是只要用户会以“聊天”的方式使用就选 Chatflow凡是程序主动触发的处理流程一律 Workflow。混用两者会带来一个隐蔽的问题——你想在 Workflow 里引用上一轮对话但系统根本没有这个变量最后只能自己维护一个外部存储来做上下文等于把简单问题复杂化。3.2 知识库流水线文档处理不是“上传”就完事知识库是整个 RAG 链路里最需要手动干预的部分。上传文档只是第一步后续的解析、分段、向量化、检索每一步都有参数可以调也都有坑可以踩。先看解析。Dify 默认支持 txt、md、pdf 等格式但对 docx 这类富文本格式内置解析器效果不稳定。平台提供了 Unstructured 解析器作为增强但需要你在 .env 里单独配置 UNSTRUCTURED_API_URL 和 UNSTRUCTURED_API_KEY。不配置的后果很直接上传 doc 文件时提示 unstructured api url is not configured for doc file processing。如果你不打算部署 Unstructured就老老实实先把 docx 转成 md 再上传别指望平台替你搞定一切。再看分段。分段参数决定检索质量Dify 的默认分段长度是 500 字符重叠 50 字符。这个参数对英文文档还可以但中文场景建议调小我一般在 200 到 300 之间。原因很简单中文一句话包含的信息密度比英文高500 字符切出来的块往往跨了好几个语义段落检索时召回的内容会掺杂大量无关信息。分段参数改成 250、重叠 30在中文知识库问答里的相关性有明显提升。向量化模型的选型也值得说。如果你对接的是开源 Embedding 模型注意向量维度要一致中途换模型会导致已有索引全部失效必须重建。这个问题在测试阶段最折磨人——知识库里明明有内容检索却一直返回空。3.3 工作流节点参数实测变量赋值与 API 调用工作流编排里最常见的翻车点有两个变量作用域和 HTTP 节点的鉴权。先看变量Dify 的变量分为输入变量、中间变量、输出变量。很多新手会把 LLM 节点的输出直接当字符串拼到下一个节点的 Prompt 里结果发现渲染出来的是一串 JSON。原因很简单LLM 节点的输出默认是结构化对象你需要先用“变量赋值”或“代码执行”节点把它展开成字符串再传给下游。{ title: 知识库检索结果处理, type: code, input_variables: [ {variable: retrieved_docs, value: {{#context#}}} ], code: def main(retrieved_docs: list) - str:\n texts [item.get(content, ) for item in retrieved_docs]\n return \\n\\n.join(texts) }代码说明这个代码节点从上游的检索节点接收 retrieved_docs 列表提取每条的 content 字段用空行拼接成单字符串。下面是参数逻辑input_variables 里的 value 用{{#context#}}语法引用上游节点的输出这是 Dify 节点间传值的关键写法函数入口固定叫 main返回值会被作为该节点的输出变量供下游使用。注意 final 节点只能识别字符串类型如果你不经过这一步处理最终返回给用户的就是一坨没解析过的 JSON前端表现是“答非所问”。HTTP 节点的鉴权是另一个高频报错点。Dify 的 HTTP 节点支持 GET/POST 等常见方法但请求头需要自己拼。我见过很多人调用内部服务时报 403排查后发现是没带 Authorization 头。Dify 里的鉴权信息要用环境变量或密钥管理来存不要把密钥直接写在节点配置里否则导出应用模板时会一起带出去。顺带说一句 cursor 连接 Dify 知识库的常见姿势。cursor 本身不是 Dify 的客户端但你可以把知识库发布成 API 应用用 Dify 提供的接口地址和密钥在 cursor 的 MCP 或自定义工具里注册。我一般更推荐一个土办法直接让 cursor 读知识库导出的 Markdown 文件实时性要求高的数据再走 API既省 token 又少一层网络故障。4. 排坑与常见问题六个反复出现的运行故障4.1 SSL 证书报错curl 能通平台却提示证书无效现象浏览器访问 Dify 页面正常但应用内部调用模型 API 时报 SSL 证书验证失败错误信息类似 certificate verify failed。原因Dify 容器内的系统证书库没有更新或者你给域名配置的证书链不完整容器内 curl 验证时缺少中间证书。解决先确认你的证书部署在反向代理层而不是容器内如果反代证书链完整仍然报错把宿主机的 ca-certificates 更新到最新再重建 api 容器。最省事的办法是让 api 容器复用宿主机时区与证书库在 volumes 里挂载 /etc/localtime 和 /etc/ssl/certs。4.2 credentials validation 报错模型供应商配置总失败现象在设置里填写模型 API Key点保存后立刻提示 an error occurred during credentials validation。原因Dify 在校验凭据时会真实调用一次模型服务的接口任何网络不可达、Key 无效、接口路径填错都会触发这个报错。解决先拿 curl 直接请求模型供应商的 endpoint确认 Key 和地址都通再确认你在 Dify 填的 API 地址没有多余斜杠和拼写错误最后检查 api 容器是否能访问外网有些内网部署环境需要单独给 api 容器配置 HTTP 代理。4.3 知识库处理 doc 文件报错unstructured API 未配置现象上传 Word 文档后文档状态一直停在“解析中”过一会儿变红提示 unstructured api url is not configured for doc file processing。原因文档走的是 Unstructured 解析服务但 .env 里没配置对应的服务地址。解决要么在 docker 目录下额外起一个 unstructured 容器并配置 UNSTRUCTURED_API_URL要么把 doc 文件转成 PDF 或 Markdown 再上传。前者适合批量处理后者适合偶尔用一下的轻量场景。4.4 工作流返回 403密钥没传对还是接口受限现象用 API 调用工作流应用返回 403 拒绝访问。原因请求头里没带 Authorization Bearer 密钥或者带了错误工作区的密钥。Dify 的 API 密钥是按应用维度分配的创建应用后要到「访问 API」页面单独生成不是用登录密码去调接口。解决确认请求头格式为 Authorization: Bearer app-xxx并且这个密钥属于你正在调用的应用。另一个 403 原因是服务端限流免费额度或默认速率不够时会返回这个状态码看响应体里有没有 rate limit 字样。4.5 登录被锁too many incorrect password attempts现象连续输错几次密码后页面提示 too many incorrect password attempts请稍后再试即使密码正确也进不去。原因Dify 在登录接口做了暴力破解防护短时间内失败次数超过阈值会锁定该账号一段时间。解决不要频繁重试等冷却时间结束。如果服务器日志里看到大量来自同一 IP 的尝试说明有人在探测你的后台应该在反向代理层加 IP 限流而不是跟它硬刚。4.6 升级后数据还在但功能多了乱码现象执行完镜像升级和数据库迁移页面功能多了但知识库里的中文标题变成乱码。原因环境里默认字符集不是 UTF-8或者是旧版本用 latin1 存的元数据。解决升级前先备份数据库用 docker compose exec db pg_dump 导出 SQL升级后检查 PostgreSQL 的 encoding 参数。这个问题的教训是永远不要跳过备份尤其跨大版本升级时。5. 模型微调与插件开发延长 Dify 到业务边界的两个入口5.1 先把概念厘清Dify 不训练模型它消费模型关键词里出现“模型微调”这里必须说清楚一件事Dify 是应用开发平台不是训练平台。你不会在 Dify 里找到跑微调任务的入口它的定位是把微调好的模型接入到应用里。正确的路径是先在外部完成模型微调拿到可用的模型服务地址再通过模型供应商配置接入 Dify。接入方式有两种。第一种是 OpenAI 兼容接口大多数微调服务商都提供这个协议Dify 里直接在供应商处选 OpenAI-API-Compatible填 base_url 和 key。第二种是自定义模型适合私有化部署的推理服务。curl http://your-model-endpoint/v1/chat/completions \ -H Content-Type: application/json \ -d { model: your-finetuned-model, messages: [{role: user, content: ping}] }命令说明这段 curl 模拟一次对话请求用来验证微调模型服务的连通性。参数上注意三点model 字段必须填服务端模型名而不仅是别名messages 数组最后一条必须是 user 消息如果服务在 NAT 后面确认 Dify 的 api 容器能访问到该地址容器网络和宿主机不是一回事。5.2 插件开发用最小 Python 插件打通私有数据Dify 的插件机制本质上是通过 HTTP 服务扩展工具节点。你写好一个服务注册成工具然后在工作流里像调用内置节点一样调用它。下面这个例子实现了一个查询内部订单状态的接口代码量很小但覆盖了插件开发的核心路径。from flask import Flask, request, jsonify app Flask(__name__) orders {A1001: 已发货, A1002: 待支付} app.route(/order/status, methods[POST]) def order_status(): data request.get_json() order_id data.get(order_id) if not order_id: return jsonify({error: order_id is required}), 400 status orders.get(order_id, 订单不存在) return jsonify({order_id: order_id, status: status}) if __name__ __main__: app.run(host0.0.0.0, port8090)代码说明这个服务接收 POST 请求从 JSON 中取 order_id返回订单状态。Dify 插件的 HTTP 节点只要求你返回合法 JSON所以用 Flask 写一个简单的接口就行。参数设计上input_schema 要声明 order_id 是 string 类型且必填这样 Dify 侧会做基础校验避免把非法请求打到你的服务上。服务跑起来后在 Dify 的「工具」里添加自定义工具填好 URL 和参数描述就能在工作流里使用了。5.3 多租户隔离与二次开发的三个目录社区版从较新版本开始支持多租户能力表现形式是工作区隔离。每个工作区有自己的成员、知识库、应用和 API 密钥互相不可见。这对企业内部多部门使用很关键——避免所有人挤在一个工作区里互相污染数据。如果你打算做二次开发源码里优先看三个目录api/core 是后端核心逻辑工作流引擎和知识库处理的代码都在这web 是前端工程改界面和交互在这层docker 是部署相关配置。我见过不少团队把全部代码改了却忘了更新 docker 目录里的环境变量模板结果部署到新环境时缺配置这类问题最难排查。6. 用日志与 API 验证你的 Dify 应用是否真的健康工作流搭完、应用发布不等于事情结束了。真正应该做的是建立一套验证习惯每次改动都走一遍检查和回归。我先说日志再讲 API 验证最后是一个我坚持到现在的工作流改动习惯。docker compose logs -f --tail200 api docker compose logs api 21 | grep -i error | tail -50第一条命令跟踪 api 服务的实时日志第二条从历史日志里捞 ERROR。看日志的时候重点找两个信息节点执行耗时和 HTTP 状态码。Dify 的日志里会打出每个工作流节点的运行时间如果某个节点耗时突然翻倍优先检查上游服务是否变慢而不是盲目调超时时间。API 验证比页面点按更可靠。应用发布后用 curl 直接调工作流接口检查返回结构是否符合预期。curl -X POST http://localhost/v1/workflows/run \ -H Authorization: Bearer app-xxxxx \ -H Content-Type: application/json \ -d { inputs: {query: 测试问题}, response_mode: blocking, user: tester-001 } | jq .data.outputs这段命令把测试问题送进工作流blocking 模式会等待执行完再返回jq 提取 outputs 字段。参数上注意三点Authorization 的密钥要在应用详情页单独生成inputs 里的键必须与工作流输入变量名完全一致response_mode 有 blocking 和 streaming 两种测试用 blocking生产对接用 streaming。返回结果里还要看 status 字段是不是 succeeded如果超时会返回 partial 之类状态说明节点配置里得把超时时间调大。最后一个习惯。我从第一次被变量作用域坑过之后每次改完工作流都强制自己做两件事第一在“预览”里用真实数据跑一遍而不是只点“运行”看绿色勾第二发布后用 curl 重新验证一次 API 返回。预览运行时用的是草稿配置API 跑的是已发布版本两者结果不一致的情况我遇到过不止一次。保持这个流程能过滤掉大部分低级回归也省得每次上线后被业务方反馈“怎么突然不对了”。希望帮到你。本文还有配套的精品资源点击获取