
在 LLM 推理能力研究中多语言推理迁移Multilingual Reasoning Transfer是一个既关键又棘手的问题。简单来说我们希望模型在使用英文推理数据训练之后不仅能在英文上做数学、逻辑或代码推理也能在中文、西班牙语、印地语、法语等语言上表现出稳定的推理能力。但实际效果往往不理想模型在英文上表现良好一旦切到其他语言推理能力就明显下滑甚至出现“语言切换后智商下降”的现象。RP-OPSD 正是针对这一问题提出的一种新的训练范式。它的全称是 Reasoning-Pivot-Guided On-Policy Self-Distillation核心思路可以概括为通过“推理枢轴引导”的方式让模型在在线策略自蒸馏过程中逐步把英文推理能力迁移到多语言场景。本文将从问题背景、方法拆解、训练流程、代码实现、常见问题等几个方面完整梳理 RP-OPSD 的思路与实战要点。无论你是研究 LLM 对齐、推理增强还是在工程中做多语言模型的训练与微调都能从中找到可参考的框架。1. 背景与核心概念为什么多语言推理迁移这么难1.1 什么是多语言推理迁移多语言推理迁移指的是用某一种语言通常是英文的推理数据训练模型期望模型在多种语言上都具备推理能力。这种迁移能力在现实应用中非常重要因为大多数开源的高质量推理数据集都集中在英文而实际用户的使用语言却覆盖全球上百种。举个例子我们用 GSM8K 英文数学题训练模型希望模型能解答中文数学应用题、西班牙语逻辑题或印度尼西亚语的几何题而不需要在每种语言上都重新标注大量数据。但问题在于大语言模型在预训练阶段虽然见过多种语言其推理能力却往往与“推理语言”高度绑定。也就是说模型的推理路径、思维链模式在英文上更容易被激活而切到其他语言后同样的推理链条可能变得脆弱甚至失效。1.2 现有方法的局限性在 RP-OPSD 出现之前业界和学术界尝试过多类方法来解决这个问题方法类型代表思路主要局限直接翻译把英文推理数据翻译成多种语言再训练推理链翻译后容易语义走样且成本高多语言 SFT用多语言混合数据做监督微调需要大量多语言标注小语种覆盖难度大机器翻译增强对思维链进行翻译回填翻译质量直接影响推理链质量多语言 RLHF在多语言偏好数据上做强化学习偏好数据昂贵且对齐难度指数上升这些方法有一个共同问题它们大多把“语言”当成一个静态的翻译问题来处理而没有考虑推理过程本身的动态性。换句话说推理不是“把英文句子翻译成中文”这么简单而是“在不同语言中激活同一种逻辑推理能力”。1.3 RP-OPSD 的突破口RP-OPSD 的思路与上述方法有本质区别。它不依赖大规模多语言标注数据也不要求高质量的机器翻译结果而是提出一种“自蒸馏 推理枢轴”的组合策略推理枢轴Reasoning Pivot选定一种模型推理能力最强、最稳定的语言通常是英文作为枢轴让模型先在该语言上生成高质量推理路径。在线策略自蒸馏On-Policy Self-Distillation让模型以当前策略生成多语言推理路径以枢轴结果为参考进行蒸馏从而逐步提升其他语言的推理水平。这听起来有点像“先让师傅英文推理做一遍题再让徒弟多语言推理照着师傅的思路做不过要求徒弟不仅会翻译还要理解师傅的推理逻辑”。2. RP-OPSD 方法原理拆解2.1 推理枢轴为什么选择英文作为锚点在多语言模型中英文通常拥有最丰富的训练语料、最稳定的推理能力和最成熟的思维链表达方式。因此在 RP-OPSD 中英文被设定为“推理枢轴”。但这并不代表英文是唯一选择。如果你的模型在某种语言上表现更强或者你的业务场景以某种语言为主也可以把那种语言作为枢轴。关键在于枢轴语言应该是模型最“擅长”的语言这样才能提供高质量的推理参考。推理枢轴在这套方法中承担两个职责生成高质量的推理参考路径作为蒸馏的“软标签”。提供跨语言的推理逻辑支架让模型在切换到其他语言时能借助枢轴理解“这个问题应该按什么思路去解”。2.2 在线策略自蒸馏让模型自己教自己自蒸馏的核心思想是用模型自身生成的输出作为训练目标。与离线蒸馏使用固定教师模型不同在线策略自蒸馏强调的是教师与学生是同一个模型。教师输出来自模型“当前策略”on-policy而不是某个冻结的旧版本。训练过程中教师输出会随着模型能力提升而动态更新。这种设计有两点优势第一避免教师模型与学生模型之间的能力断层。如果使用固定的教师模型当学生模型能力逐步提升后教师模型的输出可能反而成为限制学生进步的“天花板”。而在线策略让教师始终与学生保持同步蒸馏目标会越来越贴合模型当前的推理水平。第二显著降低数据成本。不需要额外训练一个大教师模型也不需要对每一条数据做人工标注模型自身的生成结果就可以作为训练信号。2.3 训练流程总览RP-OPSD 的训练流程可以划分为以下阶段方便理解我们用一个表格来梳理阶段输入输出作用1. 枢轴推理生成多语言问题每种语言对应问题在枢轴语言上的推理路径提供稳定的推理参考2. 多语言路径生成多语言问题 枢轴推理路径目标语言上的推理路径让模型尝试用目标语言表达推理3. 在线自蒸馏目标语言推理路径 枢轴推理路径蒸馏损失拉近目标语言与枢轴语言的推理分布4. 策略更新蒸馏损失更新后的模型参数提升模型多语言推理一致性需要特别说明的是流程中的第 2 步和第 3 步不是静态的而是交替进行的。每训练一个或多个 step模型参数更新后后续生成的“多语言推理路径”就会更接近枢轴语言的质量从而形成一种螺旋式上升的训练循环。3. 实验环境准备与数据组织3.1 运行环境与依赖RP-OPSD 的训练流程涉及大模型推理、自回归生成、KL 散度计算、策略梯度更新等环节因此环境配置上建议满足如下条件。依赖项建议配置操作系统LinuxUbuntu 20.04 / 22.04Python3.10 及以上深度学习框架PyTorch 2.x模型库Hugging Face Transformers 4.40分布式训练DeepSpeed / FSDP显存要求至少 4 × 40GB以 7B13B 模型为例参考框架TRL、PEFT、FlashAttention-2版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。3.2 数据组织假设你要在 GSM8K、MGSM 或其他多语言推理数据集上复现 RP-OPSD数据组织可以分为三层data/ ├── source/ │ ├── train_en.jsonl # 英文推理问题 │ ├── train_zh.jsonl # 中文推理问题 │ └── train_de.jsonl # 德文推理问题 ├── pivot/ │ ├── train_en_pivot.jsonl # 英文枢轴推理路径 │ ├── train_zh_pivot.jsonl # 中文问题对应的英文推理路径 │ └── train_de_pivot.jsonl └── eval/ └── mgsm_eval.jsonl # 多语言评测集每条数据的 JSON 结构可以设计为{ problem: 如果一个商店以 3 元的价格卖出 5 个苹果那么 15 个苹果需要多少钱, language: zh, pivot_reasoning: First, we need to find the price of one apple. ..., target_reasoning: 首先我们需要求出一个苹果的价格。... }当然target_reasoning在初始阶段可能不存在或质量较低这正是训练过程中需要逐步优化的对象。4. 核心代码实现搭建 RP-OPSD 训练循环这里给出一个便于理解且能直接运行的“最小训练框架”核心思路是先使用模型生成 pivot 推理和对应语言的推理路径再基于蒸馏损失更新策略。4.1 创建项目结构rp_opsd/ ├── config.py # 训练配置 ├── data.py # 数据读取与预处理 ├── model_utils.py # 模型加载与保存 ├── train.py # 主训练循环 ├── generate.py # 推理路径生成 └── eval_mgsm.py # 多语言评测脚本4.2 模型加载与配置# 文件路径model_utils.py import torch from transformers import AutoModelForCausalLM, AutoTokenizer def load_model_and_tokenizer(model_name: str, use_flash_attn: bool True): tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, attn_implementationflash_attention_2 if use_flash_attn else sdpa, device_mapauto, trust_remote_codeTrue, ) model.config.use_cache False # 训练阶段关闭缓存 return model, tokenizer这段代码的核心点是device_mapauto让模型自动分布到可用 GPU 上。use_cacheFalse是训练阶段的常规设置避免缓存导致显存溢出。如果显存不足可以配合 PEFT 使用 LoRA 来降低显存占用。4.3 推理枢轴生成阶段在生成阶段我们让模型用英文枢轴语言生成推理路径同时把这条路径保留下来供后续自蒸馏使用。# 文件路径generate.py import torch from tqdm import tqdm def generate_pivot_reasoning(model, tokenizer, problems, languageen, max_new_tokens512, temperature0.7): 为多语言问题生成枢轴语言默认英文的推理路径。 prompt_template ( Please solve the following problem step by step in {lang}.\n Problem: {problem}\n Reasoning: ) results [] model.eval() with torch.no_grad(): for problem in tqdm(problems, descGenerating pivot reasoning): prompt prompt_template.format(langEnglish, problemproblem) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokensmax_new_tokens, temperaturetemperature, do_sampleTrue, top_p0.9, ) generated tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) results.append(generated) return results这里有一个容易被忽略的细节生成枢轴推理时虽然问题是多语言的但 prompt 指令部分是英文。这样做的目的是让模型自动切换到英文推理模式产生更稳定的推理路径。4.4 目标语言推理路径生成完成枢轴推理生成后再把“问题 枢轴推理”一起作为输入让模型用目标语言生成推理路径。# 文件路径generate.py续 def generate_target_reasoning(model, tokenizer, problems, pivot_reasonings, target_langChinese, max_new_tokens512): 在枢轴推理的引导下让模型生成目标语言的推理路径。 prompt_template ( Here is a reasoning chain in English:\n {pivot}\n\n Now solve the original problem in {lang}, and keep the reasoning logic similar.\n Problem: {problem}\n Reasoning: ) results [] model.eval() with torch.no_grad(): for problem, pivot in tqdm( zip(problems, pivot_reasonings), totallen(problems), descGenerating target reasoning ): prompt prompt_template.format( langtarget_lang, pivotpivot, problemproblem ) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokensmax_new_tokens, temperature0.7, do_sampleTrue, top_p0.9, ) generated tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) results.append(generated) return results这个设计可以理解为“给模型一张英文答题卡要求它用中文把同样的推理过程重新写出来”。注意不是让模型逐句翻译而是要求它保持推理逻辑一致用目标语言重新组织表达能力。4.5 在线策略自蒸馏训练训练阶段是整个 RP-OPSD 的核心。我们把“目标语言推理路径”作为训练输入把“枢轴语言推理路径”映射到目标语言的 token 分布上用 KL 散度计算蒸馏损失。# 文件路径train.py import torch import torch.nn.functional as F from torch.utils.data import DataLoader, Dataset class ReasoningDistillDataset(Dataset): def __init__(self, problems, target_reasonings, tokenizer, max_length2048): self.problems problems self.target_reasonings target_reasonings self.tokenizer tokenizer self.max_length max_length def __len__(self): return len(self.problems) def __getitem__(self, idx): prompt ( Problem: {problem}\n Reasoning: {reasoning} ).format( problemself.problems[idx], reasoningself.target_reasonings[idx] ) enc self.tokenizer( prompt, max_lengthself.max_length, truncationTrue, paddingmax_length, return_tensorspt ) return { input_ids: enc[input_ids].squeeze(0), attention_mask: enc[attention_mask].squeeze(0), } def compute_kl_loss(logits, target_logits, mask): 计算在线自蒸馏的 KL 散度损失。 这里 target_logits 可以理解为枢轴路径经模型前向得到的结果。 vocab_size logits.size(-1) log_probs F.log_softmax(logits, dim-1) target_probs F.softmax(target_logits, dim-1) kl F.kl_div( log_probs, target_probs, reductionnone ).sum(-1) # (batch, seq_len) mask mask.float() kl (kl * mask).sum() / mask.sum().clamp(min1.0) return kl def train_one_step(model, batch, optimizer, tokenizer): input_ids batch[input_ids].to(model.device) attention_mask batch[attention_mask].to(model.device) # 前向传播 outputs model( input_idsinput_ids, attention_maskattention_mask, labelsinput_ids, # 先算语言建模损失保证基础生成能力 ) lm_loss outputs.loss # 在线自蒸馏损失 # 这里假设我们另有一套“枢轴推理”输入实际工程中需要从同一批次构造 # 简化示例直接使用当前模型在另一种语言 prompt 上的前向 logits # 作为教师分布演示思路如下 kl_loss torch.tensor(0.0, devicemodel.device) # 总损失 loss lm_loss 0.5 * kl_loss optimizer.zero_grad() loss.backward() optimizer.step() return { lm_loss: lm_loss.item(), kl_loss: kl_loss.item() if isinstance(kl_loss, torch.Tensor) else 0.0, total_loss: loss.item(), }需要提醒的是上面的compute_kl_loss是一个简化实现。在实际论文复现中在线自蒸馏损失通常需要模型对“目标语言推理路径”和“枢轴参考路径”分别做前向然后对两组 logits 计算 KL 散度。更完整的工程实现还需要考虑如何对 token 序列做对齐如何用 mask 屏蔽 padding 位置如何处理两种语言 tokenizer 不一致的问题是否在蒸馏损失中加入辅助的 SFT 损失防止模型遗忘基础能力。4.6 训练主循环# 文件路径train.py主循环节选 from transformers import get_cosine_schedule_with_warmup from model_utils import load_model_and_tokenizer from data import load_multilingual_dataset def main(): model_name Qwen/Qwen2.5-7B-Instruct # 示例模型按需替换 model, tokenizer load_model_and_tokenizer(model_name) # 数据加载 problems, target_reasonings load_multilingual_dataset( pathdata/source/train_zh.jsonl ) dataset ReasoningDistillDataset(problems, target_reasonings, tokenizer) dataloader DataLoader(dataset, batch_size4, shuffleTrue) optimizer torch.optim.AdamW(model.parameters(), lr1e-5) scheduler get_cosine_schedule_with_warmup( optimizer, num_warmup_steps100, num_training_stepslen(dataloader) * 3, ) global_step 0 for epoch in range(3): for batch in dataloader: metrics train_one_step(model, batch, optimizer, tokenizer) if global_step % 10 0: print(fStep {global_step}: {metrics}) scheduler.step() global_step 1 model.save_pretrained(output/rp_opsd_model) tokenizer.save_pretrained(output/rp_opsd_model) if __name__ __main__: main()5. 实验评测如何验证多语言推理迁移效果RP-OPSD 的效果不能只靠单个训练集上的 loss 来判断必须在多语言基准集上做系统评测。比较常用的评测集包括MGSMMultilingual Grade School Math覆盖 10 种语言的数学应用题。MMMLUMultilingual MMLU多语言版本的综合知识推理。MultiArith 多语言翻译版。自建业务数据集。评测代码可以从简到繁实现下面是一个基于 MGSM 的示例# 文件路径eval_mgsm.py import json import torch from tqdm import tqdm def evaluate_mgsm(model, tokenizer, eval_filedata/eval/mgsm_eval.jsonl, langzh): model.eval() correct 0 total 0 with open(eval_file, r, encodingutf-8) as f: samples [json.loads(line) for line in f if json.loads(line)[language] lang] prompt_template ( Please solve the following math problem step by step.\n Problem: {problem}\n Answer: ) with torch.no_grad(): for sample in tqdm(samples, descfEvaluating {lang}): prompt prompt_template.format(problemsample[problem]) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokens512, temperature0.0, do_sampleFalse, ) prediction tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) if sample[answer] in prediction.strip(): correct 1 total 1 accuracy correct / max(total, 1) print(fLanguage: {lang}, Accuracy: {accuracy:.4f}) return accuracy需要注意的是MGSM 的答案匹配逻辑在真实评估中并不只是“答案字符串包含”这么简单。实践中建议使用规则抽取模型输出中的最终数字答案再做归一化比较。6. 常见问题与排查思路在复现或应用 RP-OPSD 的过程中最容易遇到的问题集中在训练不稳定、显存溢出、路径生成退化等方向。下面整理了一份排查清单。问题现象常见原因解决思路训练时显存溢出序列长度过长batch size 过大降低 batch size使用梯度累积开启 FlashAttention枢轴推理路径质量不稳定解码温度过高模型本身在该域弱降低 temperature改用贪心解码或自洽性采样目标语言推理路径与枢轴逻辑脱节prompt 引导不够明确缺少推理链约束在 prompt 中增加“请保持与英文推理相同的逻辑结构”KL 损失持续不下降两个语言的 token 分布差异过大先做语言适应如多语言继续预训练再上自蒸馏模型基础生成能力下降蒸馏损失权重过大调整 lm_loss 与 kl_loss 的比例加入参考 SFT 数据评测分数不升反降训练数据过于单一灾难性遗忘混合各语言数据训练时加入原始 SFT 数据在实际项目中遇到最多的问题其实是“目标语言推理路径生成质量差”。这通常不是模型能力不足而是 prompt 设计不够好。建议在正式训练前先在少量数据上人工检查生成路径看模型是否真正理解了“逻辑保持一致但语言切换”的要求。7. 最佳实践与工程建议7.1 严格区分枢轴生成与训练阶段在实现 RP-OPSD 时最容易踩的坑是把“枢轴推理路径生成”和“目标语言路径生成”都放到训练阶段里在线进行。这样虽然更接近 on-policy 的精确定义但工程复杂度呈指数上升。更稳妥的做法是阶段一冻结模型离线生成枢轴推理路径和目标语言路径。阶段二加载这些路径训练模型。阶段三每训练 N 个 step重新生成一次路径更新训练集。这样既保留了 on-policy 的动态性又不会让训练代码变成一团乱麻。7.2 设置合理的蒸馏损失权重蒸馏损失权重是一个需要反复调试的超参数。权重过大模型会过度关注与枢轴语言的对齐导致目标语言的表达能力下降权重过小多语言迁移效果不明显。从经验角度看可以按下面顺序调整先用纯 SFT 损失训练一个 baseline。加入蒸馏损失权重从 0.1 开始尝试。观察目标语言验证集上的 accuracy 变化。如果准确率上升但不稳定适当降低学习率。如果准确率停滞适当提高蒸馏权重。7.3 使用多语言混合数据避免灾难性遗忘RP-OPSD 的训练数据如果只包含单一目标语言模型很容易在训练过程中遗忘掉其他语言的推理能力。因此建议每个 training batch 中混合多种语言的数据让模型在每一轮更新中都能接触到不同的语言分布。例如一个 batch 中可以有2 条中文数据2 条德文数据2 条法文数据2 条英文数据这样做的另一个好处是模型能自然地学习到不同语言之间的推理共享模式而不是简单地对单一目标语言过拟合。7.4 保留一个冻结的参考模型虽然 RP-OPSD 强调 on-policy但在工程实现中保留一个冻结的参考模型依然有重要价值。这个参考模型可以用于计算生成的路径是否发生质量退化作为 PPO 式训练的 reward model在蒸馏损失中加入正则项防止模型偏离原始能力太远。冻结参考模型不会影响 on-policy 的核心特性反而能提供更稳定的训练信号。7.5 数据安全与生产合规如果你的训练数据来自真实用户务必注意训练数据必须经过脱敏处理涉及用户生成内容的需要确认授权范围多语言数据中可能包含不同地区的文化、政治敏感内容建议先做内容安全过滤模型发布前应做安全评测避免在多语言环境下产生有害输出。8. 总结与学习路线RP-OPSD 提供了一条不同于“翻译 微调”的多语言推理迁移路径。它通过“推理枢轴引导”和“在线策略自蒸馏”让模型在保持推理逻辑一致的前提下逐步增强目标语言的表达能力。这个方法更适合以下场景高质量多语言标注数据稀缺已有英文推理数据但需要快速扩展到多语言模型本身具备一定的多语言基础能力但推理能力集中在单一语言上。如果你想在工程中落地这个方法建议按以下路线推进先构建一个小规模的多语言推理数据集100500条跑通训练流程。人工检查生成的枢轴路径和目标路径质量。在小规模评测集上对比 RP-OPSD 与直接翻译微调的效果差异。确认收益后再扩大数据规模并接入分布式训练。加入多语言安全评测与业务指标验证。接下来可以进一步学习的内容包括多语言 RLHF / DPO 与自蒸馏的结合推理时自洽性self-consistency与多语言采样跨语言表示对齐的最新方法基于对比学习的多语言推理路径对齐。RP-OPSD 不是一条“搭好即跑”的现成通道它更像是一套训练方法论。只有理解了它背后的设计动机并根据自己的模型、数据和业务场景做适配才能发挥出预期的效果。如果你正在被多语言推理迁移问题困扰不妨从今天给出的最小框架开始在小数据上跑通验证再逐步迭代到完整的训练流程。