00471f80
tangwang
trans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 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)
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
16
|
- 性能报告:[`perf_reports/20260318/translation_local_models/README.md`](/data/saas-search/perf_reports/20260318/translation_local_models/README.md)
|
00471f80
tangwang
trans
|
17
18
19
|
## 1. 设计目标
|
3eff49b7
tangwang
trans nllb-200-di...
|
20
|
翻译模块采用:
|
00471f80
tangwang
trans
|
21
22
23
24
25
26
|
- 一个 translator service
- 多个 capability backend
- 一个统一外部接口:`model + scene`
这套设计的目标是:
|
00471f80
tangwang
trans
|
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
- 翻译能力可以独立扩展、独立启停
- 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 翻译
|
ea293660
tangwang
CTranslate2
|
59
60
|
- [`translation/backends/local_ctranslate2.py`](/data/saas-search/translation/backends/local_ctranslate2.py)
本地 CTranslate2 翻译模型,包括 NLLB 和 Marian/OPUS MT
|
00471f80
tangwang
trans
|
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
## 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:
|
00471f80
tangwang
trans
|
78
79
|
ttl_seconds: 62208000
sliding_expiration: true
|
00471f80
tangwang
trans
|
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
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
|
cd4ce66d
tangwang
trans logs
|
94
|
use_cache: true
|
00471f80
tangwang
trans
|
95
96
97
98
99
|
deepl:
enabled: false
backend: "deepl"
api_url: "https://api.deepl.com/v2/translate"
timeout_sec: 10.0
|
cd4ce66d
tangwang
trans logs
|
100
|
use_cache: true
|
00471f80
tangwang
trans
|
101
102
103
104
105
|
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"
|
ea293660
tangwang
CTranslate2
|
106
107
108
109
|
ct2_model_dir: "./models/translation/facebook/nllb-200-distilled-600M/ctranslate2-float16"
ct2_compute_type: "float16"
ct2_conversion_quantization: "float16"
ct2_auto_convert: true
|
00471f80
tangwang
trans
|
110
111
|
device: "cuda"
torch_dtype: "float16"
|
3eff49b7
tangwang
trans nllb-200-di...
|
112
|
batch_size: 16
|
00471f80
tangwang
trans
|
113
|
max_input_length: 256
|
3eff49b7
tangwang
trans nllb-200-di...
|
114
|
max_new_tokens: 64
|
00471f80
tangwang
trans
|
115
|
num_beams: 1
|
cd4ce66d
tangwang
trans logs
|
116
|
use_cache: true
|
00471f80
tangwang
trans
|
117
118
119
120
121
|
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"
|
ea293660
tangwang
CTranslate2
|
122
123
124
125
|
ct2_model_dir: "./models/translation/Helsinki-NLP/opus-mt-zh-en/ctranslate2-float16"
ct2_compute_type: "float16"
ct2_conversion_quantization: "float16"
ct2_auto_convert: true
|
00471f80
tangwang
trans
|
126
127
128
129
130
131
|
device: "cuda"
torch_dtype: "float16"
batch_size: 16
max_input_length: 256
max_new_tokens: 256
num_beams: 1
|
cd4ce66d
tangwang
trans logs
|
132
|
use_cache: true
|
00471f80
tangwang
trans
|
133
134
135
136
137
|
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"
|
ea293660
tangwang
CTranslate2
|
138
139
140
141
|
ct2_model_dir: "./models/translation/Helsinki-NLP/opus-mt-en-zh/ctranslate2-float16"
ct2_compute_type: "float16"
ct2_conversion_quantization: "float16"
ct2_auto_convert: true
|
00471f80
tangwang
trans
|
142
143
144
145
146
147
|
device: "cuda"
torch_dtype: "float16"
batch_size: 16
max_input_length: 256
max_new_tokens: 256
num_beams: 1
|
cd4ce66d
tangwang
trans logs
|
148
|
use_cache: true
|
00471f80
tangwang
trans
|
149
150
151
152
153
154
155
156
157
158
159
160
161
|
```
配置边界:
- `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 读取
- 不再通过环境变量静默覆盖翻译行为配置
- 密钥仍通过环境变量提供
|
ea293660
tangwang
CTranslate2
|
162
|
- `local_nllb` / `local_marian` 当前由 CTranslate2 运行;首次启动时若 `ct2_model_dir` 不存在,会从 `model_dir` 自动转换
|
00471f80
tangwang
trans
|
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
## 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
{
|
cd4ce66d
tangwang
trans logs
|
263
|
"status": "healthy",
|
00471f80
tangwang
trans
|
264
265
266
267
268
|
"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"],
|
cd4ce66d
tangwang
trans logs
|
269
|
"loaded_models": ["qwen-mt", "llm", "nllb-200-distilled-600m", "opus-mt-zh-en", "opus-mt-en-zh"]
|
00471f80
tangwang
trans
|
270
271
272
|
}
```
|
cd4ce66d
tangwang
trans logs
|
273
274
275
276
|
说明:
- translator service 进程启动时会一次性初始化全部已启用 capability
- 因此本地模型加载失败、依赖缺失、配置错误会在启动阶段直接暴露,而不是拖到首个在线请求
|
00471f80
tangwang
trans
|
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
## 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",
)
```
|
1d6727ac
tangwang
trans
|
306
307
308
309
310
311
|
接口 shape 约定:
- `translate(text="...")` 返回 `Optional[str]`
- `translate(text=[...])` 返回 `List[Optional[str]]`
- 批量模式始终保持“等长、同序返回”;某条失败时对应位置为 `None`
- backend/client 可通过 `supports_batch` 暴露是否支持原生批量;服务端会在必要时自动逐条拆分并保持返回 shape 不变
|
00471f80
tangwang
trans
|
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
|
## 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
- 更灵活,但成本和稳定性取决于上游模型
|
cd4ce66d
tangwang
trans logs
|
337
|
- 支持 Redis 翻译缓存
|
00471f80
tangwang
trans
|
338
339
340
341
342
343
344
345
346
347
|
### 8.3 DeepL
实现文件:
- [`translation/backends/deepl.py`](/data/saas-search/translation/backends/deepl.py)
特点:
- 商业翻译 API
- scene 会映射到内部上下文
- 当前默认关闭
|
cd4ce66d
tangwang
trans logs
|
348
|
- 支持 Redis 翻译缓存
|
00471f80
tangwang
trans
|
349
350
351
352
|
### 8.4 `facebook/nllb-200-distilled-600M`
实现文件:
|
ea293660
tangwang
CTranslate2
|
353
|
- [`translation/backends/local_ctranslate2.py`](/data/saas-search/translation/backends/local_ctranslate2.py)
|
00471f80
tangwang
trans
|
354
355
356
|
模型信息:
- Hugging Face 名称:`facebook/nllb-200-distilled-600M`
|
1d6727ac
tangwang
trans
|
357
|
- 简介:多语种翻译:覆盖约 200 种语言。作为NLLB-200系列的蒸馏版本,该模型通过知识蒸馏技术将原130亿参数模型压缩至600M,同时保持了80%以上的翻译质量。
|
00471f80
tangwang
trans
|
358
359
|
- 本地目录:`models/translation/facebook/nllb-200-distilled-600M`
- 当前磁盘占用:约 `2.4G`
|
cd4ce66d
tangwang
trans logs
|
360
|
- 支持 Redis 翻译缓存
|
00471f80
tangwang
trans
|
361
|
- 模型类型:多语种 Seq2Seq 机器翻译模型
|
3eff49b7
tangwang
trans nllb-200-di...
|
362
|
- 来源:Meta NLLB(No Language Left Behind)系列的 600M 蒸馏版
|
00471f80
tangwang
trans
|
363
|
- 结构特点:
|
3eff49b7
tangwang
trans nllb-200-di...
|
364
365
366
|
- Transformer encoder-decoder 架构
- 12 层 encoder + 12 层 decoder
- `d_model=1024`
|
3eff49b7
tangwang
trans nllb-200-di...
|
367
368
|
- 通过 `source_lang + forced_bos_token_id` 控制翻译方向
- 语言标识采用 `language_script` 形式,例如 `eng_Latn`、`zho_Hans`
|
1d6727ac
tangwang
trans
|
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
|
- 改良 encoder-decoder(含嵌入层缩放 `scale_embedding`、相对位置等)
核心配置如下:
| 配置项 | 参数值 | 备注 |
| --- | --- | --- |
| 隐藏层维度(`d_model`) | 1024 | |
| 编码器 / 解码器层数 | 12 / 12 | |
| 注意力头数 | 16 | |
| FFN 维度 | 4096 | |
| 词表大小 | 256,206 | 多语统一词表 |
| 最大序列长度 | 1024 tokens | 满足长文本翻译 |
`config.json` 片段(示意):
```json
{
"d_model": 1024,
"encoder_layers": 12,
"decoder_layers": 12,
"attention_dropout": 0.1,
"use_cache": true,
"torch_dtype": "float32",
"max_length": 200
}
```
|
3eff49b7
tangwang
trans nllb-200-di...
|
395
396
397
398
|
模型定位:
- 优势是多语覆盖面广,一个模型可以支撑很多语言方向
- 劣势是相较于 Marian 这种双语专用模型,推理更重、延迟更高
|
1d6727ac
tangwang
trans
|
399
|
- 更适合做**索引翻译**(离线 / 批量),不建议作为在线 query 翻译的默认方案
|
3eff49b7
tangwang
trans nllb-200-di...
|
400
401
|
显存占用情况:
|
1d6727ac
tangwang
trans
|
402
|
- 600M 模型半精度(float16)权重约 `~1.25G`;推理还会叠加 CUDA context、allocator reserve、激活张量、batch、输入/生成长度等开销
|
3eff49b7
tangwang
trans nllb-200-di...
|
403
|
- 当前这台 `Tesla T4` 上,优化后的实际运行峰值大约在 `2.8-3.0 GiB`
|
00471f80
tangwang
trans
|
404
405
406
|
当前实现特点:
- backend 类型:`local_nllb`
|
ea293660
tangwang
CTranslate2
|
407
|
- 运行时:`CTranslate2 Translator`
|
00471f80
tangwang
trans
|
408
409
410
|
- 支持多语
- 调用时必须显式传 `source_lang`
- 语言码映射定义在 [`translation/languages.py`](/data/saas-search/translation/languages.py)
|
ea293660
tangwang
CTranslate2
|
411
|
- 当前 T4 推荐配置:`device=cuda`、`ct2_compute_type=float16`、`batch_size=16`、`max_new_tokens=64`
|
00471f80
tangwang
trans
|
412
|
|
1d6727ac
tangwang
trans
|
413
414
|
当前实现已经利用的优化:
- 已做批量分块:`translate()` 会按 capability 的 `batch_size` 分批进入模型
|
ea293660
tangwang
CTranslate2
|
415
416
417
|
- 已切换到 CTranslate2 推理引擎:不再依赖 PyTorch `generate()`
- 已设置方向控制:NLLB 通过 target prefix 指定目标语言
- 已启用半精度:当前配置为 `float16`
|
1d6727ac
tangwang
trans
|
418
419
420
421
422
423
424
425
426
427
|
- 已关闭高开销搜索:默认 `num_beams=1`,更接近线上低延迟设置
和你给出的批处理示例对照:
- 核心思路已经覆盖,现有实现与 `tokenizer(batch) -> model.generate(...) -> batch_decode(...)` 一致
- 差异在于服务端额外做了语言校验、统一 chunking、输入长度约束和单条/批量 shape 保持
- “预计算 attention mask” 目前没有单独缓存层;现状是每个 batch 在 tokenizer 阶段实时生成 `attention_mask`,这也是 HF 常规推理路径
优化空间(按场景):
- **线上 query**:优先补测 `batch_size=1` 的真实延迟与 tail latency,而不是继续拉大 batch。
- **离线批量**:可再尝试更激进的 batching / 长度分桶 / 独立批处理队列(吞吐更高,但会增加在线尾延迟风险)。
|
ea293660
tangwang
CTranslate2
|
428
|
- **进一步降显存 / 提速**:可在当前 CT2 方案上继续评估 `int8_float16`。
|
1d6727ac
tangwang
trans
|
429
|
|
00471f80
tangwang
trans
|
430
431
432
|
### 8.5 `opus-mt-zh-en`
实现文件:
|
ea293660
tangwang
CTranslate2
|
433
|
- [`translation/backends/local_ctranslate2.py`](/data/saas-search/translation/backends/local_ctranslate2.py)
|
00471f80
tangwang
trans
|
434
435
436
437
438
439
440
441
442
443
444
445
|
模型信息:
- 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
- 聚焦特定语言对
- 模型更小、加载更轻、吞吐更高
|
cd4ce66d
tangwang
trans logs
|
446
|
- 支持 Redis 翻译缓存
|
00471f80
tangwang
trans
|
447
448
449
450
|
### 8.6 `opus-mt-en-zh`
实现文件:
|
ea293660
tangwang
CTranslate2
|
451
|
- [`translation/backends/local_ctranslate2.py`](/data/saas-search/translation/backends/local_ctranslate2.py)
|
00471f80
tangwang
trans
|
452
453
454
455
456
457
458
459
460
461
462
463
|
模型信息:
- 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
- 双语定向模型
- 更适合中英双向拆分部署
|
cd4ce66d
tangwang
trans logs
|
464
465
466
467
468
469
470
|
- 支持 Redis 翻译缓存
### 8.7 翻译缓存
- 所有 translation capability 都使用统一的 Redis 缓存层
- 每个 capability 通过各自的 `use_cache` 控制是否启用缓存
- 缓存 key 格式固定为 `trans:{model}:{target_lang}:{source_text[:4]}{sha256}`
|
00471f80
tangwang
trans
|
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
|
## 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 只建议用于功能验证或离线低频任务
|
ea293660
tangwang
CTranslate2
|
512
|
- 对 NLLB,T4 上优先采用 `batch_size=16 + max_new_tokens=64 + ct2_compute_type=float16`
|
00471f80
tangwang
trans
|
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
|
### 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. 性能测试与复现
|
ea293660
tangwang
CTranslate2
|
538
539
540
541
|
说明:
- 本节现有数值是 `2026-03-18` 的 Hugging Face / PyTorch 基线结果。
- 切换到 CTranslate2 后需要重新跑一轮基准,尤其关注 `nllb-200-distilled-600m` 的单条延迟、并发 tail latency 和 `opus-mt-*` 的 batch throughput。
|
00471f80
tangwang
trans
|
542
543
544
545
546
547
|
性能脚本:
- [`scripts/benchmark_translation_local_models.py`](/data/saas-search/scripts/benchmark_translation_local_models.py)
数据集:
- [`products_analyzed.csv`](/data/saas-search/products_analyzed.csv)
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
|
最新报告:
- 摘要:[`perf_reports/20260318/translation_local_models/README.md`](/data/saas-search/perf_reports/20260318/translation_local_models/README.md)
- 完整 Markdown:[`perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.md`](/data/saas-search/perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.md)
- 完整 JSON:[`perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.json`](/data/saas-search/perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.json)
### 10.1 先看哪组数据
这里把 3 类结果分开看,不再混在一张表里:
- `batch_sweep`
固定 `concurrency=1`,只比较不同 `batch_size` 的单流批处理性能
- `concurrency_sweep`
固定 `batch_size=1`,看“单条请求”在不同并发下的延迟和吞吐
- `batch x concurrency matrix`
同时看 `batch_size` 和 `concurrency` 的交互效应;本轮限制为 `batch_size * concurrency <= 128`
建议:
- 看线上 query 翻译延迟:优先看 `concurrency_sweep`
- 看离线批量翻译吞吐:优先看 `batch_sweep`
- 看单 worker 服务容量边界:再看 `batch x concurrency matrix`
### 10.2 本轮补测参数
测试时间:`2026-03-18`
环境:
- GPU:`Tesla T4 16GB`
- Python env:`.venv-translator`
- Torch / Transformers:`2.10.0+cu128 / 5.3.0`
统一参数:
- cache:关闭(`--disable-cache`),避免缓存命中干扰性能结果
- `batch_sweep`:每档 `256` items
- `concurrency_sweep`:固定 `batch_size=1`,每档 `32` requests
- `batch x concurrency matrix`:每档 `32` requests,且只保留 `batch_size * concurrency <= 128`
- 预热:`1` batch
|
00471f80
tangwang
trans
|
586
587
588
589
590
591
592
|
复现命令:
```bash
cd /data/saas-search
./.venv-translator/bin/python scripts/benchmark_translation_local_models.py
```
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
593
594
595
596
597
598
599
600
601
602
603
604
605
606
|
本轮扩展压测复现命令:
```bash
cd /data/saas-search
./.venv-translator/bin/python scripts/benchmark_translation_local_models.py \
--suite extended \
--disable-cache \
--serial-items-per-case 256 \
--concurrency-requests-per-case 32 \
--concurrency-batch-size 1 \
--output-dir perf_reports/20260318/translation_local_models
```
单模型扩展压测示例:
|
00471f80
tangwang
trans
|
607
608
609
610
|
```bash
./.venv-translator/bin/python scripts/benchmark_translation_local_models.py \
--single \
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
611
|
--suite extended \
|
00471f80
tangwang
trans
|
612
613
614
615
|
--model opus-mt-zh-en \
--source-lang zh \
--target-lang en \
--column title_cn \
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
616
617
618
619
620
621
622
|
--scene sku_name \
--disable-cache \
--batch-size-list 1,4,8,16,32,64 \
--concurrency-list 1,2,4,8,16,64 \
--serial-items-per-case 256 \
--concurrency-requests-per-case 32 \
--concurrency-batch-size 1
|
00471f80
tangwang
trans
|
623
624
|
```
|
1d6727ac
tangwang
trans
|
625
626
627
628
629
|
单条请求延迟复现:
```bash
./.venv-translator/bin/python scripts/benchmark_translation_local_models.py \
--single \
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
630
|
--suite extended \
|
1d6727ac
tangwang
trans
|
631
632
633
634
635
|
--model nllb-200-distilled-600m \
--source-lang zh \
--target-lang en \
--column title_cn \
--scene sku_name \
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
636
637
638
639
640
641
|
--disable-cache \
--batch-size-list 1 \
--concurrency-list 1,2,4,8,16,64 \
--serial-items-per-case 256 \
--concurrency-requests-per-case 32 \
--concurrency-batch-size 1
|
1d6727ac
tangwang
trans
|
642
643
|
```
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
|
### 10.3 单流 batch 结果
这组只看 `concurrency=1`,不要把这里的 `request p95` 当作线上并发请求的 p95。
`nllb-200-distilled-600m zh -> en`
| Batch | Items/s | Avg item ms | Req p95 ms |
|---:|---:|---:|---:|
| 1 | 2.91 | 343.488 | 616.27 |
| 4 | 8.44 | 118.545 | 722.95 |
| 8 | 14.85 | 67.335 | 728.47 |
| 16 | 27.28 | 36.662 | 769.18 |
| 32 | 38.6 | 25.908 | 1369.88 |
| 64 | 58.3 | 17.152 | 1659.9 |
`nllb-200-distilled-600m en -> zh`
| Batch | Items/s | Avg item ms | Req p95 ms |
|---:|---:|---:|---:|
| 1 | 1.91 | 524.917 | 866.33 |
| 4 | 4.94 | 202.473 | 1599.74 |
| 8 | 8.25 | 121.188 | 1632.29 |
| 16 | 13.52 | 73.956 | 1649.65 |
| 32 | 21.27 | 47.017 | 1827.16 |
| 64 | 32.64 | 30.641 | 2031.25 |
|
1d6727ac
tangwang
trans
|
669
|
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
670
|
`opus-mt-zh-en zh -> en`
|
1d6727ac
tangwang
trans
|
671
|
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
|
| Batch | Items/s | Avg item ms | Req p95 ms |
|---:|---:|---:|---:|
| 1 | 6.15 | 162.536 | 274.74 |
| 4 | 15.34 | 65.192 | 356.0 |
| 8 | 25.51 | 39.202 | 379.84 |
| 16 | 41.44 | 24.129 | 797.93 |
| 32 | 54.36 | 18.397 | 1693.31 |
| 64 | 70.15 | 14.255 | 2161.59 |
`opus-mt-en-zh en -> zh`
| Batch | Items/s | Avg item ms | Req p95 ms |
|---:|---:|---:|---:|
| 1 | 4.53 | 220.598 | 411.57 |
| 4 | 10.12 | 98.844 | 761.49 |
| 8 | 14.63 | 68.361 | 1930.85 |
| 16 | 24.33 | 41.1 | 2098.54 |
| 32 | 33.91 | 29.487 | 2152.28 |
| 64 | 42.47 | 23.547 | 2371.85 |
批处理结论:
- 纯吞吐看,4 个方向的最佳 raw throughput 都出现在 `batch_size=64`
- 如果还要兼顾单个 batch 的尾延迟,`batch_size=16` 往往更均衡
- `opus-mt-zh-en` 是本轮 bulk 场景最快模型,`nllb en->zh` 最慢
### 10.4 单条请求并发结果
这组固定 `batch_size=1`,可以直接理解成“单条请求在不同并发下的表现”。
`nllb-200-distilled-600m zh -> en`
| Concurrency | Items/s | Avg req ms | Req p50 ms | Req p95 ms |
|---:|---:|---:|---:|---:|
| 1 | 4.17 | 239.99 | 226.34 | 373.27 |
| 2 | 4.1 | 477.99 | 459.36 | 703.96 |
| 4 | 4.1 | 910.74 | 884.71 | 1227.01 |
| 8 | 4.04 | 1697.73 | 1818.48 | 2383.8 |
| 16 | 4.07 | 2801.91 | 3473.63 | 4145.92 |
| 64 | 4.04 | 3714.49 | 3610.08 | 7337.3 |
`nllb-200-distilled-600m en -> zh`
| Concurrency | Items/s | Avg req ms | Req p50 ms | Req p95 ms |
|---:|---:|---:|---:|---:|
| 1 | 2.16 | 463.18 | 439.54 | 670.78 |
| 2 | 2.15 | 920.48 | 908.27 | 1213.3 |
| 4 | 2.16 | 1759.87 | 1771.58 | 2158.04 |
| 8 | 2.15 | 3284.44 | 3658.45 | 3971.01 |
| 16 | 2.14 | 5669.15 | 7117.7 | 7522.48 |
| 64 | 2.14 | 7631.14 | 7510.97 | 14139.03 |
`opus-mt-zh-en zh -> en`
| Concurrency | Items/s | Avg req ms | Req p50 ms | Req p95 ms |
|---:|---:|---:|---:|---:|
| 1 | 9.21 | 108.53 | 91.7 | 179.12 |
| 2 | 8.92 | 219.19 | 212.29 | 305.34 |
| 4 | 9.09 | 411.76 | 420.08 | 583.97 |
| 8 | 8.85 | 784.14 | 835.73 | 1043.06 |
| 16 | 9.01 | 1278.4 | 1483.34 | 1994.56 |
| 64 | 8.82 | 1687.08 | 1563.48 | 3381.58 |
`opus-mt-en-zh en -> zh`
| Concurrency | Items/s | Avg req ms | Req p50 ms | Req p95 ms |
|---:|---:|---:|---:|---:|
| 1 | 3.6 | 277.73 | 145.85 | 1180.37 |
| 2 | 3.55 | 559.38 | 346.71 | 1916.96 |
| 4 | 3.53 | 997.71 | 721.04 | 2944.17 |
| 8 | 3.51 | 1644.28 | 1590.93 | 3632.99 |
| 16 | 3.5 | 2600.18 | 2586.34 | 5554.04 |
| 64 | 3.52 | 3366.52 | 2780.0 | 7950.41 |
|
00471f80
tangwang
trans
|
745
|
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
746
747
748
749
750
751
752
753
754
755
756
757
|
并发结论:
- 当前本地 seq2seq backend 内部是单模型锁,单 worker 下提高客户端并发基本不会提升吞吐,主要会把等待时间堆到请求延迟上
- 线上 query 翻译如果追求稳定延迟,应优先控制在低并发;`8+` 并发后,4 个方向的 p95 都明显恶化
- 在线场景里,`opus-mt-zh-en` 延迟最稳;`nllb en->zh` 最慢,且并发放大后尾延迟最明显
### 10.5 batch x concurrency 怎么看
完整矩阵见:
- [`perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.md`](/data/saas-search/perf_reports/20260318/translation_local_models/translation_local_models_extended_221846.md)
这张表主要回答两个问题:
|
00471f80
tangwang
trans
|
758
|
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
759
760
761
762
763
764
765
766
|
- 如果已经知道自己要跑离线批处理,`batch_size` 拉大后,在不同并发下吞吐会不会继续涨
- 如果要拿单 worker 服务扛请求,在哪个 `batch_size x concurrency` 组合下开始明显排队
本轮矩阵的共同特征:
- 吞吐主要由 `batch_size` 决定,`concurrency` 不是主要增益来源
- 在 `batch_size` 固定时,`concurrency` 从 `1` 升到 `2/4/8/...`,`items/s` 变化很小,但 `avg req ms / p95` 会持续抬升
- 因此当前实现更像“单 worker + 内部串行 GPU 推理服务”,不是一个靠客户端并发放大吞吐的服务
|
3eff49b7
tangwang
trans nllb-200-di...
|
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
|
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 后,整体延迟进一步下降
|
1d6727ac
tangwang
trans
|
782
783
784
|
- 已有但不需要单独开关的点:`attention_mask`
- 当前实现会在 tokenizer 阶段自动生成并传入 `generate()`
- 它属于标准推理路径,不是一个额外的“高级优化开关”
|
3eff49b7
tangwang
trans nllb-200-di...
|
785
786
787
788
789
790
791
|
为什么最终没有采用其它方案:
- 当前 HF 原生方案已经能在 T4 上稳定跑通
- 在 `10G+` 可用显存下,原生 `float16` 已足够支撑 NLLB-600M
- 因此暂时不需要为这个模型额外引入 GGUF 或 CT2 的新运行栈
- 如果未来目标变成“继续压缩显存”或“进一步追求更低延迟”,再评估 `ct2-int8` 会更合适
|
00471f80
tangwang
trans
|
792
793
794
795
796
|
关键结论:
- 当前机器上,`opus-mt-zh-en` 是三个新增本地模型里最快的
- `opus-mt-en-zh` 大约是 `opus-mt-zh-en` 吞吐的一半
|
3eff49b7
tangwang
trans nllb-200-di...
|
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
|
- `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,避免重复加载
|
00471f80
tangwang
trans
|
812
813
|
更详细的性能说明见:
|
2a6d9d76
tangwang
更新了压测脚本和文档,让“单条请求...
|
814
|
- [`perf_reports/20260318/translation_local_models/README.md`](/data/saas-search/perf_reports/20260318/translation_local_models/README.md)
|
00471f80
tangwang
trans
|
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
|
## 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. 相关文档
|
1d6727ac
tangwang
trans
|
843
|
- [`docs/翻译模块说明.md`](/data/saas-search/docs/翻译模块说明.md)(已收口到本 README,保留为跳转页)
|
00471f80
tangwang
trans
|
844
845
846
|
- [`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)
|