在Dify里新建应用的时候,平台会让你在Chatflow和Workflow之间做一个看起来简单、实际上很关键的选择。我在带团队做智能客服和知识库问答项目时,几乎每次都要跟新同事解释一遍这两个东西到底差在哪里:为什么客服机器人必须用Chatflow,而批量文本处理却适合用Workflow。选错了一开始可能没感觉,等流程复杂起来再回头改,成本和返工量都相当难受。
这篇我打算把Dify的这两类工作流一次讲透,包括两者的设计逻辑、适用场景、节点搭配思路、常见坑位,并且各用一个完整可照抄的搭建实例,带你把流程从零跑到上线。不管你是刚接触AI应用开发的新手,还是已经在用Dify做项目的开发者,这篇应该都能帮你少踩几个坑。
1. Chatflow和Workflow到底是什么,一句话记住它们的定位
1.1 Chatflow:给“有来有回”的对话应用准备的骨架
很多第一次用Dify的朋友都会在控制台前愣住:聊天助手、Agent、Chatflow、Workflow,一堆选项看起来都差不多。我后来把Dify当作一个可视化编程工具而不是“AI玩具”来理解,才把这件事彻底想明白。Chatflow,中文叫聊天流,定位非常清楚——它就是用来搭建“对话型应用”的。你在界面上画的每个方块,最终呈现给用户的都是一个聊天窗口,用户在里面发消息、收回复,整个过程像跟人聊天一样。
聊天窗口看起来轻巧,背后其实有一套和普通表单提交完全不同的状态管理逻辑。用户说一句“我想查一下订单状态”,紧接着又问“那运费是多少”,这两句话单独看没有意义,只有放在同一个会话上下文里才成立。Chatflow天生就处理这种带记忆、带上下文、带意图连续性的场景。它内部有“会话”这个概念,每一次用户发消息,平台都会按你配置的规则把历史记录带进后续的LLM节点里,这是它能做客服、导购、答疑机器人的根本原因。
1.2 Workflow:给“输入变输出”的自动化流程准备的骨架
Workflow就完全是另一套思路了。它没有聊天窗口,没有会话记忆,也没有“上一轮说了什么”这个概念。你提供给它的是一组输入参数,它把这些参数跑完一整套节点,最终在结束节点吐出一个结果。本质上,它是一条自动化流水线。
我习惯把它理解成“带AI节点的后端服务”。你可以拿它做批量文本分类:传100条评论进去,每条评论走一遍相同的LLM调用,输出每个评论的情感标签。也可以拿它做接口封装:上游系统POST一条工单内容,Workflow负责调用大模型提取结构化字段,再把结果JSON返回给上游。整个过程没有用户参与,也不需要“聊天”,但它一样能用上LLM、知识库、条件判断、代码处理这些核心能力。
1.3 两者的核心差异对照与选型逻辑
虽然都叫“流”,底层用的节点类型也几乎一样,但两者的产品逻辑天差地别。我整理了一张表,建议你直接收藏:
| 对比维度 | Chatflow | Workflow |
|---|---|---|
| 应用形态 | 有聊天界面,用户可自然语言交互 | 无聊天界面,面向API或后台任务 |
| 会话记忆 | 原生支持,可配置多轮记忆窗口 | 默认无记忆,每次运行相互独立 |
| 变量类型 | 会话变量(跨轮保留)、聊天变量(单轮) | 输入变量、输出变量,着眼于数据流 |
| 触发方式 | 用户发消息触发 | 手动运行、API调用、定时任务触发 |
| 典型场景 | 客服、导购、知识库问答、角色对话 | 批量处理、内容生成、数据清洗、接口编排 |
| 调试方式 | 聊天窗里模拟对话,观察上下文 | 点运行按钮传参,看每个节点的输入输出 |
所以选型逻辑可以浓缩成一句话:如果用户面对的是一个对话框,且多轮上下文很重要,优先选Chatflow;如果用户面对的是一个接口或一批待处理的数据,不需要闲聊,那就选Workflow。这个判断比任何花哨的技巧都管用,也是我反复跟团队强调的决策标准。
2. 场景选型:什么时候用Chatflow,什么时候用Workflow
2.1 最适合Chatflow的典型场景
从实际项目来看,Chatflow的黄金场景有三个。第一个是智能客服和知识库问答,这是我把Dify用得最多的方向。用户可以在对话框里连续提问,比如先问“退货政策是什么”,接着问“那发票怎么开”,机器人能记住前面聊到退货,知道第二个问题是在问退货场景下的发票问题,而不是泛泛的发票规则。第二个是售前导购和产品推荐助手,用户先说预算,再说想看什么品类,最后问发货时间,这些问题是在一轮会话中逐步收窄的,没有记忆的机器人根本接不住。第三个是角色扮演和教学助手,这类应用天然依赖连续上下文,既要记住用户之前说过什么,又要保持人设稳定。
值得留意的是,上面的例子并非Chatflow独占。理论上Workflow加上记忆模块也能做客服,但Dify把记忆、会话变量这类能力内置到了Chatflow里,你用Chatflow做等于开箱即用,省掉了大量状态管理代码。这也是我强烈建议新手别用Workflow硬做客服的原因——你不是不能实现,而是没必要跟框架对着干。
2.2 最适合Workflow的典型场景
Workflow的强项在于确定性和可复用性。我接过好几个内容工厂类项目:运营团队每天要处理几百条产品评论,原来靠人工看、手写回复,后来用Workflow搭了一条流水线:传入评论列表,迭代节点逐条拆开,LLM判断情感,条件分支分桶,最后把标签和回复建议汇总成表格。整个流程没有对话框,但吞吐量远不是人肉可以比的。
另一个典型场景是接口编排。比如你有一个内部系统,需要根据客户提交的工单自动提取“问题类型”“紧急程度”“需要转交的部门”。你可以把Workflow发布成API,上游系统把工单文本POST过来,Workflow内部完成LLM提取和分支判断,再把结构化JSON返回。这种场景如果硬套Chatflow,等于给后端接口加了一个没必要的前台聊天壳子,调试和调用都更麻烦。
2.3 一个反复被问到的例子:知识库问答到底选哪个
“我在Dify里上传了一堆企业文档,想做一个内部问答系统,到底该用Chatflow还是Workflow?”这是我被问过最多的问题。标准答案其实是:看你把问答系统暴露给谁、以什么形式暴露。
如果是给内部员工或用户在网页对话框里用,Chatflow是更舒服的选择。员工提问可以连续追问:先问“报销流程”,再问“住宿费标准是多少”,Chatflow能记住他在问报销相关的内容。如果用Workflow,每次请求都是孤立的,用户多问几轮你就得自己设计上下文传递方案,等于把框架已经解决的问题重新发明一遍。
但如果你做的不是人机交互页面,而是把这个问答能力嵌进另一个业务系统,上游系统直接把“用户输入的问题”传过来、只要一个“答案+引用来源”的结果,那我更推荐用Workflow发布API。因为Workflow的输入输出是明确的结构化参数,调用方只要传一个字符串、收一个JSON,干净利落,不会因为会话机制带来额外的状态同步问题。
3. 实操一:用Chatflow搭一个多轮客服问答流程
3.1 最小可用链路怎么搭
理论说再多都不如跑通一个真实流程。我以一个常见的售前客服场景为例:用户会问商品信息、报价、发货时效,机器人需要先从知识库检索,再根据检索结果回答,检索不到就转人工提示。这套流程在Chatflow里只需要6个节点就能跑起来。
第一个节点是「开始」,它默认带用户输入变量,你在Chatflow的应用设置里还可以配置系统变量,比如会话ID、用户ID。第二个节点是「知识检索」,选择你预先建好的数据集,建议开启混合检索并设置一个合理的Score阈值,比如0.6到0.7,低于这个分数的片段干脆不返回。第三个节点是「条件分支」,判断检索结果是否为空,为空说明知识库没有覆盖到,直接走兜底话术;不为空就进入回答节点。第四个节点是「LLM」,系统提示词里明确写“你是客服,只能根据参考内容回答,不能编造”,然后把检索结果变量通过模板引用进去。第五个节点是「模板转换」,把最终回答拼接成带换行的清晰文本。最后一个节点是「结束」,输出答案。
这套链路看着不长,但它把Chatflow最核心的骨架体现出来了:用户输入、检索增强、分支兜底、大模型生成、结构化输出。你后续加“转人工”“记录订单号”等功能,都是在这些节点之间插入更多分支和变量赋值而已。
3.2 会话变量和多轮记忆怎么配
多轮对话是Chatflow的看家本领,但默认配置往往不够用。第一件事是检查记忆开关:在LLM节点的高级设置里,有「记忆」选项,开启后平台会把历史对话按窗口大小传给模型。我一般把窗口调成6到10轮,太少记不住上下文,太多则既浪费token又容易让模型被旧消息干扰。
第二件事是学会用会话变量。举个例子,客服机器人需要知道用户当前在咨询哪个订单号。用户第一轮说“帮我查一下订单B12345”,你可以在一个LLM节点里提取出订单号,用「变量赋值」节点存到会话变量order_no里。之后不管用户在第几轮问“那这个订单到哪了”,系统提示词里都可以直接引用{{#conversation.order_no#}},让大模型知道他说的是B12345。这个能力在Workflow里是没有的,因为Workflow不跨轮保留状态。会话变量用得好,客服机器人的体验会立刻上一个台阶。
3.3 调试时最容易忽略的细节
Chatflow的调试在右侧聊天框里进行,很多人点几次没反应就开始怀疑平台坏了,其实多数是节点配置的问题。排障时第一优先看「开始」节点是否成功接收用户消息,再看「知识检索」的实际返回结果。Dify每个节点点击后都能看到输入输出详情,这是一把排障金钥匙。
我调试时会刻意模拟连续场景:先问“你们有无线耳机吗”,再问“续航多久”,观察第二轮请求的上下文里是否包含了第一轮的信息。如果第二轮模型回答得很空泛,大概率是记忆未开启,或者系统提示词没有引用会话变量。还有一个隐藏坑:如果你在「开始」节点之外改了变量名,很多下游节点引用的旧变量会变成未定义并报错,所以变量名定义好后尽量别改,真要改就把相关节点的引用全部检查一遍。
4. 实操二:用Workflow搭一个评论批量情感分析流程
4.1 输入输出设计与迭代节点的作用
下面这个场景是我实际给一个电商团队做的:批量商品评论,人工看不过来,需要自动给每条评论打上“正面/中性/负面”标签,负面评论额外生成一段客服回复建议。这套流程在Workflow里非常顺手,因为它的输入输出都结构化:输入是一个评论数组,输出是带标签的汇总结果。
这里必须引入Workflow里的「迭代」节点。之前有人问我:我把100条评论通过开始节点传进去,LLM节点会自己处理完100条吗?答案是不会。Dify的LLM节点默认只处理一个输入,一次只调用一次模型。要处理列表,必须用迭代节点把它们拆开,逐个送入LLM,再汇总输出。迭代节点左下角和右上角各有一个端口:左侧接收列表,右侧输出单条item,循环体内部按你连接的子流程依次执行。
4.2 节点串联与参数配置细节
这段流程我建议按8个节点来搭。开始节点定义输入参数review_list,类型选array,方便外部传多条评论。接「迭代」节点,来源填{{#start.review_list#}}。迭代内部接「LLM」节点,系统提示词设置情感分析师的角色,用户消息里用{{#item#}}引用当前迭代到的这条评论,要求模型只输出JSON格式,比如{"sentiment":"negative","reason":"..."}。之后接「条件分支」,用模型输出的sentiment字段做判断,是negative走负面通道,否则走正常通道。每个通道后面接一个「模板转换」节点,把当前评论、标签、回复建议拼成一行的结构化文本。最后在迭代外部再接一个「模板转换」,把循环输出的所有结果用换行符拼起来,交给「结束」节点输出。
参数上有几个地方要提醒。第一,LLM节点的输出格式如果不稳,可以开启模型的JSON输出模式,或者用Dify的「结构化输出」相关节点固定Schema。第二,条件分支的判断字段要选对路径:模型输出通常是一个JSON对象,你要深入到{{#llm.text#}}里的对象属性,千万别直接拿整个文本去等号匹配。第三,如果评论数量很大,建议在开始节点加一个分批参数,比如每次只处理50条,避免单次调用超时。
调用时上游系统传来的JSON长这样:
{ "review_list": [ "发货速度快,但包装有点破了。", "客服很耐心,问题顺利解决了。", "差评,商品和描述完全不符。" ] }Workflow跑完后结束节点会输出一个汇总文本,比如每条评论一行,包含原始内容、情感标签和回复建议,可以直接落库或者推送通知。手动调试时,先拿两三条短文本跑通,再接真实批量数据,能省下不少模型调用费用。
4.3 Workflow的DSL/YAML导出与迁移
Workflow跑通之后,整个应用会被Dify保存成一个DSL文件,本质上是YAML格式。你在应用设置里可以一键导出,这个YAML里面记录了应用基本信息、节点定义、节点之间的连线,甚至可以当作文本文件来阅读和修改。我自己的经验是:遇到需要批量改提示词的时候,与其在界面上一个个节点点开改,不如导出来用文本工具批量替换,再导入回去,效率高很多。
这也解释了为什么很多人讨论“AI workflow yaml解析执行”——Dify这类平台把可视化流程和底层DSL做了绑定,可视化是编辑态,YAML是持久化和传输形式。你在Dify里配置的每个节点、每条连线,最终都会落到这样一份结构化的描述里。官方社区版升级、迁移服务器时,备份和恢复应用基本就是靠这份YAML。会读一点YAML的人,排障和批量维护的能力会明显更强。
5. 常见问题、避坑心得与实战建议
5.1 新手最容易踩的三个坑
第一个坑是把Workflow当成对话应用用。我见过有人用Workflow搭了一个“聊天机器人”,因为每次运行都拿不到上一轮的上下文,最后不得不写一堆代码节点自己拼接历史记录,吃力不讨好。判断标准还是要回到第1节:用户面对的是对话框,还是有待处理的数据。
第二个坑是一把梭,把所有逻辑全塞进一个LLM节点。有人为了偷懒,让一个LLM节点同时完成“提取关键信息、判断情感、生成回复”三件事,结果输出格式极其不稳定。正确做法是利用条件分支和代码节点拆解职责,让每个LLM节点只做一件小而明确的事,模型出错的概率会指数级下降。
第三个坑是记忆窗口过大导致token爆炸。Chatflow里记忆开得太大,对话超过20轮后,每轮请求都会携带海量历史,延迟和费用一起涨。我一般用“只保留最近N轮”的配置,再把真正要用的关键信息通过会话变量单独提炼出来,而不是依赖模型从头到尾翻历史记录。
5.2 本地部署、版本升级与模型配置的实战提醒
很多朋友是在自己服务器上用Docker Compose部署Dify的,这套部署方式本身很稳,但升级时容易遇到坑。我遇到最典型的案例是:升级版本后,打开知识库或保存知识库某条记录时报internal server error。这种问题十有八九是数据库迁移没有正确执行,或者容器里跑的代码版本和数据库结构版本不一致。建议先看容器日志确认报错点,再检查是否需要手动执行迁移脚本,必要时把旧容器数据备份好、重新拉取镜像启动。
如果你想把知识库放到本机、数据不出内网,可以在Dify里配置Ollama作为模型供应商,用本地部署的Embedding模型来做向量化。我在内网项目里就搭配过bge-m3这类模型,效果能满足大多数中文场景,而且完全离线可用。配置时注意模型名称要和Ollama拉取的名称完全一致,向量维度设置也要对应,否则知识库检索会报维度不匹配。
5.3 我自己的三个使用习惯
项目做得多了,我慢慢形成几个习惯,供你参考。第一,任何流程都先搭最小可用版本:一条主链路、一个LLM、一个结束节点,确认输入输出通畅后再往里加分支和变量。很多人一上来就想做复杂多人协作流程,结果连最基础的数据流通都没跑通,排查起来非常痛苦。
第二,在开始节点上就把所有外部输入定义清楚,并且命名带前缀,比如input_、config_,这样节点多了以后不会混淆。第三,调试时固定输入。Workflow每次运行都会消耗模型额度,不要拿大量真实数据随便试。我先用一条短文本反复跑,确认链路稳定后再接完整数据。这个习惯帮我省下不少时间,也少烧了很多token。
最后再分享一点个人体会。Chatflow和Workflow不是竞争关系,它们是Dify为两种不同场景准备的“模具”。你不需要两个都会到精通,但至少要能一眼判断项目该用哪个模具。判断对了,后面搭节点、调参数都顺理成章;判断错了,后面每一步都在跟框架的设计初衷较劲。遇到不确定的项目,我通常会问自己一句:这需求最后交付给用户的是一个“对话框”,还是一个“处理结果”?答案清楚了,选型的事基本就定了。