当前位置: 首页 > news >正文

Dify 中级实验(07):子工作流——如何把公共逻辑做成可复用积木?

Dify 中级实验(07):子工作流——如何把公共逻辑做成可复用积木?

Dify 实验系列 · 中级 07/20 | 实验编号:DIFY-102-08
基于 Dify 1.16.1 实测(2026-08)

1. 业务场景

先讲一个我们实际遇到的场景。

一家同时做客服、产品调研、舆情监控的公司:客服要实时看客户情绪,产品团队要分析用户反馈,舆情部门要盯社区言论。三拨人各自开发了一套「情绪分析」——三份重复代码、三套维护成本、三个不一致的口径:客服判「负面」的,舆情可能判「中性」。

我们第一次接这类需求时,第一反应也是「把情绪分析的代码复制三份,各改各的参数」。真正动手才发现——需求一样、代码三份,改一处要改三处,漏改一套口径就漂移。后来翻 Dify 的节点列表才发现:模块化设计有原生手段——子工作流(Sub-workflow):把「情绪分析」这类公共逻辑抽成独立工作流,一处定义、多处调用(1.16 的真实做法是发布为工具调用)。

这不是个例。任何「多个业务线共用同一能力」的业务场景都是这个模式:情绪分析、文本清洗、格式化输出……公共逻辑不做模块化,就是在重复造轮子,而且每个轮子还不太一样。

2. 场景痛点

这个流程的痛点,在研发/业务团队身上体现得最直接:

  • 同一逻辑重复开发:三条线各写一份情绪分析,需求一样、代码三份,开发资源被重复消耗——重复的代码不是资产,是负债,每次升级都要连本带利还。
  • 改一处要改三处:分析逻辑升级(比如紧急度规则调整),三套代码要同步改,漏改一套口径就漂移——线上行为从此不一致。
  • 调用方被实现绑架:每个调用方都要关心「怎么分析」——传什么参数、用什么模型、怎么解析输出,而不是只关心「分析结果是什么」。
  • 输出格式不统一:三条线产出的字段名、格式各异,下游汇总统计对不上,数据越攒越乱。

本质上,公共逻辑每多一个调用方,重复成本就翻一倍——模块化的价值不在「少写代码」,而在「一处定义、多处调用、接口即契约」

3. 方案:为什么是子工作流

选子工作流的理由,我们实际对比过:

  • 一处定义、多处调用:情绪分析做成独立工作流,两个主工作流消费它——客服看板逐条分析,批量反馈迭代内逐条调用;
  • 接口即契约:输入text/language、输出 6 个结构化字段(sentiment/score/confidence/keywords/brief/urgency),边界清晰,调用方只看接口不看实现;
  • 1.16 的真实实现:Dify 1.16 没有 sub-workflow 节点类型,真实做法是发布子工作流为工具(Workflow as Tool),用 tool 节点调用——本实验完整演示这条路。

这篇文章我们就用它搭「情绪分析引擎」子工作流 + 两个消费它的主工作流(客服情绪看板 / 批量反馈分析)。

4. 整体架构

主工作流 2:批量反馈分析

开始:feedback_list JSON 数组

解析反馈列表:Code

逐条情绪分析:迭代 Tool + 解析 Code

汇总情绪分布:Code

结束

主工作流 1:客服情绪看板

case_high

case_normal

开始:customer_message / agent_name

调用情绪分析引擎:Tool provider_type workflow

解析情绪结果:Code 从 json 数组展平字段

紧急度分支:IF-ELSE

高优安抚回复:LLM

结束:高优

常规回复:LLM

结束:常规

子工作流:情绪分析引擎

开始:text / language

情绪分析:LLM

提取结构化字段:PE

结束

链路很清晰:子工作流定义能力,主工作流消费能力——情绪分析引擎只做「分析并输出结构化字段」,两个主工作流各自编排自己的业务逻辑(看板按紧急度分流、批量分析走迭代)。

5. 模块设计

5.1 子工作流:枚举字段必须给显式规则

LLM 输出的 JSON 里urgency是枚举字段——只写 low/medium/high 不给规则,LLM 会随意输出(实测负面投诉返回 low,下游分支全走错):

prompt_template:-id:p_sentimentrole:systemtext:|你是一个专业情绪分析师。分析以下文本的情感,输出 JSON 格式(不要 Markdown): 文本:{{#start.text#}} { "sentiment": "positive/negative/neutral/mixed", "score": 0.0 到 1.0 之间的浮点数, "confidence": 0.0 到 1.0, "keywords": ["关键词1", "关键词2", ...], "brief": "一句话情感总结", "urgency": "low/medium/high" } 紧急度规则:负面情绪/投诉/损坏/退款/愤怒类内容 → "high";中性咨询类 → "medium";正面/普通内容 → "low"reasoning_format:separated

参数提取器 6 个参数(sentiment string / score number / confidence number / keywords array[string] / brief string / urgency string),reasoning_mode: function_call

5.2 主工作流:发布子工作流为工具(核心)

Dify 1.16.1没有 sub-workflow 节点类型(运行时报No class mapping found for node type: sub-workflow),必须「发布为工具」后用 tool 节点调用:

-data:provider_type:workflowprovider_name:dify102_08_01_情绪分析引擎provider_id:11e9699e-ffa8-448f-8278-e16799e5912a# 发布时的注册 ID,重发会变!tool_name:dify102_08_01tool_description:情绪分析引擎(子工作流)——输入文本,输出结构化情绪字段type:tooltitle:调用情绪分析引擎tool_configurations:# ⚠️ 与 tool_parameters 双写同一份值(UI 权威格式)text:{type:mixed,value:'{{#start.customer_message#}}'}language:{type:mixed,value:中文}tool_parameters:text:{type:mixed,value:'{{#start.customer_message#}}'}language:{type:mixed,value:中文}paramSchemas:-name:textdefault:示例:太棒了,五星好评# default 决定 UI 面板显示值required:truetype:stringid:tool_sentiment

5.3 输出不透传:必须解析展平

工具输出固定三件套text(string)/files(array[file])/json(array[object])——子工作流 end 的自定义字段名不透传,下游直接引用{{#tool.sentiment#}}取不到。必须加代码节点从json数组提取:

defmain(sent_json:list)->dict:importjson data={}ifisinstance(sent_json,list):foriteminsent_json:ifisinstance(item,dict):data.update(item)return{"sentiment":str(data.get("sentiment","未知")),"brief":str(data.get("brief","无摘要")),"urgency":str(data.get("urgency","low")),"score":str(data.get("score","")),"sentiment_json":json.dumps(data,ensure_ascii=False),}

紧急度分支用字符串比较(is/is not):

cases:-case_id:case_highconditions:-comparison_operator:isvalue:highvariable_selector:[cd_parse_sent,urgency]varType:stringlogical_operator:and-case_id:case_normalconditions:-comparison_operator:is notvalue:highvariable_selector:[cd_parse_sent,urgency]varType:stringlogical_operator:and

6. 运行验证

输入预期实测
正面:太棒了!客服很贴心,五星好评!sentiment=positive,urgency=low → 常规回复与预期一致
负面:东西收到就坏了,联系客服三天没人理,太失望了!sentiment=negative,urgency=high → 安抚回复与预期一致
中性:周二下午三点可以安排配送吗?sentiment=neutral,urgency=medium → 常规回复与预期一致
批量:3 条反馈 JSON迭代逐条分析,汇总情绪分布与预期一致

7. 实战坑

现象修复
用 sub-workflow 节点类型运行报No class mapping found for node type: sub-workflow1.16 必须「发布为工具」:tool 节点 +provider_type: workflow
子工作流重导后 provider_id 失效主工作流调用报 workflow provider not found重发后从 tool-providers 动态查最新 provider_id 同步(实测 2a6187e8 → 11e9699e)
下游直接引用工具的自定义字段{{#tool.sentiment#}}取不到值,分支全走默认工具输出只有 text/files/json,必须 code 解析 json 展平(见 5.3)
tool 参数只写 tool_parametersUI 配置面板显示参数为空,手动调试报「要分析的文本不能为空」tool_parameterstool_configurations双写同一份值;paramSchemas[].default填占位值让 UI 不空
枚举字段不给规则负面投诉消息返回 urgency=low,下游分支全走错prompt 给显式映射规则(负面/投诉/退款→high,咨询→medium,正面→low)
迭代内 item 是字符串却传 item.content工具收到空文本,全部判默认值字符串 item 直接传{{#iter.item#}}

💡 什么时候该抽子工作流:同一逻辑出现在 ≥2 个流程、接口稳定、输入输出边界清晰。接口即契约——改子工作流输出结构,所有调用方都要跟着改,这是模块化的真实成本。

8. 实验文档及源码获取

  • 实验文档(完整操作步骤):DIFY-08:子工作流——搭积木式模块化设计.md
  • 源码(可直接导入,先导子工作流再导主工作流):
    • dify102_08_01_情绪分析引擎.yml
    • dify102_08_02_客服情绪看板.yml
    • dify102_08_03_批量反馈分析.yml

文章聚焦核心配置与采坑点;实验的完整分步操作(节点搭建/参数表/调试指引)见实验文档原文。


下一篇:Dify 中级实验(08):代码节点进阶——如何用标准库处理文件与数据?

💬 你在这个实验的场景里踩过什么坑?欢迎评论区分享你的实战经验。

http://www.jsqmd.com/news/1400812/

相关文章:

  • 基于Human Behavior分析的AI原生应用设计:从行为流协同到工程实践
  • Python开发轻量级员工管理系统的实践与优化
  • 最长公共前缀算法精解:横向与纵向扫描的实战剖析
  • AtCoder Beginner Contest 471 ABCDE
  • 中美Robotaxi“四国杀”:2026,谁在领跑万亿出行终局?
  • Gitee高人气开源项目深度解析:从筛选到源码学习的全链路指南
  • AOSP-- 第 2 章:源码与构建系统
  • IDEA中git stash可视化操作指南:提升多任务开发效率
  • 学习25
  • 从2020亚太赛A题看数学建模:数据驱动与机理分析的融合实践
  • OpenSpec自定义步骤实战:从数据清洗到复杂工作流构建
  • 《ETA1476FT2G 使用笔记|SOT23‑6 2A 同步降压 DC‑DC 芯片》#ETA1476FT2G #钰泰 ETA #DC‑DC 降压 #电源设计 #国产电源芯片
  • SQL GROUP BY 详解:从分类汇总到多维度聚合实战
  • 物流行业GEO优化公司哪家好?2026物流企业AI搜索获客选型全指南 - 科技前沿信息
  • 免费离线OCR软件Umi-OCR完整上手指南:截图、批量、PDF识别一次讲透
  • 无人机维修入门必修课|看懂无人机结构,认识每一个零件 - 湖南阳光技术
  • C++时间处理实战:从time_t到localtime,掌握时间戳与日期转换
  • OpenClaw AI智能体框架:从部署到十大核心Skills实战指南
  • 泰迪狗场选购测评|正规犬舍筛选干货指南 - Full19
  • ArcGIS Pro要素裁剪进阶:从基础操作到自动化工程实践
  • 电动汽车集群优化:Matlab与Yalmip建模实践
  • 小白吃透DeepSeek Harness:新一代AI Agent框架保姆级实战教程
  • 系统重构与现代化改造:从概念到实践的避坑指南
  • 《文明6》DLC解锁补丁技术解析:原理、安装与问题排查
  • 免费Windows内存清理工具Mem Reduct完整上手指南
  • Go缓存策略实战从本地缓存到Redis多级缓存
  • XML Schema 实例详解:从入门到实战
  • XR虚拟演播室:重构视听内容生产的沉浸式未来
  • Claude Sonnet 5 入门定价永久化:从成本变量到稳定生产力工具的实战指南
  • Nginx HTTPS与TLS 1.3实战:从安全配置到性能调优的避坑指南