- Refactor codebase into src/ (preprocessing, translation, assembly) - Add pipeline/ scripts for individual stages - Externalize configuration to config/config.yaml - Fix Cover Image preservation - Update documentation and manuals
7.0 KiB
7.0 KiB
纯中文模式格式丢失问题 - 深度分析
🔴 根本原因:Mode 参数未被正确传递
问题概述
当前 translator.py 的 translate_epub() 方法签名只有 3 个参数:
async def translate_epub(self, epub_path: str, test_mode: bool = False, output_dir: str = None) -> str:
缺失 mode 参数! 这意味着:
- 无论用户指定
-m chinese还是-m bilingual,都走相同的代码路径 - 永远使用
BilingualEPUBBuilder - 格式提取功能 (
format_extractor.py) 从未被调用
问题链路分析
main.py 调用
# main.py:55-59
await translator.translate_epub(
args.epub_path,
test_mode=args.test,
output_dir=args.output,
mode=args.mode # ❌ 此参数被忽略!因为 translate_epub 不接受 mode
)
translator.py 未处理 mode
# translator.py:39 - 缺少 mode 参数
async def translate_epub(self, epub_path: str, test_mode: bool = False, output_dir: str = None) -> str:
# translator.py:53 - 提取时未传 mode
self.text_processor.extract_to_manifest(item['content'], item['file_name'], manifest)
# 应该是: extract_to_manifest(..., mode=mode)
# translator.py:72 - 分块时未传 mode
chunks = self.text_processor.create_chunks_from_manifest(manifest)
# 应该是: create_chunks_from_manifest(manifest, mode=mode)
# translator.py:84 - 永远使用 BilingualBuilder
builder = BilingualEPUBBuilder(self.parser.book, self.config)
# 应根据 mode 选择 ChineseEPUBBuilder
完整的格式保留流程 (应有逻辑)
┌─────────────────────────────────────────────────────────────────┐
│ 1. 提取阶段 (format_extractor.py) │
│ Input: <p>This is <strong>bold</strong> text.</p> │
│ Output: │
│ - clean_text: "This is bold text." │
│ - text_with_placeholders: "This is φc00001φboldφc00002φ text." │
│ - placeholder_map: {c00001: "<strong>", c00002: "</strong>"} │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. 翻译阶段 (llm_client.py) │
│ Prompt: p_00001 [BODY] This is φc00001φboldφc00002φ text. │
│ LLM Response: p_00001 这是φc00001φ粗体φc00002φ文本。 │
│ ⚠️ 问题:LLM 可能丢失/错放占位符! │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. 还原阶段 (format_restorer.py) │
│ Input: "这是φc00001φ粗体φc00002φ文本。" │
│ Output: "这是<strong>粗体</strong>文本。" │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. 构建阶段 (chinese_builder.py) │
│ 使用 translation_with_original_html 替换原始内容 │
└─────────────────────────────────────────────────────────────────┘
当前状态: 步骤 1、3、4 从未执行!
LLM 占位符丢失的常见原因
即使修复了 mode 传递问题,LLM 仍可能丢失占位符:
| 原因 | 示例 | 解决方案 |
|---|---|---|
| 占位符被"翻译" | φc00001φ → φ中00001φ | 强调 Prompt: "φ...φ 是代码,禁止修改" |
| 占位符位置错误 | 原: Aφc1φB → 译: φc1φAB | 修复 Agent (repair_format) |
| 占位符完全丢失 | 原: φc1φ → 译: (无) | 后处理:从原文恢复 |
| 幻觉占位符 | 原: (无) → 译: φc99φ | 忽略未知 ID |
修复建议
修复 1: translator.py 添加 mode 参数
async def translate_epub(self, epub_path: str, test_mode: bool = False,
output_dir: str = None, mode: str = "bilingual") -> str:
# ...
# 提取时传递 mode
self.text_processor.extract_to_manifest(item['content'], item['file_name'], manifest, mode=mode)
# 分块时传递 mode
chunks = self.text_processor.create_chunks_from_manifest(manifest, mode=mode)
# 翻译时传递 mode
await self._translate_concurrently(chunks, manifest, profile, mode=mode)
# 构建时选择正确的 Builder
if mode == "chinese":
builder = ChineseEPUBBuilder(self.parser.book, self.config)
result_file = builder.create_chinese_epub_with_mapping(manifest.get_items(), output_path)
else:
builder = BilingualEPUBBuilder(self.parser.book, self.config)
result_file = builder.create_bilingual_epub_with_mapping(...)
修复 2: llm_client.py 添加占位符指令
if mode == "chinese":
base_sys_prompt += """
Placeholder Instructions:
1. Text contains φcXXXXXφ placeholders representing HTML formatting.
2. These are CODE tokens - DO NOT translate, modify, or remove them.
3. Keep placeholders in corresponding positions in your translation.
4. Example: "This is φc00001φboldφc00002φ text." → "这是φc00001φ粗体φc00002φ文本。"
"""
修复 3: 增强 format_restorer.py 容错
def restore(self, text_with_placeholders, placeholder_map):
# 如果 LLM 完全丢失占位符,尝试智能合并
if not self.PLACEHOLDER_REGEX.search(text_with_placeholders):
logger.warning("所有占位符丢失,降级为纯文本")
return text_with_placeholders, False
# 现有逻辑...
优先级
| 优先级 | 修复项 | 工作量 |
|---|---|---|
| P0 | translator.py 传递 mode 参数 | 小 |
| P0 | translator.py 选择正确 Builder | 小 |
| P1 | llm_client.py 占位符 Prompt | 小 |
| P2 | format_restorer.py 容错增强 | 中 |
| P2 | repair_format 机制完善 | 中 |