dsh-paper-translate 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +185 -0
- package/LICENSE +21 -0
- package/README.md +211 -3
- package/config.example.json +6 -0
- package/cordis.patch.yml +3 -0
- package/package.json +47 -4
- package/python/_deps.py +32 -0
- package/python/audit.py +236 -0
- package/python/build_docx.py +329 -0
- package/python/build_summary.py +296 -0
- package/python/check_layout.py +75 -0
- package/python/consistency.py +284 -0
- package/python/crop_figs.py +132 -0
- package/python/doc2pdf.py +118 -0
- package/python/env_check.py +240 -0
- package/python/extract.py +1443 -0
- package/python/fill.py +351 -0
- package/python/glossary.py +619 -0
- package/python/journal.py +548 -0
- package/python/lexicon.py +23 -0
- package/python/make_skeleton.py +187 -0
- package/python/regress.py +239 -0
- package/python/requirements.txt +10 -0
- package/python/run.py +437 -0
- package/python/summarize.py +1627 -0
- package/python/verify.py +449 -0
- package/references/terms.md +219 -0
- package/scripts/pick-dir.ps1 +37 -0
- package/src/index.js +640 -0
- package/src/paths.js +141 -0
- package/src/picker.js +82 -0
- package/src/runner.js +149 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# 更新记录
|
|
2
|
+
|
|
3
|
+
版本号对应 git tag 与 npm 版本,旧版本不会被覆盖。
|
|
4
|
+
|
|
5
|
+
## 0.1.2
|
|
6
|
+
|
|
7
|
+
修复三处译文/总结质量问题(test1 复测后用户反馈),并重译第一篇验证:
|
|
8
|
+
|
|
9
|
+
- **标题必译**:`fill.py` 里 `title` 类型此前一律放行不译,导致所有篇标题保持英文。改为与 h1/h2/p 一起查「未见中文」,标题译成中文。
|
|
10
|
+
- **front 残留英文**:第 1 篇作者行前出现 `I`、`Results` 两个不应存在的英文。根因两处:
|
|
11
|
+
- `extract.py` 标题/正文残行未归并——`I` 是正文首段 drop-cap 首字母下沉(41.6pt 装饰字)被拆成独立块;新增 `merge_drop_caps` 归并「超大号单字符 + 紧随残句」,`merge_title_lines` 同步放宽归并条件。
|
|
12
|
+
- `make_skeleton.py` 把 `Results`/`Abstract`/`摘要`/页眉残留 `e59` 等误抓成 authors;新增 `front_done` 状态 + `authorish` 收紧(排除页眉残留词、摘要标题、纯编号短串),并让正文开始前的 h1 无 title 时进 front。
|
|
13
|
+
- **图解读逐子图**:总结此前只做整图概括,未对组图每张子图逐一介绍。`summarize.py` 补「逐子图介绍」提示与「组图子图未逐一介绍」缺漏校验,read 字数上限随子图数动态放宽。
|
|
14
|
+
- **Nature 系图注子图标记补全**:子图标记此前只认 `(A)` 与 `a `,漏掉 Nature/Cell 系两种常见写法——单写 `a,`("a, Adult humans…")与连写 `c,d,`("c,d, Data in c…")。已补上,`panel_count` 不再恒 0、图注不再被误判「未分 panel」,连写里非首字母也能正确识别。
|
|
15
|
+
|
|
16
|
+
## 0.1.1
|
|
17
|
+
|
|
18
|
+
新增「仅总结」「关键图表解读」与「输出目录设置」,工具数 9 → 16。
|
|
19
|
+
|
|
20
|
+
- **`paper_grep` 工具**:按关键词回原文检索句子。素材包是按启发式规则挑句的,实测只覆盖正文
|
|
21
|
+
8%–15%,段落首句之外的关键结论、作者的反例、条件限定都可能没进来;某一节找不到依据时用它
|
|
22
|
+
回原文捞,捞回的句子与素材包同一套清洗口径,可直接当 `evidence`。命令行同款:
|
|
23
|
+
`run.py summary-grep <工作目录> <关键词> [--limit 20] [--sec results,discussion]`。
|
|
24
|
+
- **素材包补漏**(实测两篇:覆盖率 5.6%→7.7%、10.0%→14.9%):
|
|
25
|
+
- 结果节补取解法句:该分支此前没有取解法的逻辑,而新方法多在结果节首次出场(「we developed…」),
|
|
26
|
+
导致难点一节只能写困难、写不出对策(实测某篇素材包 0 句解法 → 现在 3 句,并验证能通过校验)。
|
|
27
|
+
- 解法词表加被动语态:「a clustering-based strategy was implemented」这类表述原来不认。
|
|
28
|
+
- 方法节改为全节均匀采样(最多 6 段):此前按顺序只取最前面 3 句,全落在试剂与质粒构建上,
|
|
29
|
+
关键技术步骤在中后段取不到;顺手滤掉「详见补充方法」这类纯指路句。
|
|
30
|
+
- 解法配额修正:`limit` 此前当全局计数用,摘要里取到一句就把后面的调用一并堵死;
|
|
31
|
+
改为「本次最多取几句 + 全文封顶 4 句」。
|
|
32
|
+
- 预算 10000 → 12000 字符:补漏后单篇约 9.1k,原上限会开始丢句子。
|
|
33
|
+
- **多篇总结不设目录页**:多篇合并时第一篇直接从文档开头排(标题带序号 `1.`),篇间照旧分页;
|
|
34
|
+
去掉原来的「文献总结 / 共 N 篇 / 目录」整页,少一页、打开就是正文。
|
|
35
|
+
- **输出目录可配置**:DSH 设置 → 插件 → dsh-paper-translate 里有 `projectRoot` / `outputDir` /
|
|
36
|
+
`pythonPath` 三个字段(留空即用默认)。产物默认落到 `<工作根>/translate_result`,不存在自动创建。
|
|
37
|
+
- **`paper_output` 工具**:`get` 看当前目录与来源、`pick` 弹 Windows 原生文件夹选择框、
|
|
38
|
+
`set` 直接指定、`reset` 回到默认。改完立即生效,不需要重启。
|
|
39
|
+
- **仅总结模式**:用户只说「总结 / 概括 / 讲了啥 / 这篇说了什么」时,不再跑全文翻译。
|
|
40
|
+
`prepare --mode summary` 只抽取版式与裁图,不生成 `content.json` 骨架,因此
|
|
41
|
+
`paper_next / fill / status` 因缺文件自然拒绝执行,不靠提示词约束。
|
|
42
|
+
- **关键词触发**:`paper_summary_brief` 先判 `intent`,未出现总结类词直接返回、不花 token;
|
|
43
|
+
句中出现「翻译」时同时输出 `TRANS: YES`,「翻译并总结」两件都做。
|
|
44
|
+
- **关键图表**:优先方法示意图、正文引用最多、带网格的对比表、末图,各保一张交模型定;
|
|
45
|
+
图形摘要与无主图区排除。图注按子图(`a ...` 与 `(A)` 两种写法)保留。
|
|
46
|
+
- **图表候选打分纠错**(两篇真实论文 8 图 / 5 图复算):
|
|
47
|
+
- 示意图只认「整图就是示意」:关键词必须出现在图注**标题段**(第一个子图标记之前)。
|
|
48
|
+
原来按整段匹配,复合图的第一个子图写「a Schematic of…」就给整张图加 1.5 分,
|
|
49
|
+
实测 8 张里 5 张被误判,图 3(引用 6 次)反超图 4(引用 8 次)、图 8(引用 4 次)挤掉图 4。
|
|
50
|
+
- 匹配前抹掉空白:PDF 把 `Research flow chart` 抽成 `Researc h flo w chart`,原正则认不出,
|
|
51
|
+
真正的方法流程图反而拿不到分(该篇里引用 7 次的图 1 一度垫底,现在排第一)。
|
|
52
|
+
- 末图加分 1.5 → 0.5,且引用次数不低于中位数才加分、才占保位名额。
|
|
53
|
+
- 引用计数展开并列与范围:`Fig. 4 and 5` 原来只计图 4、`Fig. 4–6` 只计图 4;
|
|
54
|
+
`Supplementary Fig.` 不再计入(断字 `Supple- mentary` 也认)。实测 t8 引用分布被修正
|
|
55
|
+
(图 4:8→14、图 7:5→8、图 8:4→1)。
|
|
56
|
+
- **落选图不再完全看不见**:素材包「其他」一行由「图号(引用 N 次)」扩展为再加图注开头 70 字;
|
|
57
|
+
想选就 `paper_grep(fig=图号)` 或 `run.py summary-fig <目录> <图号>` 取全文图注 + 正文引用句,
|
|
58
|
+
`anchor` 从那里逐字复制即可(已用真实图注验证:正例通过、拿正文句子当 anchor 仍被拒)。
|
|
59
|
+
- **校验扩到 12 项**:新增图号存在性、`anchor` 必须逐字命中该图图注、子图字母不越界、
|
|
60
|
+
数字白名单(全文 ∪ 该图图注)、视觉细节越界(图注没写的颜色/曲线/坐标轴会点名),
|
|
61
|
+
以及术语括注(中文句子里只写英文术语会被点名,不会被「连续 ≥4 个英文词」那条漏掉)。
|
|
62
|
+
- **图注识别补三个洞**(test1 三篇实测:没图的 2 篇现在各出 3 张):
|
|
63
|
+
- 与正文同字号的长图注被排掉:Scientific Reports 一类把图注排成 9pt(正文也 9pt)、长度 1500 字上下,
|
|
64
|
+
原规则「同字号时短于 120 字才算图注」把整篇 4 张图全判成 orphan。现在「编号紧跟句点/冒号」
|
|
65
|
+
(`Figure 3. …`)的块直接认作图注;正文里的 `Figure 3 shows that…` 编号后是小写词,不会误认。
|
|
66
|
+
- 图注被参考文献状态机覆盖:图常排在全篇末尾、位于 References 之后,原逻辑遇到 References 就把
|
|
67
|
+
后面所有块标成 ref,图注跟着变成文献条目。现在遇到 caption 即退出该状态。
|
|
68
|
+
- 图注索引错位:拆分参考文献会在列表中间插块,`caption_block` 序号整体后移(实测第 2 篇错位 34 位,
|
|
69
|
+
图注指到了「8. Cao S…」这条文献)。改为按块对象重新定位,增删块都不再受影响。
|
|
70
|
+
- **标题补两个洞**:
|
|
71
|
+
- 跨行标题被拆成多个块、只取第一块,英文标题因此断掉(`…for in vitro`、`Changes in global translation`)。
|
|
72
|
+
现在把「同字号 + 上下紧邻 ≤4pt + 左边对齐」的标题块合并成一条。
|
|
73
|
+
- 页眉当标题:PMC 的 `HHS Public Access` 22pt 比真标题还大,抢走 title 位。加页眉词表降级,
|
|
74
|
+
title 为空时回落到首页最长的大标题块。第 2 篇原来的英文标题是模型按文件名重建的
|
|
75
|
+
(多了一个 `mRNA`、少了 `Regulation`),现在取到原文:`…to Study Translation Regulation in
|
|
76
|
+
Poxvirus-infected Cells`。
|
|
77
|
+
- **【总结】排版**:原图截图 + 「图 N|入选理由」+ 中文解读 + 灰色英文原图注,便于读者核对。
|
|
78
|
+
- **术语必须配中文**:保留英文术语时写成「持续合成能力(processivity)」,只写 `processivity`
|
|
79
|
+
算不合格——总结侧 `--check` 直接判 `rc=2` 并点名到节(`processivity ×3(研究方法、难点与解决方案、图 2)`),
|
|
80
|
+
译文侧 `verify.py` 点名告警。基因名、载体名、试剂货号、方法缩写(NaP-TRAP、CHX)按原文保留,
|
|
81
|
+
不受此限;「非翻译区(untranslated regions,UTRs)」这类英文括注内部不逐词判定。
|
|
82
|
+
术语词表口径行同步从「首次给英文原词」改成「中文(English)」。
|
|
83
|
+
- **图注跨栏/跨页续接**(test1 三篇实测:第 1 篇 2 处、第 2 篇 2 处):
|
|
84
|
+
- 长图注写到页底时,续片落在下一页顶部,而且常与上一段正文粘在同一个块里(第 1 篇 Fig.1 的续片
|
|
85
|
+
开头是 `compared to an A at +4. (E–E′) …`)。整块被当成正文,图注停在 (D′),E 与 F 两个子图
|
|
86
|
+
在总结里整段消失。现在按「块内出现图注还没有的子图字母」定位切点:续片接回图注,
|
|
87
|
+
前面的正文尾巴并回上一段(Fig.1 图注 1469 → 2368 字符,子图 A–F 齐)。
|
|
88
|
+
- 续句型(Fig.3 末尾 `…causes a larger drop`,次页 `in translation of…`):下一块以小写词开头
|
|
89
|
+
且紧贴页/栏边界时,取到第一个句末为止。
|
|
90
|
+
- 「标题句 + 子图说明分块」(第 2 篇 Fig.2/3:50 字标题 + 独立 `(A)…(B)…` 块):紧随其后、
|
|
91
|
+
以子图标记开头且含 ≥2 个子图的块并回图注(50 → 559、42 → 927 字符)。
|
|
92
|
+
- 判据一律用子图字母,不用「有没有句号」——图注合法地可以以 `(D′)`、缩写收尾。
|
|
93
|
+
- **子图不再被压缩丢掉**:图注进素材包的上限 1000 → 2600 字符,并改成「一个子图都不丢」:
|
|
94
|
+
超预算时逐级缩短每段(240→180→140→100→70),最后均分兜底。第 1 篇 Fig.4 的 `(D)` 原来正是
|
|
95
|
+
被 1000 字上限砍掉的。实测三篇图注 1650–2368 字全部完整进入素材包。
|
|
96
|
+
合写标记 `(D,E)`、`(A–E)` 按多个子图处理(压缩后写作 `[d/e]`);行内引用
|
|
97
|
+
(`…varying strengths (B) is tested…`)不当作子图起点,否则会切出 `[b] , RLuc values…` 这类碎片。
|
|
98
|
+
`run.py summary-fig` 取全文图注时也走同一上限(原来另设 1400,长图注在这里又被砍一次)。
|
|
99
|
+
- **子图覆盖自检**:素材包每张图多一行「子图 a/b/c…」;正文引用到、图注却没写的子图标
|
|
100
|
+
`[PANEL]`(`正文提到但图注未写 E/F`),压缩致子图丢失则标 `素材包漏 X`,同时记 `FIG_PANEL_GAP`
|
|
101
|
+
到 journal。把图注截回 1469 字即可复现第 1 篇的原缺陷,自检准确报出 E/F。
|
|
102
|
+
- **术语「原文照写」类型**:词表说明列写 `原文照写`(如 5′UTR)、或中文列与英文列相同(spike-in)
|
|
103
|
+
的条目,校验时只要原文写法或译名出现其一即可,不再因为「没写中文长名」误判术语漂移;
|
|
104
|
+
素材包术语对照显示为 `5′UTR → 原文照写(不加括注)`。
|
|
105
|
+
- **英文保留改为判定顺序**(素材包硬规则第 4 条):不再靠「这是不是术语」猜,按
|
|
106
|
+
「词表标照原文写 → 有译名 → 全大写/含数字/含 ′- → 首字母大写专名 → 其余小写实词必须译 →
|
|
107
|
+
拉丁短语与单位」六步判定,命中即停。原先那份枚举(基因名、载体名、试剂货号、方法缩写)
|
|
108
|
+
覆盖不到 5′UTR、3′UTR、T7 这类。
|
|
109
|
+
- **词边界修正**:术语匹配的左边界排除数字与撇号,`5′UTR`/`3′UTR` 不再重复计入 `UTR` 一条
|
|
110
|
+
(此前正文照写 5′UTR 会被判「没用非翻译区」)。`RT-qPCR` 里的 `qPCR` 仍照旧命中。
|
|
111
|
+
- **回归指标新增 `captions_stitched`**:图注接续次数进 `structure.json` 的 stats,改抽取逻辑时
|
|
112
|
+
一眼能看出「接了几处」。
|
|
113
|
+
|
|
114
|
+
修复:
|
|
115
|
+
|
|
116
|
+
- `--status` 不再用退出码表示「还有待译」,改为解析 `RESULT: PENDING n / DONE`,避免壳误判失败。
|
|
117
|
+
- 中文纯度阈值 0.80 → 0.55:术语密集段落天然偏低,主要由「≥4 连续英文词」检测兜底。
|
|
118
|
+
- 图注清洗:修正 `( A )` 这类字距伪影(`Researc h` 一类单词内断字无法可靠还原,原样保留)。
|
|
119
|
+
- evidence 校验容忍上标标记:素材包给模型看的是 `strip_markup` 后的干净句,原文里仍带 `~{44}`
|
|
120
|
+
这类标记,照素材包原样复制的证据曾被判成「改写」;现在去掉标记的基准也算命中。
|
|
121
|
+
|
|
122
|
+
新增「过程记录」与「黄金样本回归」:
|
|
123
|
+
|
|
124
|
+
- **`paper_journal` 工具**:读 `<工作目录>/journal.jsonl`。原来 verify 的十几项告警只 `print`
|
|
125
|
+
到终端,模型读完就丢,工作目录不留痕迹——「第 2 篇为什么没抽出图」只能靠人重跑一遍去猜。
|
|
126
|
+
现在每个阶段都记事件:`action=issues` 看问题(带节点与出现次数)、`timing` 看各阶段耗时占比、
|
|
127
|
+
`decisions` 看「为什么选这张图/这些句子」、`tail` 看原始事件流、`runs` 看每次工具调用的墙钟。
|
|
128
|
+
命令行同款:`run.py journal <工作目录> [--issues|--timing|--decisions|--tail|--runs] [--last]`。
|
|
129
|
+
- **耗时支持「只算最后一次运行」**(`last=true` / `--last`):`timing` 原本把日志里所有事件
|
|
130
|
+
相加,同一篇 `prepare` 两次就报「次数 2、总耗时=两次相加」,拿去和上一版比是错的。
|
|
131
|
+
现在按 `env_check`(`prepare` 的第一个阶段)切分运行,加 `last` 只汇总最后一段,
|
|
132
|
+
表头写明起点与事件数;目录里没跑过 `prepare` 时会明确说「未找到 prepare 起点」,
|
|
133
|
+
不会把累计值当本次值糊过去。
|
|
134
|
+
- **问题单支持「只看本次」并分三态**:`issues` 加 `last` 后只汇总最后一次运行,并把每条标成
|
|
135
|
+
「本次新增 / 历史遗留 / 本次已修」——原来只有 `×2`,分不清是老病还是本轮新病,改完词表重跑
|
|
136
|
+
最想知道的恰恰是这个。注意不能只取最后一段:上一轮报、本轮没报的问题会查无此事,看着像
|
|
137
|
+
修好了,其实是没检查到,所以要和上一轮比对之后再标。
|
|
138
|
+
- **`runs.jsonl` 补 `flags` 与 `path`,并加 `v` 版本号**:原来只记 `sub`(第一个非 `-` 参数),
|
|
139
|
+
`journal --timing` 与 `journal --timing --last` 记下来一模一样,也无法知道是哪篇的调用。
|
|
140
|
+
怕的是把两件事搞混:`glossary`/`fill` 这类调用本来就没有开关,`flags` 会是空数组;而早期记录
|
|
141
|
+
根本没写这两个字段。所以写 `v: 2`,读取方按「有没有 v」判断,老记录把 `flags`/`path` 记成
|
|
142
|
+
`None`(未知)而不是 `[]`(空)。配套加 `paper_journal action=runs` / `run.py journal <work> --runs`:
|
|
143
|
+
列出属于这篇的每次调用(参数、墙钟、结果),老记录单独计数并说明「参数与归属都未知」。
|
|
144
|
+
- **问题用稳定 code + 定位标识**:`TERM_BARE @body|42`、`FIG_MISSING @fig3`、`TERM_DRIFT @western blot`。
|
|
145
|
+
多 agent 互相校对时,同一处同一类问题永远是同一个 key,不必靠复述对账;状态
|
|
146
|
+
`open / resolved / waived` 由同一 key 的最后一条事件决定,日志本身只追加不改写。
|
|
147
|
+
- **耗时分两层记**:Python 侧记本地计算(`extract` / `crop` / `fill` / `build` …),
|
|
148
|
+
壳侧 `runPy` 把每次工具调用的墙钟耗时写进 `<插件>/data/runs.jsonl`。翻译最慢的是模型
|
|
149
|
+
读写那一段,只埋 Python 计时会得出「翻译只花几百毫秒」的错误结论,两层合起来才准。
|
|
150
|
+
- **翻译阶段当场落盘**:`fill.py` 每批写完就把数字缺项、术语漂移记进日志,能知道问题出在
|
|
151
|
+
哪一批,而不是等交付自检时才发现。
|
|
152
|
+
- **`regress.py` 黄金样本回归**:`--save` 存基线(块数/字符数/图表数/图号序列/术语命中条数/
|
|
153
|
+
素材包字符数/问题计数),`--check` 只打印变化的指标。改脚本前先存,改完跑一次,
|
|
154
|
+
哪项退化立刻显形——写这个功能时正好复现过一次:重写词表把 22 条核心术语丢掉,
|
|
155
|
+
术语命中数 35 → 2,靠人眼看输出是发现不了的。
|
|
156
|
+
- **`paper_consistency` 工具**:把 `consistency.py` 暴露成工具(此前只有脚本,对话里调不到)。
|
|
157
|
+
三类提示——覆盖率偏低(原文出现过、多数块没用约定译名)、篇内写法不一致、跨篇不一致。
|
|
158
|
+
与 `paper_finish` 的自检互补:自检看单篇有没有用错,它看全篇/多篇用齐没、统一没;只读,
|
|
159
|
+
多篇装订时把所有工作目录一起传。命令行同款 `run.py consistency <目录…> [--json] [--strict]`。
|
|
160
|
+
- **多篇总结加目录页**:`paper_summary_doc` 传多个工作目录时,先出一页目录(序号 + 中英文标题
|
|
161
|
+
+ 生成日期)再逐篇成章,篇间分页;单篇仍不设目录。
|
|
162
|
+
|
|
163
|
+
修复:
|
|
164
|
+
|
|
165
|
+
- **`references/` 之前没进 npm 包**:`package.json` 的 `files` 只写了 `src` / `python` / `scripts`,
|
|
166
|
+
`terms.md` 因此没随包分发。而 `glossary.py:load_terms()` 遇到文件不存在直接返回空表、不报错,
|
|
167
|
+
结果是从 npm 安装的插件词表恒为 0 条,`terms_hit`、`paper_terms`、术语检查全部静默失效。
|
|
168
|
+
已把 `references` 加进 `files`,并在 README 标出「要随包分发」。
|
|
169
|
+
- **`python/__pycache__/*.pyc` 被打进包**:`files: ["python"]` 是整目录照收,19 个陈旧字节码
|
|
170
|
+
跟着发布。修法要写对位置:**有 `files` 字段时根 `.npmignore` 不生效**,必须在 `files` 里写
|
|
171
|
+
排除项 `"!python/__pycache__"`;另加 `.npmignore` 兜底(`__pycache__`、`*.pyc`、`data/`、
|
|
172
|
+
`config.json`),供将来去掉 `files` 时仍然有效。实测包体 356.8 kB → 140.1 kB,文件数 51 → 32。
|
|
173
|
+
- `terms_block` 排序改为「三分之二名额给短语、三分之一给单词」:词表扩到上百条后按命中数
|
|
174
|
+
排会被 `amino acid`、`translation` 这类泛词占满,`signal-to-noise ratio` 这种真正需要
|
|
175
|
+
对齐写法的短语反而挤不出去。
|
|
176
|
+
|
|
177
|
+
## 0.1.0
|
|
178
|
+
|
|
179
|
+
首个发布版本(npm `dsh-paper-translate@0.1.0`)。
|
|
180
|
+
|
|
181
|
+
- 论文 PDF 中译并保留原版式:插图、图注、三线表、参考文献原文不译。
|
|
182
|
+
- 9 个工具:`paper_prepare` / `paper_terms` / `paper_next` / `paper_fill` / `paper_status` /
|
|
183
|
+
`paper_audit` / `paper_finish` / `paper_harvest` / `paper_doctor`。
|
|
184
|
+
- 分批翻译,模型只输出译文 JSON;回填时当场做数字与术语检查。
|
|
185
|
+
- 依赖自带 Python 脚本,安装后无需编译。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 linlinxxy77-hue
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,211 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# dsh-paper-translate
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/dsh-paper-translate)
|
|
4
|
+
|
|
5
|
+
把英文论文 PDF 译成中文 DOCX,**按原版式重排**:插图、图注、三线表、公式、参考文献位置不变,参考文献正文保留英文不译。
|
|
6
|
+
|
|
7
|
+
这是 paper-translate 技能流水线的 DeepSeek Harness 插件封装 —— 插件是壳,真正的解析、重建、校验逻辑在 `python/` 目录里。
|
|
8
|
+
|
|
9
|
+
## 它和「让 AI 直接翻译」的区别
|
|
10
|
+
|
|
11
|
+
| | 直接对话翻译 | 本插件 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 版式 | 打散成 Markdown | 按 PDF 原始坐标重建,双栏、跨栏、页眉页脚都还原 |
|
|
14
|
+
| 图片 | 丢失 | 按图注编号裁切嵌入,图形摘要单独识别 |
|
|
15
|
+
| 表格 | 变成文本 | 重建网格,`header`/`rows` 对齐原表 |
|
|
16
|
+
| 参考文献 | 一并译掉(往往译错) | 骨架预填英文原文,跳过不译 |
|
|
17
|
+
| 术语 | 每段各译各的 | 全文一张术语表;保留英文须写「中文(English)」 |
|
|
18
|
+
| 数字 | 可能改写成中文数字 | 逐项比对,缺一个就点名到段落 |
|
|
19
|
+
| 抽检 | 无 | 按风险打分挑段落,原文译文并排复核 |
|
|
20
|
+
| 总结 | 每次重读全文,口径不一 | 素材包 + 证据锚点,机械校验后才出稿 |
|
|
21
|
+
|
|
22
|
+
代价是慢:一篇 13 页的论文约 10 分钟,绝大部分时间花在逐段翻译本身。
|
|
23
|
+
|
|
24
|
+
## 安装
|
|
25
|
+
|
|
26
|
+
### 1. 安装插件
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd ~/.dsh/profiles/desktop # Windows: %USERPROFILE%\.dsh\profiles\desktop
|
|
30
|
+
|
|
31
|
+
pnpm add dsh-paper-translate # 从 npm 安装(推荐)
|
|
32
|
+
pnpm add dsh-paper-translate@0.1.0 # 锁定版本
|
|
33
|
+
pnpm add github:linlinxxy77-hue/dsh-paper-translate # 从 GitHub 源码
|
|
34
|
+
pnpm add link:<插件目录绝对路径> # 本地开发
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
然后在同一个 `package.json` 的 `dsh.profile.bundles` 数组末尾加一行:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
"dsh-paper-translate"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
重启 Harness(完全退出再打开,不是刷新窗口)。
|
|
44
|
+
|
|
45
|
+
> npm 上的版本是预构建产物,安装时不需要编译,也不用点 `allowBuilds` 授权;从 GitHub 源码安装会走 pnpm 的源码拉取,国内网络更慢。
|
|
46
|
+
|
|
47
|
+
版本历史见 [CHANGELOG.md](CHANGELOG.md)。GitHub 上每个版本都有独立 tag(`v0.1.0`、`v0.1.1`…),旧版本可用
|
|
48
|
+
`git checkout v0.1.0` 或下载对应 tag 的压缩包,不会被新版本覆盖。
|
|
49
|
+
|
|
50
|
+
### 2. 安装 Python 依赖
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd node_modules/dsh-paper-translate # Windows: node_modules\dsh-paper-translate
|
|
54
|
+
python -m venv .venv
|
|
55
|
+
.venv/bin/pip install -r python/requirements.txt # Windows: .venv\Scripts\pip
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
需要 Python 3.10+,三个依赖共约 25 MB:`pymupdf`、`python-docx`、`pillow`。
|
|
59
|
+
|
|
60
|
+
插件也会自己找项目内的 `.venv`,装在别处的话用 `config.json` 的 `pythonPath` 指过去。
|
|
61
|
+
|
|
62
|
+
### 3. 验证
|
|
63
|
+
|
|
64
|
+
对模型说「检查论文翻译环境」,它应该调用 `paper_doctor` 并报告三个依赖是否就绪。
|
|
65
|
+
|
|
66
|
+
## 使用
|
|
67
|
+
|
|
68
|
+
说一句「把这篇论文译成中文,保留图表」即可,模型会自己走完:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
paper_prepare → paper_terms → paper_next ─┐
|
|
72
|
+
↑ │
|
|
73
|
+
paper_fill ─┘ (分批循环)
|
|
74
|
+
↓
|
|
75
|
+
paper_audit → paper_finish
|
|
76
|
+
paper_consistency ↗
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| 工具 | 作用 |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `paper_doctor` | 检查 Python、虚拟环境、依赖,并报当前输出目录 |
|
|
82
|
+
| `paper_output` | 查看/修改输出目录;`pick` 弹系统文件夹选择框 |
|
|
83
|
+
| `paper_prepare` | 解析 PDF,生成骨架、裁图、表格网格(`mode=summary` 时跳过骨架) |
|
|
84
|
+
| `paper_terms` | 列出本文术语的约定译名 |
|
|
85
|
+
| `paper_next` | 取下一批原文(默认 20 条) |
|
|
86
|
+
| `paper_fill` | 回填译文,当场做数字与术语检查 |
|
|
87
|
+
| `paper_status` | 进度与下一批序号 |
|
|
88
|
+
| `paper_audit` | 语义抽检,原文译文并排 |
|
|
89
|
+
| `paper_consistency` | 术语一致性:覆盖率偏低 / 篇内写法不一致 / 跨篇不一致(只读,可多篇一起传) |
|
|
90
|
+
| `paper_finish` | 排版生成 DOCX、自检,可选导出 PDF |
|
|
91
|
+
| `paper_harvest` | 抽取新术语候选,用于沉淀词表 |
|
|
92
|
+
| `paper_summary_brief` | 只总结不翻译的入口:传 pdf 一步完成轻量准备 + 素材包 |
|
|
93
|
+
| `paper_grep` | 兜底检索:按关键词回原文捞句子;传 `fig=图号` 则展开该图完整图注(候选池外的也能取) |
|
|
94
|
+
| `paper_summary_write` | 提交五节总结 + 图表解读,12 项机械校验 |
|
|
95
|
+
| `paper_summary_doc` | 生成【总结】DOCX/PDF(含关键图表),多篇可合并 |
|
|
96
|
+
| `paper_journal` | 过程记录:哪一步出过什么问题、定位到哪一条、各阶段耗时(`summary`/`issues`/`timing`/`decisions`/`tail`/`runs`;`timing`/`issues` 加 `last=true` 只算最后一次运行,`issues` 还会标「本次新增 / 历史遗留 / 本次已修」;`runs` 列出每次工具调用的参数与墙钟) |
|
|
97
|
+
|
|
98
|
+
工作目录默认落在 `<工作根>/build/papers/<篇名>/`,同一篇重复准备会复用,不会覆盖已填译文。
|
|
99
|
+
|
|
100
|
+
### 过程记录与回归
|
|
101
|
+
|
|
102
|
+
每篇工作目录下会生成 `journal.jsonl`(一行一个事件,只追加不改写):
|
|
103
|
+
|
|
104
|
+
- **问题**带稳定 `code` + 定位(如 `TERM_BARE @body|42`),同一处同一类问题永远同一个 key。
|
|
105
|
+
多个 agent 互相校对时,看 `paper_journal action=issues` 就能对齐,不必靠复述对账。
|
|
106
|
+
- **状态**分 `○ 待处理 / ✓ 已修复 / — 已豁免`,由同一 key 的最后一条事件决定。
|
|
107
|
+
- **耗时**按阶段记录(`extract` / `crop` / `fill` / `build` …),本地合计不含模型侧思考时间。
|
|
108
|
+
工具调用的墙钟耗时另记在 `<插件>/data/runs.jsonl`,两者合起来才是完整效率图景。
|
|
109
|
+
|
|
110
|
+
改过脚本之后,用回归比对确认没有改坏:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
python regress.py --save build/golden/baseline.json <工作目录...> # 存基线
|
|
114
|
+
python regress.py --check build/golden/baseline.json # 只打印变化的指标
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 输出目录与设置
|
|
118
|
+
|
|
119
|
+
DSH 的 **设置 → 插件 → dsh-paper-translate** 里有三个字段,都遵循「留空即用默认」:
|
|
120
|
+
|
|
121
|
+
| 字段 | 作用 | 留空时 |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `outputDir` | 译文与总结的输出目录 | `<工作根>/translate_result`,不存在会自动创建 |
|
|
124
|
+
| `projectRoot` | 工作根目录(放中间产物) | `config.json` 的值;再退到插件目录旁的 `paper-translate-work` |
|
|
125
|
+
| `pythonPath` | Python 解释器绝对路径 | 自动探测插件 `.venv` 与项目内虚拟环境 |
|
|
126
|
+
|
|
127
|
+
也可以直接说「把输出目录设成 D:/papers/out」,或说「选个输出文件夹」——后者会弹出 Windows 原生文件夹选择框(工具 `paper_output`)。
|
|
128
|
+
|
|
129
|
+
生效顺序:环境变量 `DSH_PAPER_OUTPUT` > `paper_output` 保存的值 > 设置页 `outputDir` / `config.json` > 默认值。
|
|
130
|
+
改完立即生效、不用重启;**已经生成的文件不会自动搬家**,只影响之后的排版。
|
|
131
|
+
|
|
132
|
+
### 文献总结(可选,默认不做)
|
|
133
|
+
|
|
134
|
+
**只有用户说「总结 / 概括 / 归纳 / 提炼 / 讲了什么」才会触发**,普通翻译请求不会顺手多出一步。
|
|
135
|
+
反过来,用户只想要总结、没提翻译时,**不生成任何待译项**,自然也就不会跑全文翻译。
|
|
136
|
+
|
|
137
|
+
| 用户说 | 走什么 | 产出 |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| 翻译这篇 | `paper_prepare` → `next/fill` → `finish` | 译文 DOCX/PDF |
|
|
140
|
+
| 概括 / 总结 / 这篇说了什么 | `paper_summary_brief`(直接传 pdf)→ `write` → `doc` | 只有【总结】DOCX/PDF |
|
|
141
|
+
| 翻译,再总结一下 | 翻译全流程 + 总结 | 两份 |
|
|
142
|
+
| 总结,别翻译 | 同第二行 | 只有总结 |
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
paper_summary_brief → paper_summary_write → paper_summary_doc
|
|
146
|
+
轻量准备 + 素材包 五节+图 + 12 项校验 【总结】DOCX/PDF
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
- 五节:研究目的 / 研究方法 / **研究难点与解决方案** / 创新点 / 局限,合计 410–790 字
|
|
150
|
+
- 「研究难点与解决方案」要先写卡在哪,再写作者用什么办法绕过去;只写困难、不写解法会被判不合格、退回重写
|
|
151
|
+
- 每节附一句原文证据(难点一节可给难点、解法两句),`paper_summary_write` 会要求它**逐字命中原文**——编不出引文就过不了
|
|
152
|
+
- 素材里确无依据时写「原文未明确说明」,不猜
|
|
153
|
+
- 多篇:把多个 workdir 一起传给 `paper_summary_doc`,每篇一章(标题带序号)+ 中英文名、五节与图表,篇间分页,不设目录页
|
|
154
|
+
- 成本:单篇约 2k token(摘要级);带 3 张图约 4.5k(约为整篇翻译的 1/10),1–2 分钟
|
|
155
|
+
|
|
156
|
+
### 关键图表
|
|
157
|
+
|
|
158
|
+
`paper_summary_brief` 的素材包里带图表候选(默认 3 张,`max_figs=0` 关闭):
|
|
159
|
+
|
|
160
|
+
- **候选怎么挑**:方法示意图(必须是「整图就是示意」——关键词出现在图注标题段,而不是某个子图)、正文引用最多、
|
|
161
|
+
有网格的对比表、末图(引用不低于中位)各保一个,再按分数补位;图形摘要与无主图区不参与。引用次数按
|
|
162
|
+
「并列/范围引用」展开计数(`Fig. 4 and 5` 两张都算),`Supplementary Fig.` 不计
|
|
163
|
+
- **没进候选的图**:素材包只给一行「图号 + 引用次数 + 图注开头 70 字」;觉得值得选就用 `paper_grep(fig=图号)`
|
|
164
|
+
取全文图注再写,不必整包重切
|
|
165
|
+
- **喂什么**:图注按子图(panel)保留,加正文里引用该图的句子、表格的表头与行列数——**不喂图片像素**
|
|
166
|
+
- **写什么**:每张 `why`(为什么值得看)+ `read`(先答问题、再按子图顺序说看了什么、最后落到支撑哪个结论)+ `anchor`
|
|
167
|
+
- **检查**:图号必须真实存在;`anchor` 必须逐字来自该图图注;提到的子图字母图注里要有;数字只能来自全文或该图图注;**描述了图注没写的视觉细节(颜色/曲线/坐标轴)会被点名**
|
|
168
|
+
- **排版**:原图截图 + 中文解读 + 灰色英文原图注(供核对);图注没裁出来时降级为纯文字
|
|
169
|
+
|
|
170
|
+
这样解读的准确上限由图注决定:Nature/Cell 式图注把每个子图的样本量、统计检验都写了,能讲透;句式图注只够讲整图结论,这时不写子图。
|
|
171
|
+
|
|
172
|
+
## 配置
|
|
173
|
+
|
|
174
|
+
复制 `config.example.json` 为 `config.json`(已在 `.gitignore` 中,不会提交):
|
|
175
|
+
|
|
176
|
+
| 字段 | 说明 |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `projectRoot` | 数据根目录,默认 `~/paper-translate-work` |
|
|
179
|
+
| `pythonPath` | 指定解释器,默认自动找 `.venv` |
|
|
180
|
+
| `skillDir` | 指向外部脚本目录,用于跟技能仓库联动 |
|
|
181
|
+
| `dataDir` | 状态文件目录,默认插件内 `data/` |
|
|
182
|
+
|
|
183
|
+
也可以用环境变量覆盖:`DSH_PAPER_PROJECT`、`DSH_PAPER_PYTHON`、`DSH_PAPER_SKILL`、`DSH_PAPER_DATA`。
|
|
184
|
+
|
|
185
|
+
## 目录结构
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
src/index.js 工具定义(16 个)
|
|
189
|
+
src/runner.js spawn Python,UTF-8 与超时处理,记录工具调用耗时
|
|
190
|
+
src/paths.js 路径解析(环境变量 → config → 内置默认)
|
|
191
|
+
python/ 解析、重建、校验流水线(从 paper-translate 技能同步)
|
|
192
|
+
references/ 术语词表 terms.md(要随包分发,否则词表为空且不报错)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`python/` 是技能脚本的副本,行为固定可复现。技能更新后需要手动同步一次。
|
|
196
|
+
|
|
197
|
+
## 已知限制
|
|
198
|
+
|
|
199
|
+
- **扫描版 PDF 不支持**:没有文字层就抽不出段落,先做 OCR。
|
|
200
|
+
- **图形摘要靠判据识别**:图注文本 + 位置/面积打分,仍可能误判,可用 `figs_override.json` 手工指定裁切框。
|
|
201
|
+
- **表格重建会失败**:行列数异常时标 `_manual`,需要手工填 `header`/`rows`,不会瞎猜。
|
|
202
|
+
- **PDF 导出依赖外部程序**:优先 Microsoft Word(COM),否则 LibreOffice;两者都没有时只出 DOCX。
|
|
203
|
+
- **图表解读不看图**:只读图注与正文引用句,所以图注没写的视觉细节(颜色、曲线走势)一律不写;个别 PDF 的字距伪影(`Researc h`、`( A )`)会原样留在英文图注里,括号已自动修。
|
|
204
|
+
- **图注质量决定上限**:一句话图注的论文只能给「这张图证明了什么」,讲不到子图层面。
|
|
205
|
+
- **图注必须落在文本层**:印在图里、或整段扫描进图注的,抽不出来;与正文同字号的长图注(`Figure 3. …`,
|
|
206
|
+
1500 字上下)靠「编号后紧跟句点」识别,正文里以 `Figure 3.` 独立成段的句子理论上可能误判,
|
|
207
|
+
核对 `structure.json` 的 `captions_linked` 与 `orphans` 即可。
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
package/cordis.patch.yml
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-paper-translate",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "论文 PDF 中译(版式保留)与文献总结:把 paper-translate skill 的 Python 脚本暴露为 DeepSeek Harness 工具",
|
|
5
|
+
"author": "linlinxxy77-hue",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"src",
|
|
11
|
+
"python",
|
|
12
|
+
"!python/__pycache__",
|
|
13
|
+
"references",
|
|
14
|
+
"scripts",
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"config.example.json",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
20
|
+
"dsh": {
|
|
21
|
+
"bundle": {
|
|
22
|
+
"patch": "./cordis.patch.yml"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@deepseek-ai/dsh-tools": "^0.2.1-rc.3"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@deepseek-ai/schemastery": "~3.18.5"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"dsh": ">=0.2.1-rc.3 <0.3.0",
|
|
33
|
+
"node": ">=22"
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/linlinxxy77-hue/dsh-paper-translate.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/linlinxxy77-hue/dsh-paper-translate#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/linlinxxy77-hue/dsh-paper-translate/issues"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"dsh-plugin",
|
|
45
|
+
"pdf",
|
|
46
|
+
"translation",
|
|
47
|
+
"deepseek-harness"
|
|
48
|
+
]
|
|
49
|
+
}
|
package/python/_deps.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""_deps.py —— 第三方依赖缺失时给出可执行的修复提示,而不是抛 ImportError 栈。
|
|
3
|
+
|
|
4
|
+
用法(必须在 import pymupdf / docx / PIL 之前调用):
|
|
5
|
+
import _deps; _deps.ensure()
|
|
6
|
+
import pymupdf
|
|
7
|
+
"""
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
PKG = {"pymupdf": "pymupdf", "docx": "python-docx", "PIL": "pillow"}
|
|
11
|
+
DEFAULT = ("pymupdf", "docx", "PIL")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def ensure(mods=DEFAULT):
|
|
15
|
+
missing = []
|
|
16
|
+
for m in mods:
|
|
17
|
+
try:
|
|
18
|
+
__import__(m)
|
|
19
|
+
except Exception:
|
|
20
|
+
missing.append(m)
|
|
21
|
+
if not missing:
|
|
22
|
+
return
|
|
23
|
+
pkgs = [PKG.get(m, m) for m in missing]
|
|
24
|
+
sys.stderr.write(
|
|
25
|
+
"\n[paper-translate] 缺少依赖: " + ", ".join(pkgs) + "\n"
|
|
26
|
+
"不要直接 pip install 到系统环境。请先执行环境自检:\n"
|
|
27
|
+
" python scripts/env_check.py\n"
|
|
28
|
+
"它会列出缺失的包;获得用户同意后加 --bootstrap,在**项目文件夹内**建立\n"
|
|
29
|
+
"虚拟环境并安装(不写系统目录、不写 C 盘临时目录)。\n"
|
|
30
|
+
"安装完成后用报告中给出的 PYTHON 路径重新运行本脚本。\n\n"
|
|
31
|
+
)
|
|
32
|
+
sys.exit(2)
|