Introduction
In this tutorial, you'll learn how to implement invisible text watermarks using the SynthID-Text approach, similar to what Anthropic uses for Claude. This technique helps identify AI-generated content by embedding detectable patterns in text without affecting readability. We'll build a practical watermarking system that demonstrates core concepts of probability-based text watermarking.
Prerequisites
- Python 3.7+ installed
- Familiarity with basic Python programming concepts
- Understanding of probability distributions and text processing
- Basic knowledge of NLP concepts (tokenization, vocabulary)
Step-by-Step Instructions
Step 1: Set Up Your Environment
Install Required Libraries
We need several libraries to implement the watermarking system. The main dependencies are numpy for probability calculations and random for token selection.
pip install numpy
Create Project Structure
First, create a new directory for our watermarking project:
mkdir watermarking_project
cd watermarking_project
touch watermark_system.py
touch test_watermarking.py
Step 2: Implement Core Watermarking Functions
Create the Watermarking Class
We'll build a class that handles the core watermarking logic using probability distributions:
import numpy as np
import random
from collections import Counter
class SynthIDWatermarker:
def __init__(self, vocab_size=10000, watermark_probability=0.05):
self.vocab_size = vocab_size
self.watermark_probability = watermark_probability
self.watermark_tokens = []
def _get_probability_distribution(self, text):
# Generate a probability distribution for token selection
# This simulates the "synthetic" pattern that makes watermarks detectable
tokens = text.split()
token_counts = Counter(tokens)
# Create a weighted probability distribution
total_tokens = len(tokens)
probabilities = [token_counts[token]/total_tokens for token in tokens]
return np.array(probabilities)
def _insert_watermark_token(self, text, watermark_token):
# Insert watermark token at strategic positions
tokens = text.split()
if not tokens:
return text
# Insert watermark with specified probability
if random.random() < self.watermark_probability:
position = random.randint(0, len(tokens))
tokens.insert(position, watermark_token)
return ' '.join(tokens)
def watermark_text(self, text):
# Main function to watermark text
if not text:
return text
# Create a watermark token using vocabulary
watermark_token = f"[WM_{random.randint(1000, 9999)}]"
# Insert watermark token
watermarked_text = self._insert_watermark_token(text, watermark_token)
# Store watermark for detection
self.watermark_tokens.append(watermark_token)
return watermarked_text
def detect_watermark(self, text):
# Detect if text contains watermarks
tokens = text.split()
detected_tokens = []
for token in tokens:
if token.startswith('[WM_') and token.endswith(']'):
detected_tokens.append(token)
return len(detected_tokens) > 0, detected_tokens
Step 3: Build a Detection System
Implement Watermark Detection Logic
The detection system needs to identify patterns that indicate watermark presence:
def analyze_text_patterns(text):
# Analyze text for watermark-like patterns
tokens = text.split()
# Look for tokens that follow watermark pattern
watermark_patterns = []
for i, token in enumerate(tokens):
if token.startswith('[WM_') and token.endswith(']'):
# Check context around watermark
context = []
if i > 0:
context.append(tokens[i-1])
if i < len(tokens) - 1:
context.append(tokens[i+1])
watermark_patterns.append({
'token': token,
'position': i,
'context': context
})
return watermark_patterns
# Enhanced detection function
def enhanced_watermark_detection(text, watermark_tokens):
# More sophisticated detection using multiple heuristics
tokens = text.split()
detected = []
for i, token in enumerate(tokens):
if token in watermark_tokens:
detected.append({
'token': token,
'position': i,
'confidence': 0.9
})
return detected
Step 4: Test the Watermarking System
Create Test Script
Now we'll create a test script to demonstrate how the watermarking works:
from watermark_system import SynthIDWatermarker
# Initialize watermarker
watermarker = SynthIDWatermarker(vocab_size=5000, watermark_probability=0.1)
# Test text
original_text = "The quick brown fox jumps over the lazy dog. Artificial intelligence is transforming our world."
print("Original Text:")
print(original_text)
print()
# Apply watermark
watermarked_text = watermarker.watermark_text(original_text)
print("Watermarked Text:")
print(watermarked_text)
print()
# Detect watermark
has_watermark, watermark_tokens = watermarker.detect_watermark(watermarked_text)
print("Watermark Detection Result:")
print(f"Has watermark: {has_watermark}")
print(f"Detected tokens: {watermark_tokens}")
Step 5: Analyze Watermark Effectiveness
Measure Watermark Impact
Let's add analysis to understand how watermarks affect text quality:
def analyze_watermark_impact(original_text, watermarked_text):
original_tokens = original_text.split()
watermarked_tokens = watermarked_text.split()
# Calculate token count difference
token_difference = len(watermarked_tokens) - len(original_tokens)
# Calculate insertion rate
insertion_rate = token_difference / len(original_tokens) if original_tokens else 0
print(f"Original tokens: {len(original_tokens)}")
print(f"Watermarked tokens: {len(watermarked_tokens)}")
print(f"Token difference: {token_difference}")
print(f"Insertion rate: {insertion_rate:.2%}")
return insertion_rate
# Test impact analysis
original = "This is a test of watermarking technology."
watermarked = watermarker.watermark_text(original)
impact = analyze_watermark_impact(original, watermarked)
Step 6: Run Complete Test
Execute the Full System
Let's run a complete test to see the watermarking system in action:
# Complete system test
print("=== SynthID-Text Watermarking System Test ===")
# Test multiple texts
test_texts = [
"Machine learning models require large datasets for training.",
"Natural language processing enables computers to understand human language.",
"Deep learning networks can recognize complex patterns in data.",
"Neural networks are inspired by the human brain structure."
]
for i, text in enumerate(test_texts):
print(f"\nTest {i+1}:")
print(f"Original: {text}")
# Watermark
watermarked = watermarker.watermark_text(text)
print(f"Watermarked: {watermarked}")
# Detect
has_watermark, tokens = watermarker.detect_watermark(watermarked)
print(f"Detected: {has_watermark}, Tokens: {tokens}")
Summary
This tutorial demonstrated how to implement a text watermarking system based on the SynthID-Text approach used by Anthropic. You've learned how to:
- Create a watermarking class that embeds invisible tokens in text
- Implement detection logic to identify watermark presence
- Analyze the impact of watermarks on text quality
- Test the system with various text inputs
The key concept is using probability distributions to make watermark insertion statistically detectable while maintaining text readability. This approach helps comply with AI transparency regulations by allowing content to be identified as AI-generated without compromising the user experience.



