每家厂商到底吃什么输入格式:文本、图片 URL、Base64 与文件片段
多模型聚合 API 里最容易被忽略的坑,是不同后端对 content 数组的接受程度并不一致:你按 A 家写法传的图片 part,到了 B 家可能被静默丢弃,模型照样回你一段像模像样的文字,但你根本不知道它其实没看到图。本文按「内容块类型」这条线索,把文本、图片 URL、Base64、文件片段四类常用输入逐层拆开,讲清楚聚合层做格式转换时哪些字段会保留、哪些字段会掉,并给出一套可复用的自查方法。
为什么同一个 content 数组,换一家后端就失灵
在聚合站里,你调用的其实是同一套 HTTP 接口,但请求最终会被路由到六家不同厂商的后端。问题在于:把「多模态输入」序列化成 JSON 这件事,各家并没有统一标准。
- 有的后端只接受字符串形式的 content,任何数组都会被拍平成纯文本;
- 有的接受数组,但只认
text类型的 part,遇到image_url直接跳过; - 有的支持图片,但只接受 URL,不接受内联 Base64;
- 有的对文件片段(PDF、文档摘录)有独立字段,位置和命名都不一样。
聚合层通常的职责,是在请求发出前把一种通用形状「翻译」成目标后端认识的形状。翻译不了的部分,常规做法是丢弃而不是报错——因为报错会让大量正常文本请求也失败。这就是静默丢弃的来源。
四类内容块,各自的兼容性风险
1. 纯文本 part
风险最低。几乎所有后端都接受 {"type": "text", "text": "..."} 或等价的纯字符串。
需要注意的只有两点:
- 当后端只认字符串时,聚合层会把多个 text part 拼接起来,中间插入的分隔符各家实现不同;
- 如果你依赖 part 之间的边界来控制模型输出结构(比如「第一个 part 是系统约束,第二个是数据」),拼接后这条边界就消失了。
2. 图片 URL
这是最容易出现「看起来成功、实际没生效」的一类。
- 支持的后端会真的去拉取这个 URL,因此 URL 必须对目标后端可访问。指向内网、需要鉴权、或带签名的临时链接,可能在层与层之间失效。
- 不支持的后端会忽略整个 part。你得到的回答仍然通顺,但所有关于图片的提问都会变成模型在凭空猜。
- 还有一种半支持情况:接受 URL,但对图片的尺寸、数量、格式有额外约束,超出的部分被裁剪或跳过,且不返回任何提示。
判断是否真的被读取,一个实用做法是在请求里附一个只能从图中得到的事实,让模型复述。复述不出来,就是没读到。
3. Base64 内联图片
Base64 的兼容性通常比 URL 更差,原因很直接:它把请求体撑大,后端要么在网关层被体积上限截断,要么干脆不支持这种传输方式。
- 体积越大,越容易在链路的某一跳失败;失败表现常常是整段请求被拒,而不是安静地丢掉图片。
- 有些后端接受 Base64,但要求显式的 MIME 类型前缀;前缀写错时,行为可能是报错,也可能是当作空图片。
- 用 Base64 时,重试成本高,因为每次重试都要重传整个体积。
实践上,如果目标后端支持 URL,优先用 URL;只有当你无法提供一个可被外部访问的地址时,才退回到 Base64,并且尽量在传输前压缩。
4. 文件片段
文件片段的定义最模糊:它可以是一段被抽出来的文本,也可以是一份被编码的文档,还可以是带页码引用的结构化摘录。
- 如果它本质上是文本,那它和 text part 一样安全,只是语义标签会丢。
- 如果它是二进制文档,兼容性取决于后端是否原生支持文档解析。不支持的会跳过,支持的则可能对页数、大小有限制。
- 同一个「文件」概念,在不同后端的字段名和嵌套层级往往不同,聚合层需要做映射;映射不到就是丢弃。
一个可复用的自查流程
与其记住每家的细节,不如在接入时跑一遍固定流程:
- 先用纯文本请求打通,确认 key、路由、计费都正常。
- 再单独加一个图片 URL part,并在提示里要求模型回答一个只有看图才知道的事实。
- 换 Base64,重复第 2 步,观察是否报错、是否变慢、是否结果变差。
- 最后加文件片段,同样用「只有读了文件才知道」的问题来验证。
- 每换一个后端,重跑这五步。
把这套流程写成脚本,返回结果里包含「是否读到素材」的判据,就能在几分钟内摸清一把 key 背后各后端的真实能力边界,而不是靠猜。
计费与失败的现实
需要提醒的是,静默丢弃不会让你少付钱。请求按输入内容计费,被丢弃的 part 如果在发送前仍计入 token 估算,成本照样发生,但你得到的是没有用到这些素材的回答。
因此,把「输入格式兼容性」当成一次性的接入工作,比当成运行时碰运气要划算得多。在聚合场景下,先验证、再依赖,是比任何提示词技巧都更稳的做法。