AI出题答案泄漏实测:15186道真题
出题检测最常被推荐的一招,是数答案和题干共享多少词。在15186道人写的题上,它只在22%的题上给出判定,命中率25.8%,z=1.0,等于瞎猜。真正能用的是把每道题的三个干扰项当对照组:真人考试里,答案只比自己三个干扰项长1.8个字符,其余特征全贴在零上。
出题检测里常见的一条规则,是数每个选项和题干共享多少词,共享多的那个当答案。不用参照题库,几分钟就能写出来,听起来应该有效。
我在15186道人写的选择题上跑了这条规则,命中率25.8%。四选一瞎猜是25%。在ARC-Challenge上,题目取自真实小学科学考试,同一条规则只有10.3%,低于瞎猜。
量的是什么
参照题库是MMLU完整测试集(14042道四选项题,57个学科)和ARC-Challenge测试集(1172道题,取自美国科学考试)。ARC里有1150道的答案是字母,其中6道是三选项或五选项,剩下1144道可比。合计15186道,全部数据在2026年11月9日跑出。
判定规则决定结论,必须讲清楚。选项的「词」指三个字母以上的词,剔除一张130词的停用表(冠词、疑问词、following、statement、correct这类),复数折回单数。只有当一个选项和题干共享的实词最多且唯一时,这道题才算给出判定;并列时按期望值计分,k个并列各计1/k。答案字母本身没有偏斜:MMLU是a 22.9%、b 24.7%、c 25.5%、d 26.9%。
判定只覆盖22%,命中率比瞎猜高0.8个百分点
15186道题里,共享词规则只在3348道题上给出判定,占22.0%。判对863道,25.8%,z=1.0,翻译过来就是什么都没发生。分题库看:MMLU触发3145道(22.4%),判对26.8%;ARC触发203道(17.7%),判对10.3%。
只能覆盖五分之一,原因在另外两个数里。51.1%的题,四个选项和题干一个实词都不共享,规则只能沉默。78.0%的题,至少两个选项并列最高,就算有共享词,通常也分不出胜负。MMLU里答案唯一共享最多的是6.0%。
出题人既不刻意重复题干的词,也不刻意回避。14042道题上,答案自身的实词有18.8%出现在题干里,三个干扰项是18.7%。在这个特征上,答案就是它自己四个选项里的一个随机抽样。
我踩的两个坑
第一个坑是并列。78%的题并列,怎么处理并列不是细节,就是结论本身。并列算错,这条规则看起来只有6%,彻底死掉;并列算对,它看起来有78%的准确率。只有按期望值算才诚实,而算出来是25.8%,回到抛硬币。任何引用这个检查的数字却不说并列怎么处理的人,引用的其实是自己的并列规则。
第二个坑在敏感性测试里冒出来。为了看脚本能不能抓住真的泄漏,我拿500道MMLU题,给答案后面硬加了十二个词("which is why the statement above holds in every case")。字符差距跳到+56.1,脚本报了不合格,符合预期。题干回声的差距反而降到-0.09,因为回声是拿选项自身的词做分母,选项一长就被稀释。单个特征有确定方向,就能被措辞骗过去,所以下面的体检一次上六个。
每道生成的题自带对照组
体检一份生成题库,不需要参照题库。每道题都自带三个干扰项,同一个模型写、同一个题干、同一种笔法。答案和这三个混在一起分不出来,这道题就没有送分;哪个特征上答案和自己的三个干扰项分得开,注意到规律的学生就多一条策略。
六个特征,都取「答案减三个干扰项均值」,在两个人写题库上各跑一遍:
| 特征 | 答案减三个干扰项均值(MMLU) | 同上(ARC) | 答案唯一最大占比,MMLU / ARC |
|---|---|---|---|
| 字符数 | +1.8 | +1.4 | 23.7% / 21.9% |
| 实词数 | +0.11 | +0.14 | 12.9% / 10.1% |
| 题干回声(选项自身用词出现在题干里的比例) | +0.00 | -0.03 | 7.5% / 2.6% |
| 抽象名词后缀(tion/ment/ity 这类) | +0.00 | +0.04 | 4.0% / 4.7% |
| 带数字 | +0.00 | +0.00 | 0.8% / 0.3% |
| 带专有名词 | -0.01 | +0.01 | 1.4% / 0.7% |
先看字符那一行。真人写的考试里,答案比自己的干扰项长1.8个字符。不是30个。到处被引用的「最长选项」效应真实存在,但只有这么大,而且跟上一篇对得上:答案在所有题里占唯一最长的是23.7%,在「有唯一最长选项」的那82.9%的题里是28.6%,同一个量,分母不同。
要让生成的题走到这条线上,靠的是「干扰项要像真的」这句要求,而不是长度。一个题干加四个选项,对和错的差别应该只在内容,不在包装。
多大的差距才算信号
一份20道题的小卷只能承受很粗的结论,算术能给出多粗。字符差距的单题标准差是24个字符,20道题的标准误是5.4,三个标准误的位置在人写题库均值上方约16个字符。具体说:20道题时,答案比干扰项长16个字符是真信号,长8个字符不是。同样的算法套到别的特征上,20道题只可能因为字符(+16)、实词(+1.5个)、题干回声(+0.10)、抽象名词占比(+26个百分点)被判定不合格。50道题时,这两条线收到+3.4个字符和+0.06的回声。
这也是逐题打标在生成题库上没用的原因。单题噪声比效应本身还宽:干净的人写题库里,回声差距的十分位是-0.13,九十分位是+0.12。整份先跑,再去看把均值拉上去的是哪几道。
不合格时改什么
保留答案,只重新生成干扰项,再跑一遍。四条约束解决了大部分问题:
- 同一个长度带。要求每个干扰项和答案的实词数相差不超过三个。一次就能把+50个字符的差距压掉。
- 同一个类别。答案是条约,干扰项就是别的条约;答案是机制,干扰项就是别的机制。类别不对的选项,学生不用读完就能排除。
- 同一份材料,别的段落。干扰项的内容取自这份文档里出题没有用到的部分,这样干扰项更可能是「有道理地错」,而不是「一看就错」。
- 每个干扰项配一句话理由。「错在把1919写成1921」。模型说不出某个选项错在哪,那个选项就是填充物。
然后对导出的文件跑脚本,不要对着工具里的预览跑。预览给你看的是前三道,那是模型花了最多力气写的三道。
脚本
只用标准库,Python 3.8以上。把题导出成CSV,表头stem,a,b,c,d,answer,answer填a/b/c/d,然后运行python3 leak_gap.py bank.csv。14042道题的MMLU导出,跑完两秒。
import csv, math, re, statistics as st, sys
STOP = set("""the a an of to in and or is are was were which what who whom whose when where why how
that this these those it its be been being has have had do does did can could will would should may
might must not no all any both each few more most other some such than then there their them they you
your we our us i he she his her him on at by for with about into over after before between during from
up down out off again further once here only own same so too very just also as if because while
according following above below statement statements question answer answers correct true false one two
three first second best likely main primary except least""".split())
WORD = re.compile(r"[A-Za-z]+"); CAP = re.compile(r"\b[A-Z][a-zA-Z]{2,}\b")
ABS = re.compile(r"(tion|sion|ment|ness|ity|ism|ance|ence|ology|acy)$")
NAMES = ["chars", "words", "echo", "abstract", "digit", "proper"]
HUMAN = {"chars": 1.8, "words": 0.1, "echo": 0.0, "abstract": 0.0, "digit": 0.0, "proper": 0.0}
SD = {"chars": 24.0, "words": 2.23, "echo": 0.15, "abstract": 0.38, "digit": 0.15, "proper": 0.32}
def toks(s):
return [w for w in WORD.findall(s or "") if len(w) >= 3 and w.lower() not in STOP]
def stem(w):
w = w.lower()
if len(w) > 4 and w.endswith("ies"): return w[:-3] + "y"
if len(w) > 3 and w.endswith("s") and not w.endswith("ss"): return w[:-1]
return w
def sset(s): return {stem(w) for w in toks(s)}
def feats(opt, S):
t = toks(opt); ts = {stem(w) for w in t}
return {"chars": len(opt.strip()), "words": len(t),
"echo": len(ts & S) / len(ts) if ts else 0.0,
"abstract": 1.0 if any(ABS.search(w.lower()) for w in t) else 0.0,
"digit": 1.0 if re.search(r"\d", opt) else 0.0,
"proper": 1.0 if [w for w in CAP.findall(opt) if w.lower() not in STOP] else 0.0}
rows = []
for r in csv.DictReader(open(sys.argv[1], encoding="utf-8-sig")):
o = [(r.get(k) or "").strip() for k in ("a", "b", "c", "d")]
k = (r.get("answer") or "").strip().lower()
if all(o) and k in "abcd" and len(k) == 1:
rows.append((r.get("stem") or "", o, "abcd".index(k)))
n = len(rows)
gaps = {f: [] for f in NAMES}; maxrate = {f: 0 for f in NAMES}
for q, opts, k in rows:
S = sset(q); F = [feats(x, S) for x in opts]
for f in NAMES:
gaps[f].append(F[k][f] - sum(F[i][f] for i in range(4) if i != k) / 3)
top = max(x[f] for x in F)
if F[k][f] == top and sum(1 for x in F if x[f] == top) == 1:
maxrate[f] += 1
print("items audited: %d" % n)
print("%-9s %12s %10s %12s %8s" % ("feature", "key-minus-3d", "P(key=max)", "noise line", "verdict"))
for f in NAMES:
gap = st.mean(gaps[f]); se3 = 3 * SD[f] / math.sqrt(n)
print("%-9s %+12.2f %9.1f%% %+12.2f %8s"
% (f, gap, 100 * maxrate[f] / n, HUMAN[f] + se3,
"LEAK" if gap - HUMAN[f] > se3 else "ok"))
MMLU导出文件上的输出,原样贴出:
items audited: 14042 feature key-minus-3d P(key=max) noise line verdict chars +1.77 23.7% +2.41 ok words +0.11 12.9% +0.16 ok echo +0.00 7.5% +0.00 ok abstract +0.00 4.0% +0.01 ok digit +0.00 0.8% +0.00 ok proper -0.01 1.4% +0.01 ok
同一份脚本跑那500道被我动过手的题:
items audited: 500 feature key-minus-3d P(key=max) noise line verdict chars +56.14 95.6% +5.02 LEAK words +3.17 84.4% +0.40 LEAK echo -0.09 6.8% +0.02 ok
第二段输出是这篇的重点。一个老师坐下来看一遍就能发现的泄漏,在500道题的规模上被两个特征抓住,而被抓住的这两个,都不是那种「出题检测文章」会推荐你去查的。
这查不出什么
答案标错。一份题库可以六项全过,同时有10%的题答案标错,那才是真正伤课堂的失败:对的判成错,然后家长来信。这需要另一道工序,自己照原文把每道题答一遍,或者让另一个模型重新标一次,比较两边不一致的地方。十道题就够看出答案稳不稳。
也查不出歧义、查不出这些题有没有覆盖整份材料、查不出难度。六个特征是应试技巧线索的一个样本,不是完整清单。实词匹配不认同义词和改写,靠共享概念而不是共享词来泄漏的题会漏过去。两个题库都是英文、四选项、美式考试,换成五选项或判断题,常数要重新跑。
如果还在挑工具,最该比的是各家怎么处理答案和导出,五款出卷工具我按这个评过:五款AI出卷工具,按答案与批改怎么落地来评。如果问题是价格和导出限制,免费档的对比在这篇:九个免费出题工具,各自能给到什么。上一篇关于选项长度和答案字母分布的体检,这篇做了复核和延伸:28.6%的题能靠选项长度蒙对。
记两个数就行:25.8%,共享词这条线索不是检查;+1.8个字符,真人卷子在长度上的对照线。题库是公开的(MMLU、ARC),数可以自己重跑,不必信我。
相关文章
本站文章由编辑人工撰写,收录的工具均经过实测或公开资料核验。文中链接指向工具官网或 GitHub 仓库,仅作信息参考,不构成付费推广。