跨年夜的意外发现
2025年12月31日凌晨,当大多数人还在准备跨年倒计时的时候,我正盯着一组让我困惑的数字:
旧版 COMET-QE: 0.5143
新版 COMET-QE: 0.4649
新版怎么比旧版还差?
几天前我刚给 Master-Translator-MCP-Server 做了一轮重构,加了术语表支持、优化了分块算法。按理说应该更好才对。但 COMETKiwi 评估结果无情地告诉我:新版翻译质量下降了近5%。
这不对劲。作为一个追求极致的工程师,我决定彻底搞清楚原因。
于是,一场深夜 Debug 马拉松开始了。
抽丝剥茧:四个隐藏的Bug
Bug 1: Prompt 残留污染
翻开新版翻译的输出文件,我发现了一些不该出现的东西:
---BEGIN CONTENT---
# 第一章 人工智能的浪潮
<key_terminology>
- The Coming Wave → 浪潮将至
</key_terminology>
这些 ---BEGIN CONTENT---、<key_terminology> 是我在 Prompt 中用来标记内容边界的标签。LLM 本应只输出翻译内容,但它"照搬"了部分 Prompt 结构。
根因:clean_llm_output() 函数的清理规则不够全面,没有覆盖这些新增的标签模式。
修复:增加了15+个正则表达式模式来清理各类 Prompt 残留:
# 清理 Prompt 残留的各种标记
patterns_to_remove = [
r'---\s*BEGIN\s*CONTENT\s*---',
r'---\s*END\s*CONTENT\s*---',
r'<key_terminology>.*?</key_terminology>',
r'<previous_context>.*?</previous_context>',
# ... 更多模式
]
Bug 2: 分块边界重复
对比原文和译文的结构时,我发现一个诡异的现象:
原文: 107 个标题, 2632 行
译文: 107 个标题, 但有些章节标题出现了两次!
问题出在分块合并时的重叠处理。当两个相邻块的边界恰好在章节标题附近时,remove_overlap() 函数只检测了标题级别的重复,没有正确处理段落级别的重复。
修复:重写了 remove_overlap() 函数,改为按段落处理,一旦检测到重复段落,跳过整个段落而非仅删除标题:
def remove_overlap(self, prev_text: str, curr_text: str) -> str:
# 按段落分割
paragraphs = curr_text.split('\n\n')
result = []
for para in paragraphs:
# 检查是否与前文重复
if para.strip() and para.strip() in prev_text:
continue # 跳过重复段落
result.append(para)
return '\n\n'.join(result)
Bug 3: 模型别名缺失
查看日志时发现一条警告:
⚠️ 模型 deepseek 未在配置中找到,使用 deepseek-free
原来我在 config.env 中配置的是 MODEL=deepseek,但 llm_provider.py 中只定义了 deepseek-official 和 deepseek-free。于是系统回退到了免费版模型——这可能是质量下降的重要原因之一!
修复:在 MODEL_CONFIGS 中添加 deepseek 作为 deepseek-official 的别名:
MODEL_CONFIGS = {
"deepseek": {...}, # 别名
"deepseek-official": {...}, # 正式名
"deepseek-free": {...},
}
Bug 4: 术语表格式解析错误
这是一个更隐蔽的问题。术语表有两种格式:
// 格式1
{"source": "The Coming Wave", "target": "浪潮将至"}
// 格式2
{"term": "The Coming Wave", "translation": "浪潮将至"}
代码只正确处理了格式1,对格式2只读取了 term 字段,完全忽略了 translation!这意味着术语表实际上没有生效。
并行翻译:从57分钟到10分钟
修完这些 Bug 后,我萌生了另一个想法:能不能让翻译更快?
当前的串行模式下,60万字符的书需要约57分钟。每个 Chunk 串行处理,等待上一个完成才开始下一个。
但仔细想想,如果我们有术语表来保证一致性,是否还需要上下文传递?
并行翻译的核心思想:让多个 Chunk 同时翻译,依靠术语表(而非前文上下文)来保证术语一致性。
实现
使用 Python 的 asyncio 实现并发控制:
async def translate_document_parallel(self, document_path, target_language):
# 控制并发数,避免 API 限流
semaphore = asyncio.Semaphore(max_concurrent)
async def translate_with_limit(chunk_id, chunk_content):
async with semaphore:
return await self._translate_single_chunk(chunk_id, chunk_content)
# 所有 Chunk 并行翻译
tasks = [translate_with_limit(i, chunk) for i, chunk in enumerate(chunks)]
results = await asyncio.gather(*tasks)
return merge_results(results)
效果
| 模式 | 翻译时间 | 相对速度 |
|---|---|---|
| 串行 | ~57 min | 1x |
| 并行 (5并发) | 10.3 min | 5.5x |
速度提升 5.5 倍!
Temperature 的意外发现
在优化过程中,我还做了一个对照实验:Temperature 对翻译质量的影响。
旧版使用 temperature=0.3(更确定性),而 DeepSeek 官方推荐翻译场景使用 temperature=1.3(更多样性)。
| 配置 | COMET-QE | 结论 |
|---|---|---|
| 并行 t=1.3 | 0.5016 | ✅ 更好 |
| 并行 t=0.3 | 0.4983 | 略差 |
意外的是,高 temperature 反而产生了更好的翻译质量!
这可能是因为:
- 高 temperature 让模型有更多空间选择自然流畅的表达
- 对于翻译任务,"创意"体现在措辞的地道性上
- 术语表已经约束了关键词的一致性,无需用低 temperature 来"控制"
最终结果:33.3% 质量提升
经过一夜的调试和优化,凌晨2点多,我运行了最终版本的翻译:
🎉 翻译完成!
模式: parallel
并发数: 5
总 Chunks: 60
输入字符: 611,586
输出字符: 189,931
翻译耗时: 616 秒 (10.3 分钟)
成本: $0.85
然后是激动人心的 QE 评估:
✅ COMETKIWI 系统分: 0.5428
0.5428!
让我整理一下完整的对比:
| 方法 | COMET-QE | 相对 Baseline | 翻译耗时 |
|---|---|---|---|
| Baseline (overlap_12k) | 0.4071 | - | - |
| 旧版 ContextWeave (串行) | 0.5143 | +26.3% | ~57 min |
| 新版 ContextWeave (并行) | 0.5428 | +33.3% | 10.3 min |
这意味着:
- 🚀 质量提升 33.3%:比 Baseline 提升了三分之一
- ⚡ 速度提升 5.5x:从近1小时缩短到10分钟
- 💰 成本仅 $0.85:60万字符完整书籍翻译
在 Layer 3 的验证:超越人工翻译
除了 Mustafa Book (The Coming Wave) 这本书,我还在 FIDIC EPC 工程合同上进行了验证。这是一份专业的法律文档,有严格的术语要求。
| 方向 | BLEU | COMETKiwi | vs 人工翻译 | 术语一致率 |
|---|---|---|---|---|
| 中→英 | 89.30 | 0.4163 | +3.7% | 100% |
| 英→中 | 65.32 | 0.4040 | +1.4% | 100% |
两个方向都超越了人工翻译!
更有意思的是,在评估过程中,我还发现了官方中文译本中的一个 OCR 错误——"免除"被误录入为"危险"。而 ContextWeave 的翻译是正确的。
技术总结
这次优化的核心经验:
- 不要假设代码正确 - 即使是自己写的代码,也可能有隐藏 Bug
- 评估指标很重要 - 没有 COMET-QE,我可能永远不知道新版更差
- 并行不一定牺牲质量 - 用术语表替代上下文传递,可以兼得速度和一致性
- 官方推荐值有道理 - DeepSeek 推荐的 temperature=1.3 确实更适合翻译
- 模型选择很关键 - 回退到免费版模型是质量下降的重要原因
跨年感言
写完这篇博文,窗外的天已经亮了。2025年的最后一天,我在键盘前度过。
有人可能觉得这样过节有点"卷",但对我来说,解决一个困扰已久的问题、看到评估分数一步步提升,这种成就感比任何跨年烟火都让我兴奋。
2025年,我从一个 C++ 工程师转型为 AI 工程师,开发了 Master-Translator、参加了 Hackathon、写了专利申请...
2026年,ACL 论文投稿在即。这个 33.3% 的质量提升,将成为论文中最硬核的实验数据之一。
新年快乐!🎉
如果你也在做长文档翻译相关的工作,欢迎关注 Master-Translator-MCP-Server 项目。
祝大家2026年,代码无 Bug,论文全中稿!
