# 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. 设计目标 翻译模块已经从旧的 provider 体系中独立出来,采用: - 一个 translator service - 多个 capability backend - 一个统一外部接口:`model + scene` 这套设计的目标是: - 业务侧不再关心具体翻译 provider 细节 - 翻译能力可以独立扩展、独立启停 - 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: 8 max_input_length: 256 max_new_tokens: 256 num_beams: 1 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 机器翻译模型 - 结构特点: - encoder-decoder 架构 - 面向多语种互译 - 通过语言码控制源语言和目标语言 当前实现特点: - backend 类型:`local_nllb` - 支持多语 - 调用时必须显式传 `source_lang` - 语言码映射定义在 [`translation/languages.py`](/data/saas-search/translation/languages.py) 适合场景: - 需要多语覆盖 - 需要一个模型处理多语言对 不太适合: - 当前共享 GPU 环境下的常驻在线服务 ### 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 只建议用于功能验证或离线低频任务 ### 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` | `cpu` | 128 | 4.4589 | 132.3088 | 0.97 | 1033.662 | 3853.39 | 6896.14 | | `nllb-200-distilled-600m` | `en -> zh` | `cpu` | 128 | 4.5039 | 317.8845 | 0.40 | 2483.473 | 6138.87 | 35134.11 | 关键结论: - 当前机器上,`opus-mt-zh-en` 是三个新增本地模型里最快的 - `opus-mt-en-zh` 大约是 `opus-mt-zh-en` 吞吐的一半 - `nllb-200-distilled-600M` 在当前共享 T4 环境下无法完成 GPU 冷启动,会 OOM - `nllb` 的 CPU fallback 可用,但明显更慢,更适合隔离部署或离线任务 更详细的性能说明见: - [`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)