一、一次回答其实是两个阶段
1.1 一个常见的困惑
不少使用大模型Token推理服务的团队第一反应是“模型太慢”,于是想换更大的算力或者更小的模型。但如果连慢在哪一段都没分清,换完之后很可能只解决了一半问题,甚至出现“首字更快、整体更慢”的错位。分开看两段,是理解一切的前提。
1.2 三个需要先说清的名词
① 预填充:模型把输入的全部内容一次性读入并建立起内部表示的过程。这一步结束后,模型才“知道自己要回答什么”。
② 解码:模型逐个生成输出片段的过程,每生成一个都要参考此前所有内容(输入加上已经生成的输出),直到遇到终止条件。
③ 首Token时延:从请求发出到第一个输出片段出现的时间,它主要由预填充与排队决定,与输出长度基本无关。
1.3 两段的资源特性几乎相反
预填充处理的是整段输入,可以分批并行推进,属于计算密集型:内容越多,算得越久,但内部的并行度也高。解码则不同,每一步只能生成一个片段,而且必须等上一步结束后才能继续,属于访存密集型:计算量不大,却要反复读取模型参数与上下文,串行程度高。一个怕长输入,一个怕长输出,这就是两段最本质的差别。
二、第一阶段:预填充在做什么
2.1 把输入整段读进来
预填充要完成任务:把输入切成片段、转成向量、逐层计算出可供后续使用的中间结果,并把这些结果保存下来供解码阶段反复使用。这一步的工作量与输入长度直接相关,输入翻倍,计算量大致也翻倍。
2.2 为什么它能并行
因为输入的每个片段都已经确定,不存在先后依赖。计算设备可以成批处理,把整段输入一起推进。这也是为什么长输入虽然慢,但慢得相对“线性”:长度增加一倍,等待时间大约增加一倍,而不是成倍恶化。
2.3 哪些输入特征会拉长这一段
① 总长度:最直接的因素,包括系统提示、检索资料、对话历史在内的一切内容。
② 检索片段的数量:知识库问答里常见的放大项,召回越多,这一段越长。
③ 内容密度:术语密集、数字与符号多的文本,切出来的片段更多,实际长度高于字数给人的印象。
2.3.1 一个粗略的估法
在接入前判断预填充压力,可以用一个简单办法:把系统提示、检索片段、历史的实际内容拼起来看总篇幅,再按最坏情况(召回全满、历史全带)取一次值。这个值决定了首字等待的上限,也决定了高峰期的排队情况。
2.4 首Token时延主要由它决定
用户在界面上感知到的“点了之后没反应”,几乎都发生在这一段。因此想改善首字体验,着力点应放在输入侧:压缩系统提示、收敛召回数量、控制对话历史长度。反过来,把输出长度调短对首字几乎没有帮助。
三、第二阶段:解码为什么一步一挪
3.1 每一步只产出一个片段
解码是按顺序推进的:生成第一个片段时,参考的是输入;生成第二个片段时,参考的是输入加第一个片段;依此类推。每一步都要把此前积累的中间结果读一遍,才能决定下一个片段。这种“边写边看”的方式决定了它无法像预填充那样整段并行。
3.2 计算量不大,读取量很大
单看每一步的计算,规模远小于预填充,真正的负担在于反复读取。模型参数与上下文中间结果需要被多次访问,读取效率成为限制速度的关键。这也解释了为什么有些场景下算力明明有余,出字速度却上不去——受限的不是算得快不快,而是取得快不快。
3.3 输出长度直接决定总时长
因为是一步一个,输出越长,总时长越长,增长基本成正比。这带来一个实用结论:控制输出长度是压缩整体耗时最直接的手段,效果往往比升级算力更明显。此前所说的“越吐越慢”,其实是因为剩余内容在变少,而每一步的固定开销不变,感知上便显得慢。
3.4 并发上升为何拉低速度
解码阶段的每一步都要读取大量数据,多个请求同时进行时,读取能力被分摊到各个请求上。结果常见的是:吞吐总量上去了,单个请求的出字速度下来了。这不算异常,而是资源在多个请求之间重新分配的结果,规划时应把“单请求体验”与“整体吞吐”分开设定目标。
3.4.1 两个目标的区别要提前说清
面向后台的处理任务,看的是每小时能完成多少,单请求慢一些无妨;面向人工交互的界面,看的是用户等多久,单请求速度优先。这两类需求若混在同一批资源里,很容易出现“为了总量牺牲体验”的情况,拆开安排更稳妥。
四、两段之间的接缝:缓存
4.1 前缀复用省掉的正是预填充
如果两次请求的开头完全一致,那么开头部分的中间结果可以直接复用,不必重算。这让预填充的工作量大幅减少,首字明显更快。多轮对话、同一份文档的多次提问,都是受益场景。
4.2 缓存生效的三个前提
① 前缀一致:从第一个片段开始就必须相同,中间插入任何变动都会让后续失效。
② 未被淘汰:缓存占用有限,长时间不用的内容会被清理。
③ 同一模型:换到另一个模型,缓存的中间结果不能通用。
4.2.1 一条实用的写法约定
把提示分成固定的三段来写:第一段是角色与规则,永远不变;第二段是场景资料,按需替换;第三段是本次问题,每次不同。顺序固定之后,前两段在多次请求中能稳定复用,缓存命中率自然提高。
4.3 多轮对话里缓存为何常常失效
常见原因是把动态内容放在了最前面。比如系统提示开头带上了当前时间、会话标识,或者每轮都在开头拼接用户信息,前缀一变,后面全部作废。比较稳妥的写法是把稳定内容放前面、变化内容放后面,让可复用的部分尽量长。
五、四个常见现象的解释
5.1 长文档问答:首字慢,之后顺畅
整篇文档进入预填充,开头自然要等;输出通常不长,解码负担有限。这类场景的优化重心在输入侧,把文档切分得当、只送相关段落,效果最直接。
5.2 长文生成:首字快,整体耗时高
输入很短,预填充几乎没有负担;输出很长,解码一路推进。这类场景的优化重心在输出侧:设定长度边界、明确答完即止、把格式要求写清,比提升算力更有效。
5.3 同一请求两次耗时不同
三个来源:一是缓存是否命中,命中则首字快很多;二是当时的并发状况,解码阶段的读取能力被分摊;三是排队位置,高峰期可能需要等前面的请求。想让结果可比,比较时需把这三项条件对齐。
5.4 加了并发反而更慢
原因在解码段。并发提高后,各请求在读取环节相互竞争,单请求速度下降。此时应区分目标:面向海量短请求的后台处理,追求整体吞吐是合理的;面向人工交互的前台应用,单请求体验优先,盲目提并发只会让体验变差。
六、按阶段着力的六个优化点
6.1 影响预填充的三个点
① 精简固定内容:把每次都要带的说明压到最短,能放到流程里的细则不要塞进提示。
② 稳定前缀:把不常变的内容放在最前,让缓存有机会生效。
③ 收敛检索与历史:召回够用即可,历史按话题截断,避免把无关内容一起送进去。
6.2 影响解码的三个点
① 约束输出长度与终止条件:给明确边界,避免无意义的收尾段落。
② 批量与优先级搭配:后台任务合并处理以提升总量,前台交互优先保障单请求速度。
③ 按任务选模型档位:不是所有任务都需要最强模型,常规任务用轻量档位,解码负担自然下降。
6.2.1 参数调整的先后顺序
建议的顺序是先定输出边界,再定模型档位,最后才调批量与并发。前两项一旦确定,耗时的量级基本就定了;批量与并发影响的是分配方式,放在后面调整,观察起来也更清楚。
6.3 两段之间的取舍
两段的优化有时相互牵制:把输入压短能改善首字,但可能让模型缺少必要背景,输出变长、反复追问;把输出压短能改善整体,但可能答不完。务实的做法是先测出两段各自的耗时占比,再决定往哪边用力,而不是两头同时收紧。
七、天翼云息壤在两侧的支撑
7.1 推理加速与请求合并
息壤模型推理服务在推理链路上做了工程化处理,通过请求合并与批处理提升整体处理效率,缓解解码阶段在高并发下的读取压力。对于后台批量任务,这类处理能明显改善总体完成时间。
7.2 上下文复用减少重复计算
针对前缀一致的场景,缓存与上下文复用机制可以减少重复的预填充工作,让多轮对话与同一文档反复提问的首字更快。使用方把稳定内容前置,配合这一机制效果更好。
7.3 弹性供给与调度
平台支持按需调整资源规格,配合统一调度与就近接入,缓解高峰期的排队。对两段耗时占比不同的业务,可以据此选择更匹配的规格,而不是一味加大。
7.4 记录与观测
请求级的记录可用于回看耗时分布与用量情况,为“先测占比、再定方向”提供依据。缺少这类记录时,优化很容易变成凭感觉调整。
7.5 安全合规与公开可查的信息
在数据传输、权限管理与合规方面有相应机制。关于大模型Token推理服务的具体能力、覆盖范围、实践案例与所获认可,均以天翼云官网和官方渠道发布的信息为准,本文不作超出官方口径的表述,建议在评审时按需核对。
八、科普小结
把一次回答拆成预填充与解码两段,很多看似矛盾的现象就有了统一的解释:首字慢是输入太长,出字慢是输出太多,两次耗时不同是缓存与并发在变,加并发更慢是解码段的读取能力被分摊。理解这层机制之后,优化不再靠试,而是先测出两段各占多少,再决定压输入还是压输出。这也是大模型Token推理服务从“能用”走向“好用”的分水岭。