# Translation Module `translation/` 是当前项目翻译能力的主目录。 如果要开发、部署、联调、压测翻译服务,优先看这份文档。 对应服务: - translator service:`http://127.0.0.1:6006` - 业务侧统一通过 [`translation/client.py`](/data/saas-search/translation/client.py) 调用 - 服务内统一通过 [`translation/service.py`](/data/saas-search/translation/service.py) 路由到具体翻译实现 相关脚本与报告: - 启动脚本:[`scripts/start_translator.sh`](/data/saas-search/scripts/start_translator.sh) - 虚拟环境:[`scripts/setup_translator_venv.sh`](/data/saas-search/scripts/setup_translator_venv.sh) - 模型下载:[`scripts/download_translation_models.py`](/data/saas-search/scripts/download_translation_models.py) - 本地模型压测:[`scripts/benchmark_translation_local_models.py`](/data/saas-search/scripts/benchmark_translation_local_models.py) - 性能报告:[`perf_reports/20260317/translation_local_models/README.md`](/data/saas-search/perf_reports/20260317/translation_local_models/README.md) ## 1. 设计目标 翻译模块采用: - 一个 translator service - 多个 capability backend - 一个统一外部接口:`model + scene` 这套设计的目标是: - 翻译能力可以独立扩展、独立启停 - scene、语言码、prompt 模板、模型方向约束等翻译域知识集中在 `translation/` - 配置尽量集中在 [`config/config.yaml`](/data/saas-search/config/config.yaml) 的 `services.translation` - 配置错误应尽早报错,不做静默兼容和隐式回退 ## 2. 目录结构 核心文件: - [`translation/client.py`](/data/saas-search/translation/client.py) 业务侧 HTTP client,供 query/indexer 等模块调用 - [`translation/service.py`](/data/saas-search/translation/service.py) translator service 内部的统一编排层 - [`translation/settings.py`](/data/saas-search/translation/settings.py) 翻译配置的规范化与校验辅助函数 - [`translation/scenes.py`](/data/saas-search/translation/scenes.py) scene 规范和值校验 - [`translation/languages.py`](/data/saas-search/translation/languages.py) 语言码映射、Marian 方向映射等静态知识 - [`translation/prompts.py`](/data/saas-search/translation/prompts.py) LLM 翻译 prompt 模板 - [`translation/protocols.py`](/data/saas-search/translation/protocols.py) 输入输出协议类型 后端实现: - [`translation/backends/qwen_mt.py`](/data/saas-search/translation/backends/qwen_mt.py) Qwen-MT 云端翻译 - [`translation/backends/llm.py`](/data/saas-search/translation/backends/llm.py) 通用 LLM 翻译 - [`translation/backends/deepl.py`](/data/saas-search/translation/backends/deepl.py) DeepL 翻译 - [`translation/backends/local_seq2seq.py`](/data/saas-search/translation/backends/local_seq2seq.py) 本地 Hugging Face Seq2Seq 模型,包括 NLLB 和 Marian/OPUS MT ## 3. 配置约定 翻译的部署配置统一放在: - [`config/config.yaml`](/data/saas-search/config/config.yaml) -> `services.translation` 示例: ```yaml 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_url`、`default_model`、`default_scene`、`enabled`、`base_url`、`api_url`、`model_dir`、`device` - translation 目录内部放翻译静态知识 例如 scene 规则、语言码映射、prompt 模板、Marian 方向约束 说明: - `service_url`、`default_model`、`default_scene` 只从 YAML 读取 - 不再通过环境变量静默覆盖翻译行为配置 - 密钥仍通过环境变量提供 ## 4. 环境变量 当前翻译模块主要依赖: ```bash # Qwen / LLM DASHSCOPE_API_KEY=sk-xxx # DeepL DEEPL_AUTH_KEY=xxx ``` 服务启动端口仍可以由启动脚本环境控制: ```bash TRANSLATION_HOST=0.0.0.0 TRANSLATION_PORT=6006 ``` ## 5. Scene 规则 当前只支持 3 个标准 scene: - `general` - `sku_name` - `ecommerce_search_query` 定义位置: - [`translation/scenes.py`](/data/saas-search/translation/scenes.py) 约定: - `scene` 是公共接口字段 - 不再接受旧的 `context` - 不再对外暴露 `prompt` - LLM prompt 在服务内根据 `scene` 自动生成 ## 6. 对外 HTTP 接口 服务入口在: - [`api/translator_app.py`](/data/saas-search/api/translator_app.py) 默认地址: - `http://localhost:6006` 提供接口: - `POST /translate` - `GET /health` ### 6.1 POST /translate 请求体: ```json { "text": "商品名称", "target_lang": "en", "source_lang": "zh", "model": "opus-mt-zh-en", "scene": "sku_name" } ``` 字段说明: - `text` 支持 `string` 或 `string[]` - `target_lang` 目标语言 - `source_lang` 源语言 - `model` 已配置的 capability 名称 - `scene` 翻译场景 响应体: ```json { "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 返回示例: ```json { "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. 代码调用方式 业务侧统一这样调用: ```python 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", ) ``` 批量调用: ```python 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 实现文件: - [`translation/backends/qwen_mt.py`](/data/saas-search/translation/backends/qwen_mt.py) 特点: - 云端机翻 - 支持 Redis 翻译缓存 - 适合质量优先、非超高并发场景 注意: - 当前默认 `qwen-mt-flash` 限速较低 - 大量重复请求应依赖缓存 ### 8.2 LLM Translation 实现文件: - [`translation/backends/llm.py`](/data/saas-search/translation/backends/llm.py) 特点: - 通用大模型翻译 - 根据 `scene` 生成内部 prompt - 更灵活,但成本和稳定性取决于上游模型 ### 8.3 DeepL 实现文件: - [`translation/backends/deepl.py`](/data/saas-search/translation/backends/deepl.py) 特点: - 商业翻译 API - scene 会映射到内部上下文 - 当前默认关闭 ### 8.4 `facebook/nllb-200-distilled-600M` 实现文件: - [`translation/backends/local_seq2seq.py`](/data/saas-search/translation/backends/local_seq2seq.py) 模型信息: - 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_Latn`、`zho_Hans` 模型定位: - 优势是多语覆盖面广,一个模型可以支撑很多语言方向 - 劣势是相较于 Marian 这种双语专用模型,推理更重、延迟更高 - 在我们当前业务里,它更适合“多语覆盖优先”的场景,不适合拿来和专用中英模型拼极致吞吐 显存占用情况: - 600M模型半float16权重约1.25G,推理时会叠加 CUDA context、allocator reserve、激活张量、batch、输入长度、生成长度等开销 - 当前这台 `Tesla T4` 上,优化后的实际运行峰值大约在 `2.8-3.0 GiB` 当前实现特点: - backend 类型:`local_nllb` - 支持多语 - 调用时必须显式传 `source_lang` - 语言码映射定义在 [`translation/languages.py`](/data/saas-search/translation/languages.py) - 当前 T4 推荐配置:`device=cuda`、`torch_dtype=float16`、`batch_size=16`、`max_new_tokens=64`、`attn_implementation=sdpa` ### 8.5 `opus-mt-zh-en` 实现文件: - [`translation/backends/local_seq2seq.py`](/data/saas-search/translation/backends/local_seq2seq.py) 模型信息: - 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` 实现文件: - [`translation/backends/local_seq2seq.py`](/data/saas-search/translation/backends/local_seq2seq.py) 模型信息: - 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 准备环境 ```bash cd /data/saas-search ./scripts/setup_translator_venv.sh ``` ### 9.2 下载模型 下载全部本地模型: ```bash ./.venv-translator/bin/python scripts/download_translation_models.py --all-local ``` 下载完成后,默认目录应存在: ```bash 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 打开能力 编辑 [`config/config.yaml`](/data/saas-search/config/config.yaml),把对应模型的 `enabled` 改成 `true`。 ### 9.4 启动服务 ```bash ./scripts/start_translator.sh ``` 建议: - 本地模型服务使用单 worker - 避免多 worker 重复加载模型 - GPU 机器上优先使用 `cuda + float16` - CPU 只建议用于功能验证或离线低频任务 - 对 NLLB,T4 上优先采用 `batch_size=16 + max_new_tokens=64 + attn_implementation=sdpa` ### 9.5 验证 健康检查: ```bash curl http://127.0.0.1:6006/health ``` 翻译测试: ```bash 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. 性能测试与复现 性能脚本: - [`scripts/benchmark_translation_local_models.py`](/data/saas-search/scripts/benchmark_translation_local_models.py) 数据集: - [`products_analyzed.csv`](/data/saas-search/products_analyzed.csv) 复现命令: ```bash cd /data/saas-search ./.venv-translator/bin/python scripts/benchmark_translation_local_models.py ``` 单模型复现示例: ```bash ./.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->en` 与 `en->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_length`:`256` - 推荐 `max_new_tokens`:`64` - 推荐 `num_beams`:`1` - 推荐注意力实现:`sdpa` - 运行方式:单 worker,避免重复加载 更详细的性能说明见: - [`perf_reports/20260317/translation_local_models/README.md`](/data/saas-search/perf_reports/20260317/translation_local_models/README.md) ## 11. 开发说明 如果要新增翻译 backend,最少需要做这些事: 1. 在 [`translation/backends/`](/data/saas-search/translation/backends) 下新增实现 2. 在 [`translation/service.py`](/data/saas-search/translation/service.py) 注册 backend 创建逻辑 3. 在 [`config/config.yaml`](/data/saas-search/config/config.yaml) 的 `services.translation.capabilities` 中新增 capability 配置 4. 如果有新的静态规则: - scene 规则放到 [`translation/scenes.py`](/data/saas-search/translation/scenes.py) - 语言映射放到 [`translation/languages.py`](/data/saas-search/translation/languages.py) - prompt 模板放到 [`translation/prompts.py`](/data/saas-search/translation/prompts.py) 原则: - 不要再引入 translation provider 兼容层 - 不要把 scene / prompt / 语言方向规则重新散落到别的目录 - 不要在代码里写隐式默认和静默兼容 ## 12. 常见建议 - 中英商品标题双向场景,优先考虑 `opus-mt-zh-en` 和 `opus-mt-en-zh` - 多语种统一方案,可以考虑 `nllb-200-distilled-600M` - 但 `nllb` 更适合独占资源环境 - 如果追求更高质量或更复杂语义处理,可使用 `qwen-mt` 或 `llm` - 如果追求稳定商业 API,可考虑 `deepl` ## 13. 相关文档 - [`docs/翻译模块说明.md`](/data/saas-search/docs/翻译模块说明.md) - [`docs/QUICKSTART.md`](/data/saas-search/docs/QUICKSTART.md) - [`docs/DEVELOPER_GUIDE.md`](/data/saas-search/docs/DEVELOPER_GUIDE.md) - [`docs/搜索API对接指南.md`](/data/saas-search/docs/搜索API对接指南.md)