← 返回文章列表

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

1. 业务场景

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

一家互联网公司的用户运营团队,要看一个用户的完整画像:身份信息(姓名/年龄/等级)、消费行为(订单数/客单价)、服务记录(工单数/满意度)——数据分散在用户档案、订单系统、客服工单三个系统里。运营每次看用户都要开三个后台、手工拼信息,看完还说不清全不全。

我们第一次接这类需求时,第一反应也是「把三路 JSON 丢给 LLM,让它合并成一份」。真正动手才发现——LLM 合并的字段偶尔丢、偶尔被改写,同名冲突谁覆盖谁全看运气,输出不可预测。后来翻 Dify 的节点列表才发现:平台原生的 Variable Aggregator(变量聚合) 就是干这个的——用确定性方式合并多路分支输出,零 Token、结果可预测。

这不是个例。任何「多源数据要精确合并成一份」的业务场景都是这个模式:多源数据拼装用户画像、配置合并、日志/结果收集——数据在多个地方,最终要合成一个对象。

2. 场景痛点

这个流程的痛点,在运营/数据团队身上体现得最直接:

本质上,「合并」要的是精确、可预测、不烧 Token——这不是 LLM 的活,是确定性工具的活。LLM 负责把结构讲成人话,结构本身不该交给它。

3. 方案:为什么是变量聚合

选变量聚合的理由,我们实际对比过:

这篇文章我们就用它搭一个「用户 360 报告生成器」:并行获取用户画像/订单/客服交互三路数据,聚合后生成完整报告。

4. 整体架构

graph TD start["开始:user_name"] profile["用户画像数据:Code object"] orders["订单数据:Code object"] service["客服交互数据:Code object"] agg["聚合多源数据:variable-aggregator output_type string"] report["生成用户 360 报告:LLM max_tokens 8000"] end1["结束"] start --> profile --> agg start --> orders --> agg start --> service --> agg agg --> report --> end1

链路很清晰:入口收用户名 → 三路并行取数 → 聚合器确定性合并 → LLM 生成报告。聚合器是架构核心——三个分支的数据结构同构、字段互补,深合并后零丢失,LLM 只负责把合并好的 JSON 讲成人话。

5. 模块设计

5.1 三个数据源分支(Code)

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

# 分支 A:用户画像

def main(user_name: str) -> dict:

    name = (user_name or "张三").strip() or "张三"

    return {

        "profile_data": {

            "user": {"name": name, "age": 28, "level": "VIP"},

            "metrics": {"login_count": 45, "last_active": "2026-07-21"},

        }

    }

5.2 聚合节点(核心)

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

- data:

    output_type: string

    title: 聚合多源数据

    type: variable-aggregator

    variables:

    - - cd_profile    # 注意:variables 是 [[节点id, 字段], ...] 嵌套数组

      - profile_data

    - - cd_orders

      - orders_data

    - - cd_service

      - service_data

  id: agg_merge

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

5.3 消费聚合结果的 LLM

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

model:

  completion_params:

    max_tokens: 8000

    temperature: 0.7

  mode: chat

  name: deepseek-v4-flash

prompt_template:

- id: p_report

  role: system

  text: |

    用户全景数据如下(JSON 格式,由用户画像/订单/客服交互三路数据源合并而来):

    {{#agg_merge.output#}}

    请生成一份用户 360 报告,包括:

    1. 用户身份概览

    2. 行为画像

    3. 价值评估

    4. 服务建议

    直接输出报告正文,不要输出任何解释性文字。

reasoning_format: separated

6. 运行验证

检查项 预期 实测
合并后的 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 覆盖」的差异。

7. 实战坑

现象 修复
同名冲突字段被覆盖 并行分支完成顺序不确定,「后到者覆盖」不可预测 设计阶段约定冲突策略:字段互补(本实验)或代码节点自定义合并加后缀
把聚合当数值累加 期望 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 讲成人话)。

8. 实验文档及源码获取

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

本系列 · Dify 实验 · 中级
  1. Dify 中级实验(01):参数提取器实战——如何从自然语言中提取结构化数据?
  2. Dify 中级实验(02):问题分类器——智能路由引擎如何四路分发?
  3. Dify 中级实验(03):模板转换实战——如何用零 Token 完成文本加工?
  4. Dify 中级实验(04):迭代进阶——如何批量处理数据并守住性能边界?
  5. Dify 中级实验(05):并行执行——如何让多路任务同时跑?
  6. Dify 中级实验(06):变量聚合——如何确定性合并多路分支结果?
  7. Dify 中级实验(07):子工作流——如何把公共逻辑做成可复用积木?
  8. Dify 中级实验(08):代码节点进阶——如何用标准库处理文件与数据?
  9. Dify 中级实验(09):HTTP 节点进阶——如何搞定认证、分页与错误重试?
  10. Dify 中级实验(10):知识库深度调优——如何科学评估检索质量?
  11. Dify 中级实验(11):高级 RAG 流水线——如何搭建多路检索与精排?
  12. Dify 中级实验(12):Agent 深度配置——如何让智能体自主调用工具?
  13. Dify 中级实验(13):多 Agent 协作——如何编排多个智能体分工干活?
  14. Dify 中级实验(14):对话变量与状态管理——如何让工作流记住多轮对话的状态?
  15. Dify 中级实验(15):条件分支高阶策略——多条件路由如何避免分支爆炸?
  16. Dify 中级实验(16):错误处理与降级——工作流如何有尊严地失败?
  17. Dify 中级实验(17):调试监控与性能优化——响应慢和 Token 超支如何定位?
  18. Dify 中级实验(18):插件开发入门——如何把工作流变成 Agent 可调用的工具?
  19. Dify 中级实验(19):综合实战——如何把 19 个实验串成一条生产级流水线?
  20. Dify 中级实验(20):综合实战——自动化报告生成流水线如何从数据到周报一步到位?

联系我

15088711270

手机端点击号码可直接拨打 · 桌面端可复制

微信二维码

扫码加微信 · 备注「门户」更快通过