README.md 17.4 KB

Translation Module

translation/ 是当前项目翻译能力的主目录。
如果要开发、部署、联调、压测翻译服务,优先看这份文档。

对应服务:

相关脚本与报告:

1. 设计目标

翻译模块采用:

  • 一个 translator service
  • 多个 capability backend
  • 一个统一外部接口:model + scene

这套设计的目标是:

  • 翻译能力可以独立扩展、独立启停
  • scene、语言码、prompt 模板、模型方向约束等翻译域知识集中在 translation/
  • 配置尽量集中在 <code>config/config.yaml</code>services.translation
  • 配置错误应尽早报错,不做静默兼容和隐式回退

2. 目录结构

核心文件:

后端实现:

3. 配置约定

翻译的部署配置统一放在:

示例:

services:
  translation:
    service_url: "http://127.0.0.1:6006"
    default_model: "llm"
    default_scene: "general"
    timeout_sec: 10.0
    cache:
      enabled: true
      key_prefix: "trans:v2"
      ttl_seconds: 62208000
      sliding_expiration: true
      key_include_scene: true
      key_include_source_lang: true
    capabilities:
      qwen-mt:
        enabled: true
        backend: "qwen_mt"
        model: "qwen-mt-flash"
        base_url: "https://dashscope-us.aliyuncs.com/compatible-mode/v1"
        timeout_sec: 10.0
        use_cache: true
      llm:
        enabled: true
        backend: "llm"
        model: "qwen-flash"
        base_url: "https://dashscope-us.aliyuncs.com/compatible-mode/v1"
        timeout_sec: 30.0
      deepl:
        enabled: false
        backend: "deepl"
        api_url: "https://api.deepl.com/v2/translate"
        timeout_sec: 10.0
      nllb-200-distilled-600m:
        enabled: true
        backend: "local_nllb"
        model_id: "facebook/nllb-200-distilled-600M"
        model_dir: "./models/translation/facebook/nllb-200-distilled-600M"
        device: "cuda"
        torch_dtype: "float16"
        batch_size: 16
        max_input_length: 256
        max_new_tokens: 64
        num_beams: 1
        attn_implementation: "sdpa"
      opus-mt-zh-en:
        enabled: true
        backend: "local_marian"
        model_id: "Helsinki-NLP/opus-mt-zh-en"
        model_dir: "./models/translation/Helsinki-NLP/opus-mt-zh-en"
        device: "cuda"
        torch_dtype: "float16"
        batch_size: 16
        max_input_length: 256
        max_new_tokens: 256
        num_beams: 1
      opus-mt-en-zh:
        enabled: true
        backend: "local_marian"
        model_id: "Helsinki-NLP/opus-mt-en-zh"
        model_dir: "./models/translation/Helsinki-NLP/opus-mt-en-zh"
        device: "cuda"
        torch_dtype: "float16"
        batch_size: 16
        max_input_length: 256
        max_new_tokens: 256
        num_beams: 1

配置边界:

  • config.yaml 只放部署和运行参数 例如 service_urldefault_modeldefault_sceneenabledbase_urlapi_urlmodel_dirdevice
  • translation 目录内部放翻译静态知识 例如 scene 规则、语言码映射、prompt 模板、Marian 方向约束

说明:

  • service_urldefault_modeldefault_scene 只从 YAML 读取
  • 不再通过环境变量静默覆盖翻译行为配置
  • 密钥仍通过环境变量提供

4. 环境变量

当前翻译模块主要依赖:

# Qwen / LLM
DASHSCOPE_API_KEY=sk-xxx

# DeepL
DEEPL_AUTH_KEY=xxx

服务启动端口仍可以由启动脚本环境控制:

TRANSLATION_HOST=0.0.0.0
TRANSLATION_PORT=6006

5. Scene 规则

当前只支持 3 个标准 scene:

  • general
  • sku_name
  • ecommerce_search_query

定义位置:

约定:

  • scene 是公共接口字段
  • 不再接受旧的 context
  • 不再对外暴露 prompt
  • LLM prompt 在服务内根据 scene 自动生成

6. 对外 HTTP 接口

服务入口在:

默认地址:

  • http://localhost:6006

提供接口:

  • POST /translate
  • GET /health

6.1 POST /translate

请求体:

{
  "text": "商品名称",
  "target_lang": "en",
  "source_lang": "zh",
  "model": "opus-mt-zh-en",
  "scene": "sku_name"
}

字段说明:

  • text 支持 stringstring[]
  • target_lang 目标语言
  • source_lang 源语言
  • model 已配置的 capability 名称
  • scene 翻译场景

响应体:

{
  "text": "商品名称",
  "target_lang": "en",
  "source_lang": "zh",
  "translated_text": "Product name",
  "status": "success",
  "model": "opus-mt-zh-en",
  "scene": "sku_name"
}

批量时:

  • 返回列表和输入等长
  • 单条失败返回 null

6.2 GET /health

返回示例:

{
  "status": "healthy",
  "service": "translation",
  "default_model": "llm",
  "default_scene": "general",
  "available_models": ["qwen-mt", "llm", "nllb-200-distilled-600m", "opus-mt-zh-en", "opus-mt-en-zh"],
  "enabled_capabilities": ["qwen-mt", "llm", "nllb-200-distilled-600m", "opus-mt-zh-en", "opus-mt-en-zh"],
  "loaded_models": ["llm"]
}

7. 代码调用方式

业务侧统一这样调用:

from translation.client import create_translation_client

translator = create_translation_client()
result = translator.translate(
    text="商品名称",
    source_lang="zh",
    target_lang="en",
    model="opus-mt-zh-en",
    scene="sku_name",
)

批量调用:

results = translator.translate(
    text=["商品1", "商品2"],
    source_lang="zh",
    target_lang="en",
    model="opus-mt-zh-en",
    scene="sku_name",
)

8. 具体实现说明

8.1 Qwen-MT

实现文件:

特点:

  • 云端机翻
  • 支持 Redis 翻译缓存
  • 适合质量优先、非超高并发场景

注意:

  • 当前默认 qwen-mt-flash 限速较低
  • 大量重复请求应依赖缓存

8.2 LLM Translation

实现文件:

特点:

  • 通用大模型翻译
  • 根据 scene 生成内部 prompt
  • 更灵活,但成本和稳定性取决于上游模型

8.3 DeepL

实现文件:

特点:

  • 商业翻译 API
  • scene 会映射到内部上下文
  • 当前默认关闭

8.4 facebook/nllb-200-distilled-600M

实现文件:

模型信息:

  • Hugging Face 名称:facebook/nllb-200-distilled-600M
  • 本地目录:models/translation/facebook/nllb-200-distilled-600M
  • 当前磁盘占用:约 2.4G
  • 模型类型:多语种 Seq2Seq 机器翻译模型
  • 来源:Meta NLLB(No Language Left Behind)系列的 600M 蒸馏版
  • 目标:用一个模型覆盖大规模多语言互译,而不是只服务某一个固定语言对
  • 结构特点:
    • Transformer encoder-decoder 架构
    • 12 层 encoder + 12 层 decoder
    • d_model=1024
    • 多头注意力,适合多语统一建模
    • 通过 source_lang + forced_bos_token_id 控制翻译方向
    • 语言标识采用 language_script 形式,例如 eng_Latnzho_Hans

模型定位:

  • 优势是多语覆盖面广,一个模型可以支撑很多语言方向
  • 劣势是相较于 Marian 这种双语专用模型,推理更重、延迟更高
  • 在我们当前业务里,它更适合“多语覆盖优先”的场景,不适合拿来和专用中英模型拼极致吞吐

显存占用情况:

  • 600M模型半float16权重约1.25G,推理时会叠加 CUDA context、allocator reserve、激活张量、batch、输入长度、生成长度等开销
  • 当前这台 Tesla T4 上,优化后的实际运行峰值大约在 2.8-3.0 GiB

当前实现特点:

  • backend 类型:local_nllb
  • 支持多语
  • 调用时必须显式传 source_lang
  • 语言码映射定义在 <code>translation/languages.py</code>
  • 当前 T4 推荐配置:device=cudatorch_dtype=float16batch_size=16max_new_tokens=64attn_implementation=sdpa

8.5 opus-mt-zh-en

实现文件:

模型信息:

  • Hugging Face 名称:Helsinki-NLP/opus-mt-zh-en
  • 本地目录:models/translation/Helsinki-NLP/opus-mt-zh-en
  • 当前磁盘占用:约 1.2G
  • 模型类型:Marian / OPUS MT 专用双语翻译模型
  • 方向约束:只支持 zh -> en

结构特点:

  • encoder-decoder Seq2Seq
  • 聚焦特定语言对
  • 模型更小、加载更轻、吞吐更高

8.6 opus-mt-en-zh

实现文件:

模型信息:

  • Hugging Face 名称:Helsinki-NLP/opus-mt-en-zh
  • 本地目录:models/translation/Helsinki-NLP/opus-mt-en-zh
  • 当前磁盘占用:约 1.5G
  • 模型类型:Marian / OPUS MT 专用双语翻译模型
  • 方向约束:只支持 en -> zh

结构特点:

  • encoder-decoder Seq2Seq
  • 双语定向模型
  • 更适合中英双向拆分部署

9. 本地模型安装与部署

9.1 准备环境

cd /data/saas-search
./scripts/setup_translator_venv.sh

9.2 下载模型

下载全部本地模型:

./.venv-translator/bin/python scripts/download_translation_models.py --all-local

下载完成后,默认目录应存在:

models/translation/facebook/nllb-200-distilled-600M
models/translation/Helsinki-NLP/opus-mt-zh-en
models/translation/Helsinki-NLP/opus-mt-en-zh

9.3 打开能力

编辑 <code>config/config.yaml</code>,把对应模型的 enabled 改成 true

9.4 启动服务

./scripts/start_translator.sh

建议:

  • 本地模型服务使用单 worker
  • 避免多 worker 重复加载模型
  • GPU 机器上优先使用 cuda + float16
  • CPU 只建议用于功能验证或离线低频任务
  • 对 NLLB,T4 上优先采用 batch_size=16 + max_new_tokens=64 + attn_implementation=sdpa

9.5 验证

健康检查:

curl http://127.0.0.1:6006/health

翻译测试:

curl -X POST http://127.0.0.1:6006/translate \
  -H 'Content-Type: application/json' \
  -d '{
    "text": "男士偏光飞行员太阳镜",
    "source_lang": "zh",
    "target_lang": "en",
    "model": "opus-mt-zh-en",
    "scene": "sku_name"
  }'

10. 性能测试与复现

性能脚本:

数据集:

复现命令:

cd /data/saas-search
./.venv-translator/bin/python scripts/benchmark_translation_local_models.py

单模型复现示例:

./.venv-translator/bin/python scripts/benchmark_translation_local_models.py \
  --single \
  --model opus-mt-zh-en \
  --source-lang zh \
  --target-lang en \
  --column title_cn \
  --scene sku_name

当前压测环境:

  • GPU:Tesla T4 16GB
  • Python env:.venv-translator
  • 数据量:18,576 条商品标题

最终性能结果:

Model Direction Device Rows Load s Translate s Items/s Avg item ms Batch p50 ms Batch p95 ms
opus-mt-zh-en zh -> en cuda 18,576 3.1435 497.7513 37.32 26.795 301.99 1835.81
opus-mt-en-zh en -> zh cuda 18,576 3.1867 987.3994 18.81 53.155 449.14 2012.12
nllb-200-distilled-600m zh -> en cuda 500 7.3397 25.9577 19.26 51.915 832.64 1263.01
nllb-200-distilled-600m en -> zh cuda 500 7.4152 42.0405 11.89 84.081 1093.87 2107.44

NLLB 性能优化经验:

  • 起作用的优化点 1:float16 + cuda
    • 模型确认以 torch.float16 实际加载到 cuda:0
    • 优化后在 T4 上的峰值显存约 2.8-3.0 GiB
  • 起作用的优化点 2:batch_size=16
    • 相比 batch_size=8,吞吐提升明显
    • 继续提升到 32 虽然还能增吞吐,但 batch p95 和 batch max 会恶化很多
  • 起作用的优化点 3:max_new_tokens=64
    • 商品标题翻译通常不需要 256 的生成上限
    • 收紧生成长度后,zh->enen->zh 都有明显收益
  • 起作用的优化点 4:attn_implementation=sdpa
    • 对当前 PyTorch + T4 环境有效
    • 配合半精度和较合理 batch size 后,整体延迟进一步下降

为什么最终没有采用其它方案:

  • 当前 HF 原生方案已经能在 T4 上稳定跑通
  • 10G+ 可用显存下,原生 float16 已足够支撑 NLLB-600M
  • 因此暂时不需要为这个模型额外引入 GGUF 或 CT2 的新运行栈
  • 如果未来目标变成“继续压缩显存”或“进一步追求更低延迟”,再评估 ct2-int8 会更合适

关键结论:

  • 当前机器上,opus-mt-zh-en 是三个新增本地模型里最快的
  • opus-mt-en-zh 大约是 opus-mt-zh-en 吞吐的一半
  • nllb-200-distilled-600M 在显存充足时可以用 cuda + float16 + batch_size=16 + max_new_tokens=64 + sdpa 正常运行
  • nllb 最终可用,但吞吐仍明显低于两个 Marian 模型,更适合多语覆盖或独立资源环境

最终推荐部署方案:

  • 模型:facebook/nllb-200-distilled-600M
  • 设备:cuda
  • 精度:float16
  • 推荐卡型:至少 Tesla T4 16GB 这一级别
  • 推荐 batch:16
  • 推荐 max_input_length256
  • 推荐 max_new_tokens64
  • 推荐 num_beams1
  • 推荐注意力实现:sdpa
  • 运行方式:单 worker,避免重复加载

更详细的性能说明见:

11. 开发说明

如果要新增翻译 backend,最少需要做这些事:

  1. <code>translation/backends/</code> 下新增实现
  2. <code>translation/service.py</code> 注册 backend 创建逻辑
  3. <code>config/config.yaml</code>services.translation.capabilities 中新增 capability 配置
  4. 如果有新的静态规则:

原则:

  • 不要再引入 translation provider 兼容层
  • 不要把 scene / prompt / 语言方向规则重新散落到别的目录
  • 不要在代码里写隐式默认和静默兼容

12. 常见建议

  • 中英商品标题双向场景,优先考虑 opus-mt-zh-enopus-mt-en-zh
  • 多语种统一方案,可以考虑 nllb-200-distilled-600M
  • nllb 更适合独占资源环境
  • 如果追求更高质量或更复杂语义处理,可使用 qwen-mtllm
  • 如果追求稳定商业 API,可考虑 deepl

13. 相关文档