跳转到主要内容

多模态追踪:当各种模态必须共享一个 ID

阅读需 1 分钟Tian PanTian Pan

一位用户拨通了你的客服 Agent。他们说话,Agent 倾听,用户在通话中途上传了一张错误截图,Agent 同时对图片和转写文本进行推理,最后通话以一封总结修复方案的邮件收尾。三天后用户投诉过来:修复没有生效,邮件也从未送达。你打开可观测性栈,发现三个独立 UI 里躺着三条互不相干的追踪。语音流水线给你一条 ASR 追踪。视觉流水线给你一段图片上传的 span。LLM 调用给你一条带 token 数和工具调用的聊天追踪。这些仪表盘里没有任何东西告诉你:它们其实是同一次对话。

这就是没人愿意写的那种复盘。不是因为数据缺失——每一个模态都老老实实记录了它该记录的东西——而是因为跨模态的"接合"从来就没建起来。每条流水线都从自家模型供应商默认配置里长出了自己的追踪约定,而把它们绑在一起的那一次对话轮次,只存在于设计这个 Agent 的那位工程师的脑子里。

多模态首先是一个追踪问题,其次才是一个建模问题。我们花了两年时间争论哪个模型能同时处理文本、像素和波形,几乎没花时间争论:当它真的这么干的时候,我们怎么调试。结果就是这一代生产级 Agent——happy path 上跑得漂亮,可一旦有人需要回溯实际发生了什么,立刻变成考古项目。

那棵忘了根的 span 树

分布式追踪是建立在一个干净的心智模型之上的。用户点了一下。一个根 span 打开。每一个下游调用都成为一个子 span。父子关系刻画了执行层级,三个月后你能调出这条追踪,看到完整故事。

多模态流水线在大多数团队还没察觉的地方破坏了这个模型。音频开始流式传输的那一刻,语音子系统打开自己的根 span。图片通过另一个通道到达时,视觉子系统打开自己的根 span。当编排器终于触发一次 chat completion,LLM 调用又打开自己的根 span。这些子系统每一个都是由不同团队、用各自 SDK 自带的默认值进行埋点的,没有谁被告知:它们其实都是同一次对话轮次的孩子,而那一次轮次在任何地方都没有表征。

你最后得到的是三棵 span 树,本来它们应该是同一棵树的三条分支。语音追踪有 ASR 延迟和轮换节奏的详尽时序数据。视觉追踪有图片二进制工件和编码流水线。LLM 追踪有 prompt、响应和工具调用。统一它们的那段对话不是 span,甚至不是一个 header。它只是一个事实,存在于你的代码里,而你的遥测管线里没有任何东西知道这个事实本应顺流传递下去。

W3C 的 traceparent header 正是为这种缝合而设计,但它是为通过 HTTP 流动而设计的。当你的模态边界并不是 HTTP 边界时——音频走 WebRTC 管道在流式传输,图片走另一个独立的上传通道,而 LLM 调用是唯一拥有 HTTP 请求可以挂 header 的环节——这套标准的传播机制就悄无声息地失效了。修复办法不是技术性的。修复办法是认识到:你流水线中的每一个模态边界都是上下文可能丢失的地方,要把每一次穿越都当作一次网络调用来埋点。

对话轮次才是真正的工作单元

多模态 Agent 中真正重要的"跳"不是 span,而是轮次。一个轮次是对用户而言有独立意义的最小交互单元:用户说话、Agent 倾听、Agent 思考、Agent 回应。在那个轮次内部,Agent 可能转写音频、检索文档、查看图片、调用工具,并生成一段合成回复。用户并不把这些感知为彼此独立的事件。对用户来说,这一轮要么成了,要么没成。

语音可观测性平台已经开始把轮次视作一等原语——把音频输入、转写候选、prompt 执行、工具调用和合成语音作为一条相互关联的记录来记录。这是正确的抽象,而且它能从语音推广出去。一个多模态轮次就是用户做了什么、以及 Agent 回应了什么,全部串在一个能跨越这一轮所触及的所有模态而存活下来的 ID 之下。

要点是:在用户动作边界处铸造这个 ID——在任何子系统有机会打开自己的 span 之前的那一刻——并把它作为不透明的元数据穿过每一种模态的中间表示。音频帧带上轮次 ID。图片上传带上轮次 ID。工具调用带上轮次 ID。缓存写入带上轮次 ID。LLM 调用最终发生时,它继承轮次 ID。当追踪 UI 加载时,每一个打上这个 ID 标签的 span 都按用户实际经历的顺序排列在同一条时间线上。

这件事比听上去更难,因为轮次 ID 必须在每一个模态把数据移交给另一个模态的地方都能存活下来。视觉流水线吃进一张图片,吐出一个特征向量和一段描述;这两者都得把轮次 ID 向 LLM 一路携带过去。ASR 流水线吃进音频,吐出转写;转写也得带上轮次 ID。负责这些流水线的团队往往没有动力去穿一段他们自己根本不消费的元数据,而消费它的 Agent 团队,只有在有人请他们从日志里重建一次轮次时,才会发现这条缺口。

模型到底看到了什么

最糟糕的多模态复盘是那种最终答案为"我们不知道"的复盘。你有 LLM 的响应。你有用户的投诉。你没有用户上传的图片,因为它进了视觉流水线的 bucket,按自己的留存周期被清掉了。你没有音频,因为它进了 ASR 厂商的存储,你从来没拿过副本。你只有 ASR 产出的转写,而它未必准确反映音频里真正说了什么。

会员专享

余下内容仅对会员开放。

会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。

  • 完整文章,包含未公开存档的部分
  • 可落地的工作框架,附带权衡与决策依据
  • 新文章抢先看,先于公开发布

随时取消 · 一次订阅,畅读全部

参考资料

保持联系,关注我获取更多内容

阅读需 10 分钟

Agent 调试器没有断点:为什么追踪优先工作流正在取代单步执行

当输入具有随机性时,单步调试就会失效。替代方案是基于追踪和重放的工作流,它具有四种功能——时间轴拖动、分支对比、扰动重放以及每一步的意图恢复——这些功能与 IDE 的调试工具栏完全不同。

insider
ai-engineering
阅读需 11 分钟

工具重入:你的函数调用层尚未察觉的 Bug 类别

函数调用层默认采用“即发即弃”模式,既没有调用栈也没有环路检测器——其代价体现在随着工具库的增长,单个请求的 Token 消耗量会不断攀升。

insider
agents
阅读需 11 分钟

你的智能体追踪在撒谎:LLM 智能体的基数、采样与 Span 层级结构

分布式追踪最初是为每个请求约 10 个 Span 设计的。而单个智能体运行可能会产生数百个 Span,默认的 OpenTelemetry 配置会系统性地漏记工作负载。本文将介绍能够经受住生产环境智能体工作负载考验的 Span 层级、尾部采样策略以及 Payload 处理方式。

insider
observability
阅读需 11 分钟

代理墙钟预算:一场与工具超时机制的赛跑

在代理技术栈内部,代理的时钟与工具的时钟几乎从未共享同一个零时刻 (t-zero)。当它们的预算发生偏差时,一个耗时 8 秒的工具调用可能会撞上 7.9 秒的截止期限,导致框架针对一个它从未见过的“成功”结果进行重新规划。

insider
agents
阅读需 11 分钟

供应商将你的模型标识符重定向到特定租户的微调模型,而其他人使用的却是基础模型

如果将 LLM 模型标识符视为权重的名称而非路由决策的标签,那么供应商可能会在评估套件仍保持“绿色”通过状态时,静默地将你的租户从微调模型切换回基础模型,导致客户最先察觉到问题。

insider
llm