常見問題先回答
先抓住直覺,再往下看演算法
浮水印是偷偷在文字裡加字元嗎?
不是。這類 watermark 不多塞任何字元,也不靠 metadata。輸出的每個字都是正常的字, 訊號在「模型選了哪些 token」的統計分布裡。所以純文字複製貼上,訊號跟著走。
為什麼目前只有 Anthropic 驗得出來?
因為決定「偏好哪些 token」的那把 secret 只有它有。這不是加密——內容照樣看得懂、沒有任何東西被藏起來; 比較像是拿著同一把 key 把生成過程重跑一次,檢查這篇文章符合那套偏好的比例是不是異常高。 Anthropic 說會開放第三方偵測,但截至寫這篇時,公開的偵測工具和演算法細節都還沒出來。
手動改幾個字,不就把 hash 全打亂了?
如果每一步都拿整個前綴去 hash,確實會——改一個 token,後面全部 desync。 所以實務上的設計不會把命運綁在無限長的前綴上,而是只看最近幾個 token, 並把訊號分散到大量位置。改一個字只毀掉附近幾個位置,過幾個 token 就重新同步。
改 sampling 機率不會傷品質嗎?
一定有 trade-off,但不代表看得出來。關鍵是只在模型本來就猶豫的地方偏: 「有效 / 實用 / 有用」三選一時偏個兩三個百分點,讀起來沒差;1 + 1 = 這種只有一個答案的位置就不該碰。
所以文章要夠長?
對。每個位置只帶一點點證據,訊號隨 累積、雜訊只隨 累積,所以可信度大致按 成長。十幾個 token 幾乎沒有統計能力,上千個才談得上證據。
先認識幾個會出現的詞
不用先讀 watermark 論文;下面六個概念夠我們把整篇走完。
Token
LLM 實際 sampling 的單位,不一定等於一個中文字或一個英文單字。
Logit / Softmax
Logit 是模型給候選 token 的原始分數;softmax 再把它們轉成總和為 1 的機率。
Entropy
這裡只要理解成模型的猶豫程度:候選越平均,entropy 越高;答案越唯一,entropy 越低。
Secret / PRF
PRF 可以先想成帶 secret key 的 hash:知道 key 就能重現同一組偽隨機規則,外界則難以預測。
Green list
經典 toy algorithm 裡,由 secret 規則選出的偏好 token 集合;只是加一點分數,不代表禁止其他 token。
z-score
「實際命中數離隨機預期有幾個標準差?」數字越大,越不像只是運氣。
Anthropic 公開了什麼、沒公開什麼
這篇的切入點是 Claude 新加的文字浮水印,但演算法本身 Anthropic 沒有公開。 為了不把論文裡的做法講成「Claude 就是這樣做」,全文分三層,並且會用標籤標出來:
沒有標籤的段落就是 LLM watermark 這個領域的公開常識。先把已知事實列清楚:
- Claude 用兩套互補的標記:文字走 watermark, 產生的
.svg/.png/.jpg檔案走 C2PA 簽章 metadata。 這是兩件不同的事,後面會說差在哪。 - 2026-08-02 之後推出的 Claude 模型上線即支援,先前的模型陸續補上。
- 標記做在模型層,所以 API、Claude、Claude Code、Claude Cowork、Claude Tag, 以及 AWS / Google Cloud / Microsoft Foundry 上的 Claude 都涵蓋,全球一致。
- 官方措辭是浮水印「是文字的一部分」,所以複製貼上會跟著走, 而且「可能撐過一些編輯」(may persist through some editing)——用的是可能,不是保證。
- 驗到浮水印只代表這段內容可能被 Claude 處理過,不代表 Claude 是作者—— 因為很多人拿 Claude 潤稿、翻譯、改寫自己的文章。反過來,沒驗到也不代表不是 AI 寫的。
- 太短的文字不會有可靠訊號。官方沒有給具體字數門檻。
- Anthropic 說正在讓使用者與第三方能夠偵測,細節「之後的技術文件會說明」。截至 2026-08-13,演算法與公開偵測工具都還沒釋出。
動機方面,多家媒體報導與歐盟 AI Act 的透明度義務有關;Anthropic 自己的說法比較泛, 提到的是合規與透明度承諾。
剩下的就是這篇要談的:在這些約束下,演算法可以怎麼設計。
訊號不在字裡,在選字裡
先排掉幾個容易混在一起的東西。「AI 浮水印」常被想成在文字裡塞看不見的字元(zero-width space 之類), 或是在檔案裡寫 metadata。這兩種都有人做,但都不是 Claude 文字浮水印的路子—— 官方明說浮水印「是文字的一部分」,而塞字元跟 metadata 都會被純文字複製、重新排版洗掉。
四個常被混為一談的技術,攤開來看:
| 技術 | 訊號在哪 | 純文字複製後 | 需要 secret | 能證明什麼 |
|---|---|---|---|---|
| 統計式文字 watermark | token 選擇的統計分布 | 還在 | 要(產生端與偵測端共用) | 這段文字很可能經過該系統產生或處理 |
| 隱藏字元 | 多插入的不可見碼位 | 看情況,很脆弱 | 不一定 | 有人在這串字裡插了東西 |
| 檔案 metadata | 檔案標頭欄位 | 沒了 | 不用 | 檔案自稱來自哪裡 |
| C2PA 簽章 | 附在檔案上的 manifest,用 hash 綁定 bytes | 不適用(純文字沒檔案可綁) | 要私鑰 | 這個檔案確實由某方簽發,且 bytes 未被竄改 |
| AI detector | 沒有訊號,靠文風分類器猜 | 不適用 | 不用 | 看起來像 AI 寫的(誤判率高) |
最後兩列特別容易被混淆。C2PA 是密碼學簽章:對檔案 bytes 做 hash、寫進 manifest、 用私鑰簽名,驗證時重新 hash 再驗簽。它能給出「未被竄改」這種強保證,但前提是有檔案、而且 metadata 沒被剝掉。AI detector 則完全沒有訊號可言,它只是個文風分類器,說的是「這看起來像 AI 寫的」。 統計式 watermark 夾在中間:沒有簽章那麼強的保證,但只要文字還在就跟著走。
一個 token 怎麼被偏
LLM 生成時,每一步會對詞表裡每個候選 token 給一個未正規化的分數(logit),再過 softmax 變成機率:
白話說就是「分數高的機率大,但不是贏者全拿」,溫度 控制拉開的程度。 接下來只需要記得一件事:watermark 最自然的插入點,就是在 softmax 之前動 logit。
經典做法:green list
持有 secret key 的一方,在每一步先算一個偽隨機狀態:
(偽隨機函數)可以先當成「帶 key 的 hash」: 沒有 key 的人看輸出像亂數,知道 key 的人可以穩定重現同一個結果。 是這一步用到的 context——選什麼很關鍵,第五節整節在談這件事。
用 當種子,把整個詞表偽隨機切成兩半:green list (比例 )和其餘的 red list。 然後給 green 的 token 一點分數:
是 indicator:在 green list 裡就是 1,否則 0。 所以整條式子只是說「green 的加 ,其他不動」,再重新 softmax。
要強調的是:red token 沒有被禁止。如果某個 red token 原本機率 90%, 加了 的競爭者也很難翻盤——它照樣會被選中。 這正是品質不會崩掉的原因。
注意每一步的 green list 都不一樣——context 換了,PRF 輸出就換了,切法也跟著換。 所以不存在「某些詞永遠被偏好」這種可以直接觀察出來的模式。
產生端大概十行:
# toy watermark — 產生端ctx = prompt_tokensfor _ in range(max_new_tokens): logits = model(ctx) # 原始 logits s = PRF(K, ctx[-k:]) # 只餵最近 k 個 token G = green_set(s, vocab_size, gamma) # 偽隨機挑出 gamma 比例的詞表 logits[G] += delta # green 的各加一點分數 tok = sample(softmax(logits / T)) # 照常 sampling ctx.append(tok)除了兩行,其餘跟一般的 decode loop 一樣。這也是為什麼這類方法可以做在模型層、 不必動上層產品——跟官方說的「標記做在模型層,所有產品都涵蓋」是吻合的。
Detector 在算什麼
偵測端拿同一把 key,把文章重新 tokenize,逐位置重算一次 green list,數命中幾個:
# toy watermark — 偵測端hits = total = 0for t in range(k, len(toks)): s = PRF(K, toks[t-k:t]) G = green_set(s, vocab_size, gamma) total += 1 hits += (toks[t] in G)
z = (hits - gamma*total) / sqrt(total * gamma * (1-gamma))這裡沒有「解密」任何東西,只是重跑一次規則再數數。統計上要問的是: 如果這篇文章跟 watermark 無關,命中數會長什麼樣? 那就是每個位置獨立以機率 命中,也就是
拿實際命中數跟這個基準比,換算成 z-score:
逐項拆開來看,這條式子其實沒什麼玄機:
- :沒有 watermark 時,預期命中幾個。
- 分子 :實際比預期多命中了幾個。
- 分母 :純靠運氣的話,命中數本來就會上下晃動, 這是晃動的標準差。
- 整體:多出來的部分,相當於幾個標準差。
舉個 toy example。、1000 個可計分位置, 一篇沒被 watermark 的文章預期命中 500,標準差 。也就是說 470~530 都很正常。 如果實際數到 570:
單看任何一個 token 都證明不了什麼——它落在 green list 的機率本來就有一半。 但 1000 個位置一起看,多出 70 個命中就不像是運氣了。
為什麼改幾個字不會整篇失效
這是我一開始最卡的地方。既然每一步的 green list 由 hash 決定,那把中間某個 token 改掉, 後面所有 hash 輸入不就全變了嗎?
如果 context 取整個前綴,這個擔心完全正確:
hash 的雪崩效應保證輸入差一個 bit、輸出就完全不同。所以改掉第 3 個 token, 第 4 個之後每一步重算出來的 green list 都跟當初生成時不一樣,命中率直接掉回 。整篇的證據從修改點開始歸零。
所以 robust 的設計不會把命運綁在無限長的前綴上。最容易理解的改法是只看最近 k 個 token:
拿 走一遍。原本是 A B C D E F G H I, 把 C 改成 X:
- 位置 D 的 window 是
{A, B, X}→ 含 X,算出來的 green list 錯了。 - E 的 window 是
{B, X, D}、F 的是{X, D, E}→ 一樣受影響。 - G 的 window 是
{D, E, F}→ X 已經滑出去了, 跟生成時完全一致,命中判斷恢復正常。
一次修改的破壞半徑就是 ,不是「到文章結尾」。 這就是 self-synchronization:不需要任何額外的同步機制, 單純因為 context 是滑動窗口,錯誤自己會滑出去。
代價也很明顯: 越小越耐改,但 context 太短會讓同一組 window 頻繁重複, green list 的切法跟著重複,「每個位置獨立」這個統計假設就開始失真。 是最耐改的極端,也是統計上最不乾淨的極端。
為什麼微調機率不一定傷品質
先講一個沒得繞過的事實。設原始輸出分布是 、加了 watermark 之後是 。如果
那麼一個只看得到輸出文字的 detector,理論上不可能區分兩者—— 它拿到的樣本來自同一個分布,沒有任何資訊可用。所以想要可偵測,就必須 。「完全零影響又能可靠偵測」是矛盾的。
真正的工程問題因此不是「怎麼做到零影響」,而是:怎麼讓單步的 與 差距小到讀不出來, 但幾百上千步累積後統計上分得開。衡量那個差距常用 KL divergence , 直覺就是「兩個分布差多遠」,這裡不需要展開。
把 bias 放在模型本來就猶豫的地方
關鍵在於分布形狀差很多。有些位置模型本來就沒主見:
「這是一個非常 ___ 的方法」 有效 27% 實用 25% 有趣 21% 強大 18% ...四個都合理,換哪個都不影響句子品質。這種位置(高 entropy,也就是不確定性大) 偏個兩三個百分點,讀者不可能察覺。
但有些位置只有一個答案:
「1 + 1 =」 2 99.99% 其他 0.01%這裡任何有意義的 bias 都是在把正確答案換掉。所以合理的設計會看分布的形狀決定要不要動手: 低 entropy 的位置放過,不計分也不干預。
這對幾類輸出特別重要,因為它們幾乎整段都是低 entropy:
- 程式碼:變數名、關鍵字、括號結構,改一個 token 就是 bug。
- 數學與計算:答案唯一。
- JSON / URL / 結構化輸出:格式錯了就不能用。
- 逐字引用、專有名詞、事實性答案:改掉就是錯的。
反過來說,這也直接解釋了官方那句「太短的文字沒有可靠訊號」: 一段文字裡真正能承載 watermark 的,只有高 entropy 的那些位置。 一段幾乎全是程式碼的回覆,可計分的位置可能少到根本驗不出來—— 這裡的 從來就不等於 token 總數。
長度、門檻與誤判
把上一節的 定義成「可計分的位置數」。 每個位置貢獻一點點偏差,那麼
白話說:文章長 100 倍,辨識能力大概只強 10 倍。證據會一直累積,隨機波動也會,只是波動長得比較慢。
延續前面的 toy 設定(,watermark 把命中率從 50% 推到 55%), z-score 剛好有個很乾淨的形式:
代進幾個長度:
N = 20 → z ≈ 0.45 什麼都證明不了N = 100 → z ≈ 1.0 還在雜訊範圍內N = 400 → z ≈ 2.0 有點意思,但遠遠不夠N = 1000 → z ≈ 3.2 開始像回事N = 4000 → z ≈ 6.3 幾乎不可能是巧合門檻怎麼定,誤判怎麼算
偵測就是選一個門檻 ,超過就判「有 watermark」。兩種錯誤方向相反:
- False positive:人寫的文章被判成有 watermark。 在常態近似下, 對應單尾機率約 , 約 。
- False negative:有 watermark 卻沒驗出來。 文章太短、可計分位置太少、被改寫過,都會落在這一類。
門檻拉高,false positive 變少但 false negative 變多,反之亦然。這裡沒有兩全的選項。 而且真實場景是「拿去掃幾百萬份文件」,那個看起來很小的 乘上一百萬份就是幾十份冤枉—— 所以實務門檻通常訂得比直覺高很多。
還有一個容易被忽略的坑:上面整套推導假設每個位置獨立,但自然語言會重複。 同一個片語出現兩次,window 一樣、green list 就一樣,兩次命中並不是獨立事件, 這會讓 z-score 被高估。實作上通常要對重複的 window 去重之後再算, 論文裡也是這樣處理的。
這一節的結論,也正好對上官方那句「驗到浮水印只代表可能被 Claude 處理過」: 這是統計證據,不是簽章。它給的是「這篇文章符合某套祕密偏好到不太可能是巧合」, 而不是「這篇文章由誰產生」的密碼學證明。
什麼才真的洗得掉
複製貼上
文字完全沒變,可計分位置一個不少,z-score 原則上一樣。這是統計式 watermark 相對於 metadata 的主要優勢, 也是官方明確講的行為。
局部修改
改幾個詞、刪一兩句、調換段落。如果 context 是滑動窗口, 每處修改大約毀掉 個位置的證據,其餘不受影響。 2000 個位置裡毀掉 60 個,z 會掉但不會歸零。
不過有個工程細節值得一提:detector 必須重新 tokenize。 編輯過的文字切出來的 token 邊界可能跟原本不同,這種 misalignment 造成的損失 比「被改掉的字數」本身更難預測。
整篇改寫、翻譯、丟給另一個模型重寫
這是本質上不同的攻擊。前兩者是保留大部分原 token 序列, 這一種是讓另一個模型從頭 sample 一遍——新的 token 沒有經過原本的 green list 偏好, 命中率就是 。剩下的訊號只來自碰巧沒被改掉的片段。
官方對這點的說法也很保留,只說「可能撐過一些編輯」, 並列出「大幅編輯、改寫、翻譯、混合」是驗不出來的情況之一。沒有給任何比例數字, 我這裡也不編一個。
順帶一提,這個領域有個結構性難題:一旦公開偵測工具, 想洗掉浮水印的人就有了 oracle——反覆微調直到分數低於門檻即可。 這是「開放第三方驗證」與「防規避」之間的真實矛盾,也可能是 Anthropic 的偵測工具 還沒直接公開的原因之一。(這句是我的推測。)
三角 trade-off
整篇最後會收斂到三個量互相拉扯:
- Detectability:多短的文章驗得出來。
- Robustness:被改過之後還剩多少證據。
- Quality:為了 watermark,輸出分布被拉走多少。
用 當旋鈕就看得很清楚。 調大, 每步命中率提高,短文就能累積到門檻,改掉一部分也還撐得住;代價是模型越來越常放棄它原本最想選的詞, 用字開始被拉走。 調小,品質幾乎不受影響, 但需要更長的文章才驗得出來,而且稍微改一改就掉到門檻以下。
這也是為什麼近年研究往「不動到期望分布」的方向走—— 例如 SynthID-Text 的 tournament sampling,在期望上不改變輸出分布, 等於試圖把品質那一角從這個三角裡拿掉。代價是演算法複雜不少。
收尾
真正巧妙的地方不是「把一串祕密資料藏進文字」。 而是:在大量原本就幾乎等價的 token 選擇裡,按照只有 watermark 持有者知道的微弱偏好去 sampling; 任何單一次選擇都看不出異常,但幾百上千次累積之後, 知道 secret 的人可以看到統計上異常一致的 pattern。
這也決定了它的能力邊界:它是統計證據不是簽章,需要長度, 怕整篇改寫,而且只能說「這段文字可能經過某個系統」,不能說「這是誰寫的」。 官方文件其實把這幾點都寫得很清楚,只是容易被「隱形浮水印」這個詞蓋過去。
參考
- How Claude marks AI-generated content — Anthropic 官方說明,本文第一節的事實來源。
- A Watermark for Large Language Models (Kirchenbauer et al., ICML 2023) — green list、 bias、z-score 檢定的原始論文。
- Scalable watermarking for identifying large language model outputs (Dathathri et al., Nature 2024) — SynthID-Text 與 tournament sampling,Gemini 的實際部署經驗。
- google-deepmind/synthid-text — 上面那篇的參考實作,想直接讀 code 的話從這裡開始。
- A Survey of Text Watermarking in the Era of Large Language Models — 想看全景的話,這篇 survey 把各家做法的分類整理得不錯。