vLLM 内置文本水印,吞吐几乎不掉

开源推理框架 vLLM 9 月 24 日在官方博客宣布,框架里加入了基于 Gumbel-max 方法的文本水印,服务端只要一个启动参数就能打开。文章署名三位作者,一位来自 Mistral,两位来自红帽。

打开的方式很简单,在 vllm serve 命令后面加一个 --watermark-config,写明算法用 gumbel、再给一把密钥即可。之后这台服务生成的所有文本都会带上肉眼看不见的统计信号。

水印怎么藏进去

大模型每生成一个词,都会先给所有候选词打一个概率,再从中抽一个。Gumbel-max 水印动的就是”抽”这一步。

具体做法是:用密钥、最近几个词的上下文和候选词编号,算出一组看起来完全随机、但只要知道密钥就能复现的数,把它变换成 Gumbel 噪声加到模型的打分上,取最大的那个作为输出。数学上,这样抽出来的结果和普通随机采样的分布完全一致,所以作者称之为”无失真”:模型不会因此偏好某些词、某种文风或某类解法。

检测一方不需要模型权重,只要密钥和分词器。把文本还原成 token,用同一把密钥重算那组伪随机数,逐个打分再求和,和没有水印时应有的分布比一比,得出一个 p 值。按作者给的校准口径,没有水印的文本大约有 1% 会被误报。

代价和效果的两组数

性能上,作者在单张 H100 上用 Qwen3.5-27B 测了输出 512 个 token 的场景:批大小为 1 时吞吐变化 -0.23%,批大小 32 时 +2.03%,各组平均落在 -1.1% 到 +2.0% 之间,作者的结论是没有一致的吞吐变化。为了省显存,vLLM 把伪随机数生成、Gumbel 变换和取最大值合成了一个 GPU 核。

模型质量上,同样是 Qwen3.5-27B,加水印和不加水印的对比是:GSM8K 93.0% 对 94.2%,MBPP 79.2% 对 77.2%,IFEval 90.7% 对 91.9%,作者认为差异都在误差范围内。

检测率差别就大了。在 1% 误报率下,创意写作大约 100 个 token 就能做到全部检出;MBPP 代码题写到 400 个 token,检出率只有 43%。原因在原理里:代码这类输出,模型对下一个词往往很有把握,可供水印操作的随机性本来就少。短文本同样信号弱。文本被人改过,改动处附近的分数会被打乱,离开这段上下文后信号还能恢复。

实现上还有两个坑。一个是投机解码,作者用两把密钥分别处理草稿 token 和目标模型的残差采样,保住接受率,代价是检测信号被分到两把钥匙上。另一个是重复上下文会产生同一组随机数,可能让模型陷入无限重复,解决办法是遇到重复上下文就跳过水印,这一步对吞吐的影响最多 0.19%。

对国内部署方意味着什么

国内《人工智能生成合成内容标识办法》去年 9 月起施行,要求生成内容加显式或隐式标识。落到文本上,隐式标识目前多靠元数据,统计水印能嵌进文字本身,vLLM 这次等于把它做成了一个开关,国内大量用 vLLM 自建推理服务的团队可以直接试。

但这套方案的边界也很清楚:检测靠密钥,谁部署谁持有,第三方无法独立验证;代码和短回复检出率偏低;遇到人工大段改写,信号会被削弱。能不能满足监管对”隐式标识”的具体要求,还要看后续有没有配套的检测标准,目前没有公开口径。

参考来源:vLLM 官方博客、CocoLoop、《人工智能生成合成内容标识办法》;吞吐、基准分数与检出率均为作者在 Qwen3.5-27B 与单张 H100 上的测试口径。