三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?

Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?

Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?

Dify 实验系列 · 中级 06/20 | 实验编号:DIFY-102-07

上篇:Dify 中级实验(05):并行执行——如何让多路任务同时跑?

1. 实验目的

掌握Variable Aggregator(变量聚合)节点——用确定性方式合并多路分支输出,替代上一课的 LLM 合并。理解三种合并心智:覆盖(后到者赢)、深合并(对象递归合并)、自定义(代码节点兜底)。

适合场景:多源数据拼装用户画像、配置合并、日志/结果收集——需要「精确、可预测、不烧 Token」的合并。

2. 场景设计

并行获取同一个用户的三种数据,聚合后生成用户 360 报告:

  • 分支 A 用户画像user.name/age/level+metrics.login_count/last_active
  • 分支 B 订单数据user.total_orders/avg_order_value+metrics.return_rate
  • 分支 C 客服交互user.ticket_count/satisfaction+metrics.avg_response_time

聚合后同一个user对象里应包含全部字段(A/B/C 各自贡献一部分)——这正是「深合并」的价值:三个分支的数据结构同构、字段互补,合并后零丢失。

输入user_name(可选,默认张三);输出:用户 360 报告(身份概览 / 行为画像 / 价值评估 / 服务建议)。

3. 节点拓扑

开始(user_name) ├─ 用户画像数据(Code:object) ├─ 订单数据(Code:object) └─ 客服交互数据(Code:object) ↓ 聚合多源数据(variable-aggregator,output_type: string) ↓ 生成用户 360 报告(LLM,max_tokens 8000)→ 结束

4. 关键配置

4.1 三个数据源分支(Code)

每个分支输出一个 object,字段刻意设计成同构互补

# 分支 A:用户画像defmain(user_name:str)->dict:name=(user_nameor"张三").strip()or"张三"return{"profile_data":{"user":{"name":name,"age":28,"level":"VIP"},"metrics":{"login_count":45,"last_active":"2026-07-21"},}}

4.2 聚合节点(核心)

聚合器把三个 object 合并成一个,output_type: string时输出合并后的 JSON 文本:

-data:output_type:stringtitle:聚合多源数据type:variable-aggregatorvariables:--cd_profile# 注意:variables 是 [[节点id, 字段], ...] 嵌套数组-profile_data--cd_orders-orders_data--cd_service-service_dataid:agg_merge

⚠️ aggregator 的variables格式与 LLM 节点不同:LLM 是[{value_selector, variable}]对象数组,aggregator 是嵌套数组[[节点id, 字段], ...],别搞混。

4.3 消费聚合结果的 LLM

长报告输出把max_tokens提到 8000,prompt 加「直接输出正文」约束(DeepSeek 长输出被思考挤空 text 的坑):

model:completion_params:max_tokens:8000temperature:0.7mode:chatname:deepseek-v4-flashprompt_template:-id:p_reportrole:systemtext:|用户全景数据如下(JSON 格式,由用户画像/订单/客服交互三路数据源合并而来): {{#agg_merge.output#}} 请生成一份用户 360 报告,包括: 1. 用户身份概览 2. 行为画像 3. 价值评估 4. 服务建议 直接输出报告正文,不要输出任何解释性文字。reasoning_format:separated

5. 运行验证

检查项预期实测
合并后的 user 对象含 name/age/level/total_orders/avg_order_value/ticket_count/satisfaction 全部 7 字段与预期一致
合并后的 metrics 对象login_count/last_active/return_rate/avg_response_time 全部保留与预期一致
LLM 报告四段式:身份概览/行为画像/价值评估/服务建议与预期一致

对比实验:把聚合策略换成「覆盖」再跑一次——后完成分支会覆盖先完成的同名字段,user对象只剩最后一个分支的字段(数据丢失)。这一对比直观展示「深合并 vs 覆盖」的差异。

6. 采坑点

现象修复
同名冲突字段被覆盖并行分支完成顺序不确定,「后到者覆盖」不可预测设计阶段约定冲突策略:字段互补(本实验)或代码节点自定义合并加后缀
把聚合当数值累加期望 total_orders 相加,实际是对象合并合并 ≠ 累加:数值统计(求和/均值)必须走代码节点
aggregator 的 variables 格式写错用 LLM 的[{value_selector, variable}]格式,校验报错用嵌套数组[[节点id, 字段], ...]
长报告输出 text 为空DeepSeek 把内容写进思考/解释部分,max_tokens 被挤空max_tokens 提到 8000 + prompt 明确「直接输出正文」
校验脚本在 aggregator 上崩check_dsls.py 报AttributeError: 'list' object has no attribute 'get'脚本局限(已修),非 DSL 错误——aggregator 格式以本文为准

💡 选型心法:要「精确、可预测」→ variable-aggregator;要「理解语义、自由组织」→ LLM 合并。两者不冲突:聚合器负责结构(JSON 全字段保留),LLM 负责叙事(把 JSON 讲成人话)。

7. 实验文档及源码获取

  • 实验文档(完整操作步骤):DIFY-07:变量聚合——多路分支结果合并.md
  • 源码(可直接导入):dify102_07_多源数据合并器.yml

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


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

← 返回列表