Anthropic's Invisible AI Text Watermarking and the KGW Algorithm Behind It
I saw some news online in the past couple of days saying that Anthropic plans to launch an invisible watermarking technology.
The core purpose is to identify text content generated by AI.
Could it be that there are requirements over there too? That public accounts posting AI-generated content have to label it? Haha!
The key point is: Anthropic has stated that starting with models released on or after August 2, the company will embed a watermark directly into text generated by Claude AI that is imperceptible to humans and only machine-recognizable.
The watermark is invisible to the human eye and does not degrade text quality or readability.
Even if the text is copied and pasted, the watermark is retained, and some light editing operations cannot remove it.
Why do I vaguely feel like this description is so familiar?
Did I write about this technology before?
I finally remembered — I wrote an article back in March this year, mainly about frontend zero-width invisible watermarks.
When I wrote that article, the phrasing I used was actually quite similar. The core advantages of frontend zero-width character invisible watermarks are:
Completely invisible to the naked eye, survives copy-paste.
Of course, I'm not just speculating here!
Anthropic isn't necessarily using this exact technology; it's just that the "effect description" is similar to that of zero-width characters.
For a technical approach that is "invisible to the naked eye but machine-recognizable," besides zero-width characters, there is actually a more sophisticated solution — LLM Statistical Semantic Watermarking.
The detailed technical approach can be found in the paper "Kirchenbauer 2023 KGW Algorithm".
To understand it simply: It does not insert any invisible special characters, nor does it modify the literal text.
It embeds a statistical fingerprint within the word selection probabilities during the model's text generation. To a human reader, there is no discernible difference at all.
But using a dedicated algorithm for statistical testing, one can determine whether the text was generated by that large model.
The core principle is generating a watermark during word selection via the KGW Red-Green List Algorithm.
Large models generate text autoregressively: based on the preceding context, they output a probability distribution for the next token (word fragment) and pick a word from it to output.
Statistical watermarking is about slightly intervening at each word selection step, biasing the selection probability toward a certain type, artificially creating a statistical deviation.
Let's use an analogy. It's like our human eyes see beans and can't tell the difference between mung beans and red beans — we think they're all just beans.
Originally, the large model picks beans randomly; it might pick red ones or green ones, with no pattern.
Now, after statistical watermark intervention, the large model picks mostly red ones, trying to avoid or completely not picking green ones.
But human eyes can't tell the difference; a machine can.
Generation Phase (Embedding the Watermark)
- Take the already generated preceding token sequence, and use a key + hash function to compute a random seed K.
- Using this seed K, randomly split the model's entire vocabulary into two categories: Green List, Red List.
- Do not forbid the Red List; just add a small uniform bias to the logits (scores) of all tokens on the Green List, thereby increasing the probability of selecting Green List words.
- The model continues normal sampling to output the next word, looping to generate the complete text.
Under this slight bias operation, the content output by the model is indistinguishable to humans.
For example, originally the large model's output was: The weather is sunny today.
Under statistical watermark intervention, it becomes: The weather is bright today.
To a human, these two words don't have much difference; the word order/semantics are almost completely identical.
But a machine can recognize that one of these words is on the Red List and the other on the Green List.
Statistical watermarking relies on this kind of word selection preference to embed markers, not on swapping the order of words.
Note: It does not force the selection of Green words here; it only increases the probability.
Forcing the selection of Green words might cause problems with the output content, so it's just a probability here.
This way, the output content naturally has more Green words and fewer Red words, and the machine can recognize it.
Detection Phase (Extracting the Watermark)
Given a piece of text, without knowing its generation process, only knowing the public detection key.
- Token by token, reproduce the original hash + seed logic, reconstructing the Green/Red list for each step;
- Count how many Green List tokens actually appear in the entire text;
- Use a statistical Z-test to calculate the p-value: determine whether the "higher proportion of Green words" is a random coincidence or caused by watermark intervention.
If the p-value is sufficiently small, it is highly likely generated by a large model.
If the p-value is not small enough, it might be written by a human, or adapted by a human.
Understanding the principle of LLM statistical watermarking explains why this watermark has limitations:
For already written text, statistical watermarking is powerless.
Because statistical watermarking itself relies on word selection probabilities for identification, and already written text no longer has any word selection probabilities — it's fixed.
Also, if you make extensive modifications to AI-generated text, such as synonym replacement, a large number of tokens are replaced, making correct identification impossible.
Additionally, for very short sentences or paragraphs, correct identification is also difficult and prone to false positives.
Furthermore, precisely because of this bias effect of LLM statistical watermarking, the content output by the large model may have negative impacts.
After all, not every word or meaning has a corresponding word to replace it with; replacement might make people slightly feel that the word order or semantics are problematic.
This might be okay for English, but for Chinese, this problem is especially pronounced.
The semantics of Chinese are extremely complex; without a long context, it's hard to fully understand what a part is expressing. (Flashback to Classical Chinese reading comprehension)
Here's a simple Demo to give you a taste of the LLM statistical watermarking effect:
import hashlib
import random
from scipy.stats import norm
# ====================== KGW Watermark Simulation Demo ======================
# 1. Simulate vocabulary, simulating the large model's token vocabulary
VOCAB = [
"sunny", "bright", "rainy", "humid", "windy", "cold", "warm", "cool",
"ocean", "mountain", "forest", "river", "city", "night", "morning", "dusk"
]
WATERMARK_SEED = 12345 # Watermark key; must be the same for generation and detection
GAMMA = 0.5 # Red-Green split ratio; Green words account for 50% of the vocabulary
DELTA = 2.0 # Bias added to Green word scores; larger delta means stronger watermark signal
def get_green_red_list(context_tokens: list, seed: int):
"""
Generate this step's Green List and Red List based on preceding context + seed hash (KGW core)
"""
ctx_str = "|".join(context_tokens)
h = hashlib.sha256(f"{ctx_str}_{seed}".encode()).hexdigest()
rand = random.Random(int(h, 16) % (2**32))
shuffled_vocab = VOCAB.copy()
rand.shuffle(shuffled_vocab)
split_idx = int(len(shuffled_vocab) * GAMMA)
green = set(shuffled_vocab[:split_idx])
red = set(shuffled_vocab[split_idx:])
return green, red
def watermarked_generate(max_len=12):
"""Simulate watermarked text generation: prioritize raising Green word probability at each step"""
output = []
for _ in range(max_len):
green_set, red_set = get_green_red_list(output, WATERMARK_SEED)
logits = {}
for word in VOCAB:
base_score = random.uniform(0, 1)
if word in green_set:
base_score += DELTA # Green word gets a score boost, increasing selection probability
logits[word] = base_score
# Pick the word with the highest score to output
next_word = max(logits.items(), key=lambda x: x[1])[0]
output.append(next_word)
return " ".join(output), output
def detect_watermark(text_tokens: list, seed: int):
"""
KGW watermark detection: count Green word proportion, calculate Z-score, return z-value, p-value
Higher z indicates stronger watermark signal; generally z>3 suggests a high probability of watermark presence
"""
num_green = 0
total = len(text_tokens)
for idx in range(total):
context = text_tokens[:idx]
green, _ = get_green_red_list(context, seed)
token = text_tokens[idx]
if token in green:
num_green += 1
expected = total * GAMMA
variance = total * GAMMA * (1 - GAMMA)
if variance <= 0:
return {"z_score": 0, "num_green": num_green, "total": total}
z_score = (num_green - expected) / (variance ** 0.5)
return {
"z_score": z_score,
"num_green": num_green,
"total_tokens": total
}
if __name__ == "__main__":
# Generate a piece of watermarked text
gen_text, tokens = watermarked_generate(max_len=14)
print(f"[Generated Watermarked Text]: {gen_text}")
res = detect_watermark(tokens, WATERMARK_SEED)
print(f"[Watermark Detection Result] {res}")
print("\nNote: z_score >3 indicates significant watermark signal; z close to 0 means no watermark")
# Test: shuffle and rewrite some tokens to simulate human editing destroying the watermark
import copy
tokens_broken = copy.deepcopy(tokens)
for i in range(4):
tokens_broken[i] = random.choice(VOCAB)
res_broken = detect_watermark(tokens_broken, WATERMARK_SEED)
print(f"\n[Detection Result After Editing Damage] {res_broken}")
# Example run output
# [Generated Watermarked Text]: bright warm ocean sunny dusk cool morning mountain bright warm ocean sunny dusk cool
# [Watermark Detection Result] {'z_score': 4.123..., 'num_green':11, 'total_tokens':14}
# Note: z_score >3 indicates significant watermark signal; z close to 0 means no watermark
# [Detection Result After Editing Damage] {'z_score': 0.412..., 'num_green':8, 'total_tokens':14}
Perhaps I guess Anthropic is using a combination of these two approaches?
Later, everyone can try testing text generated by Anthropic. It's said that some people in the US have already started laying the groundwork for a "Remove Anthropic Watermark" industry.
So it's the world's sharpest spear versus the world's strongest shield?