09 - 通用框架怎么 serve 多模态
点单机器人加了个新功能:用户可以拍一张菜单照片,问「这个有什么推荐」。
你手上的推理框架(vLLM 或者 SGLang)本来就支持图片输入,所以这事看起来只是换个请求格式。上线之后你发现两个怪现象:
第一个:同一个用户对着同一张菜单连问五个问题,五次请求耗时几乎一样。按理说第二次开始那张图不用再算了 —— 文本那边不是有前缀缓存吗,一样的开头能直接跳过。图片这边好像完全没生效。
第二个:只要有带图的请求进来,那一瞬间所有正在打字的用户都会卡一下。看监控,GPU 有个尖峰。
两件都不是 bug,是多模态请求在框架内部走的路跟纯文本不一样。这一篇讲通用框架为此加了哪些东西 —— 它们是所有多模态服务的公共底座,包括后面 SGLang-Omni 那套。
一、多模态请求多出来的四步
纯文本请求进到框架里,路径很短:分词、预填充、逐字解码。带图片或音频的请求在最前面多插了四步,而开场那两个怪现象分别出在第三步和第四步上。
先看这四步各自在干什么、各自会怎么坏:
二、内容哈希
现在来解开场那个「同一张图问五遍,五遍一样慢」的谜。
纯文本的前缀缓存是这么工作的:把请求的 token 编号一个个比过去。
如果前 500 个跟上一个请求一样,那这 500 个的计算结果直接拿来用就行,不用重算。省下的是实打实的。
图片这边为什么失灵?回到 02 篇:一张图进到序列里,占的是几百个占位符。占位符只是个「这里将来要填图」的记号,它的编号是固定的那一个,跟图的内容毫无关系。
于是问题来了 —— 你上传菜单 A 和我上传菜单 B,展开出来的占位符序列完全相同。缓存一比对,「前缀一样」,于是它把 A 的计算结果给了 B。
把两个用户的请求并排画出来,问题一眼就看见了: