做多模态工作流,麻烦的往往不是调通某个模型,而是把图片、语音、文本几路输入串成一条稳定流水线:哪一步该放哪个节点、失败了谁来兜、换模型要不要重写。这篇不吹框架,只给一套选型尺子和节点编排的实操顺序,照着列清单,一小时能把骨架定下来。
做多模态工作流,真正烦人的通常不是某个模型调不通,而是图片、语音、文本几路输入进来之后,怎么串成一条不容易断的流水线。哪一步该放哪个节点、失败了谁来兜、换掉一个模型要不要整条重写,这些才是天天要面对的事。
这篇不讲抽象概念,只给一套能照着走的判断标准:先想清楚要不要框架,再用几条硬尺子挑框架,然后按「可重跑」拆节点、把节点之间的数据契约定死,最后补上成本与延迟的兜底。照着列一遍清单,骨架基本能定下来。
先判断:你到底需不需要一个工作流框架
很多人一上来就挑框架,其实是把顺序搞反了。先问一句:这条链路有几个模型、有没有分支。只有一条固定链路、调用不超过三个模型时,直接写脚本再套一层重试封装就够了,引框架反而多一层调试成本,出问题时你还得先搞清是框架的问题还是自己的问题。
反过来,一旦出现按输入类型分流、多路并行、人工审核卡点,或者需要把流程画出来给不写代码的同事看,编排能力才开始划算。判断标准可以很土:一周内流程改动超过三次,或者非开发同事也要看流程长什么样,就上框架;否则先别上。
- 只有一条固定链路、模型不超过三个:脚本加重试封装,别引框架
- 有按输入类型分流、多路并行、人工审核:框架的编排能力开始回本
- 一周改流程超过三次,或非开发同事要读流程:可以上框架
- 延迟极度敏感、单次请求预算很紧:框架的调度开销要单独测,别默认它没成本
- 数据不能出内网:先看能不能自托管,不能就直接排除,这一条不看别的
框架选型看四条,不看宣传
挑框架只看四条硬指标,宣传页上的功能列表基本不解决问题。第一条是节点能不能自定义:多模态要接 ASR、图像理解、TTS 这些非标准节点,框架必须允许你自己写一个节点塞进去,只能用它内置的那几种,后面一定卡住。
第二条是状态与重试模型:失败是整条重跑还是只重跑当前节点,中间产物(转写文本、切好的图)存不存、存哪,这直接决定你后面排障要花多少时间。第三是可观测性,每个节点能不能单独看输入输出和耗时,没有这个,链路一慢你只能靠猜。
| 选型维度 | 要确认的点 | 什么情况下一票否决 |
|---|---|---|
| 节点自定义 | 能否写自定义节点接入 ASR、图像理解、TTS | 只能用它内置节点 |
| 状态与重试 | 失败重跑粒度、中间产物存在哪 | 只能整条重跑且无中间产物 |
| 可观测性 | 单节点输入输出与耗时能否单独看 | 只有整条链路的日志 |
| 部署形态 | 能否自托管、依赖哪些外部服务 | 数据必须出内网 |
补充一点:把这几条列成表,逐个框架过一遍,比看十篇上手教程都有用。想到 横向比一遍再决定,路径见下方 CTA,别只用第一篇教程里出现的那个框架。
节点怎么拆:按「可重跑」而不是按「功能」
新手最容易按功能拆节点,结果一个节点里塞了下载、转写、清洗、调用模型四件事,挂掉就得整段重来。正确思路是按可重跑拆:一个节点只做一件事,它的输入输出必须是能落地的数据,文件或结构化 JSON 都行,这样中间任何一步挂掉,都能从上一个产物接着跑。
慢且贵的外呼单独成节点,比如图像理解、语音合成,方便加缓存和失败重投,不要和纯本地处理混在一个节点里。判断边界有个土办法:这个步骤单独跑一次要花多少钱、多久,说不清的,就是拆得不够细。
- 先列产物清单把链路里每一步的输入和输出写成文件或 JSON,能落地才算一个合格的节点边界。
- 把外呼单独拎出来图像理解、TTS、ASR 这类慢且贵的调用独立成节点,方便加缓存、限流和失败重投。
- 人审当成普通节点别把人工审核做成特例,当成普通节点处理,后面加第二个审核点就不用改结构。
- 并行与串行取舍彼此不依赖的节点并行发出,但并发数要受上游限流约束,别一把全放出去。
- 验证可重跑手动让中间某个节点失败一次,确认能从上一个产物继续,而不是整条重来。
节点之间传什么:先把数据契约定死
多模态最容易出岔子的地方就是节点之间传的东西。上游输出的字段名、类型、必填项要提前定好,图和音频的元信息尤其要写清楚,比如时长、采样率、分辨率、mime 类型,少写一个下游就可能拿到脏数据。
再给每个节点加一个显式的失败状态和失败原因字段,下游看到失败状态直接短路,不要让它拿着半截数据往下跑。长文本和二进制内容不要塞进节点间传参,走对象存储或本地路径传引用,否则日志和调试都会很难看。
- 字段名、类型、必填项提前定死,别靠约定俗成
- 图音元信息写清楚:时长、采样率、分辨率、mime 类型
- 每个节点带失败状态和失败原因,下游据此短路
- 大内容传引用不传本体,走路径或对象存储
- 模型的输出也按契约约束,稳定返回格式的做法可以去提示词与结构化输出那类页面看
把模型输出也当成一种节点契约来约束,是这一步的关键。模型偶尔多吐一句话、少一个字段,都可能让下游解析失败,提前用结构化输出的方式兜住,比事后写一堆 try-catch 划算。
编排里的兜底:成本、延迟和跑飞控制
多模态链路的成本比纯文本链路难控,一个环节失控整条就烧穿。每个节点设步数上限和重试上限,重试带退避,无上限的自动重试在多模态链路上尤其危险。整条链路再设一个总超时和总花费上限,超了整体失败并记录,别让它在后台慢慢烧。
自动降级可以配:某个模型不可用时切到备用节点,但要接受质量会变,切完必须有一步校验或人工抽检,否则你只是把故障从报错变成了静默的坏结果。先量基线再优化,把各节点的真实延迟量一遍,再决定哪一步值得做缓存或替换。
| 兜底项 | 怎么设 | 超了怎么办 |
|---|---|---|
| 单节点重试 | 设次数上限,带退避间隔 | 标记该节点失败,交下游短路 |
| 链路总超时 | 按最慢路径的合理倍数设 | 整体判失败并记录 |
| 链路总花费 | 按一次任务的预算上限设 | 中止并告警,别后台继续烧 |
| 模型降级 | 配备用节点,切换后要有校验 | 抽检质量,不合格则回退报错 |
延迟基线别凭感觉,到站内工具页面量一遍真实数字再决定优化顺序,哪些节点值得缓存、哪些值得换,一目了然。
下一步想要横向比框架、查各节点的真实延迟基线,可以直接去这两个页面看当时的数字和条目,比只看一篇教程靠谱。→常见问题
多模态工作流一定要用可视化拖拽的框架吗?
不一定。可视化最大的价值是给非开发同事看懂流程和加人审卡点。如果你只是自己跑批量任务,代码加配置文件反而更好维护、更好做版本管理。判断点在于流程需不需要给别人看、需不需要经常改结构,两条都不满足就别为可视化买单。
节点拆得越细越好吗?
不是。拆得越细,节点间的传递、序列化和失败处理的开销就越多,排障也要跳更多地方。合适的分界是「这一步需要单独重跑或单独计费」。如果两个步骤永远一起成功、一起失败,也没必要拆开,合成一个节点更省事。
换掉其中一个模型,整条工作流要重写吗?
如果节点之间定好了数据契约,换模型通常只动那一个节点:把新模型的输出映射成同样的字段就行。真正会逼你重写的是两件事,一是新模型输出结构变化太大又不做适配层,二是它的延迟或并发特性改变了整条链路的编排方式,比如从同步改成异步任务。