Files
epub_bilingual_translator/CHINESE_MODE_FORMAT_ANALYSIS.md
T
2026-01-19 09:51:07 +08:00

7.0 KiB

纯中文模式格式丢失问题 - 深度分析

🔴 根本原因:Mode 参数未被正确传递

问题概述

当前 translator.pytranslate_epub() 方法签名只有 3 个参数:

async def translate_epub(self, epub_path: str, test_mode: bool = False, output_dir: str = None) -> str:

缺失 mode 参数! 这意味着:

  1. 无论用户指定 -m chinese 还是 -m bilingual,都走相同的代码路径
  2. 永远使用 BilingualEPUBBuilder
  3. 格式提取功能 (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 机制完善