Agent 工程实习复盘 15|模型能力如何贯穿上传链路:默认模型、视觉能力与文件转换契约

0 阅读11分钟

Agent 工程实习复盘 15|模型能力如何贯穿上传链路:默认模型、视觉能力与文件转换契约

本文基于 Agent 应用中模型配置、文件上传和多模态处理的一组改造整理。文中使用通用技术名称,不涉及具体项目、公司、模型供应商、密钥或用户文件。

关联工作包括默认模型显式配置、模型能力 API、上传时的模型能力校验、转换后文件路径契约,以及后台模型探测链路简化。

15c.png

一、先说结论

在多模型 Agent 应用里,“用户能不能上传 PDF”不是一个前端按钮问题,而是一个跨越配置、前端、Gateway、文件转换和 Agent Middleware 的能力契约问题。

如果这些环节各自猜测,就会出现很典型的体验断裂:

  • 页面显示当前模型支持看图,上传接口却拒绝文件。
  • 用户已切换到支持视觉的模型,预上传仍按旧模型或默认模型判断。
  • PDF 已经转换成页面图片,模型却只收到原始 PDF 路径,不知道该看哪一张图。
  • 后台探测某个模型“能连通”,产品却误把它当成“支持视觉”或“支持图片生成”。

这次改造的核心不是增加更多判断,而是把模型能力变成一条一致的事实链:配置声明能力,模型 API 下发能力,前端携带当前选择,Gateway 最终裁决,转换产物通过 manifest 交给 Agent。

二、先分清三个概念:默认模型、当前模型和能力声明

它们经常被混成一个概念,但实际职责不同。

概念含义使用场景
默认模型工作区没有显式选择时的兜底模型新会话、上传未携带 model_name、运行时 fallback
当前模型本次会话或当前输入实际选择的模型这一次上传和 Agent Run
能力声明模型是否支持视觉、思考、图片生成等UI 展示、上传校验、工具装配

默认模型不能再隐式等于配置列表的第一个元素。模型排序经常因后台操作、灰度验证或配置合并改变;一旦第一个模型变了,上传和运行时的兜底行为就会悄悄漂移。

因此配置增加显式的 default_model。解析默认模型时先看这个字段,只有旧配置没有声明时才兼容性回退到第一个已配置模型。

三、能力从哪里来:连通性不是能力证明

模型能力需要由系统配置显式声明,例如:

  • supports_vision:能否接收并理解图片或页面图像。
  • supports_thinking:是否提供可控的思考模式。
  • supports_image_generation:能否生成图片。

模型 API 会将这些非敏感字段和默认模型名一起返回给前端。前端据此决定展示什么入口、上传时附带哪个模型名;但它不拥有最终裁决权。

graph TD;
    A[模型配置];
    B[声明默认模型和能力];
    C[模型列表 API];
    D[前端模型选择器];
    E[上传请求携带 model_name];
    F[Gateway 按配置校验];
    G[Agent Runtime 使用同一模型配置];
    A --> B;
    B --> C;
    C --> D;
    D --> E;
    E --> F;
    F --> G;

这里有一个重要边界:后台探测可以检查模型地址、认证和基本调用是否可用,但它不能凭一次文本请求推断视觉、图片生成或其他复杂能力。探测用于减少配置错误;能力声明仍是产品契约,应该由管理员明确维护。

四、上传校验必须知道用户当前选的是谁

上传常常发生在真正发送消息之前。为了提升体验,前端会先执行 pending upload,再由用户确认发送。如果上传接口只读取默认模型,就会有一个竞态:

  1. 默认模型是文本模型。
  2. 用户在当前会话切到视觉模型。
  3. 用户选择 PDF 并触发预上传。
  4. 后端没有收到当前模型名,仍按默认文本模型拒绝 PDF。

因此上传 API 增加可选 model_name 参数。前端从当前模型选择状态带入该字段;后端再按下面优先级计算本次上传的有效模型:

本次 model_name > 显式 default_model > 旧配置兼容回退

不过,前端传入模型名只是提示,不是信任边界。Gateway 会检查该模型是否存在于当前服务端配置;未知模型返回客户端错误,不能通过伪造字符串绕过能力限制。

graph TD;
    A[用户选择文件];
    B[前端读取当前模型];
    C[上传请求带 model_name];
    D[Gateway 解析有效模型];
    E{模型配置存在};
    F[返回未知模型错误];
    G{文件需要视觉能力};
    H[返回能力不支持错误];
    I[保存文件并进入转换流程];
    A --> B;
    B --> C;
    C --> D;
    D --> E;
    E -->|否| F;
    E -->|是| G;
    G -->|是且不支持| H;
    G -->|否或支持| I;

五、为什么 PDF 的边界最容易暴露问题

普通文本文件可以作为文本交给模型;图片天然对应视觉输入;PDF 介于两者之间。

PDF 既可能包含可提取文字,也可能依赖表格、版式、扫描页、图表和图片。为了让 Agent 稳定理解文档,上传链路会把可转换文件处理成一组 Agent 可消费的资产,例如:

  • 从原始文件提取的 Markdown 或文本页。
  • 每页对应的页面图片。
  • 描述源文件、页序、Markdown 路径和图片路径的 manifest。

如果当前模型不支持视觉,让用户上传 PDF 并承诺完整理解页面布局是不诚实的。因此 Gateway 会在写文件和启动转换前拒绝该组合,并返回明确提示:切换到支持视觉的模型后再上传。

这不是限制用户,而是避免后续 Agent 假装看到了自己实际上无法理解的版式信息。

六、转换完成后,模型为什么还会找不到文件

文件转换不是结束,最常见的第二个问题是路径契约断裂。

早期实现容易让模型根据原文件名猜路径,例如认为 report.pdf 的页面图片一定是 report.png。这种猜测在重名文件、分页、多图、不同转换器和历史目录兼容下都会失败。

正确做法是由上传服务产出 manifest,记录真实生成的资产;Middleware 读取 manifest 后把精确路径注入本轮 Agent 上下文。模型不需要猜,也不应该扫描整个上传目录。

graph TD;
    A[上传原始文件];
    B[转换服务生成 Markdown 和页面图片];
    C[写入 manifest];
    D[Upload Middleware 读取 manifest];
    E[构造本轮 uploaded_files 上下文];
    F[模型读取精确文本路径];
    G[视觉模型按精确图片路径查看];
    A --> B;
    B --> C;
    C --> D;
    D --> E;
    E --> F;
    E --> G;

这份上下文会区分:原始文件、Markdown 文件、图片文件和 manifest 自身。对视觉模型,提示会明确哪些页面图片可以传给看图工具;对非视觉模型,至少仍可使用转换出的文本资产,而不会凭文件扩展名猜测不存在的图像路径。

七、上传与执行不是同一件事:pending 状态的意义

上传可能先于用户真正发送消息完成。pending 状态把“文件已接收并在处理”和“这批文件应当成为下一轮 Agent 输入”分开。

这样做有三个好处:

  • 用户取消输入时,可以清理尚未确认的附件和转换资产。
  • 同一轮消息可以一次确认多个已完成的附件。
  • Agent Middleware 只注入本轮确认的增量文件,不把所有历史上传重复塞进 Prompt。

能力校验发生在文件真正进入后端时,而不是等用户点击发送后才失败。这样既避免无效转换成本,也让用户在选择错误模型时立即得到可操作的反馈。

八、为什么后端还要保留最终校验

即使前端已经根据 supports_vision 隐藏或显示上传入口,后端也不能省略检查:

  • 前端代码可能尚未更新,或用户持有旧版本页面。
  • 请求可能来自移动端、脚本、外部 API 或重放流量。
  • 用户可能切换模型后仍保留旧页面状态。
  • 任何客户端字段都可以被手工构造。

因此 Gateway 是最后的能力策略执行点。前端负责尽早提示,Gateway 负责不能绕过,Runtime 负责在通过校验后正确使用产物。

九、模型探测应当简化,不应承担所有语义

后台模型管理中常见的误区是把探测流程做得过长:尝试不同请求格式、不同参数、不同工具调用,再根据某次结果推导模型是否可用。

这会让“保存配置”和“在线探测”耦合,失败原因也变得难以解释。更稳妥的拆法是:

动作解决的问题不应解决的问题
保存模型配置管理员声明地址、模型名和能力不保证上游此刻可用
最小探测请求基础连接、认证、请求格式是否通不自动推断完整能力矩阵
运行时上传校验本次模型是否允许处理该文件不替代模型健康监控

这样,模型卡片的保存语义保持确定,探测失败也不会悄悄改写已经配置好的能力声明。

十、验证:验证的是能力契约,不是上传接口 200

相关回归覆盖的重点是前后端是否对同一个模型得出同一个结论:

场景期望结果
未传 model_name 且默认模型支持视觉PDF 可以进入上传与转换流程
未传 model_name 且默认模型不支持视觉PDF 在 Gateway 被拒绝
传入当前视觉模型PDF 按当前模型能力放行
传入当前文本模型PDF 被拒绝,提示切换模型
传入不存在的模型名返回明确的 unknown model 错误
前端 pending uploadURL 包含当前 model_name 和 pending 标记
转换生成多页资产manifest 记录精确 Markdown 和图片路径
Agent 消费转换结果Middleware 只注入 manifest 中存在的精确路径
后台模型探测失败不把一次探测失败误写成能力声明变化

后端测试覆盖默认模型回退、未知模型、非视觉模型 PDF 拒绝和转换资产;前端测试覆盖上传请求是否携带当前 modelName。这些测试的重点是避免前后端各自判断、最终互相矛盾。

十一、几个看起来合理、实际会出问题的方案

11.1 用 models 数组第一个元素当默认模型

配置排序不是业务语义。只要有人调整模型顺序,上传和运行时 fallback 就会无声变化。

11.2 前端只根据模型名称写规则

用模型名字符串判断视觉能力会快速腐化:自部署模型、别名、版本更新和新增供应商都会让规则漂移。能力应来自服务端配置。

11.3 只在前端禁止 PDF 上传

脚本和旧客户端仍可以直接调接口。没有 Gateway 最终校验,能力限制不是安全或成本边界。

11.4 PDF 转换后让模型自己猜图片路径

文件重名、分页和转换器升级都会让猜测失效。manifest 才是上传服务和 Agent 的稳定契约。

11.5 一次文本探测成功就标记模型支持视觉

连通性、文本生成和视觉理解是不同能力。自动猜测容易给用户错误承诺。

十二、面试时我会怎么讲

我会这样概括:

我参与过多模型 Agent 应用的上传能力治理。问题不是单一的 PDF 校验,而是默认模型、当前选择模型、前端上传请求、Gateway 校验、文件转换和 Agent 上下文之间存在能力漂移风险。我将默认模型改为显式配置,通过模型 API 下发视觉等能力;前端预上传携带当前 model_name,Gateway 仍以服务端配置做最终校验。对于 PDF,只有视觉模型才能进入页面图片转换链路,转换后由 manifest 把精确的 Markdown 和图片路径交给 Middleware,避免模型猜路径。这样前后端对同一次上传使用同一能力事实,也避免了不支持视觉的模型假装能理解文档版式。

如果继续追问,我会补充:模型连通性探测和能力声明必须分开。前者是运维诊断,后者是产品契约。

结语

多模型 Agent 的能力不是一个静态标签。只要能力会影响上传、转换、工具调用或用户预期,它就必须从配置一路传递到运行时,并且由后端守住最后边界。

把模型能力做成可声明、可下发、可验证、可消费的契约,才能让模型切换真正成为产品能力,而不是前端换了一个名字。