说起多语言多领域机器翻译系统的搭建我先讲一个让我印象深刻的场景某电商平台把中文商品描述直接丢给通用翻译引擎出来的是“医用一次性防护服”被翻成“医疗用一次性的保护性衣服”而平台方坚持要术语表里的标准译法。这个场景基本概括了为什么我要专门搭一套系统——不是通用引擎不够好而是在多语言、多领域的真实业务里质量和可控性远比“能翻出来”重要。如果你也遇到领域术语乱翻、语种需要扩展、数据不能出内网、线上译文需要可干预这篇文章就是为你准备的。我会按实际搭建的顺序来写尽量把每一步的取舍和坑都讲清楚。包括数据从哪来、模型怎么适配领域、服务怎么稳定上线、评测怎么不被指标骗以及最后让我印象最深的几个踩坑记录。整套系统不是某个科研Demo而是能接业务、能持续迭代的工程化项目。1. 通用引擎解决不了的那部分需求才是搭建系统的理由1.1 一个让我决定自建系统的实际案例先交代背景。我参与过一个内部项目核心任务是给某制造企业的操作手册做多语言翻译源语言是中文目标语言包括英语、日语、德语、法语、西班牙语和阿拉伯语还要覆盖设备维护、电气安全、零部件名称等垂直内容。起初团队直接调商用翻译API试运行了两周问题不是“能不能翻译”而是“翻译出来没人敢用”。主要矛盾有几个。第一是术语一致性同一份手册里“紧急停机按钮”在第一章叫“emergency stop button”在第五章变成“urgent stop button”这种前后不一致在设备维护场景里不是小事。第二是数据合规企业明确要求手册原文不能传到外部服务只能在内部环境处理。第三是干预能力业务方希望某个术语必须按他们维护的词汇表翻译通用引擎不接受这种配置。第四是成本和稳定性翻译量一旦上来按字符计费并不便宜而且深夜大促期间外部API的响应时长会明显波动。这几个矛盾叠加在一起结论很明确与其继续给通用引擎“打补丁”不如搭一套自己能控制的系统。注意我没有打算做一个超越通用引擎的神器。通用引擎在泛领域文本上确实强但在垂直领域、术语可控、数据不出内网这些需求面前自建系统是更稳妥的方案。1.2 自建系统的目标拆解项目启动前我先把目标量化。不能只说“提高翻译质量”否则后面没法验收。我们当时的指标是在内部领域的测试集上术语准确率从通用引擎的82%提升到95%以上译文BLEU比直接调用通用引擎高3个点以上单条翻译500字以内P95延迟小于2秒支持至少6个目标语种所有数据留在内网。这套指标后来被证明很有用因为它逼着团队把所有决策都围绕可测量的结果展开。目标拆解之后系统边界也就清晰了。我们不做浏览器划词翻译不做语音翻译不做全自动无人工审核的无人值守服务。我们只做“文本进、译文出”的批量和实时接口并且允许业务方在中间环节配置术语表。这个边界很重要砍掉不必要的功能团队才能集中资源解决核心问题。很多项目失败不是因为模型差而是因为需求边界模糊什么都想塞进去。2. 系统整体架构先想清楚数据往哪流再谈模型2.1 训练、推理、评测三条链路的物理隔离我见过不少团队拿到开源模型就急着部署结果后面想更新模型时发现训练脚本、评测脚本和线上服务搅在一起改一个参数要停整个服务。所以从第一天开始我们把系统拆成三条物理隔离的链路离线数据与训练链路、在线推理服务、评测沙箱。离线链路负责语料清洗、数据增强、模型训练和导出。它跑在独立的计算集群上不对外提供服务训练完的模型统一写入模型仓库并附带版本号、训练数据范围、评测报告。没有这些元信息后面做灰度发布就是盲人摸象。在线推理服务只加载模型仓库里已通过评测的模型不直接接触原始训练脚本。评测沙箱则是独立的隔离环境专门跑自动指标和人工评测任务它的输入是固定版本的测试集输出是一份可对比的报告。这样做的好处是线上服务可以随时回滚到上一个稳定模型评测结果不会因为测试集被意外修改而失真训练任务也不会因为线上流量高峰而抢走计算资源。我们在实际运行中遇到过模型更新后译文质量波动的情况由于三套环境隔离定位问题只花了半天而不是整个团队停摆排查。2.2 基座模型与领域适配层的关系选基座模型是开局最重要的决定。我们的约束条件很明确必须支持多语种尤其是中文到低资源语种的能力不能太弱必须能在内部服务器上跑推理不能依赖外部服务必须允许继续训练或微调不能是纯黑盒。我们当时选定一个开源的多语种翻译基座模型内部代号叫BaseNMT-7B。它提供中文到十几个语种的预训练能力缺点是通用领域表现尚可垂直领域术语经常出错。但我不指望基座直接满足业务而是把它当成“发动机”真正决定业务表现的是领域适配层。领域适配层由三部分组成领域微调模型、术语注入模块、规则后处理。领域微调让模型熟悉目标领域的句式和词汇分布术语注入模块在翻译前和翻译中把业务方定义的术语表强制生效规则后处理则负责修复数字、单位、日期格式等模型容易忽略的硬规则。你可以把基座模型想象成一个见多识广的实习生但必须给TA一本业务手册和一套检查清单TA才能按规范交活。很多项目只做微调不做术语注入结果模型记住了领域风格但关键名词还是飘忽不定这类问题靠微调很难根治。3. 多语种语料的获取、清洗与配比策略3.1 语料从哪里来公开数据集、逆向构建、人工挑错训练多语种模型最缺的永远不是模型结构而是干净、对业务有覆盖的平行语料。我们的语料来源主要是三条线。第一条是公开的多语种平行语料。要注意公开语料的质量参差不齐很多句子来自网页爬虫存在格式错乱、语言标注错误、内容重复。直接拿去训练模型会学到很多坏习惯。第二条是内部积累的翻译记忆库。之前项目沉淀下来的历史翻译文档包括产品手册、客服话术、法律条款这些语料质量高、领域对口是真正的主力。第三条是逆向构建。当目标语言材料不足时我们会把已有中文文档交给人工翻译成目标语言再和原文对齐。成本高但效果立竿见影尤其是阿拉伯语、德语这种语法差异大的语种没有高质量平行句对模型很难学好。人工挑错是必须保留的环节。我们抽样检查了大概2000条对齐句对发现公开语料里有不少“伪平行句对”比如中文一句、英文两句或者中英内容只是主题相关但并不是互译。这类数据对模型的伤害是隐性的模型会慢慢学会“自由发挥”。我们当时的规则是每个语种至少人工抽检500条错误率超过5%就重新清洗。3.2 清洗规则与语言识别清洗规则我按优先级列一下每一条都来自实际踩坑。先做格式清洗。去掉不可见字符、控制字符、HTML标签残留。我们早期没有严格过滤模型偶尔会在译文里输出“”这种标签就是因为训练语料里混入了网页片段。再做语言识别。中文句子可能混入英文品牌名、日文假名如果不做语言识别语种标签会混乱后面多语种路由也会受影响。我们用语言识别模型先给每个句子打语种标签置信度低于阈值的一律剔除。再做长度比过滤。源句和目标句的字符数比值超过1比3的大概率是错位数据或漏译直接删。最后做相似度去重。句子级去重不能只比完全相等还要算n-gram重叠率。我们的经验是重复的n-gram占比超过0.8就认为是重复句保留最长的版本。这些规则看似简单执行顺序也很重要。如果把语言识别放在格式清洗之前乱码文本会让识别器误判如果把去重放在长度过滤之前冗余数据会干扰长度分布判断。我们最终把流程固定为格式清洗、语言识别、长度过滤、相似度去重、人工抽检。3.3 语料配比通用语料、领域语料、单语语料语料不是越多越好配比决定了模型的“性格”。我们的做法是把语料分成三类通用平行语料、领域平行语料、单语语料。通用平行语料保证模型的基础翻译能力比如句式变换、常见词汇。领域平行语料决定模型在目标领域上的表现比如设备操作、医疗说明、法律条款。单语语料主要用于数据增强和回译它本身不是平行句对但可以帮助模型熟悉目标语言的流畅表达。具体配比上我们用的基准是通用平行语料占60%领域平行语料占30%单语料增强占10%。对于某一个特定领域比如医疗我们会在领域部分中把医疗子集的权重再调高到50%。这里有一个容易犯的错一味提高领域语料占比模型会“过拟合”到领域模板句一旦遇到领域外的表达就开始胡诌。所以通用语料的比例不能低于一半这是我的个人经验不是理论推导。多语种之间的配比也要平衡。如果不做干预中英语料的数量会远远碾压中日、中阿。我们按照目标语种的难度做了加权对阿拉伯语、德语这种难点语种适当提高采样权重避免模型被英语“带跑偏”。4. 领域适配的落地方式微调、提示词与术语表的组合4.1 领域微调的具体做法领域微调是整个系统里最直接见效的步骤但操作不当也最容易产生副作用。我们用的方法是监督微调即在基座模型基础上用领域平行语料继续训练若干轮。训练数据的格式很简单输入是源语言句子输出是目标语言译文中间用分隔符隔开。每一条训练样本都带有领域标签比如“制造-设备操作”“医疗-药品说明”“法律-合同条款”。微调时我建议分开做而不是把所有领域混成一个训练集。我们一开始图省事把所有领域数据混合微调结果模型在“法律”测试集上术语准确率只有80%在“制造”测试集上也只有85%。后来改成按领域各自微调出独立模型再在推理层做路由分发每个领域的测试集都提升了5个百分点以上。多领域微调不是不能做但需要更精细的采样控制如果团队人力有限分开训练更可控。训练轮数不宜过多。我们观察到一个反直觉的现象在领域训练集上loss继续下降但在领域测试集上BLEU开始下降说明模型开始死记硬背训练集。我们最后把训练轮数控制在3到5个epoch并每隔一个epoch保存一个检查点用评测集选最好的一版而不是直接选最后一个。4.2 术语注入与上下文约束光靠微调解决不了术语一致性问题这是我们在项目里反复验证过的结论。微调只能让模型“更倾向于”使用某类词汇但无法保证100%准确。比如客户要求“断路器”必须翻译成“circuit breaker”模型可能随机输出“switch”或“disconnector”这在设备维护场景里是不可接受的。术语注入我们做了三层。第一层是翻译前替换把源文本中出现的标准术语直接替换成目标语言术语然后在句子前后加上标记告诉模型这些片段已经指定。这个方式对简单名词最有效但遇到术语被拆开、变形、搭配复杂短语时容易失效。第二层是提示词约束在模型的输入前缀中附上当前任务相关的术语表比如“翻译以下文本注意device must be translated as equipment”。提示词对模型有引导作用但不是硬约束模型可能忽略。第三层是解码约束在生成过程中把术语表的候选词强制限制在每一步生成概率最高的候选集合里。硬约束效果最稳但实现成本高需要能修改解码逻辑的推理框架。我们的最终方案是三层组合翻译前替换处理常规术语提示词约束处理领域风格解码约束锁死最关键的安全类术语。效果在后面评测表里能看到术语准确率从微调后的93%提升到96%以上。4.3 对比实测通用模型 vs 领域适配模型我们在内部测试集上做过一组对比测试集包含制造、医疗、法律三个领域每个领域1000条句子人工标注了标准译文和关键术语。数字可以用来参考不一定代表你的场景但趋势是稳定的。模型版本领域测试集BLEU术语准确率格式错误率BaseNMT-7B通用基座27.181.3%6.8%领域微调版31.593.2%3.5%领域微调 术语注入32.696.4%2.1%领域微调 术语注入 规则后处理32.496.8%0.7%注意一个细节规则后处理介入后BLEU反而略微下降但格式错误率大幅下降。这是因为BLEU对词汇重叠敏感规则后处理把“2023年5月1日”统一成“May 1, 2023”可能会降低n-gram重叠得分但它让日期格式在业务上是正确的。这也是为什么不能只看BLEU术语准确率和格式正确率往往比BLEU更贴近业务。5. 从模型到服务推理部署中的工程细节5.1 推理延迟与批处理取舍模型训练好只是第一步部署成服务还会遇到一堆工程问题。我们的在线服务目标是单条500字以内P95延迟小于2秒。一开始直接单条请求跑模型显存占用不高但GPU利用率很低延迟波动很大。后来改成动态批处理。所谓动态批处理简单说就是请求进来后不立即推理而是放进队列等一小段时间攒够一批再一起跑。我们设定的参数是最多等待50毫秒批次大小达到16就立刻发送。这样在流量平稳时延迟增加不明显但吞吐量提升明显GPU利用率从35%提升到70%以上。如果流量非常稀疏超过等待时间也只有一条请求那就单独跑不能为了批处理无限等下去。延迟优化另一个关键是量化。我们把模型权重从16位浮点量化到8位整数显存占用降低接近一半单条推理速度提升约40%。代价是评测集上BLEU降低了0.3左右但术语准确率没有变化。在业务更看重术语准确率的前提下这个牺牲是可以接受的。不同显卡、不同模型对量化的敏感度不同建议上线前跑一遍评测集确认损失可接受。5.2 多语言路由与自动语种识别多语言系统里请求过来必须先判断“源语言是什么”“目标语言是什么”再决定交给哪个模型。我们的做法是入口部署一个语种识别模块它接收源文本后输出语种和置信度。置信度大于0.9时走对应语言方向的领域模型置信度在0.7到0.9之间时走通用模型但提示词里附上领域标签置信度低于0.7时直接进入人工翻译队列不做自动翻译。这个回退策略很关键。我们遇到过用户传了一段中英文混合的SKU描述语种识别器置信度只有0.65如果硬走中文到英文模型结果会出现大量英文被当成中文重新翻译。回退到人工队列看起来“不够智能”但至少不会输出不可用的译文。目标语种的识别相对简单因为业务方通常会在接口参数里显式指定。但为了鲁棒性我们仍然会校验目标语言参数是否在支持列表内不在列表内直接返回400。不要试图用一个模型处理所有语种虽然技术上可行但领域适配时你会被各个语种的术语问题折腾到怀疑人生。5.3 服务稳定性超时、重试、熔断服务上线后稳定性问题很快浮出水面。我们的下游调用方很多高峰期并发能有每秒几百个请求。推理服务偶尔会因为显存不足或GPU过热变慢如果不做防护一个慢请求就可能拖垮整条链路。我做了三层保护。第一层是接口超时单次推理超过3秒就中断并返回错误调用方可以自行重试。第二层是重试策略调用方对于超时请求最多重试两次但重试之间需要增加随机延时避免所有请求同时打过来造成雪崩。第三层是熔断连续错误率达到10%时服务自动切换到只读模式不再接收新的翻译请求只返回“服务暂不可用”直到错误率恢复正常。缓存也是被低估的优化手段。我们发现业务方有大量重复的商品描述和FAQ不同请求只是个别字不同。我们在服务端加了一层Redis缓存key是“源语言目标语言文本哈希”缓存的命中率在10%左右。别小看这10%高峰期它能显著降低GPU压力。6. 评测体系与线上质量监控6.1 评测集怎么建才不会被指标骗评测集是整个系统最重要的资产但我见过很多团队随便找几千条句子算一个BLEU就宣布模型可以上线。这是典型的自欺欺人。BLEU对领域术语、数字格式、性别一致性都不敏感两个模型的BLEU只差0.5可能其中一个在关键术语上错得离谱。我们当初建评测集做了四层设计。第一层是通用质量集覆盖日常表达用于观察模型有没有整体退化。第二层是领域术语集每个领域挑出200个高频关键术语人工构造包含这些术语的句子统计“标准术语命中率”。第三层是格式与实体集专门测试日期、时间、数字、单位、产品型号的翻译是否准确。第四层是语用与风格集包括敬语、正式/非正式语气、性别一致性这对日语、德语、法语尤其重要。每个测试集我们都会维护一个“标准答案版本”任何评测结果必须注明测试集版本。否则你会发现某次预处理脚本改动后测试集也被悄悄改了两个模型的分数根本没有可比性。这个坑我们踩过后来所有评测报告必须带上测试集git提交号。6.2 线上反馈闭环用户纠错如何回到训练集模型上线不是终点而是数据循环的起点。我们会记录线上翻译请求的日志包括源文本、目标文本、模型版本、延迟和用户后续操作。如果用户复制了译文回去用大概率说明质量可接受如果用户手动修改了译文修改后的内容就是珍贵的纠错数据。我们把用户纠错数据分成三个等级。第一等级是术语类纠错用户把“circuit breaker”改成“breaker”说明术语表需要更新。第二等级是格式类纠错用户把日期格式改了说明规则后处理需要补充。第三等级是通顺度纠错用户只是调整了语序这类数据暂时不进训练集因为噪音太大。每隔两周我们会把积累的纠错数据整理成增量训练集对模型做一轮轻量微调。这里要注意增量训练不能只放新数据必须混合一部分旧语料否则模型会出现灾难性遗忘学会了新术语却忘了旧领域的表达。7. 复盘真正拖慢进度的不是模型而是数据与评测7.1 三个印象深刻的坑第一个坑是清洗规则太激进。我们曾经过滤掉所有包含括号的句子理由是公开语料里括号内容经常是HTML残留。但运行一个月后评测人员发现术语集里大量术语是不带括号的但真实业务文本里“断路器CB”这种写法全被删了。后来我们改成只过滤“括号内包含url或标签”的句子保留正常括号这才救回来。第二个坑是术语表没有做词形归一。英文术语表里写的是“circuit breakers”但源文本里经常出现“circuit breaker”精确匹配失败术语注入没生效。我们后来对英文术语做了小写、单复数归一并且用词形还原生成多个变体再送进匹配器。这个坑不深但很容易踩。第三个坑是评测只看BLEU导致选错模型。我们有一个中间版本模型BLEU比当前版本高1.2但线上反馈说译文经常“自己加内容”。后来用忠实度检查一查发现它在长句上会脑补不存在的信息。BLEU完全不惩罚这类“加戏”从那以后我们的评测必须同时跑忠实度检查即对比源文本和目标文本在关键词上的覆盖度覆盖度过低直接判负。7.2 给后来者的一句话建议如果你也想搭一套多语言多领域机器翻译系统我的建议很简单先建评测集和术语资产再选模型和训练方案。没有可靠的评测集你的一切优化都是盲目的没有术语资产领域适配就是纸上谈兵。我见过太多项目把精力花在换更大模型上结果上线后被术语一致性打回原形。个人体会是机器翻译系统的成功七成在数据工程两成在评测工程只有一成在模型结构。别急着追新架构先把业务语料的结构、质量、配比琢磨明白你的系统就已经超过了大多数通用方案。搭建过程确实琐碎但当你看到业务方拿着标准术语表对照译文逐条勾选通过的时候你会发现前面所有的坑都值得。