dsh-research-check
在交论文、交文档、交数据之前,先让它替你检查一遍。
它专门抓那种"明明检查过、却还是被抓出来"的低级错误:数字前后不一致、改了标题忘了改正文、 文档属性里藏着你的名字和学校、少交了一个文件、页数超了一页。
适用于任何"有要求、要交付"的活儿:论文投稿、软件交付验收、数据交付、标书申报、技术文档。 它不是写手,是校对员——不帮你写内容,只帮你把该对的地方对上。
dsh plugin --profile web add dsh-research-check # 装进 DeepSeek Harness
也支持 MCP:Claude Code、Codex、Cursor 等任何支持 MCP 的工具都能用(见 第 3 步)。
目录
它能帮你什么(先看这个)
下面每一条,都是真实发生过、并且被这个工具抓出来的问题:
| 你可能犯的错 | 具体长这样 | 后果 |
|---|---|---|
| 数字改了正文没改 | 图表里写 4761,正文还写着 4883 | 评审一眼看出你没核对 |
| 两个口径混用 | 一张表用"计划量"算,另一张用"实际量"算,两个总数对不上 | 被认为数据不可信 |
| 比率说错 | 写"两个方案都只有 1/565",其实一个 565、一个 583 | 严谨性打折 |
| 旧版本残留 | 摘要写 1536.4,定稿是 1521.6(改稿时漏了摘要) | 摘要与正文矛盾 |
| 文档属性泄露身份 | 你的 Excel/Word 里存着账号名、学校名(肉眼看不见) | 匿名评审直接违规 |
| 页数超限 | 要求正文 ≤30 页,你交了 31 页 | 可能直接被拒 |
| 清单对不上 | 论文附录列 11 个文件,压缩包里实际 12 个 | 被视为材料不实 |
| 交付物里有报错 | 交付日志里留着 Traceback、ERROR: |
显得没测过 |
| 数据不合规 | 交付数据里混进了手机号字段 | 合规风险 |
| 占位符没删 | 对外文档里留着 TODO、待补充 |
非常尴尬 |
核心价值一句话:这些错误自己很难查(尤其是元数据里的身份信息——你根本看不见), 但被发现一次,代价往往是一整轮返工甚至取消资格。让工具在交之前替你过一遍。
三步用起来
第 1 步:把"要求"喂给它(只做一次)
你手上一定有一份要求文件:赛会格式规范、期刊投稿须知、甲方验收标准、导师给的模板。 把这个文件交给它,它会变成一份能自动核对的清单:
python python/spec_build.py --requirements 格式规范.doc --out specs/我的要求.json \
--profile academic --name "竞赛论文格式规范"
它会告诉你提取出了多少条规则,每条规则都带出处(引用要求文件里的原话),例如:
{
"id": "doc.body_pages",
"title": "正文页数上限",
"check": "max_pages",
"severity": "hard",
"params": { "limit": 30 },
"source": "…论文从第四页开始是正文内容(不要目录,不超过30页)…"
}
⚠️ 然后花两分钟人工看一眼:确认数字对不对(30 页?20 MB?)。 有些规则需要你填参数(比如"必须提交哪些文件"),空着的规则它会如实报"没检查"——不会假装通过。
第 2 步:交之前,一句命令自查
python python/check_spec.py --spec specs/我的要求.json --root . \
--pdf 我的论文.pdf --files 交付文件1.xlsx 交付文件2.docx --archive 材料.zip
输出是中文表格,通过的打 ✓,违反的标 ✗ 并告诉你为什么(引用要求原文):
[ok ] hard 正文页数上限 正文 30 页 / 上限 30 页
[FAIL] hard 文档属性不得含身份信息 属性命中:{'creator': '张三'}
[ok ] soft 图表必须被引用 全部被引用
第 3 步:用其他 AI 工具(Claude Code / Codex / Cursor)
如果你不用 DeepSeek Harness,可以用 MCP 接入——在工具的 MCP 配置里加一段:
{
"transport": "stdio",
"serverName": "research-check",
"command": "node",
"args": ["<插件目录>/mcp/server.mjs"]
}
之后你的 AI 就能调用 spec_build / spec_check / audit / numbers / ledger 五个能力。
四个工具的用法
装好之后,你用大白话让 AI 去用就行,不用背命令:
| 你可以这样说 | 实际调用的工具 | 它会做什么 |
|---|---|---|
| "帮我按格式要求检查一下论文" | research_spec |
按要求清单逐条核对 |
| "检查我的论文和压缩包,交之前看一眼" | research_audit |
查页数、空白页、图表引用、身份信息、清单一致性 |
| "我改了结果,帮我核对论文里的数字有没有漏改" | research_numbers |
找出前后矛盾的数字 |
| "把这个数字和它的来源记下来,以后好核对" | research_ledger |
建立"数字—出处"台账 |
推荐的工作流(顺序很重要):
① 先建台账,记下关键数字和它们的来源
② 跑程序,刷新台账里的数值
③ 改正文和图表(两个地方都要改!)
④ 核对:台账里的数字在正文里还找得到吗?
⑤ 交之前跑一遍格式检查
命令行直接用法:
# 建台账:从文稿里自动找出带单位的数字,登记成候选
node lib/ledger-cli.js teach --ledger paper-ledger.json --paper 论文.tex \
--unit-filter 万元 --min-abs 100
# 手动登记一条(把"这个数字从哪来"钉住)
node lib/ledger-cli.js add --ledger paper-ledger.json \
--key q3.total_cost --value 1521.6 --unit 万元 \
--source code/q3.py --anchor 全年费用
# 核对:台账里的值还在文稿里吗?(--near 会额外提示"同位置的相似数值")
node lib/ledger-cli.js verify --ledger paper-ledger.json --paper 论文.pdf --near
# 体检:页数、摘要、空白页、身份信息、压缩包清单
python python/audit_paper.py --paper 论文.pdf --archives 材料.zip
支持哪些交付物
同一个工具,换一份要求文件,就能用在完全不同的场景。--profile 决定用哪套规则:
| 场景 | --profile |
它重点查什么 |
|---|---|---|
| 论文 / 学位论文 / 期刊投稿 | academic |
页数、摘要单页、图表引用、页边距、行距字号 |
| 软件交付 / 项目验收 / 发版 | software |
必备文件、LICENSE、变更记录、日志里的报错 |
| 数据交付 / 数据集 | dataset |
字段齐备、样本量、隐私字段、数据字典 |
| 说明书 / 技术文档 / 手册 | docs |
段落长度、版本号、联系方式、TODO 残留 |
| 标书 / 申报书 | tender |
章节齐备、逐条响应 |
| 任何交付物 | generic |
体积、命名、身份信息、清单一致性、占位符 |
共 37 个可判定的检查项。查看每类的规则数:
python python/spec_build.py --list-profiles
跨场景实测(python tests/test_generality.py,自动化跑,每次发布前都会验证):
| 交付物 | 干净版本 | 故意做坏的版本 → 被抓住的问题 |
|---|---|---|
| 软件包 | 0 错误 | 缺 README.md;日志里有 Traceback |
| 数据集 | 0 错误 | 缺字段;样本量不足;混入手机号 |
| 技术文档 | 0 错误 | 段落超长;TODO 没删;Word 属性里有作者名 |
它不会做什么
先说清楚,免得你误会:
- ❌ 不帮你写内容——它只核对,不生成
- ❌ 不判断两个数字谁对——它会告诉你"这里有两个互相矛盾的数"以及它们在哪, 由你来决定改哪个(只有你知道哪个是新的)
- ❌ 不重新推导公式——数字是"比对"而不是"重算"。如果程序算错了、正文照抄了这个错值, 两边一致就会通过。所以对结论起决定作用的数字,仍然要自己独立复算
- ❌ 不评价方法好坏、不做法律意见
规格文件与台账
规格(spec):把要求变成清单
{
"id": "doc.body_pages",
"title": "正文页数上限",
"check": "max_pages",
"scope": "body",
"severity": "hard",
"params": { "limit": 30, "appendix_marker": ["附录"] },
"why": "页数是评委最先感知的硬约束",
"source": "…要求文件里的原话…"
}
check:用哪个检查项,必须是 37 个之一,或manual(人工清单)scope:document(整份)/body(附录前)/per-file/bundleseverity:hard违反即报错 /soft只提醒 /info只记录
三条纪律(决定了它不会变成"只会说通过"的花架子):
- 每条规则必须指定检查项,否则加载就报错。机器判断不了的(比如"测试是否覆盖需求")
写成
manual,进入人工清单——绝不假装能查。 - 没检查 = 没检查:缺输入、缺参数时如实报
skipped,绝不混进"通过"里。 - 每条判定都带出处,你可以拿着它去答辩、回复审稿意见。
台账(ledger):把数字和出处钉在一起
{
"entries": [
{
"key": "q3.total_cost",
"value": 1521.6,
"unit": "万元",
"source": "code/q3.py",
"anchor": "全年费用"
}
]
}
key用语义名(q3.total_cost),不要用数字本身当 key——程序重跑后只改value,正文不用动unit单独放,避免把「1.5 万元」和「15000 元」当成两件不同的事anchor是正文里的固定短语,用来定位并检查"同一位置是否出现了量级相近的异值"
验证与开发
九段验证,全部可以在本地复现:
npm test # 语法 + 上架清单 + 打包清单 + 契约 + MCP + 规格 + 跨领域
npm run test:generality # 跨场景(软件/数据/文档,含"故意做坏"的负例)
npm run test:pack # 检查 npm 实际会打包什么
npm run mcp:smoke # MCP 协议层(真实报文)
npm run boot # 真启动一个临时实例,确认不会把 DSH 启动搞崩
关键设计:每个功能都配了"负例"——故意写错的东西必须被抓出来。 只会说"通过"的检查器是装饰品,所以每个功能都有对应的"必须抓住"测试。
在 CI(.github/workflows/verify.yml)上跑 Node 22/24 + Python 3.13。
常见问题
Q:装完没反应 / 工具不出现? A:DSH 插件在启动时注册,需要重启 profile。MCP 方式则要重启你的 AI 工具。
Q:报 NO_PYTHON?
A:检查核心需要 Python 3.10+。装了还是报,就设环境变量 DSH_RESEARCH_PYTHON 指向解释器路径。
Q:报 skipped 是什么意思?
A:"这条我没查"——通常缺输入(比如没给 PDF、没给文件清单)或规则参数没填。
它不等于通过,请补齐输入或转人工确认。
Q:中文输出乱码? A:1.4.1 起已修复(脚本强制 UTF-8 输出)。旧版本请升级。
Q:会不会把我的论文上传到什么地方? A:不会。所有检查都在你本机命令行完成,插件不联网、不收集任何数据。
Q:能检查 Word 文档吗?
A:能。段落长度、身份元数据类规则直接读 .docx;页数、摘要、图表引用类规则需要 PDF
(Word 转 PDF 后即可)。
Q:我的要求文件格式很乱(表格、编号、中英混排)能识别吗?
A:能解析 .doc / .docx / .md / .txt。它用的是模板匹配而不是自由发挥——
只收录要求文件里明确出现、且机器能判定的条款,其余进入"需要人工确认"清单,不会瞎猜。
License
MIT
由来
最初是给一篇真实的竞赛论文写检查脚本,写着发现每一个检查都对应一个真实犯过的错, 而这类错误与学科无关——凡是"数据 → 图表 → 结论"的活儿都会犯。 于是把"要求"抽象成规格、把"数字"绑回台账、把检查项做成词汇表, 让它能用在论文、文档、软件、数据、标书五类交付上。
No comments yet. Be the first to write one.