用户还来不及核实多模态模型的结论,预签名 URL 就已过期
用户打开了昨天的对话。在支持专员的回复旁边,原本上传收据的地方显示为一个破碎的图片占位符。回复中自信地引用了“3 月 14 日在 Coffee Tribunal 商店消费的 47.32 美元”。用户无法检查该引用是否准确,因为模型赖以工作的证据现在来自你对象存储的 403 错误。他们提交了一个“幻觉”工单。你的评估套件没有发现这个问题,因为在调用时,模型的回答确实是完全正确的。
这是一个关于“保留策略不匹配”的故事,而不是模型质量的问题。你的对话记录比它的事实依据(grounding)活得更久。事实依据是一个只有 15 分钟有效期的预签名 URL,而关于该依据的断言则是会存放在你数据库中多年的文本。当资源时钟(asset clock)和断言时钟(claim clock)以不同的速度运行时,任何有据可查的多模态答案在重新访问时,最终都会看起来像是凭空编造。
大多数首次发布多模态功能的团队都会沿用现有文件上传流程中的预签名 URL 模式。该流程设计之初只有一个目的:向浏览器提供一个临时的链接来下载用户拥有 的图像。它从未被设计为支持模型推理的持久证据。但让“模型看到这张图片”最简单的路径就是传递浏览器已经拥有的那个 URL,而让“用户重新访问对话”最简单的路径就是在对话记录中嵌入该 URL。这两个决定单独看来都是合理的。但结合在一起,它们构建了一个审计追踪系统,使得模型在 15 分钟后看起来就像个骗子。
为什么你的评估套件永远无法发现这一点
对于任何将多模态调用视为单一“请求-响应”事务的评估设计来说,这种资源过期失效模式都是不可见的。你的评估套件生成一个预签名 URL,将其交给模型,捕获响应,评分,然后丢弃该 URL。在整个测试过程中,该 URL 都是有效的。评估当然会通过。即使你出于安全原因将 TTL(生存时间)从一小时缩短到 15 分钟,评估依然会通过;因为评估从请求到响应的时间间隔是以秒计的。
这个 Bug 只有在“对话回放”时才会显现,而这正是评估不会覆盖的路径。要捕捉它,你需要一个评估切片,在数小时后加载存储的对话记录,并验证每个多模态引用是否仍能解析。大多数团队不会构建这个切片,因为从请求处理程序的角度来看,这种失效模式是不可见的——请求成功了,响应是正确的,唯一“损坏”的是两个产品层面之外的一块 UI 状态。
这与后端测试在全新数据库上通过、生产部署在全新部署上通过,而回归测试只在客户六个月前的账户中出现的 Bug 形式相同。信号存在 于时间维度上,而以请求为作用域(request-scoped)的测试无法察觉到它。你的评估套件测量的是错误的指标:它根据图像对模型的响应进行评分,但用户面临的问题是响应与用户仍能看到的图像之间的背离。这是不同的指标,而只有后者才是你的客户在提交工单时所经历的。
你系统中运行的两个时钟
每个多模态产品都在针对同一个对话运行两个时钟,而大多数团队从未将它们定义为独立的问题。
第一个时钟是资源可用性时钟。它是预签名 URL 的寿命、对象的存储策略、CDN 缓存,以及浏览器在上传期间创建的任何客户端 Blob URL。AWS 允许预签名 URL 的有效期从 60 秒到 7 天不等,大多数安全审查都会促使团队选择该范围的短端,因为有效期较长的泄露 URL 意味着更长久的风险。15 分钟是一个常见的平衡点——足够应付缓慢的客户端重试,又短到让人感到安全。
第二个时钟是对话断言时钟。它是你保留对话记录的时间。在消费级产品中,这可能是几个月。在受监管的 B2B 产品中,这通常是受合规性驱动的多年的保留周期——根据 SEC 和 FINRA 的规则,金融服务公司会将经纪人的聊天记录保留多年,医疗健康产品通常也会从 HIPAA 框架中继承类似的保留要求。重点是,断言的寿命比资源的寿命长了几个数量级。
架构上的错误不在于运行这两个时钟。错误在于将 URL(一种临时凭证)与资源(一个持久工件)混为一谈,并将前者存储在承诺后者持久性的地方。当对话记录渲 染一个指向已过期 URL 的 <img src="..."> 时,系统是在告诉用户“这张图片是永久的”,而 URL 却在告诉浏览器“这张图片在 15 分钟前是永久的”。这种矛盾就是 Bug 所在。
为什么这看起来特别像幻觉
用户对于幻觉的成因有一套非常一致的心理模型。当模型给出具体且自信的说法,而用户无法验证时,用户就会认定模型是在瞎编。当素材丢失时,这一模式的每一个环节都会被触发:
- 模型给出了具体信息:“Coffee Tribunal,$47.32,3 月 14 日”。多模态模型往往比纯文本模型更具象,因为提示词要求它们描述图像,而“描述”本身就是一种对具体性的强烈邀约。
- 用户无法验证:图像切片已损坏。没有证据可以进行交叉比对。
- 用户认定模型是瞎编的:根据用户所能看到的情况,这是唯一合理的解释。由于模型当时是正确的这一事实无法从用户现有的产物中恢复,真相也就无从考证。
关于幻觉检测和缓解的文献建议“通过要求引用并让模型通过寻找支持性引文来验证每项声明,使输出具有可审计性”。但引用的持久性取决于其引用的对象。如果引用指向一个预签名 URL (presigned URL),那么引用就会继承该 URL 的有效期。你的审计追踪记录的寿命,取决于其中最短命的链接。
还有第二个更微妙的影响:这种失败模式会训练你的用户不信任正确的输出。如果一位客户提交了三张关于“幻觉”的工单,结果发现全都是因为素材过 期引起的,那么在第四次遇到引用具体细节的多模态回答时,他将不再信任。产品界面在无形中制造了一种系统不可靠的错觉,而实际上,按照模型质量标准,系统一直表现正常。这种感知很难消除,因为证明模型正确的唯一方法就是向用户展示素材,而素材已经不在了。
真正弥合这一差距的方法
修复方法并不是“让预签名 URL 永久有效”,否则安全团队缩短其有效期的所有理由都将面临风险。修复方法是停止在转录记录中存储请求时的 URL,转而存储一个指向素材的引用,渲染层可以在查看时将其解析为新的 URL。
这种方案的最小可行化形式是为每个对话建立一个素材表,记录一个稳定的内部标识符、指向存储对象的指针,以及决定当前查看者是否有权查看所需的任何访问控制元数据。转录记录存储标识符,绝不存储 URL。当渲染转录记录时,渲染层会针对底层对象发布一个新的预签名 URL。URL 始终是新鲜的;素材本身的保留策略决定了图像实际可用的时长。
该策略是修复方案的另一半。素材的保留时间必须至少与引用它的模型输出的保留时间一样长。只要引用该收据描述的转录记录仍可查询,收据图像就不能过期。这在你使用的任何对象存储中都不是默认行为;你必须显式强制执行,要么在模型调用结束时将素材提升到具有更长保留期的存储桶中,要么在清理时将素材的 TTL 与转录记录的 TTL 绑定作为连接条件。无论哪种方式,删除素材都变成了一个“是否仍有声明指向它?”的问题, 而不是“上传任务本身的倒计时是否结束?”的问题。
接下来一个微妙的步骤是在请求时将图像字节与模型的描述一起保存为取证快照 (forensic snapshot)。这并非针对常见情况——对于常见情况,针对同一底层对象重新生成新鲜 URL 就足够了。这是为了应对模型看到图像后,底层对象被替换或修改的情况。如果用户上传了版本 1,模型描述了版本 1,随后用户在同一个键名 (key) 下重新上传了一个不同的文件,那么重新生成的 URL 提供的将是版本 2。审计追踪显示“模型描述了 $47.32”,而重新加载的图像显示的却是另一个数字。为了区分“素材在我们眼皮底下变了”和“模型错了”,你需要一个模型调用发生时的快照。对于许多产品来说,这可能有些过度,但对于那些模型输出将作为监管机构后续审查证据的产品来说,这正是正确的工程纪律。
渲染层需要针对素材真正丢失的情况采取相应的处理措施——无论是被用户删除、策略过期,还是因其他原因无法恢复。错误的做法是静默显示一个损坏的图像切片,因为这正是产生“疑似幻觉”工单的原因。正确的做法是在描述旁边显式提供一个功能入口,提示:“此图像已不可用;下方的模型描述是其在请求时观察到的内容”,并附上素材失效的时间戳。这会将用户的理解从“模型造假”重塑为“证据已被清理”。这是两种完全不同的支持工单,而且只有后者才是准确的。
架构层面的实现
多模态模型的 grounding 只有在 grounding 证据比模型对其作出的陈述存续更久时,才是持久的。这是一 个关于资产保留的陈述,而非关于模型行为的陈述,它完全存在于你的存储和渲染层中。
能够自信交付多模态功能的团队,会将资产、调用记录和转录文本视为一个单一的持久制品,其保留策略由高于任何单个组件的层级决定。而那些交付了多模态功能后又花了六个月处理幻觉工单的团队,则将上传 URL 视为请求参数,将描述视为单独的数据库行,并接受由此产生的偏移,因为没有任何单个组件出错。
检验你属于哪种团队最直接的方法,是在你自己的产品中打开一个六个月前的对话,并查看其中的多模态对话轮次。如果图片仍然存在,且描述仍然与你所见的内容相符,那么你的保留策略是连贯的。如果图片已经损坏,而描述读起来像是模型在对不存在的图片细节产生幻觉,那么这种失败模式已经存在于生产环境中,支持工单也即将接踵而至。幻觉根源于你的存储架构,而模型却在为此背锅。
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html
- https://docs.aws.amazon.com/pdfs/prescriptive-guidance/latest/presigned-url-best-practices/presigned-url-best-practices.pdf
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html
- https://fourtheorem.com/the-illustrated-guide-to-s3-pre-signed-urls/
- https://docs.aws.amazon.com/prescriptive-guidance/latest/presigned-url-best-practices/overview.html
- https://docs.vllm.ai/en/stable/features/multimodal_inputs/
- https://www.lakera.ai/blog/guide-to-hallucinations-in-large-language-models
- https://www.kdnuggets.com/7-ways-to-reduce-hallucinations-in-production-llms
- https://launchdarkly.com/blog/catch-ai-hallucinations/
- https://www.datadoghq.com/blog/ai/llm-hallucination-detection/
- https://www.digisoftsolution.com/blog/ai-chatbot-conversations-archive
