ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dify实战:从零搭建LLM应用,Workflow编排与RAG调优指南

Dify实战:从零搭建LLM应用,Workflow编排与RAG调优指南 1. 为什么“搭积木”式开发正在取代传统LLM应用开发1.1 从“写代码”到“拼节点”的范式转移过去一年我身边不少做后端和算法的朋友都在折腾同一件事把大语言模型接入自己的业务系统。最开始大家的思路都很朴素——写Python脚本调API拼Prompt手动管理上下文。一个简单的问答机器人还好说一旦要接入知识库、要支持多轮对话、要做条件分支、要对接外部工具代码量就会指数级膨胀。我见过一个团队为了做一个“客服工单自动分类知识库检索人工兜底”的流程写了将近三千行胶水代码光是状态管理就维护了七八个字典。Dify这类平台的出现本质上是在解决这个“胶水代码地狱”的问题。它把LLM应用开发中最常见的几个环节——Prompt编排、上下文管理、知识库检索、工具调用、多轮对话状态——抽象成了可视化的节点。你不再需要关心“上一轮对话的history怎么存”“检索到的文档怎么拼进Prompt”“工具调用的返回值怎么解析”这些都被封装成了标准化的积木块。你要做的就是把这些块拖到画布上连好线填好参数。这个转变的意义类似于当年从手写SQL到ORM框架的演进。不是说手写SQL不行而是在绝大多数业务场景下可视化编排的效率和可维护性都碾压纯代码方案。尤其是当你的应用需要频繁调整Prompt策略、更换模型、增减知识库的时候改一个节点的配置远比改代码、重新部署要快得多。1.2 谁最适合用Dify谁不适合先说适合的。如果你属于以下几类人Dify能帮你省下大量时间产品经理和业务人员想快速验证一个AI应用的想法不想等排期、不想求开发。Dify的可视化界面让你能自己搭出一个可用的原型拿去给团队演示。全栈开发者一个人要负责前后端没精力去研究LangChain的每一个抽象层。Dify提供了开箱即用的RAG、Agent、Workflow能力你只需要关注业务逻辑。中小团队的技术负责人需要快速交付一个AI功能但团队里没有专门做LLM应用架构的人。Dify的标准化流程能降低对个人经验的依赖。运维和DevOpsDify支持Docker Compose和Kubernetes部署有完整的日志、监控、多租户能力运维成本可控。不太适合的情况也有如果你的应用需要极其精细的底层控制比如自定义注意力机制、修改模型推理逻辑、实现非标准的Agent决策循环那Dify的抽象层反而会成为束缚。这种场景下直接用LangChain或者自己写推理服务更合适。另外如果你的业务对延迟极其敏感比如要求端到端响应在100毫秒以内Dify的编排层会引入额外的开销需要仔细评估。1.3 核心概念速览Workflow、Agent、知识库、LLMOps在深入实操之前先把Dify的几个核心概念理清楚不然后面看配置项会懵。Workflow工作流是Dify最核心的编排单元。你可以把它理解成一张流程图每个节点是一个处理步骤节点之间用连线表示数据流向。节点类型包括开始节点接收用户输入、LLM节点调用大模型、知识库检索节点、代码节点执行自定义Python、条件分支节点、HTTP请求节点、结束节点等。Workflow适合那些步骤明确、逻辑固定的场景比如“用户提问→检索知识库→生成回答→格式化输出”。Agent智能体则是另一种范式。你给Agent一个目标和一个工具列表它会自己决定调用哪个工具、按什么顺序调用。Agent适合那些步骤不固定、需要根据中间结果动态调整策略的场景比如“帮我查一下最近的订单状态如果超时了就发一封道歉邮件”。Agent的灵活性更高但可控性更低调试也更麻烦。知识库是Dify的RAG能力载体。你上传文档支持PDF、Word、Markdown、TXT等格式Dify会自动做分块、向量化、索引。在Workflow或Agent中你可以通过知识库检索节点来查询相关内容。Dify的知识库支持多种检索模式向量检索、全文检索、混合检索还支持重排序Rerank来提升精度。LLMOps是Dify区别于纯开发框架的地方。它提供了应用发布后的运营能力日志查看、标注、A/B测试、成本统计、用户反馈收集。这些功能在Demo阶段可能用不上但一旦应用上线就是刚需。我见过太多团队用LangChain搭完原型后发现没有日志、没有监控、出了问题只能靠猜最后不得不回头补运维设施。2. 部署实战从零把Dify跑起来2.1 环境准备与硬件选型Dify的部署方式主要有三种Docker Compose、Kubernetes、以及源码部署。对于绝大多数个人和小团队场景Docker Compose是最省心的选择。官方提供了docker-compose.yaml文件一条命令就能拉起所有服务。硬件方面最低配置建议4核CPU、8GB内存、50GB磁盘。这个配置能跑起来但知识库检索和LLM调用会比较慢。如果要做知识库建议至少16GB内存因为向量数据库Dify默认用Weaviate和Embedding模型都会吃内存。如果并发量较大32GB起步比较稳妥。操作系统方面LinuxUbuntu 20.04、CentOS 7是最推荐的。Windows和macOS也能跑但Docker Desktop的资源占用和网络配置会带来一些额外麻烦。我实测在Windows 11 WSL2下部署整体流程和Linux一致但文件挂载的性能会差一些知识库文档多的时候索引速度明显变慢。注意CentOS 7的默认内核版本较老Docker的某些特性可能不支持。如果坚持用CentOS 7建议先升级内核到5.x以上否则可能遇到容器网络不通的问题。2.2 Docker Compose部署全流程假设你已经装好了Docker和Docker Compose接下来的步骤可以直接抄作业。第一步获取Dify的源码。从GitHub克隆仓库git clone https://github.com/langgenius/dify.git cd dify/docker第二步准备环境变量文件。Dify在docker目录下提供了一个.env.example文件复制一份改名为.envcp .env.example .env这个文件里有几个关键配置需要关注EXPOSE_NGINX_PORTDify的Web访问端口默认是80。如果80被占用改成其他端口比如8080。SECRET_KEY用于加密会话和敏感数据务必改成一个随机字符串。可以用openssl rand -base64 42生成。DB_PASSWORDPostgreSQL的密码改掉默认值。REDIS_PASSWORDRedis的密码同样改掉。STORAGE_TYPE文件存储类型默认是local。如果要做多节点部署改成s3或azure-blob。第三步启动服务docker compose up -d这条命令会拉取所有镜像并启动容器。第一次执行会比较慢因为要下载好几个GB的镜像。启动完成后用docker compose ps查看容器状态确保所有服务都是healthy。第四步初始化数据库。Dify的Web容器启动后会自动执行数据库迁移但有时候会因为网络或权限问题失败。如果访问Web界面时报数据库错误可以手动执行docker compose exec api flask db upgrade第五步访问Web界面。在浏览器打开http://你的服务器IP:端口应该能看到Dify的登录页面。首次访问需要设置管理员账号和密码。2.3 常见部署报错与排查部署过程中最容易遇到的是SSL错误和凭证验证失败。这两个问题我都在不同环境里踩过这里把排查思路整理一下。SSL错误通常出现在Dify尝试连接外部服务比如OpenAI API、外部向量数据库的时候。报错信息一般是SSL: CERTIFICATE_VERIFY_FAILED。原因可能是容器内的CA证书过期或者网络环境需要走代理。解决方法是在.env里配置HTTP_PROXY和HTTPS_PROXY或者在docker-compose.yaml里给相关服务挂载宿主机的证书目录。凭证验证失败an error occurred during credentials validation一般发生在配置模型供应商的时候。Dify需要验证你填的API Key是否有效。如果Key没问题但还是报错检查一下容器的网络是否能通到模型供应商的API地址。有时候是DNS解析问题可以在容器内执行curl测试一下。文档处理报错unstructured api url is not configured for doc file processing是因为Dify默认用Unstructured来做文档解析但需要单独配置Unstructured API的地址。如果你不想额外部署Unstructured可以在.env里把ETL_TYPE改成dify用Dify内置的解析器。内置解析器对PDF和Word的支持不如Unstructured但胜在简单。密码尝试次数过多too many incorrect password attempts是Dify的登录保护机制。默认连续输错5次密码会锁定账号一段时间。如果把自己锁了可以进数据库把account表里的failed_login_count字段清零。2.4 在线升级与数据迁移Dify的版本迭代很快升级是常态。Docker Compose部署的升级流程如下cd dify/docker docker compose down git pull origin main docker compose pull docker compose up -d升级前务必备份数据库和上传的文件。数据库备份docker compose exec db pg_dump -U postgres dify dify_backup.sql文件备份主要是dify/docker/volumes目录下的内容包括上传的文档、生成的向量索引等。如果是从旧版本升级到新版本可能会遇到数据库schema不兼容的问题。Dify的API容器启动时会自动执行迁移但跨大版本升级时建议先看Release Notes确认有没有破坏性变更。我遇到过从0.6.x升级到0.8.x时知识库的索引结构变了需要重新索引所有文档。虽然麻烦但好在Dify提供了批量重新索引的功能。3. Workflow编排把业务逻辑画出来3.1 节点类型与数据流转Workflow的核心是节点和连线。每个节点有输入和输出连线表示数据从上游节点的输出流向下游节点的输入。Dify的节点类型大致可以分为几类输入输出类开始节点、结束节点、回答节点。LLM类LLM节点、Agent节点。数据处理类代码节点、模板转换节点、变量赋值节点。检索类知识库检索节点。逻辑控制类条件分支节点、循环节点。外部集成类HTTP请求节点、工具节点。数据流转的规则是每个节点的输出是一个JSON对象下游节点可以通过变量引用的方式获取上游节点的特定字段。比如LLM节点的输出通常包含text字段下游节点可以用{{llm_node.text}}来引用。这里有个容易踩的坑Dify的变量引用是强类型的。如果上游节点输出的是字符串下游节点期望的是数组就会报类型错误。解决方法是在中间加一个代码节点做类型转换或者在LLM节点的输出配置里指定返回格式为JSON。3.2 一个完整的RAG问答Workflow拆解假设我们要做一个“基于内部文档的智能问答”应用。Workflow的结构如下开始节点接收用户问题 → 知识库检索节点查询相关文档 → 条件分支判断检索结果是否为空 → 如果为空走LLM节点生成“未找到相关信息”的回复 → 如果不为空走LLM节点结合检索结果生成回答 → 结束节点输出。知识库检索节点的配置有几个关键参数查询变量引用开始节点的用户问题。知识库选择要检索的知识库。检索模式可选“向量检索”“全文检索”“混合检索”。混合检索的效果通常最好但速度稍慢。Top K返回最相关的K个文档块。一般设3到5太多会稀释关键信息太少可能漏掉重要内容。Score阈值过滤掉相似度低于阈值的文档块。设太高会漏检设太低会引入噪声。建议从0.5开始调。LLM节点的Prompt设计是RAG效果的关键。一个经过验证的模板是这样的你是一个基于知识库的问答助手。请根据以下检索到的文档内容回答用户问题。 检索到的文档 {{knowledge_retrieval_node.result}} 用户问题{{start_node.query}} 回答要求 1. 如果文档中有明确答案直接引用并注明来源。 2. 如果文档中没有相关信息回答“根据现有资料我无法回答这个问题”。 3. 不要编造文档中不存在的信息。这个Prompt的关键在于第三条“不要编造”。RAG最大的风险就是模型“幻觉”把检索到的无关内容和自己的训练知识混在一起胡说。明确的禁止指令能显著降低幻觉率。3.3 变量赋值与条件分支的实战技巧变量赋值节点在Workflow里看起来不起眼但用好了能大幅简化流程。它的作用是把某个表达式的值赋给一个变量供后续节点使用。比如你可以在流程开始时把用户输入的问题存到一个变量里后面多个节点都引用这个变量而不是每次都从开始节点取。条件分支节点支持多条件判断每个条件可以是一个表达式。Dify的表达式语法支持比较运算符、!、、、逻辑运算符and、or、not、以及一些内置函数如contains、startsWith。一个常见的用法是判断知识库检索结果的数量{{knowledge_retrieval_node.result.length}} 0如果为真走“有结果”分支为假走“无结果”分支。实操心得条件分支的表达式里尽量不要做复杂的字符串处理Dify的表达式引擎能力有限。如果需要复杂逻辑先用代码节点处理把结果存到变量里再用条件分支判断变量。3.4 代码节点什么时候该用什么时候不该用代码节点允许你在Workflow里执行自定义Python代码。这看起来很方便但我的建议是能不用就不用。原因有三第一代码节点里的代码是在Dify的沙箱环境里执行的可用的库有限不能随便pip install。第二代码节点的调试体验很差报错信息不直观排查问题费时费力。第三代码节点会破坏Workflow的可视化优势让流程变得难以理解和维护。那什么时候该用代码节点当Dify的内置节点确实无法满足需求时。比如需要对检索结果做复杂的去重和排序。需要调用一个Dify没有内置集成的外部API且HTTP请求节点配置起来太麻烦。需要对数据进行格式转换而模板转换节点做不到。代码节点的代码要尽量简短只做一件事输入输出都用JSON格式。这样即使出问题也容易定位。4. 知识库与RAG调优让检索结果更准4.1 文档分块策略的选择知识库的效果七分靠分块三分靠模型。Dify提供了两种分块模式自动分块和自定义分块。自动分块是Dify根据文档结构自动切分适合格式规范的文档比如Markdown、HTML。自定义分块允许你指定分块长度和重叠长度。分块长度一般设500到1000个字符重叠长度设50到100。分块长度太短每个块的信息量不足检索时容易漏掉关键上下文。分块长度太长一个块里包含多个主题检索时会把无关信息也带进来。我实测下来对于技术文档800字符左右的分块长度效果比较均衡。重叠长度的作用是防止关键信息被切分到两个块的边界上。比如一句话被切成两半前半句在块A后半句在块B检索时可能只命中块A导致信息不完整。设置重叠长度能让边界附近的内容同时出现在两个块里。4.2 检索模式对比向量、全文、混合Dify支持三种检索模式各有适用场景检索模式原理优势劣势适用场景向量检索将查询和文档都转成向量计算余弦相似度语义理解强能匹配同义词和改写对专有名词和数字不敏感概念性问答、语义搜索全文检索基于关键词匹配BM25算法对专有名词、代码、数字精确匹配无法理解语义同义词匹配差查文档中的具体参数、错误码混合检索结合向量和全文加权融合兼顾语义和精确匹配配置复杂速度稍慢大多数生产场景我的建议是除非你有明确的理由用单一模式否则直接用混合检索。Dify的混合检索支持设置权重默认是向量0.7、全文0.3。如果你的文档里有很多代码和参数可以把全文权重调高到0.5。4.3 Rerank模型的价值与配置Rerank重排序是提升RAG精度的利器。它的原理是先用检索模式召回一批候选文档比如Top 20然后用一个专门的Rerank模型对这批文档做精细排序选出最相关的几个比如Top 3送给LLM。为什么需要Rerank因为向量检索的相似度计算是粗粒度的它只能判断“大致相关”无法区分“非常相关”和“有点相关”。Rerank模型通常是Cross-Encoder结构会同时看查询和文档做更精细的相关性判断。Dify支持多种Rerank模型包括Cohere Rerank、BGE Rerank等。如果不想用外部API可以本地部署BGE Rerank模型。配置方法是在.env里设置RERANK_MODEL和RERANK_API_URL。注意Rerank会增加检索延迟。如果对响应速度要求高可以只在检索结果质量差的时候启用或者减少Rerank的候选数量。4.4 知识库流水线从文档到可检索索引Dify的知识库处理流程是一条流水线文档上传 → 格式解析 → 文本分块 → 向量化 → 索引存储。格式解析环节Dify默认用Unstructured库。它对PDF的解析能力取决于PDF的类型文本型PDF直接提取文字扫描型PDF需要OCR。如果文档里有大量表格和图片Unstructured的解析效果可能不理想需要人工预处理。向量化环节Dify默认用OpenAI的text-embedding-ada-002模型。如果不想用OpenAI可以换成其他Embedding模型比如BGE、M3E等。换模型后需要重新索引所有文档因为不同模型的向量空间不兼容。索引存储环节Dify默认用Weaviate。Weaviate是一个专门做向量检索的数据库支持HNSW索引算法。如果数据量很大百万级以上可以考虑换成Milvus或Qdrant性能和扩展性更好。5. 模型接入与LLM网关配置5.1 支持的模型供应商与接入方式Dify支持的模型供应商非常多覆盖了主流的大模型API和本地部署方案。云端API包括OpenAI、Anthropic、Google Gemini、Azure OpenAI、通义千问、文心一言、智谱AI等。本地部署方案包括Ollama、LocalAI、Xinference、vLLM等。接入方式分两类一类是直接在Dify的“模型供应商”页面填API KeyDify会自动拉取该供应商支持的模型列表。另一类是通过OpenAI兼容接口接入适用于那些没有专门适配但提供了OpenAI兼容API的服务。我实测下来Ollama的接入体验最好。在Ollama里拉好模型后在Dify的模型供应商里选Ollama填上Ollama的地址默认是http://host.docker.internal:11434就能看到本地模型列表。注意Docker容器内访问宿主机服务需要用host.docker.internal而不是localhost。5.2 多模型路由与负载均衡Dify支持配置多个模型并在应用里指定用哪个。但如果你想要更精细的路由策略——比如根据问题类型选不同模型、或者做负载均衡——需要用到LLM网关。LLM网关是一个介于Dify和模型API之间的中间层。它的作用包括统一API格式、做负载均衡、实现故障转移、统计token消耗、做速率限制。常见的开源LLM网关有One API、New API等。配置方法是在Dify的模型供应商里选“OpenAI兼容”把API地址指向LLM网关的地址。然后在网关里配置多个上游模型设置路由规则。这样Dify只需要和一个网关通信网关负责把请求分发到不同的模型。这种架构的好处是当某个模型API出现故障时网关可以自动切换到备用模型Dify层无感知。另外网关可以统一做token统计和成本核算方便做预算控制。5.3 模型参数调优Temperature、Top P、Max TokensDify的LLM节点暴露了几个关键参数Temperature控制输出的随机性。0表示最确定1表示最随机。做事实性问答时设0到0.3做创意写作时设0.7到1.0。Top P核采样参数控制候选词的范围。一般设0.9到1.0和Temperature配合使用。通常只调其中一个另一个保持默认。Max Tokens限制输出的最大长度。设太小会导致回答被截断设太大会浪费token。根据应用场景设问答类设500到1000长文生成设2000到4000。Frequency Penalty和Presence Penalty控制重复内容的惩罚。如果发现模型老是重复说同一句话可以适当调高这两个值。实操心得Temperature和Top P不要同时调。我的习惯是固定Top P为1.0只调Temperature。这样参数含义更直观调起来也更容易复现。6. 常见问题排查与性能优化6.1 应用响应慢的排查思路响应慢是Dify应用最常见的问题。排查思路是从外到内逐层定位第一层检查网络延迟。如果模型API在海外网络延迟可能是主要瓶颈。可以在容器内用curl -w测试到API地址的响应时间。第二层检查知识库检索耗时。在Workflow的日志里可以看到每个节点的执行时间。如果知识库检索节点耗时超过1秒可能是向量数据库性能问题或者Rerank模型太慢。第三层检查LLM推理耗时。LLM节点的耗时取决于模型大小和输出长度。如果用的是本地部署的大模型推理速度受GPU性能限制。可以尝试量化模型比如用4-bit量化来提速。第四层检查Workflow的节点数量。节点越多数据流转的开销越大。如果节点超过20个考虑合并一些简单节点或者把部分逻辑移到代码节点里一次完成。6.2 知识库检索不准的调优清单检索不准的表现是明明文档里有答案但模型说“找不到”。排查和调优的清单如下检查分块长度是否合适。太短会丢上下文太长会引入噪声。检查检索模式。专有名词多的文档用混合检索纯概念性文档用向量检索。检查Top K和Score阈值。Top K太小会漏检Score阈值太高会过滤掉相关文档。检查Embedding模型是否适合中文。OpenAI的text-embedding-ada-002对中文的支持一般换成BGE或M3E效果更好。启用Rerank。Rerank能显著提升Top结果的精度。检查文档解析质量。如果PDF解析出来是乱码检索肯定不准。可以手动检查解析后的文本。6.3 多租户与权限管理Dify社区版从1.10开始支持多租户。多租户的核心是工作空间Workspace隔离每个工作空间有独立的成员、应用、知识库、模型配置。成员角色分为管理员、编辑者、查看者权限逐级递减。配置多租户的步骤在“设置”里创建工作空间邀请成员分配角色。每个工作空间的资源是隔离的A空间的成员看不到B空间的应用。注意多租户模式下模型供应商的API Key是按工作空间配置的。如果多个工作空间共用同一个API Key需要在每个空间里分别配置。这增加了管理成本但换来了更好的隔离性。6.4 日志、监控与成本控制Dify提供了应用级别的日志可以看到每次请求的输入、输出、耗时、token消耗。这些数据对于排查问题和优化成本非常重要。成本控制方面Dify的“成本统计”页面可以按应用、按模型、按时间段查看token消耗和费用。如果发现某个应用的成本异常高可以检查是不是Prompt太长、或者检索结果太多导致输入token膨胀。监控方面Dify本身没有提供Prometheus指标但可以通过API获取应用的健康状态。如果需要更细粒度的监控可以在Docker层面用cAdvisor采集容器指标或者用Langfuse等LLM可观测性工具做深度追踪。7. 二次开发与扩展当积木不够用时7.1 源码结构与关键模块Dify的代码结构比较清晰主要分几个部分api/后端API服务用Flask框架。核心逻辑在api/core/目录下包括LLM调用、知识库检索、Workflow引擎。web/前端界面用Next.js框架。docker/Docker部署配置。sdks/各语言的客户端SDK。如果要二次开发最常改的是api/core/下的模块。比如要新增一个模型供应商需要在api/core/model_runtime/model_providers/下新建一个目录实现供应商的接口。要新增一个Workflow节点类型需要在api/core/workflow/nodes/下添加节点实现并在前端注册节点类型。7.2 自定义工具与API扩展Dify支持自定义工具让Agent或Workflow能调用外部API。自定义工具的配置方式是在“工具”页面新建工具定义工具的输入参数和API端点。Dify会自动生成工具的调用逻辑。自定义工具的API需要符合OpenAPI规范。如果已有API文档可以直接导入。如果没有需要手动定义。关键是要把API的输入输出描述清楚因为LLM是根据这些描述来决定怎么调用工具的。一个实用的技巧是给工具的描述里加上使用示例。比如“查询天气”工具的描述可以写“输入城市名返回该城市的当前天气。示例输入‘北京’返回‘晴25度’”。这样LLM更容易理解工具的用途和调用方式。7.3 与外部系统的集成模式Dify与外部系统的集成主要有三种模式第一种Dify作为主系统通过HTTP请求节点或自定义工具调用外部API。这是最简单的模式适合Dify主导业务流程的场景。第二种外部系统作为主系统通过Dify的API调用Dify应用。Dify的每个应用都会生成一个API端点外部系统可以用HTTP请求调用。这种模式适合把Dify作为AI能力层嵌入现有系统。第三种双向集成。Dify调用外部系统的API获取数据外部系统也调用Dify的API获取AI能力。这种模式最灵活但也最复杂需要设计好数据流和错误处理。我在实际项目里用得最多的是第二种模式把Dify应用封装成一个微服务通过API网关暴露给业务系统。这样业务系统不需要关心Dify的内部实现只需要按约定的接口调用即可。7.4 版本升级与兼容性注意事项Dify的版本迭代快升级时需要注意兼容性。几个经验跨大版本升级前先在测试环境验证。特别是知识库和Workflow的schema变更可能导致现有应用无法运行。备份数据库和文件。升级失败时可以快速回滚。关注Release Notes里的“Breaking Changes”部分。Dify团队会在Release Notes里明确标注不兼容的变更。如果用了自定义工具或二次开发升级后需要重新测试这些扩展点。Dify的内部API可能会变导致自定义代码失效。最后分享一个我在多个项目里验证过的部署架构Dify用Docker Compose部署在一台独立服务器上前面加一个Nginx做反向代理和SSL终止后面接一个外部PostgreSQL和Redis而不是用Dify自带的容器。这样做的原因是Dify自带的数据库容器在数据量大时性能不稳定换成外部数据库后备份、扩容、监控都更方便。另外把数据库和Redis独立出来升级Dify时只需要重启应用容器数据层不受影响升级风险大幅降低。
返回列表