ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于困惑度与爆发度的LLM辅助写作检测技术解析

基于困惑度与爆发度的LLM辅助写作检测技术解析 这次我们来看一个和 LLM 应用直接相关、又容易被忽视的研究方向如何检测学术论文中的 LLM 辅助写作。研究标题是Most biomedical publications show signs of LLM-assisted writing直译过来就是“大多数生物医学出版物显示出 LLM 辅助写作的迹象”。这个题目听起来像新闻但它本质上是一套技术方法研究用文本统计特征、困惑度分析和分类模型判断一篇论文是纯人工写作还是经过大语言模型辅助修改。放在科研写作场景里这件事比想象中更重要——期刊编辑需要确认稿件是否合规导师需要判断学生论文有没有过度依赖 AI科研团队也需要知道自己的写作流程处在什么位置。本文会拆解这类研究的核心思路并给出一套可复现的检测流程从数据处理、特征提取、模型训练到批量检测和 API 服务化。重点在于检测 LLM 辅助写作不是靠“猜”而是可以通过困惑度、爆发度、句法复杂度等可量化指标落地。虽然论文本身没有公开完整代码但检测技术路线是通用的完全可以用开源工具本地实现。适合读者关注学术诚信、期刊投稿规范的科研人员做文本分类、AIGC 检测的技术同学以及所有使用 ChatGPT、Claude、Kimi 等工具辅助英文写作、又担心“机器味”太重的论文作者。1. 核心要点速览先给一张总览表把这次要讨论的技术内容放在一起看。项目项说明研究对象生物医学出版物中的 LLM 辅助写作迹象检测核心方法文本统计特征、困惑度Perplexity、爆发度Burstiness、分类模型检测目标判断文本是否经过大语言模型辅助写作或修改技术门槛中等Python HuggingFace 模型 文本处理库即可起步显存需求如果用向量化模型做分类6G 显存可跑纯统计特征 CPU 也能跑支持 CPU是统计特征方法完全依赖 CPU不需要 GPU主要功能单文本检测、批量文本检测、特征可视化、检测结果导出接口服务可封装为 FastAPI 服务提供 HTTP 调用批量任务支持遍历目录或读取 CSV 批量处理适合场景期刊预审、论文自查、审稿辅助、文本合规检测需要强调一点论文标题里的“大多数”是一个基于具体样本集的结论检测方法并不会有“绝对正确”的输出。实际使用中检测结果应该看成“文本呈现 LLM 辅助写作特征的概率”而不是“作者是否作弊”的最终裁决。2. 研究背景为什么生物医学文献会成为检测重心生物医学领域是 LLM 辅助写作渗透最深的学术方向之一。原因不复杂这个领域论文产量大、写作模式相对固定、方法学和结果描述高度模板化而大语言模型最擅长的就是生成“结构正确、用词规范、逻辑通顺”的段落。两者叠加导致生物医学文献成为检测 LLM 痕迹的天然试验场。从检测角度生物医学文献有几个明显的文本特征术语密度高但句式结构相对单一。被动语态使用频繁例如 “was performed”“were analyzed”“was assessed”。方法部分高度模板化模型很容易生成相似表述。结果部分往往以数据为骨架模型改写后不易暴露逻辑漏洞。这些特征决定了检测算法不需要过于复杂就能捕捉到异常。例如一篇论文如果所有句子的困惑度都异常低、句长分布非常均匀、连接词使用模式高度一致那么即便没有明确的“AI 痕迹”统计特征也已经给出了信号。更关键的是生物医学论文有大量公开语料PubMed、PMC、bioRxiv 等训练检测模型的数据来源充足。不像小说、散文这种风格多变的文本医学论文的文体约束让模型更容易学到“人工写作”和“LLM 辅助写作”之间的边界。不过要区分一个概念研究说的“LLM-assisted writing”并不等于“全文 AI 生成”。它涵盖的范围很广包括用 ChatGPT 润色语言、改进句式。用 DeepL Write、Grammarly 等工具改写段落。用 LLM 生成引言草稿再人工修改。用翻译工具先写中文再译成英文。这些场景都会在文本统计特征上留下痕迹但严重程度完全不同。因此检测工具不能只回答“是或否”最好能输出一个分数让使用者自行判断。3. 检测方法论拆解怎么识别 LLM 辅助写作的迹象从技术实现角度检测 LLM 辅助写作的方法可以分为四类。3.1 统计特征分析统计特征是最容易上手、也最稳定的检测手段。核心思路是大模型生成文本和人类写作在统计规律上存在系统性差异。常用特征包括困惑度Perplexity模型对一句话的“意外程度”打分。人类写作通常有较高的困惑度因为人类会使用更多非常规表达而 LLM 倾向于生成高概率词序列困惑度偏低。爆发度Burstiness衡量文本中“突然出现的复杂句或罕见词”的频率分布。人类写作的爆发度高句长和词频波动大LLM 写作的爆发度低语句节奏均匀。句长分布人类写作的句子长度方差大LLM 生成的句子长度相对集中。连接词频率人类写作会用更多口语化的转折结构LLM 则倾向于使用标准连接词。词汇多样性如 TTRType-Token Ratio衡量文本中不同的词占全部词的比例。这类方法不需要训练模型只要一个像样的语言模型来计算困惑度即可。缺点是对短文本不敏感也不能区分“润色”和“完全生成”。3.2 分类模型检测在统计特征基础上可以训练一个二分类器输入是句子或段落的特征向量输出是“人工写作”或“LLM 辅助写作”的概率。实现方式有很多基于 TF-IDF 逻辑回归的传统机器学习方案。基于 RoBERTa、DeBERTa 等预训练模型的文本分类方案。基于嵌入向量如 text-embedding-3-small、BGE 系列加上全连接层的方案。预训练模型方案效果通常更好但需要一定显存。如果用 6G 显存的显卡跑一个 RoBERTa-base 模型批处理大小调到 8~16基本可以工作如果没有 GPU用 CPU 推理也可以但批量任务会很慢。3.3 水印检测与采样模式分析另一条技术路线是分析生成文本的“指纹”。LLM 生成文本时会从概率分布中采样下一个 token。如果模型使用固定的采样种子或使用了水印算法那么生成文本中会出现统计上异常的 token 分布。水印检测准确率很高但限制也明显必须知道生成文本使用的是哪个模型、哪个采样参数才能有效检测。对于已经发表的论文作者用的什么模型、什么配置根本无从得知所以水印路线在学术文献检测中实用性有限。3.4 混合检测框架实际项目中效果最稳的方案是混合检测。先计算困惑度和爆发度再用分类模型做整体判断最后把两者结合成一个风险分。这也是当前 AIGC 检测工具的通用思路。混合框架的流程如下输入文本 - 文本清洗 - 分句 - 计算困惑度 - 提取统计特征 - 向量化 - 分类模型推理 - 输出风险分 - 报告这个流程每一步都有对应的开源实现下面会给出具体代码。4. 复现检测实验的环境准备与数据准备要从零跑通一个“LLM 辅助写作检测”实验不需要特别高的硬件配置。一套面向通用复现的检查清单如下。4.1 硬件环境检查项推荐配置说明CPU4 核以上统计特征计算以 CPU 为主内存16G处理大规模文献语料时推荐 32GGPU可选6G 显存即可预训练模型推理需要纯统计特征可以不用磁盘至少 20G 可用空间预训练模型和语料库占用较大4.2 软件环境# 创建独立虚拟环境避免依赖冲突 conda create -n llm-writer-detection python3.10 -y conda activate llm-writer-detection # 安装核心依赖 pip install transformers torch pandas scikit-learn pip install datasets textdescriptives # textdescriptives 用于文本统计特征 pip install fastapi uvicorn # 后续封装 API 用4.3 数据准备数据是这类实验中最重要的部分。如果目标是复现论文结论需要准备两类数据人工写作语料从 PubMed 或 PMC 下载 2000 年之前的论文摘要这一时期的文本基本不包含 LLM 辅助写作。LLM 辅助写作语料可以自己构造用 GPT-4、Claude、Kimi 等模型对人工摘要进行润色改写形成配对数据。没有现成数据时先跑通流程更重要可以从公开数据集切入- PubMed 摘要数据集 - PMC OA 子集 - HellaSwag、WritingPrompts 等生成文本基准 - 自己用 LLM 生成 500 条医学英文段落数据目录建议这样组织./data ├── human/ # 人工写作样本txt 或 jsonl ├── llm/ # LLM 辅助写作样本 ├── test/ # 测试样本 └── metadata.csv # 样本元信息5. 检测流程实现从文本预处理到判断输出下面给出一套完整的检测流程代码。这套代码不是论文源码而是按通用检测思路实现的示范具体参数需要根据实际数据调整。5.1 文本预处理与分句预处理是第一步目的是去掉参考文献、作者信息、基金声明等干扰内容。import re import json from typing import List def clean_text(text: str) - str: 清洗文本去掉URL、邮箱、参考文献标记和多余空白 text re.sub(rhttp\S, , text) text re.sub(r\b[A-Za-z0-9._%-][A-Za-z0-9.-]\.[A-Za-z]{2,}\b, , text) text re.sub(r\[\d(?:[-,]\d)*\], , text) # 参考文献标记 text re.sub(r\[\d\], , text) text re.sub(r\s, , text).strip() return text def split_to_sentences(text: str, max_len: int 200) - List[str]: 按句号拆分过滤过短或过长的句子 sentences re.split(r(?[.!?])\s, text) sentences [s.strip() for s in sentences if 20 len(s.split()) max_len] return sentences5.2 计算困惑度特征困惑度是检测 LLM 辅助写作最直观的特征。这里用 GPT-2 作为基础模型计算困惑度因为 GPT-2 体积小、推理快在 CPU 上也能运行。import torch from transformers import GPT2LMHeadModel, GPT2Tokenizer model_name gpt2 tokenizer GPT2Tokenizer.from_pretrained(model_name) model GPT2LMHeadModel.from_pretrained(model_name, torch_dtypetorch.float32) if torch.cuda.is_available(): device cuda else: device cpu model.to(device) model.eval() def compute_perplexity(text: str) - float: 计算整段文本的困惑度 encodings tokenizer(text, return_tensorspt, truncationTrue, max_length512) input_ids encodings.input_ids.to(device) with torch.no_grad(): outputs model(input_ids, labelsinput_ids) loss outputs.loss return float(torch.exp(loss).cpu().item())这一步在纯 CPU 环境下也可以运行只是长文本会慢一些。建议测试时先截取 100~200 词的摘要片段。5.3 提取爆发度与句长分布特征爆发度反映文本节奏的波动程度。实现思路很简单计算每个句子的困惑度或句长再求标准差。import numpy as np def compute_burstiness(sentences: List[str]) - dict: 计算句长分布和困惑度分布的爆发度 # 句子长度词数 sent_lens [len(s.split()) for s in sentences] # 每句困惑度 sent_ppl [compute_perplexity(s) for s in sentences] feats { mean_sent_len: float(np.mean(sent_lens)), std_sent_len: float(np.std(sent_lens)), mean_ppl: float(np.mean(sent_ppl)), std_ppl: float(np.std(sent_ppl)), } return feats人类写作的std_sent_len通常更大LLM 辅助写作更小。这在整段文本的粒度上比较稳定。5.4 用分类模型做整体判断特征提取之后可以训练一个分类模型。这里用 TF-IDF 逻辑回归作为快速基线数据量小也能跑。from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report # 假设 human_texts 和 llm_texts 是文本列表 texts human_texts llm_texts labels [0] * len(human_texts) [1] * len(llm_texts) X_train, X_test, y_train, y_test train_test_split( texts, labels, test_size0.2, random_state42, stratifylabels ) vectorizer TfidfVectorizer(max_features5000, ngram_range(1, 2)) X_train_vec vectorizer.fit_transform(X_train) X_test_vec vectorizer.transform(X_test) clf LogisticRegression(max_iter1000) clf.fit(X_train_vec, y_train) y_pred clf.predict(X_test_vec) print(classification_report(y_test, y_pred, target_names[human, llm-assisted]))如果数据量足够大建议换成 RoBERTa 等预训练模型。这里给出的是一个可运行的最小实验闭环先验证流程再逐步升级模型。5.5 输出检测报告检测不能只给出 0/1要给出可解释的特征明细。def build_report(text: str) - dict: cleaned clean_text(text) sentences split_to_sentences(cleaned) feats compute_burstiness(sentences) vec vectorizer.transform([cleaned]) prob clf.predict_proba(vec)[0][1] # 属于 llm-assisted 的概率 report { mean_ppl: round(feats[mean_ppl], 2), std_ppl: round(feats[std_ppl], 2), mean_sent_len: round(feats[mean_sent_len], 2), std_sent_len: round(feats[std_sent_len], 2), llm_assist_prob: round(float(prob), 4), } return report这份报告可以作为期刊预审或者论文自查的参考材料。要注意分数高只代表“文本特征接近 LLM 写作模式”不等于作者有学术不端行为更不等于可以据此拒稿。6. 批量检测与接口 API 化如果要把检测能力用于批量任务例如对整本期刊的投稿做预筛或者对一批论文摘要做自查需要把检测流程封装成可批量调用和可通过 HTTP 调用的服务。6.1 批量检测脚本批量场景通常有两种输入一个文本目录或者一个 CSV 文件。下面给一个 CSV 批量处理示例。import pandas as pd from tqdm import tqdm df pd.read_csv(papers.csv) results [] for idx, row in tqdm(df.iterrows(), totallen(df)): try: report build_report(row[abstract]) report[paper_id] row[paper_id] results.append(report) except Exception as e: print(fError processing {row[paper_id]}: {e}) results.append({paper_id: row[paper_id], error: str(e)}) result_df pd.DataFrame(results) result_df.to_csv(detection_results.csv, indexFalse)批量任务有一个重要原则一定要做失败重试和日志记录。文本数据千奇百怪有的句子太长、有的编码异常、有的包含特殊符号一个样本出错不能让整个任务中断。6.2 FastAPI 封装接口把检测函数封装成 API 服务这样可以让编辑系统、投稿系统或者自建工具直接调用。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class DetectRequest(BaseModel): text: str class DetectResponse(BaseModel): mean_ppl: float std_ppl: float mean_sent_len: float std_sent_len: float llm_assist_prob: float app.post(/detect, response_modelDetectResponse) def detect_text(req: DetectRequest): return build_report(req.text)启动服务uvicorn api:app --host 127.0.0.1 --port 80006.3 curl 调用示例服务启动后可以用 curl 快速验证。curl -X POST http://127.0.0.1:8000/detect \ -H Content-Type: application/json \ -d {text: This study aimed to evaluate the effect of metformin on glucose metabolism in diabetic mice. A total of 40 mice were randomly divided into four groups...}返回结果示例{ mean_ppl: 32.45, std_ppl: 5.21, mean_sent_len: 18.6, std_sent_len: 4.1, llm_assist_prob: 0.87 }接口做好后可以嵌套到期刊投稿系统里做预筛也可以做成一个小型 Web 工具让作者自查。6.4 Python 调用示例import requests response requests.post( http://127.0.0.1:8000/detect, json{text: The results showed that the treatment significantly reduced tumor volume.}, timeout30, ) print(response.json())服务化的好处是检测逻辑和业务逻辑解耦。论文数据不出内网环境时也可以把服务部署在本地服务器不用调用外部 API。7. 资源占用与性能观察在本地跑这个检测流程需要关注三类资源内存、CPU/GPU、磁盘。7.1 内存占用加载 GPT-2 模型大约占用 600~800MB 内存加载 RoBERTa-base 大约占用 1.2~1.5GB。如果同时加载 TF-IDF 向量器和逻辑回归模型总内存开销在 3GB 以内16G 内存的机器完全够用。7.2 CPU 与 GPU 的差异纯统计特征计算句长、爆发度、TF-IDF在 CPU 上运行很快一篇摘要毫秒级完成。瓶颈在困惑度计算CPU 上 GPT-2 计算一篇 200 词的摘要需要 2~5 秒。GPU 上同样推理可以压缩到 0.5~1 秒。如果换成更大的模型比如 Llama-2-7BCPU 上就要 30 秒以上建议直接用 GPU。如果只是跑单篇论文自查CPU 足够如果要批量处理几千篇摘要建议准备一块 6G 显存以上的显卡。7.3 批量任务性能观察方法批量任务跑之前先在小数据集上做压力测试time python batch_detect.py --input sample_100.csv用time命令记录总耗时然后根据耗时估算处理全部数据集需要的时间。同时可以用nvidia-smi观察显存占用nvidia-smi --query-gpumemory.used,utilization.gpu --formatcsv -l 1如果显存不足优先减小模型输入的最大长度max_length或者减小 batch size。如果 CPU 占用过高可以限制线程数torch.set_num_threads(4)7.4 降低资源占用的建议纯统计特征检测不需要 GPU可以先跑统计特征只有困惑度计算才引入模型。使用量化模型例如optimum库把 GPT-2 量化到 int8显存占用降低一半。批量任务时复用tokenizer和model不要在循环里重复加载模型。对超长文本先截断一般只取摘要部分检测即可。8. 常见问题与排查方法本地运行检测流程时最常遇到的问题集中在依赖安装、模型下载、中文文本处理和 CUDA 环境。下面是一张排查表。问题现象可能原因排查方式解决方案模型下载超时网络不稳定或模型源被限制检查网络改用镜像源使用HF_ENDPOINT镜像或手动下载模型文件KeyError: gpt2模型缓存目录权限不足检查~/.cache/huggingface权限重新设置缓存目录或指定cache_dirCUDA 不可用驱动版本和 PyTorch 不匹配运行python -c import torch; print(torch.cuda.is_available())按 PyTorch 官网安装匹配的 CUDA 版本显存不足 OOMbatch size 过大或 max_length 过长查看 nvidia-smi 显存占用减小 batch size降低max_length中文检测不准确使用的模型以英文为主换用中文语料训练的模型用bert-base-chinese或chinese-roberta-wwm-ext计算特征批量任务中途崩掉单条数据包含异常字符查看日志定位出错样本增加 try/except跳过异常样本并记录API 请求超时困惑度计算在 CPU 上太慢查看服务日志耗时缩短输入文本长度或改用 GPU 推理检测分数一直偏高文本长度太短特征不稳定检查输入是否只有一两句话建议最少输入 50 个英文单词否则结果仅供参考一个样本到另一个样本分数波动大分类模型过拟合训练集检查训练数据分布增加训练样本量使用交叉验证遇到问题时的排查顺序建议是先看日志输出再看依赖版本最后才怀疑算法本身。大多数问题不是检测逻辑错了而是环境不一致。9. 使用边界与合规提醒LLM 辅助写作检测工具的使用场景很广但也需要明确边界。第一检测结果不能作为学术不端的直接证据。论文是否违规要看期刊的政策、作者是否披露了 AI 使用情况、以及具体使用了哪些功能。检测工具只能提供一个“特征接近 LLM 写作”的概率不能替代人工审查。第二使用 LLM 辅助写作本身并不必然违规。越来越多期刊开始要求作者在投稿时披露是否使用了 AI 工具以及使用了哪些部分。如果作者如实披露检测工具的意义就变成了“辅助核查”而不是“定罪”。第三涉及版权和隐私问题时必须谨慎。检测系统如果部署在期刊编辑部处理的是作者未发表的稿件必须保证数据安全不能把稿件文本发送给第三方 API。这也是为什么本地部署检测模型比调用在线检测服务更稳妥。第四对文本进行改写再检测或者用“降 AI 率”工具刻意规避检测属于绕过检测机制的行为。技术研究者应该对这类用途保持警惕检测工具只用于合规审查、写作自查和编辑辅助。第五不要用检测工具评价学生或同事的道德水平。检测分数受文本长度、文体、母语背景影响很大非英语母语作者写出的英文论文即使完全没使用 LLM也可能被误判为“AI 痕迹明显”。这类工具更适合作为编辑审稿的辅助信号而不是直接对作者做评价。10. 总结与下一步检测 LLM 辅助写作这件事技术上已经有一条清晰可行的路线困惑度计算、爆发度分析、统计特征提取、分类模型推理、批量任务与 API 封装。这套流程不需要多高的硬件门槛也不依赖某一个特定模型核心在于理解“人类写作”和“LLM 辅助写作”在文本统计规律上的差异。如果你准备复现这套检测流程建议按这个顺序测试先跑通 GPT-2 困惑度计算看单篇摘要的输出是否稳定。用 50 条人工文本和 50 条 LLM 改写文本做一个小规模分类实验确认特征区分度。再扩展到更多文本加入句长分布、爆发度等统计特征。最后再封装 API接入批量任务。最容易踩的坑有三处一是直接用英文模型处理中文文本导致特征失真二是数据量太少就训练分类器过拟合严重三是把检测分数当成绝对结论忽略了文本长度和文体对结果的影响。后续可以扩展的方向包括针对中文生物医学文献训练专用检测模型、引入更多细粒度的句法特征、以及将检测结果与投稿系统的元数据投稿时间、作者历史、修改记录结合做更完整的写作流程分析。这套思路不只适用于生物医学也适用于计算机科学、工程技术等大量使用 LLM 辅助写作的领域。先把单篇检测跑通再考虑规模化部署是最务实的路径。
返回列表