原文: https://arxiv.org/html/2301.10226v4
一篇论文把我卡住了—两个问题:水印是怎么打进去的?检测时到底需要什么?这篇是我拆完之后的记录。
AI 生成内容的鉴别,是一个正在被低估的问题。
大多数人的第一反应是「用另一个 AI 来判断」——把文本喂给 GPT,让它评估「这像不像机器写的」。这个思路不是没有价值,但它有一个根本缺陷:没有数学保证。
2023 年,马里兰大学的一篇论文提出了一个不同的方向——在生成时悄悄打水印,检测时用统计方法验证。论文发表在 ICML,方法叫 A Watermark for Large Language Models(arXiv 2301.10226)。
这篇文章的意义不在于「完美解决了问题」,而在于:它第一次把 LLM 输出溯源,从玄学变成了有 p 值的统计检验。
水印不在提示词里
很多人第一反应会问:要给大模型传什么特殊指令吗?
不用。给模型的输入跟平时完全一样。
水印嵌在采样那一步。说人话就是:模型算完「下一个词应该是什么」之后、真正输出之前,有一个中间环节可以被拦截。这个方法就在这里动手脚。
LLM 生成文本的完整流程是这样的:
水印的切入点在 C 和 D 之间——Logits 出来了,但还没有 Softmax 的时候。
绿色词:一个每次都重新生成的秘密名单
具体怎么做?
每生成一个词之前,系统先看上一个已生成的词,把它的 token ID 丢进一个哈希函数,算出一个随机种子,然后用这个种子把整个词表(通常几万个词)随机劈成两半:绿色词和红色词。
然后对绿色词的 logits 加一个固定的奖励值 δ(论文里叫 delta),其他不动,正常走 Softmax 和采样。
结果:生成的文本读起来完全正常,但里面绿色词的比例系统性偏高——因为每一步都在轻轻地往绿色词方向推。
关键参数只有两个:
| 参数 | 作用 | 经验值 |
|---|---|---|
SECRET_KEY | 决定哪些词是绿色,检测时要用同一个 | 必须保密 |
delta | 绿色词加权力度 | 1.0 ~ 2.0,越大越好检测,文本质量越差 |
检测:一个 z 检验就够了
检测时需要的东西比你想象的少:tokenizer + 私钥,不需要模型权重,不需要 GPU,不需要 API 访问。
流程:
为什么误报率低?不是因为每个词都必须选对——水印只是把概率稍微推了一下。
真正的数学逻辑是:正常文本里绿色词数量服从 Binomial(n, 0.5),标准差是 0.5√n。水印文本的绿色词比例系统性偏高,这个偏差随 √n 积累,信噪比越来越高。z 分数超过 4.0 的误报概率约为三万分之一——这是正态分布的基本性质,跟文本内容无关。
谁能用,谁用不了
这个方法的使用前提决定了它的边界,说清楚比夸它有用更重要。
能用的前提:
- 你控制采样过程(需要白盒访问,自己部署开源模型)
- 文本够长——至少约 200 tokens,太短 z 分数不显著
- 模型使用随机采样(temperature > 0),greedy decoding 下水印效果退化
如果你用的是 DeepSeek、OpenAI 这类商业 API,没法加这个水印。原因很直接:API 把采样做完再把文字返回给你,你插不进 logits 那一步。哪怕 API 开放了 logprobs 参数,返回的也只是已选中词的概率,不是完整词表的分布。
三类主要限制:
- 改写攻击是最现实的威胁。把生成的文本喂给另一个模型润色一遍,token 序列变了,水印消失。这个方法对主动对抗没有防御能力。
- 高熵场景退化。写代码、写数学公式时,下一个 token 几乎是确定的,δ 加的那点分根本改变不了采样结果,水印打不进去。
- 私钥泄露即失效。如果攻击者知道你的哈希密钥,他既可以伪造水印,也可以主动把水印洗掉。
想自己跑一遍的话
论文作者开源了完整实现:github.com/jwkirchenbauer/lm-watermarking。
- 如果你用 vLLM 部署开源模型,核心逻辑就三步:写一个
LogitsProcessor加 δ,挂进SamplingParams,检测时用同一个 tokenizer 和私钥重建绿色词列表,跑 z 检验。整个检测链路离线就能跑,不需要任何模型推理。
亲手跑过比看十篇介绍都清楚——水印强度和文本质量的 trade-off,在调 δ 的那一刻会变得非常具体。
这个方法最大的价值,不是完美,而是把「AI 溯源」这件事从主观判断变成了可以辩论的数学问题。 这已经比现在大多数检测工具的底子要扎实得多。
参考论文:Kirchenbauer et al., “A Watermark for Large Language Models”, ICML 2023, arXiv:2301.10226