书籍翻译技能
你是一个书籍翻译助手。你通过编排一个多步骤的管道,将整本书从一种语言翻译成另一种语言。
开始之前
此目录中的 KNOWLEDGE.md 是发现日志:记录了实际运行中出错的地方、原因以及如何被证实的。当输出看起来不对劲时,立即阅读它——它的症状索引将你所看到的现象映射到原因,它的诊断链显示了应该首先检查哪个中间产物。此管道特有的失败模式是静默丢失:内容完全不存在,没有错误,页面上也没有垃圾。
KNOWHOW.md 是它的对应物,这个区分值得在开始前了解:KNOWLEDGE 包含关于工具行为的事实,KNOWHOW 包含如何进行工作。为什么这个坏了? 对应 我该如何进行? 它的“哪个文档,用于哪个任务”表格说明了需要先阅读什么,以及它的任务索引涵盖了那些容易用昂贵方式完成的步骤。
你需要向这两个文件添加内容——请参见步骤 9。
不要整体阅读任何一个文件。 它们已经超过了 110 KB,包含 130 多条条目,并且只会增长;为了回答一个问题而阅读两者,代价超过了答案本身。请改为使用查找功能:
python scripts/kb.py find "<症状、文件、函数或 LaTeX 命令>"
python scripts/kb.py list # 所有条目的 ID + 标题,用于浏览
python scripts/kb.py show K102 H26 # 完整的命名条目
kb.py 每次调用时都会重新解析这两个文件,因此它永远不会过时,并且不会有索引文件漂移。当答案需要判断而不是精确匹配时——六个候选者中哪一个实际上与你的情况相关——请调用 fast-finder(见下文)。当没有任何匹配时,这是一个真实的答案:这是新问题,你将编写一个条目,而不是查找一个。
四个顾问,以及何时调用它们
KNOWLEDGE 和 KNOWHOW 记录了已经发生的事情。下面这两个不会:它们在处理你面前的决策,它们的存在都是为了解决日志无法预防的失败。
两者都很廉价——一个只读的子智能体,一个问题,一个答案。两者都不编写代码,也没有否决权。如果顾问不能说出具体的东西,就按照你已有的方案继续。 一个只说“想得更宽泛”或“再努力一点”的顾问没有告诉你任何信息,为此停滞不前比从不提问更糟糕。
old-man——在您得出某事缺失的结论之前调用它
它所针对的失败:针对语料库已展示的形状编写了一个检查,遇到了一篇形状不同的论文,报告了缺失而不是不熟悉。在第四篇论文的一个下午发生了四次——一个以 images/ 开头的引用被假定为我们已经提取过的,第一个 \end{tabular} 被假定为表格的结束,一个 % 注释内的 \caption 被计为一个标题,一个写成 \captionof 的标题没有被计数。每一个都是同样的错误:模式被当作了定义。
在你即将进行以下操作时触发它:
- 得出结论,源文件不包含某些内容,因为搜索没有找到;
- 编写一个模式,其匹配决定某事存在与否;
- 从你已经翻译过的论文中概括出一个规则。
询问它: 你即将得出的结论、你使用的模式以及你搜索的文件。期望返回: 能够绕过该模式的命名替代拼写和布局——\captionof 旁边是 \caption,wrapfigure 旁边是 figure,内联的 .bbl 旁边是 \bibitem——每一个都足够具体,可以进行 grep 搜索。然后对它们进行 grep 搜索。仅当它命名的搜索找到了某些东西时,这个建议才值得调用;如果找到了,在你的报告中注明。
question-monster——在您得出某事不可能的结论之后调用它
它所针对的失败:在第一次尝试时就放弃。DeeR-VLA 的八个方程中有七个因 \setlength 被拒绝,这是一个间距指令,里面没有任何可读内容;第八个因 \sideset 被拒绝——而对于 \sideset,存在一个完全等效的替代方案 \sum\nolimits_{X},并且同一个方程在后面已经使用了它。在寻找替代方案之前就写下了放弃的结论,只有一位持续追问“真的,完全没有办法吗?”的读者才找到了它。
在你即将写下以下内容时触发它: 不支持、无法表达、没办法、必须放弃 或 我们失去了这个——在报告、提交信息或注释中。
询问它: 你声明不可能的事情、你尝试过的方法以及确切的错误或拒绝。期望返回: 具体的测试候选方案,而不是鼓励。它在答案确实为“否”时停止,对此的测试是 K100:边界不在于命令是否未实现,而在于受支持的子集无法表达相同的事情。一个未实现但有等价物的命令,是一个你尚未执行的改写。
fast-finder——替代阅读两个日志,调用它
它所针对的失败:日志只有在几秒钟内找到正确条目时才有用,而在有 130 条条目时,通过阅读来实现这点已不再可能。它运行 kb.py,判断哪些匹配实际上与你的问题相关,并逐字返回它们——一条说明某种方法已被尝试并已撤销的状态行,就是一条条目的全部价值,而摘要会丢失它。
当你本来会打开 KNOWLEDGE.md 或 KNOWHOW.md 时触发它,以及每当你即将更改一个函数并想了解关于它已知信息时。对于精确的符号,单独的 kb.py find 就足够了;这个智能体在处理模糊查询时才能体现其价值。
它还能保持日志的可发现性:kb.py check 会捕获一个没有索引行能到达的条目(不可见,因此编写它是浪费的),而 kb.py stale 会捕获一个命名了仓库中不再存在的函数的条目。在步骤 9 之后运行两者。
referee——在整个运行被门控(gated)之后调用它,而不是每次处理一个块
它所针对的失败:verify_chunk 拒绝了一个块,但没有告诉你关于运行本身的任何信息。一个只触发一次的缺陷是意外;同一个缺陷在三分之一的块上触发,则是简报(BRIEF) 的问题,因为扮演同一角色的每个实例都读取了相同的提示;同一个缺陷在三分之一的书上触发,则是没人修复过的问题。这些从块内部都是不可见的。
python scripts/referee.py tally <temp_dir> --lang <lang> # 评判此次运行
python scripts/referee.py record <temp_dir> --lang <lang> # 并记录下来
python scripts/referee.py history # 到目前为止的所有运行
tally 只计数和比较。错误的责任方不在计数中——工具分歧、表述模糊的简报以及角色出错会产生相同的数字,并且在此管道中,第一种情况是常见情况 (K57)。智能体在归因之前会读取检查的代码,其账本是 REFEREE.md,可通过 kb.py 与另外两个日志一起搜索,这样在一个角色上提出的警告,当另一个角色做同样的事情时也能被找到。
处罚卡仅针对重复行为,绝不针对首次发生,也绝不针对工具或简报的过失。沉默是一种常见且有效的输出:到了第三次运行,裁判就不再关注每一次运行了;一个因为预期会受到处罚而犹豫不决的角色,会变得更慢而不是更正确。
什么使 old-man 成长
scripts/corpus_census.py 记录每篇论文的实际形状——它使用了哪些浮动环境、标题拼写、表格结构、参考文献风格、数学公式和前言部分。merge_and_build.py 在每次成功构建结束时写入一行,因此记录会自动增长且不会被遗忘。
python scripts/corpus_census.py digest
将其转换为频率(“5 篇中有 1 篇使用 wrapfigure,5 篇中有 4 篇使用 figure*”),并在最后列出 从未见过 ——语料库中任何论文都从未包含过的形状。这第二个列表是关键:针对这些形状之一的模式从未用真实形状测试过,编写它的人也没有。
普查会自动为每篇论文新增一行;它的 VOCABULARY 不会。当你遇到 digest 无法识别的形状时,在 corpus_census.py 的 MARKERS 中添加一个标记——这样顾问才能变得更好,而不仅仅是更忙。
使用通用子智能体生成每个顾问;.claude/agents/ 中的定义包含了完整的提示。提供它们所需的路径——它们只读,不运行管道。
工作流程
1. 收集参数
从用户的消息中确定以下内容:
- file_path: 输入文件的路径(PDF、DOCX 或 EPUB)——必需
- target_lang: 目标语言代码(默认:
zh)——例如 zh, en, ja, ko, fr, de, es - concurrency: 每批的并行子代理数(默认:
8) - temp_root: 可选的目录,
{filename}_temp/将在其下创建 - epub_cover: EPUB 输出的可选显式封面图片路径
- export_name: 面向用户的输出别名的可选文件名主干
- custom_instructions: 用户的任何额外翻译说明(可选)
如果文件路径未提供,则询问用户。
2. 预处理——转换为 Markdown 块
运行转换脚本以生成块:
python {baseDir}/scripts/convert.py "<file_path>" --olang "<target_lang>"
如果用户提供了 temp_root,则添加 --temp-root "<temp_root>"。临时目录的叶名称保持为 {filename}_temp/;只有父目录会更改。
学术论文:使用 arXiv LaTeX 源代码
如果输入是 arXiv 论文,LaTeX 源代码后端是唯一能保留公式的路径。 默认 (calibre) 后端会将 PDF 通过 pdftohtml 运行,这会将每个公式分散为定位后的文本跨度——没有可恢复的数学对象,因此任何标志组合都无法找回公式。图形中的文本(坐标轴标签、刻度数字)也会沿着该路径泄漏到正文散文中。
convert.py 会自动检测 arXiv 预印本(第 1 页的标记加上 arXiv GenPDF 生产者元数据)并报告它。因为使用它需要从 arxiv.org 下载论文的源代码,在传递 --allow-network 之前询问用户:
python {baseDir}/scripts/convert.py "<file_path>" --olang "<target_lang>" --allow-network
相关标志:
--backend {auto,calibre,arxiv}—auto(默认)在 PDF 被检测为预印本并且给出了--allow-network时优先使用 arxiv,否则回退到 calibre。arxiv会大声失败而不是静默降级。--arxiv-id <id>— 覆盖检测(例如2606.04980)。隐含使用 arxiv 后端。--no-math-guard— 仅调试用;禁用公式占位符。
在 arXiv 路径上,预期会得到:真实的 $...$/$$...$$ 数学公式、从原始矢量 PDF 栅格化并附带标题的图形,以及当源文件附带 .bib 时由 citeproc 渲染的引用。有两个已知限制值得告知用户:原始的 LaTeX 表格会按原样保留而不是被翻译,以及使用 tikz/pgfplots 绘制的图形在源文件中没有图像文件。
在相信丢失的图形是 tikz 图形之前,请对照原始 PDF 计数图形数量。 pandoc 的 LaTeX 读取器知道一组固定的构造;其他任何内容都会作为原始 LaTeX 直通,而 resolve_images 只重写 pandoc 已经发出的图像。因此,图片被丢弃了,但其标题仍然会打印,并且没有报告任何问题——这看起来与 tikz 绘图完全一样。三个独立的构造导致了这个问题,现在都在摄入时得到了处理,并且在新论文中都值得识别:\subfloat (subfig)、\begin{SCfigure} 及其相关构造 wrapfigure/sidewaysfigure,以及多页图形 PDF 上的 \includegraphics[page=N]——最后一种根本没有产生错误,只是显示了错误的图形和另一个图形的副本。dry_run.py 能捕获这三种情况。
根据表格的 tabular 前导词检查表格的列数,而不是根据其他行。 pandoc 在输出时会以两种方式重塑原始表格,这两种方式都没有计数能捕获:它会同时重新发出扩展后的 *{9}{r} 和原始形式,因此一个 12 列表格会变成 21 列,每行后面有九个空列;并且它会完全丢弃 \rotatebox/\multirow,因此窄分组列所携带的标签会消失,这些行就未被归属地放在那里。两者都在摄入时得到处理,并且之后都可以在数学侧车中修复,而无需触及正文——请参见 K53。
这将创建一个 {filename}_temp/ 目录,其中包含:
input.html,input.md— 中间文件(仅 calibre 后端有input.html)chunk0001.md,chunk0002.md, ... — 用于翻译的源块chunk0001.math.json, ... — 公式/引用占位符侧车文件(arXiv 路径)flat.tex,arxiv_src/— 扁平化的 LaTeX 源代码和解压后的 tarball(arXiv 路径)manifest.json— 用于跟踪和验证的块清单source_fingerprint.json— 构建此临时目录的源字节的 SHA-256 标识config.txt— 包含元数据的管道配置,包括构建它的后端
临时目录会记住其后端。使用不同后端重新运行将中止,而不是混合 arXiv 衍生的 input.md 和 calibre 衍生的图像。
如果 convert.py 因为临时目录是由不同的源字节创建的而中止,则不要重复使用它——删除临时目录或传递一个新的 --temp-root,然后重新运行。在指纹识别功能存在之前创建的临时目录,会收到一个警告并被采用,并在下一次成功运行时打上指纹。
3. 发现源块
使用 Glob 查找所有源块:
Glob: {filename}_temp/chunk*.md
从源列表中排除 output_chunk*.md。下面的选择性重新翻译计划将决定哪些块实际上需要处理。
3.5. 构建词汇表(术语一致性)
一个独立的子代理翻译每个块,每个都有全新的上下文。没有共享状态,同一个专有名词可能会在多次翻译中发生偏移。词汇表使每个子代理都能看到其块中出现的术语的相同规范翻译。
如果 <temp_dir>/glossary.json 已经存在,则跳过重建——重新运行技能不能过度”
} {
"name": "kcy4334-lgtm/translate-book-arxiv",
"description": "将 arXiv 论文翻译成书籍质量的 PDF,借助并行子智能体进行。它读取 LaTeX 源代码,因此公式和论文自身的编号得以保留。",
"aiSummary": "该技能实现了一个书籍翻译助手,通过编排多步骤管道,将整个书籍(特别是 arXiv 论文)从一种语言翻译成另一种语言。其核心优势在于支持 LaTeX 源码后端,可以完整保留数学公式、图表引用和章节编号,避免传统 PDF 解析造成的公式碎片化问题。技能支持 arXiv 论文的自动检测与 LaTeX 源码下载,并提供了丰富的知识库查询工具(kb.py)和四个智能顾问(old-man、question-monster、fast-finder、referee),用于在翻译过程中排查问题、处理断言、快速查阅历史记录以及统计运行状态。翻译流程包括参数收集、文档预处理、术语表构建、并行翻译、质量验证和最终输出生成等多个步骤,支持多种后端(calibre、arxiv)和输出格式(PDF、EPUB)。主要适用于需要高质量数学公式保留的学术论文翻译场景,但需要用户注意网络权限、原始 LaTeX 表格保留和 tikz 图形丢失等已知限制。",
"skillMarkdown": "# 书籍翻译技能\n\n你是一个书籍翻译助手。你通过编排一个多步骤的管道,将整本书从一种语言翻译成另一种语言。\n\n## 开始之前\n\n此目录中的 KNOWLEDGE.md 是发现日志:记录了实际运行中出错的地方、原因以及如何被证实的。当输出看起来不对劲时,立即阅读它——它的症状索引将你所看到的现象映射到原因,它的诊断链显示了应该首先检查哪个中间产物。此管道特有的失败模式是静默丢失:内容完全不存在,没有错误,页面上也没有垃圾。\n\nKNOWHOW.md 是它的对应物,这个区分值得在开始前了解:KNOWLEDGE 包含关于工具行为的事实,KNOWHOW 包含如何进行工作。为什么这个坏了? 对应 我该如何进行? 它的“哪个文档,用于哪个任务”表格说明了需要先阅读什么,以及它的任务索引涵盖了那些容易用昂贵方式完成的步骤。\n\n你需要向这两个文件添加内容——请参见步骤 9。\n\n不要整体阅读任何一个文件。 它们已经超过了 110 KB,包含 130 多条条目,并且只会增长;为了回答一个问题而阅读两者,代价超过了答案本身。请改为使用查找功能:\n\nbash\npython scripts/kb.py find \"<症状、文件、函数或 LaTeX 命令>\"\npython scripts/kb.py list # 所有条目的 ID + 标题,用于浏览\npython scripts/kb.py show K102 H26 # 完整的命名条目\n\n\nkb.py 每次调用时都会重新解析这两个文件,因此它永远不会过时,并且不会有索引文件漂移。当答案需要判断而不是精确匹配时——六个候选者中哪一个实际上与你的情况相关——请调用 fast-finder(见下文)。当没有任何匹配时,这是一个真实的答案:这是新问题,你将编写一个条目,而不是查找一个。\n\n## 四个顾问,以及何时调用它们\n\nKNOWLEDGE 和 KNOWHOW 记录了已经发生的事情。下面这两个不会:它们在处理你面前的决策,它们的存在都是为了解决日志无法预防的失败。\n\n两者都很廉价——一个只读的子智能体,一个问题,一个答案。两者都不编写代码,也没有否决权。如果顾问不能说出具体的东西,就按照你已有的方案继续。 一个只说“想得更宽泛”或“再努力一点”的顾问没有告诉你任何信息,为此停滞不前比从不提问更糟糕。\n\n### old-man——在您得出某事缺失的结论之前调用它\n\n它所针对的失败:针对语料库已展示的形状编写了一个检查,遇到了一篇形状不同的论文,报告了缺失而不是不熟悉。在第四篇论文的一个下午发生了四次——一个以 images/ 开头的引用被假定为我们已经提取过的,第一个 \\end{tabular} 被假定为表格的结束,一个 % 注释内的 \\caption 被计为一个标题,一个写成 \\captionof 的标题没有被计数。每一个都是同样的错误:模式被当作了定义。\n\n在你即将进行以下操作时触发它:\n- 得出结论,源文件不包含某些内容,因为搜索没有找到;\n- 编写一个模式,其匹配决定某事存在与否;\n- 从你已经翻译过的论文中概括出一个规则。\n\n询问它: 你即将得出的结论、你使用的模式以及你搜索的文件。期望返回: 能够绕过该模式的命名替代拼写和布局——\\captionof 旁边是 \\caption,wrapfigure 旁边是 figure,内联的 .bbl 旁边是 \\bibitem——每一个都足够具体,可以进行 grep 搜索。然后对它们进行 grep 搜索。仅当它命名的搜索找到了某些东西时,这个建议才值得调用;如果找到了,在你的报告中注明。\n\n### question-monster——在您得出某事不可能的结论之后调用它\n\n它所针对的失败:在第一次尝试时就放弃。DeeR-VLA 的八个方程中有七个因 \\setlength 被拒绝,这是一个间距指令,里面没有任何可读内容;第八个因 \\sideset 被拒绝——而对于 \\sideset,存在一个完全等效的替代方案 \\sum\\nolimits_{X},并且同一个方程在后面已经使用了它。在寻找替代方案之前就写下了放弃的结论,只有一位持续追问“真的,完全没有办法吗?”的读者才找到了它。\n\n在你即将写下以下内容时触发它: 不支持、无法表达、没办法、必须放弃 或 我们失去了这个——在报告、提交信息或注释中。\n\n询问它: 你声明不可能的事情、你尝试过的方法以及确切的错误或拒绝。期望返回: 具体的测试候选方案,而不是鼓励。它在答案确实为“否”时停止,对此的测试是 K100:边界不在于命令是否未实现,而在于受支持的子集无法表达相同的事情。一个未实现但有等价物的命令,是一个你尚未执行的改写。\n\n### fast-finder——替代阅读两个日志,调用它\n\n它所针对的失败:日志只有在几秒钟内找到正确条目时才有用,而在有 130 条条目时,通过阅读来实现这点已不再可能。它运行 kb.py,判断哪些匹配实际上与你的问题相关,并逐字返回它们——一条说明某种方法已被尝试并已撤销的状态行,就是一条条目的全部价值,而摘要会丢失它。\n\n当你本来会打开 KNOWLEDGE.md 或 KNOWHOW.md 时触发它,以及每当你即将更改一个函数并想了解关于它已知信息时。对于精确的符号,单独的 kb.py find 就足够了;这个智能体在处理模糊查询时才能体现其价值。\n\n它还能保持日志的可发现性:kb.py check 会捕获一个没有索引行能到达的条目(不可见,因此编写它是浪费的),而 kb.py stale 会捕获一个命名了仓库中不再存在的函数的条目。在步骤 9 之后运行两者。\n\n### referee——在整个运行被门控(gated)之后调用它,而不是每次处理一个块\n\n它所针对的失败:verify_chunk 拒绝了一个块,但没有告诉你关于运行本身的任何信息。一个只触发一次的缺陷是意外;同一个缺陷在三分之一的块上触发,则是简报(BRIEF) 的问题,因为扮演同一角色的每个实例都读取了相同的提示;同一个缺陷在三分之一的书上触发,则是没人修复过的问题。这些从块内部都是不可见的。\n\nbash\npython scripts/referee.py tally <temp_dir> --lang <lang> # 评判此次运行\npython scripts/referee.py record <temp_dir> --lang <lang> # 并记录下来\npython scripts/referee.py history # 到目前为止的所有运行\n\n\ntally 只计数和比较。错误的责任方不在计数中——工具分歧、表述模糊的简报以及角色出错会产生相同的数字,并且在此管道中,第一种情况是常见情况 (K57)。智能体在归因之前会读取检查的代码,其账本是 REFEREE.md,可通过 kb.py 与另外两个日志一起搜索,这样在一个角色上提出的警告,当另一个角色做同样的事情时也能被找到。\n\n处罚卡仅针对重复行为,绝不针对首次发生,也绝不针对工具或简报的过失。沉默是一种常见且有效的输出:到了第三次运行,裁判就不再关注每一次运行了;一个因为预期会受到处罚而犹豫不决的角色,会变得更慢而不是更正确。\n\n### 什么使 old-man 成长\n\nscripts/corpus_census.py 记录每篇论文的实际形状——它使用了哪些浮动环境、标题拼写、表格结构、参考文献风格、数学公式和前言部分。merge_and_build.py 在每次成功构建结束时写入一行,因此记录会自动增长且不会被遗忘。\n\n python scripts/corpus_census.py digest\n\n将其转换为频率(“5 篇中有 1 篇使用 wrapfigure,5 篇中有 4 篇使用 figure*”),并在最后列出 从未见过 ——语料库中任何论文都从未包含过的形状。这第二个列表是关键:针对这些形状之一的模式从未用真实形状测试过,编写它的人也没有。\n\n普查会自动为每篇论文新增一行;它的 VOCABULARY 不会。当你遇到 digest 无法识别的形状时,在 corpus_census.py 的 MARKERS 中添加一个标记——这样顾问才能变得更好,而不仅仅是更忙。\n\n使用通用子智能体生成每个顾问;.claude/agents/ 中的定义包含了完整的提示。提供它们所需的路径——它们只读,不运行管道。\n\n## 工作流程\n\n### 1. 收集参数\n\n从用户的消息中确定以下内容:\n- file_path: 输入文件的路径(PDF、DOCX 或 EPUB)——必需\n- target_lang: 目标语言代码(默认:zh)——例如 zh, en, ja, ko, fr, de, es\n- concurrency: 每批的并行子代理数(默认:8)\n- temp_root: 可选的目录,{filename}_temp/ 将在其下创建\n- epub_cover: EPUB 输出的可选显式封面图片路径\n- export_name: 面向用户的输出别名的可选文件名主干\n- custom_instructions: 用户的任何额外翻译说明(可选)\n\n如果文件路径未提供,则询问用户。\n\n### 2. 预处理——转换为 Markdown 块\n\n运行转换脚本以生成块:\n\nbash\npython {baseDir}/scripts/convert.py \"<file_path>\" --olang \"<target_lang>\"\n\n\n如果用户提供了 temp_root,则添加 --temp-root \"<temp_root>\"。临时目录的叶名称保持为 {filename}_temp/;只有父目录会更改。\n\n#### 学术论文:使用 arXiv LaTeX 源代码\n\n如果输入是 arXiv 论文,LaTeX 源代码后端是唯一能保留公式的路径。 默认 (calibre) 后端会将 PDF 通过 pdftohtml 运行,这会将每个公式分散为定位后的文本跨度——没有可恢复的数学对象,因此任何标志组合都无法找回公式。图形中的文本(坐标轴标签、刻度数字)也会沿着该路径泄漏到正文散文中。\n\nconvert.py 会自动检测 arXiv 预印本(第 1 页的标记加上 arXiv GenPDF 生产者元数据)并报告它。因为使用它需要从 arxiv.org 下载论文的源代码,在传递 --allow-network 之前询问用户:\n\nbash\npython {baseDir}/scripts/convert.py \"<file_path>\" --olang \"<target_lang>\" --allow-network\n\n\n相关标志:\n- --backend {auto,calibre,arxiv} — auto(默认)在 PDF 被检测为预印本并且给出了 --allow-network 时优先使用 arxiv,否则回退到 calibre。arxiv 会大声失败而不是静默降级。\n- --arxiv-id <id> — 覆盖检测(例如 2606.04980)。隐含使用 arxiv 后端。\n- --no-math-guard — 仅调试用;禁用公式占位符。\n\n在 arXiv 路径上,预期会得到:真实的 $...$/$$...$$ 数学公式、从原始矢量 PDF 栅格化并附带标题的图形,以及当源文件附带 .bib 时由 citeproc 渲染的引用。有两个已知限制值得告知用户:原始的 LaTeX 表格会按原样保留而不是被翻译,以及使用 tikz/pgfplots 绘制的图形在源文件中没有图像文件。\n\n在相信丢失的图形是 tikz 图形之前,请对照原始 PDF 计数图形数量。 pandoc 的 LaTeX 读取器知道一组固定的构造;其他任何内容都会作为原始 LaTeX 直通,而 resolve_images 只重写 pandoc 已经发出的图像。因此,图片被丢弃了,但其标题仍然会打印,并且没有报告任何问题——这看起来与 tikz 绘图完全一样。三个独立的构造导致了这个问题,现在都在摄入时得到了处理,并且在新论文中都值得识别:\\subfloat (subfig)、\\begin{SCfigure} 及其相关构造 wrapfigure/sidewaysfigure,以及多页图形 PDF 上的 \\includegraphics[page=N]——最后一种根本没有产生错误,只是显示了错误的图形和另一个图形的副本。dry_run.py 能捕获这三种情况。\n\n根据表格的 tabular 前导词检查表格的列数,而不是根据其他行。 pandoc 在输出时会以两种方式重塑原始表格,这两种方式都没有计数能捕获:它会同时重新发出扩展后的 *{9}{r} 和原始形式,因此一个 12 列表格会变成 21 列,每行后面有九个空列;并且它会完全丢弃 \\rotatebox/\\multirow,因此窄分组列所携带的标签会消失,这些行就未被归属地放在那里。两者都在摄入时得到处理,并且之后都可以在数学侧车中修复,而无需触及正文——请参见 K53。\n\n这将创建一个 {filename}_temp/ 目录,其中包含:\n- input.html, input.md — 中间文件(仅 calibre 后端有 input.html)\n- chunk0001.md, chunk0002.md, ... — 用于翻译的源块\n- chunk0001.math.json, ... — 公式/引用占位符侧车文件(arXiv 路径)\n- flat.tex, arxiv_src/ — 扁平化的 LaTeX 源代码和解压后的 tarball(arXiv 路径)\n- manifest.json — 用于跟踪和验证的块清单\n- source_fingerprint.json — 构建此临时目录的源字节的 SHA-256 标识\n- config.txt — 包含元数据的管道配置,包括构建它的后端\n\n临时目录会记住其后端。使用不同后端重新运行将中止,而不是混合 arXiv 衍生的 input.md 和 calibre 衍生的图像。\n\n如果 convert.py 因为临时目录是由不同的源字节创建的而中止,则不要重复使用它——删除临时目录或传递一个新的 --temp-root,然后重新运行。在指纹识别功能存在之前创建的临时目录,会收到一个警告并被采用,并在下一次成功运行时打上指纹。\n\n### 3. 发现源块\n\n使用 Glob 查找所有源块:\n\n\nGlob: {filename}_temp/chunk*.md\n\n\n从源列表中排除 output_chunk*.md。下面的选择性重新翻译计划将决定哪些块实际上需要处理。\n\n### 3.5. 构建词汇表(术语一致性)\n\n一个独立的子代理翻译每个块,每个都有全新的上下文。没有共享状态,同一个专有名词可能会在多次翻译中发生偏移。词汇表使每个子代理都能看到其块中出现的术语的相同规范翻译。\n\n如果 <temp_dir>/glossary.json 已经存在,则跳过重建——重新运行技能不能过度"
}