A Watermark for Large Language Models: 让大模型“写出来就自带水印”的底层机制,一次说清
1. 论文基本信息
- 标题:A Watermark for Large Language Models
- 作者:John Kirchenbauer, Jonas Geiping, Yuxin Wen, Jonathan Katz, Ian Miers, Tom Goldstein
- 年份 / 版本:arXiv 2023,当前分析基于 2024-05 的 v4 版本
- 研究领域关键词:Large Language Models、Watermarking、Text Provenance、Statistical Testing、Security
- 论文链接:https://arxiv.org/abs/2301.10226
2. 前言
这篇论文要解决的,是一个最近特别现实的问题:如何可靠地区分“人写的文本”和“大模型生成的文本”,而且还能在不牺牲生成质量的前提下做到这一点。
更具体一点,作者想要的是一种**“隐形水印”**:水印对人类读者几乎不可感知,但只要给算法一小段模型输出(比如 25~50 个 token),就能用一个简单的统计检验判断“这段话是不是由某个带水印的大模型写出来的”。检测算法不需要访问模型参数,也不需要再去跑一次大模型。
历史意义在于:这篇工作给出了一个既工程可落地、又有理论下界的方案——它把“水印”这件事从“拍脑袋改采样策略”拉到了“有严格假设、有 z 检验和信息论分析”的层面,并系统讨论了鲁棒性与攻击方式。在实验上,他们在 OPT-1.3B / 6.7B 上验证,在质量几乎不变的情况下,几十个 token 就可以高置信度检测出水印文本。
3. 历史背景与前置技术
如果把“识别机器文本”这件事拉长到二十多年的历史,其实大致有三条线:
第一条是传统自然语言水印 / 隐写。早期的工作多数靠规则系统:改语法树、换同义词、调整语序,在不明显改变语义的前提下,把“0/1”之类的信息偷偷编码进去。典型问题也很明显:可用的改写空间太小,一旦水印强一点,语句就变得很奇怪。
第二条是后验检测(detector)。例如单独训练一个分类器,或者让更大的 LM 来判断“这段话像不像机器写的”。这类方法的隐含前提是:模型输出整体分布和人类文本有“可检测的差异”——比如困惑度模式、用词习惯等。但随着模型变强,这条路越来越难:GPT-3 之后,很多基于 GPT-2 训练的检测器几乎失效,而且还引入严重的误报风险。论文里也引用了一些工作指出:非母语写作者反而更容易被误判成“机器”,这在教育场景里很危险。
第三条则是水印模型本身,也就是给模型参数植入“背后门式”的行为,用特定触发词来证明模型来源。这在“防模型盗用”场景下有用,但它标记的是“模型是谁的”,不是“这段文本是不是模型写的”,对平台要做内容审核帮助有限。
Kirchenbauer 这篇论文接的就是第二、三条线中间的空白:
- 不想依赖“模型天生和人不一样”这种不稳定前提;
- 也不想改训练过程或参数,只在采样阶段“轻轻拧一下”;
- 同时希望检测方不需要模型,只要看文本本身就行。
为此,他们回到底层的 LM 采样过程,从“下一 token 的分布”入手设计水印:对一部分 token 进行“偏好上色”(green list),然后用统计检验看文本里绿色 token 的比例是否“高得离谱”。
4. 论文核心贡献
从整体上看,这篇论文的贡献可以用一句话概括:在“几乎不破坏文本质量”的前提下,把一个可以公开的、简单的统计检测器,和一个可插拔的采样级水印机制,严谨地绑在了一起。
具体来说,作者首先给出了一个“概念版”的硬红名单水印:每一步根据前文生成一个随机的“绿色列表 G”和“红色列表 R”,然后强行禁止模型选 R 里的词,再基于“正常人写作会有一半词落在 G、而水印模型几乎全在 G”这一事实,用一元比例 z 检验来判断文本是否被水印。这个版本很好分析,也能说明水印“难以抹除”的直觉。
但硬规则会严重伤害低熵文本(比如“Barack Obama”这种强搭配)。于是作者进一步提出软水印:不再禁止红名单,只是把绿名单里的 logit 加上一个常数 δ,从而“轻轻推一把”,在高熵位置尽可能选绿色 token,在低熵位置几乎不动。这就形成了一个两头受益的结构:该严谨的时候统计上很强,该克制的时候对文本几乎透明。
在此之上,论文做了两件让我觉得很“工程友好”的事:一是给出了完整的理论分析,用一个叫“spike entropy”的指标去刻画“分布有多平”,并给出了绿色 token 个数的期望与方差下界,直接联系到 z 统计量的敏感度;二是从攻击者视角系统地分析各种可能攻击(改写、插入、emoji、同形字、二次 LM 攻击等),并设计了带密钥的私有水印方案以及对应的安全性直觉。
5. 方法详解
5.1 整体架构
整套方法其实非常“局部”:它只在“从 logits 采样下一个 token”这一瞬间插了一步逻辑。整体流程可以想象成下面这样:
1. 标准 LM(比如 OPT-1.3B)给出当前步的 logits。
2. 用一个伪随机过程,把词表随机分成绿色列表 G 和红色列表 R。
3. 对 G 中所有 token 的 logit 加上常数 δ,得到新的分布。
4. 从这个“偏好绿色”的分布中采样下一个 token。
5. 保存上下文,进入下一步。
检测端完全不用模型,只需要:
- 给定同样的 hash / PRNG 规则;
- 在文本上滑动,复现每一步的 G / R 划分;
- 统计最终文本里落在 G 的 token 数量
∣
s
∣
G
|s|_G
∣s∣G,并对比长度 T;
- 计算 z 统计量
z
=
∣
s
∣
G
−
γ
T
T
γ
(
1
−
γ
)
z = \dfrac{|s|_G - \gamma T}{\sqrt{T\gamma(1-\gamma)}}
z=Tγ(1−γ)∣s∣G−γT,
其中
γ
\gamma
γ 是绿色列表的比例(例如 0.5)。如果 z 很大,就判定“这段文本很可能来自带水印模型”。
从系统视角看,这就是一个**“带私有 key 的采样器 + 一个人人都能跑的 z 检测器”**。

【插图:论文 Figure 1(第 1 页),展示带 / 不带水印的模型输出以及对应 z-score 和 p-value,对应整体流程示意】
5.2 硬红名单水印:概念版

作者先给了一个“极端版”的硬水印(Algorithm 1):
- 每一步,用前一个 token 作为 seed,通过 hash + PRNG 把词表随机二分为 G 和 R(各占一半);
- 采样时只能从 G 里选 token,R 里的 token 完全禁止;
- 检测时,只需重新跑一遍 G/R 分割,看看文本里有多少 token 落在 G 中。
在“没水印”的世界里,因为 G 是随机的,人写文本中预计有一半 token 落在 G,即期望是
T
/
2
T/2
T/2,方差是
T
/
4
T/4
T/4。于是 z 统计量就变成
z
=
2
(
∣
s
∣
G
−
T
/
2
)
T
z = \dfrac{2(|s|_G - T/2)}{\sqrt{T}}
z=T2(∣s∣G−T/2)。
如果 z 比如大于 4,对应的一侧 p 值大约是 3 × 1 0 − 5 3\times10^{-5} 3×10−5,也就是误把人类文本认成水印文本的概率极低。反过来,对于真正的水印模型,由于理论上“全部 token 都在 G 中”,文本长度只要稍微长一点(十几个 token)就能拉出一个巨大 z 值。
有了这个简化模型,作者还分析了水印删除难度:即便攻击者知道算法,并刻意把 1000 个 token 里 200 个改成红名单词,考虑到每个改动还能影响后一个 token 的 G/R 分割,最多也只会制造大约 400 次“违反规则”。这时绿色 token 还是有 600 个,带入公式算出的 z 仍然在 6 左右,p 值约 1 0 − 10 10^{-10} 10−10,水印依旧明显。结论是:想在保持可读性的前提下“洗干净”水印,需要改掉文本中相当可观的一部分 token(约四分之一甚至以上)。
硬水印的问题也很明显:遇到低熵内容,比如“Barack Obama”这样的强搭配,如果“Obama”被分到 R,就永远生成不了这组合,文本会非常奇怪。
5.3 软水印:真正可用的版本
为了解决硬限制带来的质量问题,作者提出了软红名单规则(Algorithm 2):
- 仍然按比例 γ 随机划分 G / R,但不再禁止 R;
- 对 G 中所有 token 的 logit 加上常数 δ;
- 再用 softmax 得到新分布 KaTeX parse error: Got function '\hat' with no arguments as superscript at position 3: p^\̲h̲a̲t̲{},照常采样。
直觉非常简单:
- 如果当前分布本来就高度偏向某个 token(低熵),那它的 logit 已经远大于其他词,加不加 δ 都是它赢,软水印几乎不干预;
- 如果分布比较平(高熵,有好几个可选 token),那对 G 加 δ 就会显著提升 G 中词的概率,在“该自由选择的时候偏向绿色”。
检测这时仍然用同一个 z 公式,只不过
∣
s
∣
G
|s|_G
∣s∣G 的期望不再是
T
/
2
T/2
T/2,而是和 δ、γ 以及真实分布的熵有关。

【插图:论文 Algorithm 2(第 4 页),水印采样伪代码截图】
5.4 spike entropy:把“可水印程度”数学化
软水印的关键问题是:在不同熵下,它到底能把绿色 token 的比例推高到什么程度?
作者定义了一个专门的熵指标
S
(
p
,
z
)
S(p, z)
S(p,z):
S
(
p
,
z
)
=
∑
k
p
k
1
+
z
p
k
S(p, z) = \sum_k \dfrac{p_k}{1 + zp_k}
S(p,z)=∑k1+zpkpk。
这里
p
p
p 是当前的 token 概率分布,
z
z
z 是一个调节参数。直觉上,
- 如果分布非常尖锐(所有质量集中在少数几个 token 上),
S
S
S 会很小;
- 如果分布接近均匀,
S
S
S 会接近词表大小的某个函数。
用这个指标,论文在 Theorem 4.2 里给出了一个下界:只要整段文本的平均 spike entropy 不太低,水印后的绿色 token 个数 ∣ s ∣ G |s|_G ∣s∣G 至少会比“随机情况下”的期望大一截,并且方差有上界。从而,z 统计量会随着序列长度 T T T 增长而稳定增大。
更直观的一个特例是:当 γ = 0.5 \gamma = 0.5 γ=0.5,δ 取 ln(2)(大约 0.7)时,下界可以写得很简洁:绿色 token 的期望比例至少和 S ⋆ S^\star S⋆(平均 spike entropy 下界)成正比。换句话说:“越难预测”的位置,水印越容易“吃到便宜”,检测就越敏感。
5.5 文本质量影响:被 δ 推了一下,PPL 会不会炸?
另一个工程上必须关心的问题是:加 δ 之后,困惑度(perplexity)会不会大幅升高?
作者给出了一个统一的上界(Theorem 4.3):在随机 G/R 的前提下,水印分布 KaTeX parse error: Got function '\hat' with no arguments as superscript at position 3: p^\̲h̲a̲t̲{} 相比原分布
p
p
p 的期望对数似然损失,最多乘上一个和
(
1
+
(
α
−
1
)
γ
)
(1 + (\alpha - 1)\gamma)
(1+(α−1)γ) 有关的因子,这里
α
=
exp
(
δ
)
\alpha = \exp(\delta)
α=exp(δ)。直觉上:
- 当 δ 较小,或者 γ 适中时,因子接近 1,对 PPL 的影响有限;
- 当 δ 很大、γ 很小(极端偏向少量绿色 token)时,PPL 会明显上升,意味着文本质量变差。
这也是为什么实验里,作者更倾向用例如
γ
=
0.25
\gamma = 0.25
γ=0.25、
δ
=
2
\delta = 2
δ=2 这种折中配置:水印足够强,质量也还能接受。

【插图:论文 Figure 2(第 8 页),展示不同 γ、δ 下 z-score 与 Oracle PPL 的 trade-off 曲线】
5.6 私有水印与鲁棒算法:把密钥引进来
前面的 G/R 划分其实是公开可复现的,只要知道 hash 规则和 seed。所以如果攻击者可以随便访问检测 API,就有机会通过统计频率、尝试各种 n-gram,慢慢反推出哪些 token 更可能在 G 或 R。
为此,论文提出了带密钥的私有水印:
- 选一个伪随机函数
F
K
F_K
FK,可以是 AES、SHA3 等,K 是私钥;
- 每步生成红名单时,不再只用上一个 token,而是用长度为 h 的窗口
(
s
t
−
h
,
.
.
.
,
s
t
−
1
)
(s_{t-h},...,s_{t-1})
(st−h,...,st−1) 作为输入,计算
F
K
F_K
FK 的输出,再据此划分 G/R;
- 攻击者如果不知道 K,即便观察很多文本,也很难把所有 G/R 规则枚举出来。
但这里有个微妙的问题:攻击放大(attack amplification)——如果 G/R 完全由长度 h 的窗口决定,那么篡改一个 token,可能会随机化接下来 h 个位置的 G/R,从而“免费”多造出很多红名单词。
为了解决这个问题,作者又设计了一个更复杂的鲁棒私有水印算法(Algorithm 3):
- 当前步 t,先把“最可能的 token”假设为候选
s
t
s_t
st;
- 用
F
K
(
s
t
,
s
t
−
1
,
.
.
.
,
s
t
−
h
)
F_K(s_t, s_{t-1},...,s_{t-h})
FK(st,st−1,...,st−h) 计算一组值,从中挑一个索引
i
⋆
i^\star
i⋆,再用对应的输出决定“这个候选到底落在 G 还是 R”;
- 如果被判定落在 G,就直接用它;
- 如果落在 R,而且往次优 token 走会导致 logit 差距超过 δ,就“认命”用这个红名单 token;
- 否则尝试下一个候选。
这种设计有两个好处:
- 每改一个历史 token,影响当前步水印的概率只有
1
/
h
1/h
1/h,不会产生大规模放大效应;
- 同时,由于
i
⋆
i^\star
i⋆ 的选择依赖整个窗口,攻击者很难从表面频率反推出“真正参与 G/R 计算的是哪几个 token”。

【插图:论文 Algorithm 3(第 7 页),鲁棒私有水印伪代码与说明】
5.7 一些实现小细节
有几个作者专门提到、但容易被忽略的工程点:
- 重复 n-gram 不计数:为了避免某个 n-gram 刚好被偏爱而导致人类重复文本被误判,检测时可以将重复 n-gram(比如“Barack Obama”)只在第一次出现时计入 G/R,之后的重复都跳过,同时也能增强对低熵模板文本的敏感度。
- 与 beam search 的配合:实验发现,用多 beam 的 greedy decoding 时,模型可以在“质量相近”的候选中自动找到 G 比例更高的序列,相当于自然地“熨平”了水印,使得在几乎不增 PPL 的情况下,大幅提升 z-score。
- 多 key 方案:可以给不同代生成随机选 key,实现“多个水印叠加”。检测时需要对多重检验做校正(比如 Bonferroni),但换来的好处是:攻击者很难通过频率统计还原某一个固定 G/R 分布。
6. 实验结果
6.1 实验设置
作者主要在 OPT-1.3B 上做实验(生成端),再用更大的 OPT-2.7B 作为“oracle 模型”来评估困惑度。Prompt 来自 C4 数据集里的 RealNewsLike 子集,每次取一段新闻,把最后大约 200 个 token 作为“人写 ground truth”,其余前缀作为 prompt。
生成配置上:
- 主要考虑两种解码:multinomial sampling 和 greedy + beam search(4 / 8 beams);
- 序列长度一般取
T
≈
200
T \approx 200
T≈200;
- 水印参数 γ 在 [0.1, 0.9] 中变化,δ 在 [0.5, 10] 中变化;
- 检测阈值通常取
z
=
4
z=4
z=4 或
z
=
5
z=5
z=5,对应非常低的类型 I 错误率(false positive)。

【插图:论文 Figure 2(第 8 页),展示不同 γ、δ 下的 PPL–z-score 散点;右图为 beam search 情况】
6.2 主要指标与图表解读
从 Figure 2 可以看出一个很清晰的 trade-off:在 multinomial sampling 下,γ 越小(绿色列表越窄),δ 越大,z-score 越高,但 PPL 也上升。而在合理范围内,比如 γ = 0.25 , δ = 2 \gamma=0.25,\delta=2 γ=0.25,δ=2,200 token 的平均 z-score 已经非常高,但 PPL 只略高于无水印版本。
更有意思的是右半图:在 4/8 beam 的 greedy search 下,同一组 (γ, δ) 基本能在几乎不增加 PPL 的情况下,把 z-score 再往上推一大截。图上很多点几乎形成垂直线,意味着“质量几乎不变、检测力显著增强”。

【插图:论文 Figure 3(第 8 页),展示不同 T 下平均 z-score 随长度增长的曲线】
Figure 3 则回答了“需要多少 token 才能检测出来”的问题:
- 在 multinomial sampling、γ=0.25、δ=5 这种强水印条件下,大约 30~40 个 token 就能把平均 z 拉到 5 以上;
- 在 8-beam 的 greedy 搜索下,即便 δ=2,γ=0.25,大概 35 个 token 就能稳定检测。
Table 2 给出了更直接的统计结果:在 T≈200、门限
z
=
4
z=4
z=4 时,像
(
γ
=
0.25
,
δ
=
2
)
(\gamma=0.25,\delta=2)
(γ=0.25,δ=2) 这样的设置,多项式采样的检测召回率(TPR)约为 0.994,漏报率只有 0.6% 左右,几乎没有误报;在 δ=5 的极强水印下,TPR 直接到 1.0。

【插图:论文 Figure 4(第 9 页),ROC 曲线,比较不同 γ、δ 以及 sampling / beam search 的 AUC】
从 ROC 曲线可以看到:
- 不同参数配置的 AUC 基本都在 0.98 以上,强水印情况下甚至接近 1.0;
- 对比 multinomial 与 8-beam greedy,可以明显看到 beam search 在同一 δ 下略优一点,说明“在高质量候选中挑 G 比例高的那条路”这件事,模型自己就帮忙做了。
6.3 攻击与鲁棒性实验

【插图:论文 Figure 5(第 10 页),展示 Emoji Attack 和字符替换攻击示例】
论文在攻击部分既给了“提示工程式”的 emoji 攻击案例(让模型生成每个词后都跟一个 emoji,再由攻击者删掉),也给了字符级替换的例子(比如系统性把 a 换成 e)。这些攻击确实能打乱 token 序列与 G/R 划分的对应关系,但代价是:
- 输出 token 数量暴涨,生成成本和上下文占用都会上升;
- 文字变得不自然,难以真正用于真实任务。

【插图:论文 Figure 6(第 11 页),T5 span 替换攻击下的 ROC 曲线】
更系统的攻击是所谓 T5 span 替换攻击:攻击者用一个 T5-Large 模型,随机 mask 掉水印文本中的一些 token,并用 T5 生成新片段替换,替换预算用 ε 表示(占总 token 的比例)。实验发现:
- 当 ε=0.1 时,AUC 只有轻微下降(从 0.998 降到 0.988),检测效果仍然很强,但文本困惑度从约 6.3 升到 13 左右,质量已经明显变差;
- 当 ε=0.3 时,水印才真正开始被大幅削弱(AUC≈0.95),但此时 PPL 已经 20+,基本回到了一个中小模型的水平。
这组实验的结论很坦诚:强力攻击是存在的,但成本是“把好文本砍成一般文本”。对于现实世界的攻击者,这会是一个实打实的权衡。
7. 创新点与不足
如果只抓住几个最核心的创新,我会这么记:
第一,检测端完全不依赖模型本身,只靠文本和公开算法就能给出带 p-value 的统计结论。这在工程上非常重要:平台可以开源检测器,让第三方复现;API 提供方可以选择只保密密钥,不必隐藏算法本身。
第二,水印是“采样级别的小改动”,不需要重新训练或修改模型参数,几乎可以“外挂”到任何基于 next-token 采样的 LM 上。对于已经上线的闭源模型,这个特性非常关键。
第三,作者不仅给了 heuristic,还给了完整的信息论与统计分析,通过 spike entropy、期望 / 方差下界和类型 II 错误率,说明在高熵文本下,短序列内也能极高置信度检测出水印;同时和 beam search 的组合提供了一条“质量几乎不降、检测很强”的范式。
第四,论文非常认真地看待攻击与对抗:从同形字、零宽字符,到 emoji、提示攻击,再到用 T5 做 span 替换,都给出了案例与实验,并提出了用私有 PRF、多 key、robust 算法 3 等方式来提高攻击成本。
当然,这套方案也有自己的边界:
- 低熵文本的不可水印性几乎是无法绕开的。典型例子是模型在新闻数据上出现的“强模板 + 记忆”片段,这类地方 spike entropy 极低,水印基本起不了作用,因此检测往往靠周边高熵位置“补回来”。
- 水印关注的是表层 token 序列,并不触及语义层面。只要有人肯花力气做大规模 paraphrasing(无论是人工还是用强大 LM),是有可能在保留核心意思的前提下洗掉水印的,只是成本较高。
- 私有水印依赖 key 管理和检测 API 的访问控制。论文假设检测 API 有合理的 rate limit,一旦这个假设不成立,攻击者可以通过批量查询尝试“反推”部分 G/R 结构。
- 还有一点常被忽略:这是一种“平台自愿”机制。如果某家模型提供方就是不愿意打水印,外部是没法强制的。所以这项技术更多是给愿意负责的平台一个工具,而不是全能的解决方案。
8. 总结
回头看整篇论文,其实作者做的事很“克制”:他们没有试图解决所有“AI 生成内容”的治理问题,而是专注在一个明确的小目标上——给大模型输出打一个隐形、可检测、难以完全抹除的水印。
技术上,这个水印实现得相当优雅:通过“绿色列表 + logit 偏置”,在高熵位置悄悄推一把采样分布,再用简单的一元比例 z 检验,从绿色 token 的比例里读出“这段文本是不是水印模型写的”。在合理参数和解码策略下,这几乎不影响文本质量,却能在几十个 token 内给出非常强的统计信号。
在实验层面,他们不仅验证了常规场景下的高检测率和低误报,还认真讨论了各种攻击,并量化了“攻击成功”所需要付出的质量代价。最后给出的私有水印、鲁棒算法和多 key 组合,也为真实系统部署提供了一套相对完整的参考设计。
如果要用几句话概括这篇论文给人的观念变化:一是“水印可以做得既实用又有理论保障”;二是“想完全洗掉一个设计良好的水印,代价可能是把强模型降成弱模型”;三是“在大模型时代,内容来源的可审计性,可以通过这种统计级的小改动被扎扎实实地嵌进系统里”。
更多推荐
所有评论(0)