LLaMA-2中文适配实战:从词表扩展到指令微调
1. 项目背景与核心挑战当我们需要让一个以英文训练为主的大语言模型如LLaMA、GPT等理解并流畅处理中文指令时会遇到几个典型问题词汇表不匹配英文预训练模型的tokenizer通常不包含中文字符导致中文文本被拆分为无意义的子词单元语义理解偏差模型在英文语料上建立的语义空间难以直接迁移到中文场景指令响应错位模型对中文prompt的响应往往不符合中文表达习惯我在实际项目中测试过直接使用原生LLaMA-2处理中文指令结果模型要么输出乱码要么给出与指令完全不相关的英文回复。这印证了直接使用未经适配的英文模型处理中文任务的不可行性。2. 技术方案设计2.1 整体技术路线我们采用预训练指令微调的两阶段方案词表扩展预训练基础适配在原有词表基础上添加中文token使用中文语料进行继续预训练指令微调能力对齐构建高质量中文指令数据集采用QLoRA等高效微调技术关键选择为什么不是从头预训练计算成本7B参数模型从头训练需要数百张A100时间成本预训练周期通常需要数周效果保障保留原模型的通用能力2.2 词表扩展实战以LLaMA-2为例原始tokenizer仅有约32k的词汇量中文字符覆盖率不足20%。我们使用以下方案扩展from transformers import AutoTokenizer # 加载原始tokenizer original_tokenizer AutoTokenizer.from_pretrained(meta-llama/Llama-2-7b-hf) # 添加中文专用token new_tokens [] with open(chinese_vocab.txt) as f: # 自定义中文词表 new_tokens.extend([line.strip() for line in f]) # 验证并添加新token num_added original_tokenizer.add_tokens(new_tokens) print(fAdded {num_added} new tokens) # 典型值5000-10000注意事项优先添加高频中文词汇如你好、请问等保留原tokenizer的特殊token如[CLS]、[SEP]添加后需要重新初始化新token的embedding2.3 中文指令数据集构建我们采用人工撰写模型增强的混合方案种子数据收集2000条覆盖常见场景问答、创作、分析等示例{ instruction: 用中文解释量子计算的基本原理, input: , output: 量子计算利用量子比特... }数据扩增10倍扩展使用已有中文模型生成变体通过回译中→英→中增加多样性质量过滤人工审核至少3人交叉验证自动过滤去除包含敏感词的内容去除低困惑度perplexity样本3. 指令微调实战3.1 微调配置使用QLoRA进行高效微调# 训练配置 base_model: meta-llama/Llama-2-7b-hf model_type: llama load_in_4bit: true adapter: qlora lora_r: 64 lora_alpha: 16 lora_dropout: 0.05 # 训练参数 batch_size: 128 micro_batch_size: 4 num_epochs: 3 learning_rate: 3e-4 lr_scheduler: cosine warmup_steps: 1003.2 关键训练技巧梯度累积在小批量情况下保持有效batch sizetrainer Trainer( gradient_accumulation_steps32, ... )动态padding优化显存使用data_collator DataCollatorForSeq2Seq( tokenizer, paddinglongest, return_tensorspt )损失权重调整更关注output部分的预测def custom_loss(output, target): output_mask (target ! tokenizer.pad_token_id) loss F.cross_entropy(output, target, reductionnone) return (loss * output_mask).mean()4. 效果评估与优化4.1 定量评估使用以下中文基准测试测试集微调前微调后C-Eval12.3%58.7%MMLU-CN9.8%52.1%CLUE15.2%63.4%4.2 典型问题排查问题1模型输出中英文混杂原因指令数据中英文比例失衡解决调整数据采样权重增加纯中文样本问题2长文本生成质量下降原因位置编码超出预训练长度解决采用NTK-aware缩放位置编码from transformers import LlamaForCausalLM model LlamaForCausalLM.from_pretrained( path/to/model, rope_scaling{ type: ntk, factor: 2.0 } )5. 部署优化建议量化部署model AutoModelForCausalLM.from_pretrained( path/to/model, load_in_4bitTrue, device_mapauto )API服务封装from fastapi import FastAPI app FastAPI() app.post(/generate) async def generate(text: str): inputs tokenizer(text, return_tensorspt).to(cuda) outputs model.generate(**inputs, max_length200) return {result: tokenizer.decode(outputs[0])}持续学习建立反馈闭环机制收集用户实际query定期增量微调在实际部署中我们使用vLLM推理框架实现了每秒50 token的生成速度A10G实例。一个典型的优化案例是将7B模型量化到4bit后显存占用从13GB降至6GB同时保持90%以上的原始精度。