之前团队要做内网专属的AIGC生成内容筛查系统,前前后后踩了快俩月的坑。
最早试过PaperPass的AI内容溯源接口,然后找了知网研学自带的生成内容筛查模块,下了团象AIGC检测的本地离线包,还申请过腾讯云的内容合规API试用,最后甚至找了百度文心百中的公有云校验接口。
结果这些方案要么必须连公网传数据,要么内置的中文技术语料太少,全都不好用,完全满足不了我们物理断网的内网需求,只能硬着头皮自研。
先给大家说下我们的硬约束需求,一条都没法妥协。 第一是绝对数据隔离,所有待校验的文档、代码,全程不能出内网一步,连接口回调都不能碰公网。 第二是多格式兼容,要支持docx、md、txt、源代码文件、扫描转PDF五类常见场景,覆盖所有办公产出。 第三是误判率指标,要求把真人手写内容被误判为AI生成的比例,压到3%以下,绝对不能打扰正常办公。 第四是并发要求,要扛住500人同时提交校验,平均响应时间不能超过10秒。
一开始图省事,我直接找到了GitHub上星标最高的开源检测库detect-gpt-zero,想着装完就能跑。
from detect_gpt_zero import Detector detector = Detector() # 喂100份中文AI生成方案+100份手写工程师文档测试 acc = detector.evaluate("test_chinese_dataset.json") print(f"中文检测准确率:{acc}")跑出来的结果我至今记得,终端输出直接跳了个中文检测准确率:0.468,差点把我显示器干碎。
后来查了源码才反应过来,这个库完全是用英文语料预训练的,对中文的语义特征几乎没有学习,连中文常用的标点逻辑都搞不懂,能到47%的准确率都算碰对了一半。
当时走的第二个弯路,是直接拿开源中文语料去微调这个检测模型,找了网上爬的10万条中文文本,扔进去训了一轮。 训完测试更离谱,误判率直接干到了27%,所有带互联网热词、口语化吐槽的技术文档,全被标成了AI生成的。 我翻了训练集才发现,里面混了大量短视频文案、社交媒体水帖,完全是垃圾数据,把模型带偏到姥姥家了。
这时候我才反应过来,做中文技术场景的AIGC检测,第一步绝对不是训模型,而是攒完全属于自己的纯净数据集。 正样本我们花了一周时间,从内网文件服务器里,导出了2018-2023年全部存量的工程师手写技术文档、代码提交记录,一共127万份,这批数据产生的时候还没有可用的开源大模型,100%是真人写的。 负样本我们在内网部署了Llama2-7B、Qwen-7B、ChatGLM3-6B三个主流开源大模型,用我们自己的业务语料微调后,生成了120万份同主题的AI技术文档、代码片段,全程没有任何数据流出内网。
有了纯净数据集之后,我放弃了传统的全文困惑度差值方案,专门针对中文技术场景做了7个维度的独立特征工程。 第一个是字符级n-gram分布特征,真人写中文技术文档的时候,几乎不会连续堆3个以上四字成语,大模型生成内容却经常出现这类规整的排比表述。 第二个是代码专属特征,真人写的Python代码,60%以上会留下调试用的废print语句、变量拼写错误,AI生成的代码往往完全符合PEP8规范,连多余的空行都找不到。 第三个是语义跳变特征,真人写文档经常插两句无关吐槽、前后段落话题跳转没有平滑过渡,大模型生成的内容逻辑顺滑到几乎没有断点。 第四个是滑动窗口困惑度特征,把文本拆成20字一个的滑动小窗口,分别算每个窗口的困惑度,真人写的内容困惑度波动极大,AI生成的内容波动几乎是平的,这个特征单拎出来区分度就能到92%。 剩下三个分别是标点使用习惯、常用术语搭配占比、段落长度分布,三个特征加起来又把准确率拉高了4个百分点。
特征工程做完之后,我根本没选大模型做检测,选了轻量的XGBoost分类器,把7个维度的特征全部向量化之后喂进去训练,整个训练过程用一张3090显卡跑了不到3小时。 最终训出来的分类器模型大小才78MB,随便找个低配服务器就能部署,完全不需要大量算力资源。 这里还要说个之前踩的隐形坑,一开始算困惑度用的是通用中文预训练模型,结果我们内网的专属项目代号,模型从来没见过,算出来的困惑度奇高,好多提到内部代号的真人文档都被误判了。 后来我们用内网全部无敏感的技术语料,微调了一个专属的轻量GPT2小模型来算困惑度,这个问题立刻就解决了,连非常冷门的内部项目代号,都不会影响特征计算的准确性。
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer from datasets import load_dataset # 加载开源中文小模型作为基座,整个过程在内网离线完成 model_name = "uer/gpt2-chinese-cluecorpussmall" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name) # 加载内网导出的无业务敏感信息的技术语料数据集 dataset = load_dataset("text", data_files="./inner_tech_corpus.txt") # 微调1个epoch就足够适配内部术语,不需要太多算力 training_args = TrainingArguments(output_dir="./p_model", per_device_train_batch_size=8, num_train_epochs=1) trainer = Trainer(model=model, args=training_args, train_dataset=dataset["train"]) trainer.train()部署架构我们做了三层解耦,全链路跑在内网隔离区,连公网网线都没插。 第一层是接入转换层,用FastAPI写的轻量接口,内置python-docx、pymupdf、mistune等依赖,自动把不同格式的文件转成纯文本,扫描件则调用本地部署的PaddleOCR离线识别。 第二层是任务调度层,用Redis+Celery做分布式任务队列,所有校验请求先入队列排队,后台4台计算节点异步取任务执行,避免突发流量打垮服务。 第三层是结果输出层,返回的报告不会只给一个干巴巴的百分制分数,而是把7个维度的得分全部列出来,异常内容直接定位到具体行数,方便审核人员人工复核。
整套系统写完我们用JMeter做压测,500并发的场景下平均响应时间7.2秒,完全达标。 在2000份样本的测试集里,最终准确率达到97.3%,误判率只有2.1%,完全符合我们最初定的要求。 我们还给系统加了两个非常实用的优化功能。 第一个是个人白名单功能,如果某些老工程师的写作风格非常特殊,容易被误判,直接把他的10份历史文档喂进去,系统就会提取他的个人写作特征,后续校验自动适配,误判率还能再降。 第二个是自动增量迭代功能,每周日凌晨系统会自动把本周人工复核过的新样本,补充到正负样本集里,自动跑一轮增量微调,模型越用越准,几乎不需要人工运维。
现在这套系统已经在内网稳定跑了3个多月,累计校验了12万份文档、37万份代码文件,从来没出过数据泄露问题。 之前行政合规抽查一份3000字的文档,人工逐字看至少要10分钟,现在系统1秒出结果,整体效率直接提了十几倍。
其实回过头来看,很多特殊场景下的通用工具不好用,本质上是需求的定制化程度太高了。 尤其是物理断网的内网合规场景,所有通用产品都不可能提前适配你们内部的专属术语、写作习惯,与其花大量时间挨个试工具踩坑,不如集中少量资源自研一套,后续迭代起来也完全灵活可控。