第一次看到“HOMURA”这个名字,基本都会被问一句:这又是什么缩写?其实不是缩写,就是我们内部给项目起的代号。这个项目做的是面向时间受限场景的LLM翻译强化学习优化,最终拿到了某国际NLP会议的Oral。用一句话解释,就是让大模型在“没时间犹豫”的翻译场景下,通过强化学习把每一毫秒的推理预算都花在刀刃上。如果你正在做低延迟翻译、同传、流式字幕,或者只是好奇强化学习怎么和推理效率结合,这篇内容适合你慢慢看。
1. 为什么“翻译质量足够好”已经不够了
1.1 LLM翻译的隐性时间账单
现在谈LLM做机器翻译,大部分团队关心的是质量指标能不能再涨零点几个点。但真正上过生产环境的人都知道,翻译场景除了BLUE、COMET之外,还有一张看不见的时间账单。
大模型翻译的“高质量”通常建立在一堆隐性开销上:先让模型思考一段再输出、反复采样多个候选再选最优、或者把上下文窗口拉得很长来获取额外信息。这些手段在离线批量翻译里无所谓,但在实时场景里完全不可接受。用一个生活化的类比:你让一位顶尖翻译家坐在家里慢慢翻一篇文章,他能给你精雕细琢的译文;但你要他在三秒内对着一句复杂长句开口翻译,表现大概率也是仓促的。LLM也一样,给它4秒和给40秒,产出的完全是两种作品。
HOMURA这个项目想解决的,就是后者。我们希望训练出这样一个翻译策略:当系统只给你很紧的生成预算时,模型自己学会判断哪些句子可以直接翻、哪些句子需要先做少量推理再下笔、哪些句子要果断放弃精修。换句话说,我们不再把时间当作一个外部约束去迁就,而是把时间当作一个可以优化的目标,直接放进强化学习的奖励信号里。
1.2 时间受限场景的“痛感清单”
到底哪些场景算时间受限?我列一个我们做需求调研时反复听到的痛感清单:
- 实时字幕翻译:视频里人物说完话到字幕出现,通常只有几百毫秒到一两秒的窗口。
- 同传会议:发言人的话已经过去,你的译文如果跟不上,后面整段节奏全乱。
- 客服实时对话:用户问完一句,你的模型如果犹豫三秒,体验已经算事故。
- 浏览器划词翻译:用户对延迟极其敏感,超过一秒就会觉得卡顿。
- 游戏本地化语音:台词语音是有时长的,译文必须在限定时间内返回,否则角色嘴型切不上。
这些场景的共性是:你不能等,也不能重来。质量再高,只要延迟破线,用户感知到的就是“卡”、“慢”、“不能用”。更麻烦的是,这些场景里句子的难度差异极大。简单短句给足预算纯属浪费,复杂长句给同样的预算又明显不够。可传统方案不会区分这些,它们只会给所有句子分配一个固定的推理时长。
1.3 现有解法为什么不解渴
我们也系统梳理过市面上常见的时间受限翻译方案,大致有三类,每一类都各有各的膈应。
第一类是直接换小模型。速度快了,但翻译质量的代差肉眼可见。尤其术语、低频表达、跨语种语序调整的场景,小模型会给出“每个词都对但整句不像人话”的译文。对生产环境来说,这种质量下降不可接受。
第二类是缩短上下文窗口,或者把历史信息塞进压缩缓存里。这类方案在长文档翻译上效果不错,但在单句级实时翻译里,上下文能给的帮助有限。难句该崩还是崩。
第三类最贪心,是给所有句子一个固定上限的推理预算,比如限制最大新token数,或者干脆禁用思考链。这样做的好处是可控,坏处是“一刀切”:简单句被白白限制,复杂句又吃不饱。我见过很多团队最后妥协成“固定短预算直出”,人为牺牲了难句质量来换取整体延迟可控。
这三类方案的共同问题,是没有把“时间”本身当作一个需要建模和优化的对象。它们都是在算力、模型容量这些静态维度上做取舍,而HOMURA希望做的是动态的、自适应的分配——而这个目标恰好是强化学习最擅长的领域。
2. HOMURA的核心设计:把时间预算变成强化学习的“传感器”
2.1 问题形式化:向质量-时间帕累托前沿推进
动手之前,我们先把问题抽象成了标准形式。假设有一个源句x,一个翻译策略π,和一个最大推理时间预算T。策略在时间T内生成译文y,我们评价它的质量用自动指标Q(比如COMET类模型得分或人工偏好得分)。
目标函数我们希望同时最大化质量、控制预算偏差、稳定策略:
max E[Q(π)] − α * E[max(0, used_budget − T)^2] − β * KL(π || π_ref)
这个公式理解起来并不复杂。第一项是翻译质量,第二项是延迟惩罚——只有当实际用时超过预算T时才开始惩罚,而且是平方增长,越超时惩罚越狠。第三项是KL散度,让策略不要偏离初始的SFT模型太远,避免训练崩溃。
有意思的是,如果只优化第一项,模型很快就会学到“多想一会儿质量更好”;如果只压第二项,模型会退化成不管什么都直出的懒汉。真正困难的,是让模型自己找到那个“既不超时、又尽力拿质量”的平衡点。
2.2 动作空间与状态空间的设计
强化学习做生成任务,最关键也最容易犯错的动作空间设计。HOMURA没有采用传统的“下一个token是什么”这种细粒度动作,而是把生成过程切成三个阶段:继续思考、输出最终译文、译文修订。
这里需要展开解释一下“思考”和“译文”的区别。我们让模型在翻译前可以生成一段内部推理前缀——类似推理模型的思考链——但它不是译文的任何一部分,真正落地的译文在思考之后才出现。“译文修订”则对应生成过程中的二次调整,模型可以在某些特殊位置决定对已生成的片段做小幅修改。状态空间则包括:源句、当前已生成的前缀、已经消耗的token数、剩余预算、以及一个轻量难度信号。这个难度信号是我们单独训练的,输入源句,输出一个0到1的难度分数,用来提示当前句子值不值得投入更多推理。
2.3 预算控制器:什么时候该闭嘴翻译
整个框架里,我们觉得含金量最高的一个部件,是预算控制器。它可以看作一个轻量的决策头,嵌在生成过程的每一层前缀里,根据当前状态决定:继续想,还是直接翻。
一开始我们用过纯规则方案:difficulty > 阈值就允许思考,否则直出。但发现阈值一设就死。难句和简单句的界限在真实语料里非常模糊,一个看似简单的短句可能包含高度歧义的指代,一个超长句也可能是流水账毫无难点。
后来我们改为让预算控制器参与强化学习训练,让策略自己学会权衡。训练之后我们发现,模型对难度信号的运用方式非常有意思:它不只是靠难度打分,还会看自己当前已经生成了多少内容、剩余预算还剩多少。如果剩余预算很充裕,即使难度一般的句子它也愿意多写两行思考;如果预算告急,哪怕是长难句它也果断下笔,先把主干翻出来再说。这其实就是“动态预算分配”,而不是我们最初理解的“静态难度门控”。
2.4 受限RL目标与训练配方
训练主算法用的是PPO。奖励函数是整篇项目的灵魂,我贴一个简化版的实现思路:
def reward_fn(quality_score, used_budget, target_budget, kl): # 质量得分来自COMET类奖励模型,范围通常0~100 reward = quality_score # 延迟惩罚:只在超预算时生效,平方惩罚让超时越久越难受 if used_budget > target_budget: over_time = used_budget - target_budget reward -= alpha * (over_time ** 2) # KL惩罚:平稳策略,不让模型和SFT参考模型偏离太远 reward -= beta * kl return reward我们实践的几组超参数可以作为一个很好的起点:学习率1e-6,KL系数β在0.1到0.2之间,目标预算T设定在2.5秒左右,GAE参数lambda取0.95,PPO clip范围0.2。训练用的batch size是64个句子,约训练5000到8000步,在单张消费级大显存卡上大概跑两天到三天。这个配方不是黄金定律,但对我们覆盖的多个语言方向都稳定有效。
这里想额外强调一点:很多人做强化学习生成任务会把动作空间直接设定成“每个token的预测概率”,这在理论上是没错的,但在时间受限翻译里会带来严重的稀疏奖励问题——你可能生成三五十个token之后,奖励才告诉你好不好。我们切分成“思考/翻译/修订”三个高层动作之后,策略在每一步拿到的反馈密度大大增加,模型更容易学到“何时该动、何时该停”这个核心技能。
3. 实验配置与关键结论:HOMURA到底赢在哪里
3.1 数据、评测与基线
实验方向我们选了中英、英德、英法三组。数据来源是公开的多语言平行语料测试集,另外从日常网络文本中抽了一部分难句测试集,确保有很多从句嵌套、长名词短语、跨语言语序差异明显的样本。评测指标用COMET类指标做质量主指标,BLEU作为参考,延迟则以端到端返回时间的中位数和P90为准。
基线设了四个,每一个都有明确的目的:
- 直出基线:无论什么句子,模型直接生成译文,不允许推理,也不做任何修订。
- 固定思考上限:所有句子都允许生成固定长度的思考前缀(比如64个token),再统一翻译。
- 模拟多候选:在延迟约束内,让模型生成一个译文之后快速做一次修订。
- 完整离线参考:不限延迟,用全量思考加多轮修订,作为质量天花板。
3.2 数据结果:延迟不变时质量更优
下面是我们在中英方向、目标延迟约1.5秒时的实验记录,贴出来给个直观感受:
| 策略 | 平均延迟 | COMET得分 | BLEU参考 |
|---|---|---|---|
| 直出基线 | 0.8s | 82.1 | 31.4 |
| 固定思考上限64token | 1.6s | 83.4 | 32.0 |
| 模拟快速修订 | 1.1s | 83.0 | 31.8 |
| HOMURA-低延迟模式 | 0.9s | 84.7 | 32.9 |
| HOMURA-中等延迟模式 | 1.5s | 85.8 | 33.5 |
| 离线参考(不限时) | 6.2s | 87.2 | 34.1 |
HOMURA有两个非常明确的结论。第一,在延迟约0.9秒时,COMET得分比直出基线高2.6分,而且延迟只多了0.1秒;这说明模型学会了在极小的额外时间窗口里做高价值的思考。第二,把延迟放宽到1.5秒时,质量继续涨到85.8,已经能达到接近离线参考的水平,但耗时只有后者的四分之一。其他语言方向结论一致,只是数字幅度略有不同。
3.3 行为分析:模型学到的翻译策略是什么
数字之外,我们花了很多时间做行为分析,想搞清楚HOMURA到底在什么情况下会选择思考、什么情况下直接翻。
统计所有测试句子的思考标记分布后,我们看到了一个非常清晰的规律:简单日常句式、日期数字、短名称短语,思考标记几乎为零,模型直接输出;涉及多重从句嵌套、长名词短语、需要语序重构的句子,模型会先“沉默”一小段再做翻译。英到德和英到汉的方向上尤其明显——因为这两对语言的语序差异大,不重构就译不通。
另一个观察是修订动作。离线参考模型会频繁做多轮修订,但HOMURA在时间受限下几乎只用一次修订,且通常发生在译文还有明显语病的地方。模型学会了“如果能通过局部修正解决,就不要推翻重来”这种非常像人类译者的习惯。
3.4 时间受限场景的上线效果
实验做完,我们把它推到真实服务环境做了一次小规模压测。我们的推理栈做了三件事:模型权重INT8量化、固定batch等于1、开启KV Cache。额外测试了投机采样来降低生成时延。
实测下来,量化和KV缓存对直出模型效果很明显,延迟降了约35%。但投机采样和HOMURA策略之间有个小坑:我们的思考阶段往往是连续多个高概率token,投机采样对这类序列的加速效果有限,但如果思考内容跳转大(比如模型突然决定改变语序),投机采样反而会拖慢速度。所以最终上线时我们只在译文生成阶段开启了投机采样,思考阶段保持原生解码。这种混合调度是实测中才发现的细节。
4. 从论文到工程:实操中踩过的坑与提示
4.1 延迟度量先统一,再来谈训练
这条我认为是整篇项目中最值得反复强调的工程经验。我们早期在训练和评测之间反复出现“指标对不上”的问题,最后定位到根因:延迟度量本身不稳定。
GPU热不热、服务器上有没有其他任务排队、输入序列长度是否统一,都会导致你测出来的延迟数字忽高忽低。同一个模型,同一句话,上午测1.2秒,下午测1.8秒,你根本没法判断是策略变差了还是机器变慢了。
我们最后定的规矩是三条:评测时固定batch等于1,保证任务之间没有相互干扰;评测前先做大量warmup,稳定核心频率和显存状态;延迟指标不取平均值,取中位数和P90分位数,并且每次连续测量多次取稳定区间。训练阶段使用token预算作为代理指标,验证阶段再用真实时间复检。这样做的效果是,我们在训练过程中再也没被延迟噪声误导过。
4.2 PPO训练现场最常见的三种翻车
强化学习训练翻车是常态,稳定跑通才是意外。我们最常遇到三种问题,这里写出来给大家避坑。
第一种是熵坍缩。因为我们的高层动作只有两三个,策略很容易快速收敛到某一个动作上,比如“永远选择翻译,不思考”,导致后续训练无效。我们的解法是加一个较小的熵奖励,并且在前2000步强制抬高思考动作的概率,让模型先充分探索。
第二种是奖励hacking。这个最坑,模型学会了生成“语义平庸但流利”的译文——因为奖励模型偏爱流畅的句式结构,它会牺牲准确术语去换取流利度。解决方法是把术语约束放进奖励里,并定期用人工盲标集做回归,发现刷分行为立刻修正训练数据分布。
第三种是KL漂移。策略在训练后期离参考模型越来越远,生成的句式模板化严重,特定句子无论输入怎么变化,翻译用词都趋于一致。我们的做法是把KL系数从0.1提升到0.2,效果立竿见影,输出多样性显著恢复。
4.3 奖励模型的选择与校准
很多人做这类项目会直接在训练里用COMET类自动指标当奖励,这没有错,但我建议一定额外配一个基于人工偏好的奖励模型做辅助。我们训练时用COMET类回归模型为主,但这玩意儿有偏好:对“忠实、流畅的改译”很慷慨,对“创新性表达”却很吝啬。人工偏好奖励模型能补上术语正确性和语义忠实性窗口。
校准的重点是准备一个约100句的人工盲标回归集。每轮训练结束后,拿当前策略跑一遍这100句,让标注者盲评,把人工分和自动指标分放在一起对比。如果自动分涨了但人工分跌了,果断回滚模型,同时调整奖励设计。这个成本看起来高,但和上线后被用户狂差评比,这点投入非常划算。
4.4 部署层面的动态预算控制细节
最后一块是部署。我们不能让强化学习策略裸奔在推理服务里,需要把一个“剩余预算”信号实时注入模型。
具体实现上,我们在模型输入的前缀里拼接了一个结构化的控制符,比如表示思考开始和结束的标记。然后把剩余预算编码成一个向量,通过模型的embedding层或prefix cache注入。这带来一个实现麻烦:同一批请求里不同句子的剩余预算不同,batch内的状态不一致,如果并行batch大于1,mask处理很容易出错。我们最终的做法是动态预算控制模块独立于生成循环,生成器每步只负责判断“继续或停止”,预算状态由外层调度器单独维护。这个拆解让调试简单非常多。
5. 这个工作还能走到哪
5.1 从离线翻译到流式同传
HOMURA目前处理的是单句级别的优化。往流式同传方向延伸的时候,问题会变成“在句子还没说完的时候,如何分配时间”。这个时候,分段策略就变得非常重要:按标点切、按语义边界切、还是按固定时间窗口切,会直接影响预算控制器的状态输入。我们下一步的想法是让预算控制器看到“已经听到的内容长度+预计会话剩余时长”,这样它会更愿意在句子开头先听够信息再做决定。
5.2 从文本到多模态:语音与图像场景的预算再分配
多模态场景对时间受限的感知比文本更强烈。语音交互的场景里,用户天然期待回答在一秒内出现,而且语音识别系统本身就有延迟,留给翻译模块的预算可能只有几百毫秒。图像OCR翻译里,图片中的文字数量、排版密度、语言方向会剧烈影响可用的推理时间。预算控制器如果能输入模态相关的“感知信号”,应该能在这些场景里迁移得很自然。
5.3 从强化学习到教模型学会规划
这个项目让我对LLM推理有了一个新的认知:很多场景下,“什么时候思考”的重要性比“思考什么”更高。强推理模型让模型拥有了很强的思考能力,但如果你不给它限制,它会过度思考,把时间花在低价值的推理上。反过来,时序受限的任务里,教模型在关键时刻才启动高成本推理、其他时候保持轻量输出,是远比提升基础能力更“性价比”的优化方向。这也是HOMURA最让我兴奋的地方:它证明了强化学习不只是把模型的答案校准得更符合人类偏好,还可以教会模型管理自己的“注意力预算”。
我个人在实操里体会最深的一件事:整个项目最难的部分不是把PPO跑通,而是把“时间”这个东西变成一套稳定、可复现的观测信号。如果你也想做类似的方向,我建议从搭建延迟评测环境开始,花一周时间把基线的延迟数字彻底打稳,后面训练强化学习策略时会省掉绝大部分debug时间。另外,训练后多花时间做行为分析,比单纯盯着训练曲线涨跌有价值得多,它会让你真正明白你的策略在想什么。