精选Ahead of AI (Sebastian Raschka)短讯
Claude 文本水印的工作原理
Anthropic 宣布为 Claude 模型输出添加水印。本视频讲座详细解释了其底层机制:基于 token 采样的水印嵌入、检测与移除方法,并讨论了水印的优缺点。
我最近在Substack上发了一篇关于Claude新水印流程及其实现的短文。由于这个话题非常热门,引发了热烈的讨论,我想或许可以更详细地解释一下它的工作原理,这样会更有意思。
与往常的文字文章不同,我就这个话题录制了一个小讲座(算是换换花样,不同于我平时的文章)。所以,下面是视频以及文字稿。
最初,我计划做10张幻灯片,录一个10分钟的短视频。然而,在整理过程中,我在这里那里补充了一些关键细节,结果变成了50多张幻灯片和48分钟的录制。
不过,我希望现在这个版本能把它解释清楚!祝观看愉快!
- 如果你更喜欢用YouTube播放器,我也有YouTube版本。
- 这里是幻灯片的链接
注:下面的文字稿略有编辑和润色,以便阅读,但保留了上述视频讲座的整体顺序和流程。
Claude文本水印的工作原理

大家好。几天前,Anthropic宣布将对其Claude模型的文本输出添加水印。我当时在社交媒体上发了一篇帖子,简要解释了其工作原理。没错,这篇帖子相当受欢迎。所以,不是水印本身受欢迎,而是我想是背后的解释或机制受欢迎。那么,或许值得扩展一下,更详细地解释这一点,因为那篇帖子只有一张图,而且有很多问题和讨论。
所以我想,好吧,让我们再多画几张图。我实际上最初计划做大约10张幻灯片,带你过一遍。结果变成了50张幻灯片,但我希望这真的能解释清楚这种水印技术是如何工作的,水印本身如何可能失效或被移除,等等。所以我认为这可能是个有趣的话题,因为现在很多人都在使用LLM,也在互联网上消费大量可能由LLM生成的文本。
而现在有了这种水印,而且,我猜,人们担心水印会让文本质量变差,或者这种水印到底有什么好处?那它意味着什么?我认为如果我们更好地理解水印是什么,那会大有帮助,然后我们就可以自己判断这是好事还是坏事,以及诸如此类的利弊。
所以,我的目标真的是解释底层机制是如何工作的,以及他们将如何实现这种类型的水印,文本水印。

这也是一个很好的例子,说明为什么从头理解事物实际上非常有用。这种水印技术也是一个很好的方式,来解释传统模型或LLM通常是如何在底层工作的。所以,是的,你可能知道我喜欢从头做起。比如,我有我的书:《从零构建大语言模型》、《从零构建推理模型》。我有一些标着“从零开始”的文章。
所以,对我来说,“从零开始”通常包括编码。所以这次不会涉及编码,但从零编码实际上是一种非常非常有用的技术,因为它真的能帮助你理解某件事是如何实现的。然后我们可以从中得出我们的理解、图表、概念,因为如果我们不真正实现东西,如果没有代码,有时真的很模糊。当然,你知道,正如我意识到的,不是每个人都在从零编码了。
就像过去,从零编码是我们所拥有的一切。我的意思是,只有人类在编码。如今,编码可以由LLM完成。然而,这并不意味着阅读代码不再有用,因为它承载着大量信息。所以在这个水印的案例中,花时间从零编码一个LLM真的会让你意识到内部这个采样是如何实现的。我们仍然有一些相关的代码片段。
然后这反过来真的帮助我们理解,哦,水印是在这个位置应用的,这有如此这般的后果,等等。所以我认为,即使人们可能不再从零编码,至少不是一直如此,但能够,比如说,为了教育目的从零构建某物以深入理解某事,然后也是为了研究目的以透明的方式操作它,而不是隐藏在层层抽象之中,这仍然是有用的。
但撇开这些不谈,我认为这里只是一个巧合的、很好的关联,因为对于这组幻灯片,我实际上用了很多来自我从零编码材料中的图。

所以几天前(今天是8月14日),有一篇文章叫《Claude的文本水印是如何工作的》,还有这边这篇文章;它就像一段屏幕录制,所以幻灯片里的所有内容都能看到,但细节非常丰富。他们实际上更新了好几次,所以我最初读到的时候,它要短得多。不过它仍然非常,我觉得,概念化;里面就是一个概述,而且,我是说,里面连一张图都没有。
所以还是很难理解他们到底想做什么。他们花了很多篇幅解释为什么要做这件事,但没有解释怎么做。他们在某处链接了一篇论文,那篇论文也非常技术性。所以我确实觉得有必要退一步,从头开始,去理解他们想通过这种水印技术实现什么。
顺便说一下,水印的动机是让他们能够识别——如果有人发布了某段文本,他们可以说,哦,这段文本是由我们的Claude Opus 4.8模型生成的,这样他们就有办法判断:好的,这段文本是AI生成的,因为它带有这个水印。而且这个水印对用户是不可见的,只有他们自己能解码并判断这段文本是否带有他们的水印。
为什么只有他们能做到?我们稍后会讲到(希望这个视频不会太长),但一次讲一件事。
LLM文本生成是如何工作的

我想先做一个简短的铺垫,解释LLM中文本生成是如何工作的,因为基于这一点,我们就能更容易理解水印是如何工作的,以及这其实并不是在它之上叠加的一个庞大而昂贵的东西。它真的只是常规文本生成过程中的一个微小调整,我想说。

所以当我们使用像ChatGPT这样的东西时,比如说我问一个问题:德国的首都是,然后ChatGPT或其他LLM,这只是一个例子,会回答“柏林”。那么在这种情况下,它生成了两个token,比如“柏林”和句号。但为了简单起见,我们假设它只生成一个token。那么下一个token就是“柏林”这个token。这个token在内部是如何生成的呢?
当我们在输入框里输入“德国的首都是”这样的内容,然后收到“柏林”这样的token时,底层到底发生了什么?在幕后实际发生了什么呢?

在接下来的几张幻灯片中,我想简要谈谈当下一个token被生成时,底层发生了什么。

再次假设我们的提示词是“德国的首都是”。第一步是将其转换为token ID。所以分词并将其转换为token ID是开头的主要步骤之一。这在外围——不在LLM内部,而是在LLM之外。我们只是简单地将文本转换为token ID。这只是一种嵌入层可以处理的格式。

然后这通过LLM。LLM给我们一个关于下一个token的分数分布。

再次强调,这只是LLM内部工作原理的一个简要概述。我不会深入LLM机制本身。我在其他“从零开始构建LLM”的视频和书籍中已经讲过很多次了。重要的是,当我们生成下一个token(例如“柏林”)时,我们此时有一个分数分布。这就是LLM产生的输出。
在这个例子中,我们看的是logit值。这些只是从负无穷到正无穷的分数,就像一个分数范围。这里有一个例子,范围大约从-8或-9到20。我们可以把这些转换成概率分布,但严格来说,取决于我们如何采样,这并不是必须的。所以你可以把logit值理解为原始分数。
而这些原始分数覆盖了整个词表。

也就是说,覆盖了LLM可能生成的每一个可能的词。现在在这里,在词表索引中,某个位置(索引位置19,846)获得了最高分。所以我把分布展开了。如果你把这个提示词输入LLM运行,你甚至会看到更极端的情况:所有值都非常非常非常接近零。而“柏林”可能会高得多得多。
但只是为了给你展示几个峰值,让图看起来更有趣一点,我稍微放大并展开了分布。现在这里,“柏林”是最高分,因为你可以把它理解为——如果我有这样一个非常具体的提示词——最可能或最合理的下一个token。至于其他的,我的意思是,可能是“汉堡”或“慕尼黑”之类的,LLM可能会猜错。
但如今,大语言模型应该相当确定“Berlin”在这里是正确答案。你在这里看到的还有词汇索引,它覆盖了整个词汇表。如今,大语言模型大约有25万个可能的输出token。我在这里把它从19,800截断到19,900,因为这张幻灯片上空间有限。如果我展示一个非常真实的25万词汇表,所有内容都会变得非常狭窄,我们几乎无法在这个分布上辨认或看到任何东西。
所以这只是为了教学目的而做的截断。重点在于,在常规文本生成中,我们会得到这个分数分布。现在,我们要做的是看最高分。

稍后我会更详细地说明这是如何被选中的。所以不一定是精确的最高分,但为了简单起见,我们假设这里取的是最高分。在这种情况下,它是19,846。

然后这个分数被去token化,我们得到“Berlin”。所以这就是这张幻灯片上的过程:从输入提示词到转换为token ID和token化,传递给大语言模型,得到这个分数分布,得到下一个token,再将其转换回文本。

然后这段文本被追加到输入中。所以如果我们有一个需要多个输出token的问题,我们会继续这个循环,直到答案完成。这通常意味着大语言模型生成了一个文本结束token,比如在这里。为了简单起见,我只展示了一次迭代,即生成一个token。但正如我所说,它会这样继续下去,我们将修改后的输入反馈给大语言模型进行下一轮。
那么,我们实际上是如何在这里采样下一个token的呢?
下一个Token采样是如何工作的

我简单说过,我们技术上可以直接选择最高的那个,即分数最高的那个。这被称为贪心解码。这是其中一种方式。但大多数大语言模型,比如你使用的那些,并不会采用总是选最高分的贪心解码。因为如果你用其他提示词去问它,我们并不总是希望它选最高分,因为那样它会记住训练数据。
它总是会给出相同的回答等等。所以我们实际上通常希望输出有一些变化,但又不能太多以至于生成随机内容。所以它的工作方式是,当我们从这个分布中采样时,我们首先通常会将其转换为概率分数。

所以这里我只是在图中展示了这些分数。为了简单起见,我使用了NumPy;无论你使用什么工具(例如PyTorch),相同的概念都适用。但假设我们这里有NumPy中的分数。那么我要做的是计算softmax。技术上,我会使用例如Torch或PyTorch中实现的softmax函数,该函数对大小数值都是数值稳定的,包括非常高的正值、非常低的正值和非常高的负值。
这里我只是这样写出来。这是标准的softmax,只是为了让它更易读一些。但细节在这里并不重要。

重要的是,在这个转换之后,这里的分数——我的意思是,幻灯片上空间有限——但这些分数加起来会等于一。所以这本质上就像是一种重新归一化。它们会被归一化,使总和为一。这就是概率转换所做的全部工作:softmax转换。那么一旦我们有了这些概率,我们就可以使用随机数或随机采样算法。
例如,在NumPy中,我们可以使用choice函数或方法。这是用一个特定的随机种子传递给词汇索引的。然后,这是关键部分,我们将概率作为权重传递。所以这些本质上就是:“某个token被选中的可能性有多大?”例如,如果“Berlin”在这个归一化步骤(即softmax步骤)之后有99%的概率,而其他所有token加起来有1%的概率,那么如果我们采样100次,其中99次我们会得到“Berlin”。
在现实的大语言模型中,例如训练良好的模型,“Berlin”可能会获得99.999999%或类似的概率。所以你几乎肯定会总是采样到“Berlin”,因为在这个特定情况下,它非常确信答案是“Berlin”。所以是的,这就是我们从这个分布中采样的方式。还有一些修改,比如top-k采样或top-p采样,其中,比如说,为了简单起见,在top-k采样中,我们会选择前100个token,然后只对这前100个(即分数最高的100个)应用随机选择,这样我们就不会在其中得到无意义的token。
对于这个例子来说,这并不重要。我的意思是,这只是另一个需要解释的东西,所以我就不详细展开了。你可以假设这已经是使用top-k或类似方法筛选后的前100个token了。

因此,举个例子来说明。如果我们以“Berlin”概率极高(99.9%)的情况采样10,000次,我们会采到“Berlin”9,997次,采到“Hal”两次,以及一次“Moh”。这些基本上都是无意义的词元。在这种情况下,LLM很少会产生无意义的内容,因为正如我之前提到的,我稍微分散了这个分布,让它更有趣一些。
一个真正的LLM很可能在10,000次采样中10,000次都采到“Berlin”,因为“Berlin”的概率实在太高了。但这只是为了说明问题。
从采样到水印

现在我们简要讨论了LLM在底层是如何工作的,我认为这本身就是一个有趣的概念。但我之前已经讲过很多次了,所以不想让你们感到无聊。我只是想为现在的内容铺垫一些背景,解释这个水印机制是如何运作的。

我们提到过,在采样时我们会选择得分最高的词元。或者我们使用这种概率采样,这会导致大多数时候选中的都是得分最高的词元之一。现在这里有另一个没有水印的例子。我稍微改了提示词。现在的提示词是:今天的天气是“cold”,一个可能的答案可以是,比如“gray”或“overcast”。所以与“Berlin”的例子相比,我认为“gray”和“overcast”在某种程度上是可以互换的。
对于这个提示词,考虑到完成这段文本或写出下一个词元的目标,它们都是合理的下一个词元。所以选择哪一个几乎就像抛硬币一样。两者之间并没有客观上更差的一个。所以当我们进行随机采样时,因为它们的得分也相对较高,而且由于它们都是合理的词元,得分也差不多高,我们可能会得到其中一个或另一个。
所以如果我们重复多次采样,大约一半的时间会得到“overcast”,大约一半的时间会得到“gray”。这就是为什么如果你提供相同的提示词,LLM往往会给出不同的答案。如果你使用相同的提示词多次询问LLM,你经常会得到略有不同的答案。这是因为在某些位置上,两个可能的词元概率几乎相等,所以它会选择其中一个或另一个。
而那个词元又会影响到所有后续的词元,以此类推。
随机种子与确定性采样

现在,我想简要谈谈随机数生成。例如,如果我们使用这样一个随机数生成器,它会生成一个随机数字序列。如果我再次运行它,这里的数字序列是不同的。所以你可以看到每次我们生成五个数字,它们都是不同的。如果我在这里设置随机种子,比如1、2、3,然后我多次运行,我们仍然会得到随机数字,但它们现在都是相同的,对吧?
所以它们仍然是随机的。如果我们使用随机种子,我们仍然会得到彼此不同的随机数字,但它们是可复现的。所以无论我们是否使用随机种子,我们仍然会得到随机数字。但有了随机种子,我们得到的是一个可复现的数字序列。请记住这一点:这只是一个小的入门知识,我们稍后会用到这个概念。

例如,我之前提到过,如果我们随机采样,可能会得到“gray”或“overcast”。现在,如果我们使用一个特定的随机种子,比如42,我们就会始终选择“overcast”。我的意思是,这仍然是随机选择,但我们让它变得确定了。在这种情况下,给定这个提示词,模型将始终选择“overcast”。

如果我们使用一个不同的随机种子,模型可能会选择“gray”。每次我们采样时,它都会始终选择“gray”作为下一个词元。所以这仍然是随机采样,但我们是基于随机种子让它变得确定了。
水印密钥如何运作

所以,在水印技术中,Claude水印有点像设置随机种子的思路。但这个随机种子,并不是像某个固定的数字那样——比如有人写下一个固定的数字——而是他们使用一个秘密密钥,本质上就像一个API密钥,一个秘密密钥,然后从这个密钥,结合前四个词,推导出这个随机种子。
但关键在于,如果我回到上一张幻灯片,这就像这里一样:本质上有一个固定的随机种子,那个随机种子总是选择相同的下一个词元。好的,所以不是在这里使用随机种子99,比如,他们有一个秘密密钥,并且还利用前一个词元的信息来推导出这个随机种子。但关于这一点稍后会有更多说明。

所以思路是,水印使文本生成在特定位置上更具确定性。例如,如果我们在左侧有这些合理的文本。所以如果我有一段文字说,
我可能会选择“overcast”或“gray”。下一句话可能是,
它们再次是可以互换的。
那么微风是“吹动”或“吹拂”着穿过树林,街道显得“安静”或“静止”。
这意味着基本上我可以说“安静”或“静止”都可以。所以在文本中有某些位置,我们面临几乎同样可能的词元选择,就像我们之前看到的那样。所以这意味着,如果我们在没有水印的情况下运行提示词,或者将提示词输入大语言模型,我们有时会得到这个答案,有时会得到那个答案,等等。
根据位置的数量,我们在这里可能有128种可能的答案。当然,文本越长,我们拥有的可以互换使用的词项位置就越多,组合就越多,或者说可能的输出文本就越多。所以,举个例子,一个可能的输出文本可以是
> 今天天气寒冷且阴云密布。一阵微风正在吹动穿过树林,街道显得安静。我想我会待在家里,泡一杯茶,读一本书。
所以这是一个可能的文本。另一个可能的文本是
> 今天天气寒冷且灰蒙蒙的。一阵轻柔的微风正在吹拂穿过树林,街道显得静止。我想我会待在室内,端着一杯茶读一本小说。顺便说一句,外面其实还在下雨。我不知道这个麦克风效果怎么样,但这里的环境倒是挺应景的。
但总之,你可以看到这里生成了两个都非常合理的文本,而且还有更多的组合。它们都是合理的。没有一个必然比另一个更好。它们只是,你知道的,细微的差异。如果我们不使用水印,我们可能会得到其中任何一个,或者只是随机的,对吧?因为随机采样的原因,我们可能会得到这一个或那一个。

现在,如果我们固定随机种子,正如我之前提到的,例如,如果随机种子是99,我们可能总是得到这个文本。所以,使用随机种子,我们可以在某种程度上固定我们得到的答案,因为那样的话随机采样仍然是随机的,但它在可复现的意义上是确定性的。它总是会是一样的。好的,所以这仍然是没有水印的情况,只是加了随机种子。

而水印本质上做的事情是一样的。现在,不仅仅是使用一个简单的随机种子,他们有一个所谓的随机密钥,这个随机密钥本质上参与文本的选择。但我们已经可以说的是,在Claude的博客文章中,他们说水印不应该让文本变得更差。如果我们看看这个机制,是的,它为什么不会让文本变得更差是有道理的。
顺便说一句,我在这里并不是在为水印辩护。我只是试图解释。所以请不要责怪传话的人。但我想说的是,对于最终用户来说,水印无非就是固定一个随机种子,让这种采样变得具有确定性,如果这样说得通的话。
水印应用在哪里

好的,到目前为止的总结是:没有水印的情况下,我们经常在没有随机种子的情况下采样,因为我知道大多数人甚至不会使用随机种子。老实说,我不认为你一定能通过Claude和OpenAI的API做到这一点。我知道你可以在Ollama中做到,但我在这方面也总是遇到一些问题,因为我在我的一本书的补充材料中使用了Ollama来生成一些文本。
我固定了随机种子,但它仍然不总是确定性的,等等。所以这很棘手。你的情况也可能有所不同,取决于软件版本等等。总之,在没有水印的情况下,我们有这种随机采样。在右侧有水印的情况下,我们仍然有随机采样。但除了完全随机的随机采样之外,我们还有这个水印密钥。
而这个水印密钥被传递给随机种子生成器,以设置一个特定的随机种子,使其具有确定性。但本质上它非常相似,而且就像我提到的,从头理解事物有很多好处。现在我们在本质上知道了这个水印应用在哪里。所以这本质上是应用在采样阶段。它不是应用在大语言模型内部的,这实际上是个很酷的知识点。
所以他们不需要为此训练一个新的大语言模型。他们可以直接使用现有的模型,只需在采样阶段应用它。他们不需要重新训练任何东西或类似的操作。所以是的,这实际上很有趣,对吧?
水印检测如何工作

但我们还没有完全结束。我还想谈谈我们如何理解或判断文本是否带有水印。检测水印只有在我们能访问密钥的情况下才有可能。所以,例如,如果我们有这些不同的文本,本质上,在文本生成之后,你在互联网上找到一些随机文本(例如,你在互联网上某个地方找到了这里的第四号文本),你想知道:这个文本有水印吗?
那么,这是不可能知道的,因为要知道,你就需要水印密钥。你需要这个评分函数,然后用评分函数对文本进行评分。思路是,如果分数超过某个阈值,那么文本就被标记为有水印。否则,就没有水印。但作为最终用户,我们无法做到这一点,因为我们没有这个密钥。所以密钥对我们来说是不可用的。
只有Anthropic会拥有这个密钥。不过,在这篇博客文章中,他们提到他们当然会提供它,或者说他们会为此开发一个API并提供出来。我不知道。说实话,我跟他们没有关联。我不知道细节。我只是在这篇博客文章里读到的。我就知道这些。所以那个API可能只对某些公司私有开放,比如X或Substack Notes,当它们想标记AI生成的帖子时。
他们也可能向最终用户公开使用。谁知道呢?我们只能等着看。但总之,这里的关键是,水印检测只有在拥有这个水印密钥,或者当然,他们将要开发的API的情况下才有可能实现。
如何移除水印

现在,移除水印很有意思。既然我们知道了水印的工作原理,我们也知道了它的缺点。我的意思是,这真的高度依赖于特定位置上的特定token。所以,例如,在这段给定的文本中,如果这些彩色单词或token是水印位置,我们知道我们可以通过编辑这些位置来移除水印,对吧?如果我们改变了这些位置上的所有单词,我们就100%能够击败这个水印。
但问题是,我们不知道,对吧?

所以我们不知道这些词在哪里,因为我们没有生成水印。所以我们不知道要看哪些位置。所以这里的实际场景是,我们可以随机编辑文本。我们会随机更改几个词,希望我们改到了足够多的位置来破坏水印。那会是移除它的一种方法。而且,因为我们也不知道哪些词得分最高,因为那需要我们能够访问LLM并重新通过LLM运行提示词来找出哪些词得分最高,所以我们基本上只能猜测。
所以例如,我们可能会说,哦,我们把“overcast”换成“cloudy”,因为我们不知道“gray”是高分词,你明白吗?所以在这种情况下,说“gray”可能很直观,但也可能有不太直观的情况。所以我想说明的只是一些通用的文本编辑,我们在修改位置,但我们仍然在某种程度上猜测水印位置是什么。
所以,既然我们不知道,我们就在各处添加了几个词。如果我们添加了足够多的词,那也能击败水印。
水印评分函数如何工作

所以,是的,这就是水印的简要介绍。我提到有一个评分函数来判断某段文本是否带有水印。我想在这里作为一个额外内容来讲一下。这已经是一个很长的视频了,但作为额外内容,我想简要解释一下这个评分函数是如何工作的,因为那也是有趣的信息。这有点复杂。理解评分函数如何工作并不是必需的。
但他们采用特定方式这样做的原因是为了让检测更便宜。因为否则的话,如果我往回翻一张或两张幻灯片,如果你想检查某段文本是否带有水印,即使他们想检查,他们也得重新运行提示词来获得这些分数,然后应用这个水印随机种子来得到这段文本,然后进行比较。那会非常昂贵,因为基本上每一段你想比较的文本,你都得重新运行LLM。
你得知道是哪个LLM,那真的不可行,因为你通常甚至不知道提示词是什么,对吧?所以,是的,他们有一个技巧,我会说,修改采样过程,这样在后面的评分阶段你就不需要LLM了。在博客文章中,他们提到这个方法源自一篇论文。
那是一篇Nature论文,这个方法叫做SynthID-Text。那是大约一两年前发表的一篇论文。它来自Google,他们使用了类似的技术,他们称之为Claude水印。我不知道,抱歉,我不知道他们是否确切使用了那种技术,但那是他们提到的那个。
SynthID Text与锦标赛采样

那么它是如何工作的呢?在我们看幻灯片之前,我们先看了常规的概览,这里有一些文本。我们把它输入大语言模型,得到这个logit分布,然后从分布中采样,得到输出token。在这里,在采样过程中,我们使用了水印密钥和随机种子生成器。所以这部分仍然是正确的,仍然是实际发生的情况,但在这个token的采样方式上,还有更多细微之处。
他们并不是简单地使用NumPy的random choice,而是使用了更复杂一些的方法。

假设我们的上下文是“the weather today is cold”,我们想生成下一个token。比如:“gray”、“overcast”、“gloomy”、“cloudy”。“gray”的概率是50%,“overcast”是30%,“gloomy”是15%。假设“cloudy”是0.05,其余的大约是0。这里看起来当然有些不同。假设那是“gray”和“overcast”,我只是重复使用这张图。但现在想象这些是最有可能的,比如“gray”和“overcast”,而其他所有的都非常小,除了“gloomy”和“cloudy”,也许。
所以本质上,想象一个非常小的词表,这个例子中只有四个词,而不是这里的50个词,只是为了更简单。现在,正如我之前提到的,我们可以使用NumPy的random choice配合这些概率来采样下一个token。

我们可以使用水印密钥配合这个随机种子生成器,使其具有确定性,并获得我们想要的特定水印。但正如我之前提到的,这会非常昂贵。不是采样本身——那不重要,那很便宜。而是之后的检测会非常昂贵,如果我们要检查互联网上的随机文本的话。

所以他们改用另一种方法,他们在采样过程中、生成过程中也使用它,这样之后在检测阶段可以重复使用。他们使用的是所谓的锦标赛采样。这是代替random choice之类方法的概念,叫做锦标赛采样。那么它是如何工作的呢?看起来可能有点复杂,但说实话,它看起来比实际要复杂得多。
你可能需要在某个时候暂停视频,仔细看一下这张图。但我认为它实际上比看起来简单。一旦你掌握了要领,就非常直白了。让我试着解释一下。我们仍然有这个上下文,然后有这些可能的或合理的下一个token,以及它们不同的概率。
现在他们有他们称之为随机水印函数的东西。
随机水印函数

这里我们有三个水印函数,G1、G2和G3。实际上,他们可能有30个、50个甚至更多。这里我只用三个,因为在这张幻灯片上更简单。就是更小,你知道,更适合放在幻灯片上。现在,如果我们看“gray”这个词,它可能会给我们一个签名101。我的意思是,如果我们用这个水印密钥生成随机种子,并且我们有三个函数G1、G2、G3。
如果我把“gray”放进去——我这里省略的是,通常你会把“gray”和上下文中的前三个或四个词放在一起。所以是“cold”和“gray”。如果我把这个和这个水印密钥一起放入G1,我得到值1。为什么?嗯,这就是这个函数的工作方式。它就像一个随机函数。随机函数要么返回0要么返回1。在这种情况下,用这个随机密钥和这个token,它返回1。
用相同的密钥,但不同的函数,你得到值0。然后这里你又得到一个1。所以如果我们有更多函数(当然,30个函数),这将是一个非常长的由1和0组成的字符串。

它基本上就像一个比特串,就像你有一串0和1的比特。好的。这是“gray”的。所以我们通过使用这些水印函数得到了签名101。现在我们可以对其他所有词做同样的事情。我们可以对“gray”做,可以对“overcast”、“gloomy”和“cloudy”做。每个都有不同的签名。比如,“overcast”是0、1、0。
“Gloomy”是0、0、1。“Cloudy”是1、0、0。好的。现在我们有了这些比特。下一步是所谓的锦标赛采样,我们只是把它们配对。
锦标赛采样逐步解析

就像足球锦标赛的淘汰赛阶段,或者美式橄榄球的季后赛,总是有两支球队互相比赛。这基本上就是同样的思路。我们有一对token,它们本质上在互相竞争。而得分来自这些函数。我们从第一轮的第一个函数开始。我们有“cloudy”和“gray”。
所以我们看这里:“gray”是1,“cloudy”是1。好,所以是1和1。“Overcast”和“gray”。所以“overcast”是0,“gray”是1。所以我们有0、1。“Gloomy”和“overcast”。这里“gloomy”是0,“overcast”是0。所以是0、0。然后我们又看到“gray”和“gray”,因为我们已经快用完了。我们没有足够的其他词了。所以有一组重复。
所以这是随机选择的。因此这里有一个1和一个1。现在我们看结果。这是平局。在平局的情况下,我们也使用随机种子和水印密钥进行随机选择。所以这里,“cloudy”胜出。而在这一组中,根据G1,“gray”是赢家,因为它有1。所以“gray”胜出。然后这里,“overcast”和“gray”是平局,随机选择,“gray”也被随机选中。
所以我们现在有“cloudy”、“gray”、“overcast”和“gray”。我们进行这个锦标赛的下一轮。在下一轮中,我们使用G2。根据G2,“cloudy”这里是0。“Gray”也是0。“Overcast”是1。“Gray”也是0,抱歉。所以,锦标赛的下一阶段又开始了。

所以这是平局。我们随机选择“gray”。而这里“overcast”是赢家。所以决赛是“gray”对“overcast”。然后我们再看分数。“Gray”是1。“Overcast”是0。所以“gray”是赢家。这就是“gray”这个token被采样的过程。水印密钥在这里起什么作用?水印密钥,如果我往回翻几页幻灯片,是用来通过这些随机水印函数生成这些分数的。
所以水印密钥本质上决定了我们在这些阶段得到什么值。因此水印密钥仍然非常重要。否则,这些签名会看起来不同。
无需重新运行LLM即可检测水印

我们现在已经采样了下一个token。这就是这个修改后的采样过程的工作方式。我们本来可以使用NumPy的random.choice。但它的缺点是,如果我们要对互联网上的随机文本进行评分,我们就必须重新运行LLM。而使用这种技术,我们不需要。我稍后会展示给你看。所以这种技术听起来确实很奇怪也很繁琐,但它的优点是我们现在可以更容易地对随机文本进行评分,而不需要重新运行LLM。
所以这本质上只是为了让检测更容易、更便宜。


所以,举个例子,如果我们有一段新文本。我这里只是用同样的文本,但假设它是新文本。这是在采样之后,当我们进行评分的时候。假设我们在互联网上发现了这段文本。文本是“the weather today is cold and ‘gray’”,我们想知道这是否是LLM生成的。那么我们会——或者说Claude/Anthropic会——拥有水印密钥和这些函数:G1、G2和G3。
然后它会将这段文本输入这些函数。对于这里“gray”的这个位置,我们会得到101,和生成过程中得到的类似。所以这和之前一样。而如果我们把这些位加起来,这里有两位,对吧?这里一个1和一个1。所以它有两位信息,为了简单起见我们这么说。这只是一个非常简单的示例。
但假设我们在这里的这个位置的“gray”得到了2分。如果这里是一个不同的词,比如“overcast”在这个位置,我们会得到1;如果是“gloomy”,我们也得到1;“cloudy”也是1。所以我只是把每一行的值加起来,对吧?这就是我们在每个位置得到的分数。而这里我只看了最后一个位置。
如果我在其他位置也这样做,我会在不同位置得到不同的分数。所以,举个例子,假设在第一个位置我得到2。这里我得到2。对于“today”,我得到3。对于“is”,我得到2。“Cold”是2。“Gray”是3。所以这里我应用了上一张幻灯片中展示的那些水印函数。

我只是把这三个函数的数值加在一起。水印函数非常便宜。所以你可以快速地在整段文本上运行它们并得到这些分数。然后基于这些,我可以计算平均位数。所以如果我平均这里所有的值,假设我得到2.23。

现在,如果我有一段略有不同的文本,这里我把“today”换成了“now”,把“gray”换成了“overcast”。这些现在得到1分和1分。如果我平均整个字符串,我得到1.71。所以为此,我不需要LLM。我只需要水印密钥、随机种子生成器,以及这些函数G1、G2和G3。这就是我需要的全部。
我不需要LLM。我可以在这里得到这个分数。而他们所做的就是应用一个阈值。

所以,举个例子,我的意思是,他们并不是用这个确切的阈值。但比如说,我们可以设定如果分数大于2,那么文本就被打上了水印。如果分数小于2,就没有水印。所以在这里,如果分数大于2,那就是“是”。是的,这段文本有水印。在这个案例中,1.71不大于2,所以这段文本没有水印。好的,这就是我们检测互联网上任意文本是否带水印的方式。
本质上就是应用这些水印函数,然后对分数取平均,再应用一个阈值。好的。

所以再说一次,锦标赛采样主要是为了让检测更容易、更便宜。我们也可以使用类似NumPy的random choice配合随机种子,或者让采样变得确定性。但那样的话,就很难对互联网上的任意文本进行评分了。
水印总结与局限性

不过,总结还是一样的。无水印和水印之间的区别在于,我们用水印密钥控制了这里的采样过程。而在其中,我们有这个锦标赛采样。而且,正如我之前提到的,检测水印需要密钥和水印函数G1到Gn。

再说一下移除水印,因为我觉得有些人可能对此感兴趣,理想情况下需要编辑这里的所有位置。但因为我们不知道哪些位置被打了水印,而且在内部,他们选择位置时会确保那些位置上的token具有相同的可能性。但可能有些位置并非如此。比如这里,对于“trees”这个词,我们可能甚至没有一个高分替代词,所以他们不会在那个位置打水印。
所以他们基本上只在某些特定位置进行水印处理。由于我们不知道哪些位置需要破解或移除水印,我们就得……

……编辑文本中的多个位置。所以我认为这对AI生成文本的未来意味着,这实际上……
这对AI生成文本意味着什么

……可能会导致AI生成文本的质量变差。我觉得如果有人在互联网上到处使用AI生成文本,比如说一个新闻网站喜欢用AI生成文本来写新闻,我不认为水印一定会阻止他们这样做。他们可能仍然会想生成AI文本,因为那是他们工作流程的一部分。所以我的猜测是,他们会使用另一个模型。

他们只会用第二个模型来编辑文本,得到所谓的“编辑后的AI生成文本”。这使流程变得更加复杂。不再是直接从Claude获取文本,而是先用Claude生成AI文本,再通过一个本地模型处理,最后得到编辑后的AI生成文本,而后者很可能不再带有水印。那为什么用本地模型呢?我只是觉得用本地模型是因为我认为所有提供商——专有LLM,不仅是Claude,还有Google——我是说,Google写了这篇论文,对吧?
所以我在想他们也在给Gemini的文本加水印。而且我认为OpenAI可能已经在做或者也将会这样做。我只是在猜测,但我想每个人可能都会做类似的事情,因为有欧盟法规要求这样做。而且根据那篇博客文章,这显然也是Claude这样做的原因。是的,所以我认为本地模型可能不会,至少目前还不会,实现这种水印。
所以我认为人们只会使用本地模型,然后生成编辑后的AI生成文本。我的猜测是,它会比原始文本稍微差一些,因为对于本地模型,你现在可能用的是更小的模型。不过,从技术上讲,你也可以直接使用本地模型来生成文本。但在我看来,编辑文本比生成文本更简单。所以对于文本生成,你可能会用一个非常昂贵的高端——我不知道——比如最贵、最高端的Claude模型来处理复杂文本。
然后你用更便宜的本地模型来做这些精准的修改,基本上就是这样。这大概就是将要发生的事情。那为什么更差呢?如果我们回头看这个添加随机位置的图表,你可能只是为了改而改。然后这就有让文本变差的风险。所以你可能仍然有生成的文本,但有点像被生硬地编辑过。
最后的想法

但不管怎样,我的目标是解释水印是如何工作的,而不是说它在全球范围内的影响。但我希望这种幕后、引擎盖下的视角能有所帮助。水印并没有看起来那么复杂,但我认为它仍然有52张幻灯片,所以也不是非常简单。我希望你觉得这个小型讲座有用。那么,下次再见,到时候见。
附:如果你喜欢更多这种风格的讲解视频,我并不是定期在YouTube上发布视频,但多年来我已积累了超过300条视频,你可以在我的YouTube频道上找到。
译文已达到本站中文翻译的字数上限,剩余内容请查看原文。