每年毕业季都有一个很折磨人的事情:上级部门通知限期完成毕业论文材料核查,要求比对同一学生在系统中提交的所有材料——开题报告、中期检查表、初稿、二稿、答辩稿、成绩评定表、终稿、查重报告——里面的课题名称是否一致,企业导师信息是否正确,佐证附件是否齐全,过程材料签字是否完整。
七个人,每人七个阶段的材料,每个阶段还有 PDF、docx、ZIP 等不同格式。手动一个一个打开、一条一条比对,再认真做表格记录,这件事很枯燥,很耗时间,而且极其容易漏。
这次演示的就是怎么用 opencode 把这件事半自动化掉——不是完全自动,是"人提问题、AI 找问题、人定问题"的模式。
用 AI 做事情,有一个很容易掉进去的陷阱:把控制权交出去。"帮我检查一下这些材料有没有问题"——这句话听起来没什么,但仔细想想,"什么算问题"是你定的,还是 AI 定的?如果你不提前说清楚,AI 就会按自己的理解去定义"问题",那最后出来的东西未必是你想要的。
所以整个流程要这样设计:
人来提出要查什么,AI 来执行查找和比对,最后人来决定查出来的结果怎么办。
从头到尾,人必须是掌控者,AI 是执行者。这个顺序一旦搞反——比如你直接跟 AI 说"帮我把材料审核一遍",什么都不限定——出来的结果可能看起来很完整,但重点完全跑偏了。
背景:一个 deadline 很近的核查任务
事情的由头是一份通知,要求在规定日期前完成毕业论文材料的全面核查,并将检查报告提交给上级部门。检查内容有好几项:
- 课题名称在开题报告、成绩评定表、查重报告、论文正文中是否一致
- 查重率是否真实、佐证附件(程序代码、设计文档等)是否齐全
- 双导师(校内导师+企业导师)信息是否一致
- 过程材料签字是否完整
七位学生,每人七个阶段的材料,格式各不相同。你要是手动查,光是打开 PDF 就要点几十次,甚至还得一条条记。这件事听起来就让人头疼。
我给 opencode 的第一句话
我一开始的需求其实很简单,用一句话说清楚就行:
帮我访问这个论文管理系统,把七位学生的所有材料全部下载下来,然后按学生、按阶段分好目录,最后做一份核查报告,对比每份材料里边的题目是否一致。
你看,这句话里有四个信息:
- 干什么:访问系统、下载材料、整理目录、做核查报告
- 范围:七位学生,每人所有阶段
- 比对维度:题目在各材料中的一致性
- 交付物:一份完整的核查报告
至于具体怎么访问浏览器、用什么库解析 PDF、怎么从 docx 里提取标题——这些技术细节我一句话都没提。
因为不需要提。 opencode 知道去启动浏览器、去写代码、去调用工具。你需要操心的只是"把需求说清楚",剩下的交给它。
第一步:打开浏览器,人工登录
这一步有一个很重要的原则:账号密码绝不交给 AI。
opencode 的做法是用 Selenium 启动一个 Firefox 浏览器窗口,然后——等你自己去登录。你在那个浏览器里手动输入用户名密码、点击登录,完成整个认证过程。opencode 不参与这一步,它看不到你的密码,也不会替你输入。
登录成功之后,opencode 从浏览器的 session 里读取一组 cookie(SESSION、XSRF-TOKEN、JSESSIONID),后续所有的 API 调用都靠这组 cookie 来维持身份。
这个设计思路值得说一下:让 AI 控制浏览器去做后续的自动化操作没问题,但登录这一步必须由人来完成。 原因很简单——把账号密码交给 AI,不管它是本地运行的还是在线的,都多了一层不必要的风险。你自己登录,它只拿 cookie,各管各的。
第二步:摸清系统 API 结构
这是整个流程里最关键的一步。登录之后,opencode 没有傻乎乎地去"翻页截图",而是去分析了系统的 API 接口。
它用浏览器开发者工具(或者说 Selenium 的 network 监控)发现了后端的几个关键接口:
dynamicListJson:列出某个阶段的所有学生材料记录getDownloadUrl:获取某个文件的下载地址checkReport:查看查重报告
每个接口需要的参数、请求头、cookie,它自己去摸索了一遍,最后把 API 的调用方式完整摸清了。
这个过程有点像你用浏览器的"检查元素"去分析网页,只不过 AI 比你快得多,而且不会漏。
第三步:批量下载所有材料
摸清 API 之后,就进入干活的环节了。
opencode 写了一个 Python 脚本,遍历七位学生的所有阶段(开题报告、初稿、二稿、中期检查、答辩稿、成绩评定、终稿),逐个调用下载接口,把文件保存到对应目录:
毕业论文材料核查/
├── 下载_学生材料/
│ ├── 学生A_2022000001/
│ │ ├── 开题报告/
│ │ ├── 初稿/
│ │ ├── 二稿/
│ │ ├── 中期检查/
│ │ ├── 答辩稿/
│ │ ├── 成绩评定/
│ │ └── 最终稿/(含佐证附件和查重报告)
│ ├── 学生B_2022000002/
│ ├── ...
73 个文件,160MB,全部按学生和阶段分目录存放。查重报告是 ZIP 压缩包,自动解压。
这一步如果手动做——打开每个学生的每个阶段、点击下载、保存到对应文件夹——大概需要一个多小时。opencode 跑了五分钟。
第四步:从 PDF 和 docx 中提取标题
接下来才是真正的难点:从不同格式的文件中,准确提取出"课题名称"或"论文题目"字段。
难点在于不同格式的结构完全不同:
- 开题报告 PDF:标题在"题目(中、外文):"这个标签后面,中文标题在第一行,英文标题在第二行。
- 成绩评定表 PDF:标题在"论文题目"字段后面,但可能跨多行。
- 查重报告 PDF:标题在"NO."编号后面,紧跟着论文题目。
- docx 文件:标题可能在封面、摘要、正文里多次出现。
刚开始我用的正则表达式是 r'论文题目\s*([^\n]+)'——只取第一个换行符之前的内容。结果成绩评定表里的长标题被截断了,比对的时候出现了大量"不一致"的假阳性。
后来改成更聪明的方案:不是精确提取标题文本,而是把系统中的完整标题做归一化处理(去除所有空白、去除字母间距),然后检查归一化后的系统标题是否出现在文件的全文中。这样就完全避免了截断问题。
def norm(s):
s = re.sub(r'\s+', '', str(s))
s = re.sub(r'([A-Za-z]) ([A-Za-z])', r'\1\2', s)
return s
# 检查系统标题是否出现在 docx 正文(归一化后)
sys_n = norm("面向本地大语言模型运行时的环境感知辅助系统设计与实现")
fulln = norm('\n'.join(p.text for p in docx_paragraphs))
hit = sys_n in fulln
归一化的逻辑还处理了 PDF 中常见的"字母间距"问题——有些 PDF 把字母间距放大了,比如"Windows"在 PDF 里可能显示为"W i n d o w s",归一化时把这些间距去掉再比较。
这个细节是人手工比对时很难注意到的,但 AI 写脚本处理起来很自然。
第五步:生成对照表格
全部文件下载、提取、比对完成后,opencode 生成了一份对照表格,把七位学生在每个阶段的题目信息排列在一起,一眼就能看出有没有不一致的地方。
表格大概是这样的结构:
| 学生 | 系统课题名称 | 开题报告题目 | 成绩评定表题目 | 查重报告标题 | 初稿正文 | 二稿正文 | 答辩稿正文 | 终稿正文 |
|---|---|---|---|---|---|---|---|---|
| 学生A | xxx | ✅ 一致 | ✅ 一致 | ✅ 一致 | ✅ 含完整题目 | ✅ 含完整题目 | ✅ 含完整题目 | ✅ 含完整题目 |
| 学生B | xxx | ✅ 一致 | ✅ 一致 | ✅ 一致 | ✅ 含完整题目 | ✅ 含完整题目 | ✅ 含完整题目 | ✅ 含完整题目 |
| ... |
查重率也一并列了出来——每位学生的论文重复率、AIGC 检测率,系统侧是否标记为"完成"。
这个表格就是整次核查的核心产出。 AI 把 73 个文件里分散的信息汇总到一张表里,人不需要再打开 73 个原始文件一个一个看了——对着这张表逐行审阅就行。
第六步:人来审阅
表格生成完,AI 的活就基本干完了。剩下的事情是人来做的:
- 逐行逐列读完整张对照表,每位学生在每个阶段的题目、查重率、附件状态,全部过一遍
- 看到哪个单元格有疑点,就打开对应的原始文件核实
- 检查佐证附件是否齐全(程序代码、运行截图、设计文档)
- 检查双导师信息在系统里是否登记完整
- 确认过程材料签字是否完整
- 最后根据表格的整体情况,写出核查结论
这一步是 AI 替代不了的。 AI 能把信息汇总成表格,但"这个表格说明了什么"、"哪些地方需要进一步确认",判断权永远在你手里。
整个过程用了多久
从登录系统到报告生成完毕,整个过程大约用了不到一个小时。其中大部分时间花在 API 探索和 PDF 解析上——登录、下载、整理目录这些都是几分钟的事。
如果完全手动做:打开 73 个文件、逐个核对标题、手工记录在表格里,保守估计需要三到五个小时,还不算中间打开错文件、找错行之类的失误成本。
但这件事的核心不是"AI 多厉害"
回到开头说的那个框架:人提出问题 → AI 发现问题 → 人决定问题。
这个流程里,每一步都不能缺。没有人提出问题,AI 不知道该查什么;没有 AI 去执行,人得自己打开 73 个文件一个一个看;没有人来决定结果,AI 给你的对照表格就只是一堆符号,你不知道该信任还是该怀疑。
拿这次的事来说:
- 人提出问题:我告诉 opencode"比对七位学生在开题报告、成绩评定表、查重报告、论文正文中的课题名称是否一致"。这一句话界定了比对的范围和维度。如果我没说"课题名称",它可能去比对学生姓名;如果我没说"论文正文",它可能漏掉 docx 里的信息。
- AI 发现问题:opencode 下载了 73 个文件,逐个解析 PDF 和 docx,把每个阶段的题目提取出来,和系统里的课题名称做归一化比对,最后生成对照表格。这个过程涉及 PDF 解析、正则表达式、文本归一化、文件名处理等一堆技术细节,全让 AI 干了。
- 人决定问题:对照表格摆到面前,我逐行逐列地读——每位学生在每个阶段的题目、查重率、附件情况,全部过一遍,然后根据结果写核查结论。AI 不能替我做这个判断——它不知道上级部门对这份报告的具体要求,也不知道哪些"看起来一致"的地方其实藏着猫腻。
AI 做的是"把材料摆到你面前",人做的是"确认材料没问题"。这两步缺一不可。
但最关键的不是这两步,而是开头那一步——你得自己先把问题想清楚。"要比对什么"、"比对的范围是什么"、"什么情况下算有问题",这些问题不先想明白,后面 AI 再厉害也是白搭。你给它一个模糊的指令,它给你一个模糊的结果,最后你还得自己从头来。
对类似场景的建议
如果你也有类似的需求——批量核查文档、比对多处信息、做交叉验证——以下几条经验可能有用:
- 明确比对维度。在你跟 AI 说需求的时候,就把"要比对什么"说清楚。"题目是否一致"、"查重率是否真实"、"签字是否完整",每一条都单独列出来。AI 不知道你关心什么,你得告诉它。
- 处理格式差异。不同文件格式(PDF、docx、图片)的解析方式完全不同,AI 会自己找工具去处理,但你可能需要在发现它解析出错的时候及时纠正——比如"成绩评定表的标题跨了两行,你的正则截断了"。
- 让 AI 汇总成表格再审。AI 的价值不只是"帮你找问题",而是把分散在 73 个文件里的关键指标汇总成一张完整的对照表格。人审阅的是这张表格,不是原始文件。表格里该有的信息都有——学生姓名、系统课题名称、各阶段题目、查重率、附件状态——逐行读完,整体判断,比自己打开文件一个个看靠谱得多,也不会漏。
- 核查报告要分优先级。所有问题都标"紧急"等于没有紧急。分成"必须处理"、"需要核实"、"建议改进"三级,对 deadline 前的决策帮助很大。
总结一下
这篇的例子:用 opencode 把"七个人的毕业论文材料核查"从一个手动三小时的活,变成了一个小时半自动完成的任务。
核心工作流是:人提出问题(比对什么、比对哪些人、比对哪些材料)→ AI 执行(登录、下载、解析、比对、生成表格)→ 人来审阅(逐行读表、写结论)。每一步都有技术难点——登录的 cookie 管理、API 的参数探索、PDF 的标题提取、docx 的文本归一化——但这些都让 AI 去处理了。
人需要做的只有两件事:开头把需求想清楚,结尾把结果审一遍。
控制权始终在你手里,AI 只是替你跑腿。工具提升的是效率,不是判断力。效率越高,越需要你把判断的事情想清楚。这件事不管用不用 AI 都是一样的。