我在实验室内网搭论文AI内容校验流水线的72小时踩坑全记录
2026/7/9 8:31:51 网站建设 项目流程

上周导师突然丢了个需求过来,要求实验室所有硕博的待投稿论文,必须先完成内网离线的AIGC痕迹筛查。

绝对不能把未发表的稿件传到任何外部公网平台,避免还没见刊的研究成果提前泄露。

我们组三个搞NLP方向的同门凑在一起啃了三天文档,踩了数不清的坑,终于把整套流水线跑通了。

最开始我们图省事,随便找了个网上热度很高的开源检测脚本,直接往主服务器上扔。

刚跑了三篇论文,24G的3090显存直接被占满,连带旁边正在跑大模型微调的师弟的进程直接被OOM Killer杀了。

吓得师弟当场跳起来,花了半个多小时从磁盘快照里找回了没存完的训练权重,差点直接延毕半个月。

踩了这次坑之后我们冷静下来,把所有硬性需求一条条列在白板上,一个都不能打折扣。

第一是数据全程不能出内网,所有依赖的模型、组件全离线部署,不能有任何访问公网的接口调用。

第二是支持doc、docx、扫描版/高清版PDF等几乎所有主流论文格式,不需要用户手动转文本。

第三是针对中文理工科学术文本做适配,准确率至少要超过学院之前抽检用的抽检工具的平均水平。

一开始我们图省事,分别用python-docx读Word文件,用PyPDF2读普通PDF,开发进度看起来很快。

结果测试的时候直接傻了,扫描版PDF读出来全是乱码,带大量公式的Word里,公式位置全是占位符乱码。

后来我们直接放弃分格式适配的思路,改用Unstructured库作为统一解析入口,搭配PaddleOCR处理扫描页内容。

为了避免一堆乱七八糟的依赖把主环境搞崩,我们直接把解析模块单独打包成一个独立Docker容器。

核心解析代码写起来其实很简单,十来行就搞定了多格式的统一输出:

from unstructured.partition.auto import partition def parse_unstructured_file(file_path: str) -> str: # 自动适配docx/pdf等格式,过滤非正文区域 elements = partition(filename=file_path, strategy="hi_res") return "\n".join([ele.text for ele in elements if ele.category == "NarrativeText"])

跑通之后我们又加了版面分析逻辑,直接把页眉、页脚、批注、图表标题区域全部过滤掉。

避免有人在论文里写的手写字批注、无关的页眉水印内容混进正文,干扰后续的特征计算结果。

之前试过的很多开源AIGC检测模型,动辄大几个G的体量,推理一次要好几秒,完全不适合批量跑。

我们干脆自己攒了一个轻量的特征校验框架,完全不用动辄十几G的大生成模型做反向推理。

核心逻辑就靠三个我们自己归纳的专属特征,专门针对中文理工科学术文本做校准。

第一个特征是文本香农熵值的波动统计,我们统计了近10万篇人工撰写的硕博论文的熵值区间。

正常人工写的学术段落,因为思考逻辑跳脱、表述习惯变化,熵值波动基本都在0.5以上。

大模型生成的内容因为采样逻辑的问题,整个文本的熵值会异常平稳,波动差很少超过0.2。

我们把熵计算的核心函数抽了出来,优化了分词后的处理逻辑,跑起来几乎不占什么显存:

import math from collections import Counter import jieba def calc_text_entropy(text: str, n=2) -> float: # 计算中文分词后文本的2-gram香农熵 seg_list = list(jieba.cut(text)) char_counts = Counter([seg_list[i:i+n] for i in range(len(seg_list)-n+1)]) total = sum(char_counts.values()) entropy = 0 for cnt in char_counts.values(): p = cnt / total entropy += -p * math.log2(p) return round(entropy, 2)

第二个特征是学术文本专属的n-gram重复阈值校验,我们整理了近5年本学科所有公开论文的语料库。

统计出来了正常人工撰写文本的2-gram重复概率上限,大模型生成的内容经常无意识重复特定词组。

比如连续好几段出现逻辑完全一致的衔接表述,这种重复率会远超人工写作的正常阈值,很容易识别。

第三个特征是引用连贯性校验,我们把实验室馆藏的所有论文参考文献全部做了向量化索引。

如果某段文字后面跟着引用标号,我们就自动把这段内容和对应参考文献的摘要做语义相似度比对。

大模型经常瞎编不存在的引用,或者把不相关的引用标在段落后面,这种情况直接标记为可疑。

核心逻辑调通之后,我们把整套服务跑在了实验室闲置的K3s边缘集群上,所有节点全部禁止公网出口。

推理服务做了资源限制,最多占用12G显存,剩下的显存空间还能留给师弟师妹平时跑小训练任务。

我们用FastAPI搭了个极简的异步提交后台,批量任务自动进队列排队,不会随便把服务搞崩。

整套服务的编排配置写在docker-compose里,所有镜像都提前拖到了本地镜像仓库,离线也能随便扩容:

version: "3" services: parse-service: image: local/parse-utils:v1 deploy: resources: limits: memory: 2G infer-service: image: local/aigc-infer:v3 deploy: resources: limits: devices: - driver: nvidia count: 1 capabilities: [gpu] reservations: memory: 12G web-service: image: local/frontend:v2 ports: - "8080:80"

我们还在输出侧做了可视化报告生成,最终导出的PDF报告里会把所有可疑段落用黄色高亮标出来。

点进去就能看到对应的可疑维度,是熵值异常、重复率超标还是引用不匹配,作者可以直接针对性修改。

上周我们拿了学院去年学术抽检攒下来的127篇标注样本做盲测,里面有60多篇是全人工撰写的。

剩下的60多篇都是被抽检出来有大段AI生成内容的待整改论文,全程盲测没给任何提示。

最终整套方案的检出率达到了94.7%,误判率只有1.8%,远超过我们最初定的验收标准。

我们之前还碰到过很极端的案例,有个师弟把GPT生成的内容逐字改了快一半,还是被系统揪出了异常段落。

后来核对了下,那段的熵值波动只有0.17,完全不符合正常人工写文本的波动特征,确实是残留了不少AI生成内容。

为了适配高峰时段的批量提交需求,我们把推理服务做了水平扩容,最多同时启动4个推理实例并行处理。

之前高峰期30多个人同时提交论文,排队最长也不会超过2分钟,完全不会出现任务堆积的情况。

中间我们还踩过个很隐蔽的坑:之前有篇带几百个公式的数学学位论文,跑出来的熵值异常偏低。

排查了半天才发现,是OCR识别公式的时候把一堆乱码字符塞进了正文,拉低了整体的熵值波动。

后来我们在特征计算前加了特殊字符过滤逻辑,把所有非中文字符、非标点符号的乱码全部清洗掉,这类误报就再也没出现过。

回头复盘这72小时的折腾,其实我们最开始想找现成的方案省点力气,根本不想自己从头撸。

之前试过付费云检测接口、GitHub标星最高的detectGPT、团象AICG检测、某985高校开源的校内校验工具、大厂公开的内容合规API,这些工具要么要求上传文件到公网服务器,要么针对中文学术内容准确率拉胯,全满足不了我们内网离线使用的需求。

折腾到最后才发现,完全贴合实验室强合规、本地化、学科定制化需求的方案,只能自己动手攒。

现在这套流水线已经推到整个学院的研究生会用了,一周大概能处理五六十篇待投稿的论文,省了大家很多事。

等后续有空了我们再把引用校验的语料库拓展到其他学科,让旁边几个文科院系的实验室也能拿去做适配改造。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询