SynthID Text 完整教學:AI 生成文字浮水印嵌入與偵測
SynthID Text (合成識別文字) 是 Google DeepMind 發表於 Nature 期刊的 AI watermarking (AI 浮水印) 技術參考實作。本教學涵蓋從原理到實務的完整流程,適用於需要辨識 AI-generated text (AI 生成文字) 的研究者、合規人員與開發者。
目錄
1. 專案概述
1.1 什麼是 SynthID Text
SynthID Text 是 Google DeepMind 開發的 text watermark detection (文字浮水印偵測) 系統,其核心論文 “Scalable watermarking for identifying large language model outputs” 於 2024 年 10 月發表在 Nature (Vol. 634, No. 8035, pp. 818-823)。
該技術的目標是在 LLM (大型語言模型) 生成文字的取樣階段嵌入統計上可偵測、但人類不可感知的 watermark (浮水印),使後續可以判定一段文字是否由特定模型產生。
1.2 專案基本資訊
| 項目 | 內容 |
|---|---|
| GitHub | google-deepmind/synthid-text |
| Stars | 912 |
| Forks | 91 |
| 語言 | Python |
| 授權 | Apache License 2.0 (程式碼) / CC-BY 4.0 (其他素材) |
| PyPI | synthid-text (v0.2.1) |
| 論文 DOI | 10.1038/s41586-024-08025-4 |
| 建立時間 | 2024-10-23 |
| 支援模型 | Gemma (2B/7B IT)、GPT-2 |
1.3 定位與適用範圍
本 repo 是研究參考實作 (reference implementation),不適合直接用於 production。正式的 production-ready 實作已整合至 Hugging Face Transformers。
本教學的價值在於:
- 深入理解 tournament-based watermarking (錦標賽式浮水印) 的演算法細節
- 學習 Bayesian scoring (貝氏評分) 偵測器的訓練流程
- 為自建 AI content labeling (AI 內容標記) 系統提供參考架構
1.4 檔案結構總覽
1synthid-text/
2├── src/synthid_text/
3│ ├── synthid_mixin.py # Transformers mixin,嵌入浮水印
4│ ├── logits_processing.py # Logits 處理器核心(G 值計算、分數更新)
5│ ├── hashing_function.py # 累積雜湊函數(LCG 線性同餘生成器)
6│ ├── detector_bayesian.py # 貝氏偵測器(Flax/JAX)
7│ ├── detector_mean.py # 均值 / 加權均值偵測器(JAX)
8│ ├── g_value_expectations.py # 理論期望 G 值計算
9│ ├── logits_processing_test.py # 測試
10│ ├── synthid_mixin_test.py # 測試
11│ └── torch_testing.py # 測試輔助
12├── notebooks/
13│ ├── synthid_text_huggingface_integration.ipynb # 主要 Colab 範例
14│ └── testing_huggingface_integration.ipynb # 測試用 notebook
15├── data/
16│ └── human_eval.jsonl # 人類評估資料
17├── pyproject.toml # 套件設定與依賴
18└── README.md
2. 核心架構與技術原理
2.1 整體架構
SynthID Text 的運作分為兩個階段:嵌入 (embedding) 與偵測 (detection)。
flowchart TD
A[使用者 Prompt] --> B[LLM 推論]
B --> C{SynthID Mixin}
C --> D[Logits Processing
Tournament Sampling]
D --> E[帶浮水印的文字輸出]
E --> F{偵測階段}
F --> G[計算 G 值]
G --> H1[Mean Detector
均值偵測器]
G --> H2[Weighted Mean
加權均值偵測器]
G --> H3[Bayesian Detector
貝氏偵測器]
H1 --> I[分數 Score
0.0 ~ 1.0]
H2 --> I
H3 --> I
I --> J{閾值判斷}
J -->|高於閾值| K[判定:AI 生成]
J -->|低於閾值| L[判定:人類撰寫]
style C fill:#4285f4,color:#fff
style D fill:#4285f4,color:#fff
style H3 fill:#ea4335,color:#fff
2.2 Tournament-Based Sampling (錦標賽式取樣)
SynthID Text 的核心創新是 tournament sampling。傳統浮水印方案直接修改 token 機率,容易被偵測且影響生成品質。Tournament sampling 則透過多層次的「錦標賽」結構,在不顯著改變輸出分布的前提下嵌入信號。
運作原理
N-gram 上下文雜湊 (Context Hashing):取前
H個 token 作為上下文 (context window),預設ngram_len=5(即 H=4),用 LCG (Linear Congruential Generator; 線性同餘生成器) 計算 hashG 值指派 (G-value Assignment):對每個 (n-gram, key) 組合,雜湊後產生二元 G 值(0 或 1),決定每個 candidate token 被歸入「綠色組 (green list)」或「紅色組 (red list)」
機率重新分配 (Probability Reweighting):透過 tournament 結構,將部分機率從 G=0 的 token 轉移到 G=1 的 token,但維持整體分布的統計特性
flowchart LR
subgraph 取樣階段
direction TB
T1[Token 機率分布
P_LM] --> T2[G 值指派
G=0 or G=1]
T2 --> T3[Tournament
機率重分配]
T3 --> T4[修改後分布
P_watermarked]
end
subgraph 多層深度
direction TB
D1[Layer 1: key_1] --> D2[Layer 2: key_2]
D2 --> D3[...]
D3 --> D4[Layer D: key_D]
end
取樣階段 --> 多層深度
機率更新公式
核心的分數更新邏輯位於 logits_processing.py 的 update_scores() 函數:
1# 對每一層深度 (depth)
2for i in range(depth):
3 g_values_at_depth = g_values[:, :, i]
4 # 計算綠色組 (G=1) 的總機率質量
5 g_mass_at_depth = (g_values_at_depth * probs).sum(axis=1, keepdims=True)
6 # 機率重分配:保持整體期望不變
7 probs = probs * (1 + g_values_at_depth - g_mass_at_depth)
這個公式的關鍵性質:
- 質量守恒 (mass-preserving):重分配後所有 token 機率總和仍為 1
- 低失真 (low-distortion):當
g_mass接近 0.5 時,修改幅度最小 - 多層堆疊:
depth層的 key 提供冗餘,提升偵測穩健性
2.3 累積雜湊函數 (Accumulate Hash)
hashing_function.py 實作了基於 LCG 的雜湊:
1def accumulate_hash(current_hash, data,
2 multiplier=6364136223846793005,
3 increment=1):
4 for i in range(data.shape[-1]):
5 current_hash = (current_hash + data[..., i]) * multiplier + increment
6 return current_hash
此函數具有遞推性質 f(x, data[T]) = f(f(x, data[:T-1]), data[T]),適合在自迴歸生成中逐步計算。使用 newlib/musl 參數的 LCG,但不提供密碼學安全保證。
2.4 浮水印設定結構 (WatermarkingConfig)
1class WatermarkingConfig(TypedDict):
2 ngram_len: int # N-gram 長度 (預設 5, 即 H=4 上下文)
3 keys: Sequence[int] # 浮水印金鑰序列 (長度 = 深度)
4 sampling_table_size: int # 取樣表大小
5 sampling_table_seed: int # 取樣表種子
6 context_history_size: int # 上下文歷史追蹤大小
7 device: torch.device # 運算裝置
預設設定使用 30 個 key (即 depth=30),ngram_len=5,context_history_size=1024。
2.5 偵測器比較
graph TB
subgraph 三種偵測器
M["Mean Detector
均值偵測器"]
WM["Weighted Mean Detector
加權均值偵測器"]
B["Bayesian Detector
貝氏偵測器"]
end
M --> M1["優點:無需訓練
缺點:對短文本敏感"]
WM --> WM1["優點:無需訓練 + 層深度加權
缺點:閾值需經驗調整"]
B --> B1["優點:最高準確率
缺點:需訓練資料"]
style B fill:#ea4335,color:#fff
style WM fill:#fbbc04,color:#333
style M fill:#34a853,color:#fff
| 偵測器 | 需要訓練 | 實作框架 | 準確度 | 適用場景 |
|---|---|---|---|---|
| Mean | 否 | JAX | 中 | 快速原型、等長文本 |
| Weighted Mean | 否 | JAX | 中高 | 不等長文本、加權深層 |
| Bayesian | 是 | Flax/JAX | 最高 | Production 偵測 |
Weighted Mean 加權策略
預設使用線性遞減權重:從 10 到 1,讓淺層 (更靠近 prompt 的) 的 G 值貢獻更大:
1weights = jnp.linspace(start=10, stop=1, num=watermarking_depth)
2weights *= watermarking_depth / jnp.sum(weights) # 正規化
Bayesian Detector 訓練流程
sequenceDiagram
participant D as 訓練資料集
participant P as Logits Processor
participant T as Bayesian Trainer
participant M as 訓練完成的模型
D->>P: 浮水印文本 + 非浮水印文本
P->>P: 計算 G 值、遮罩
P->>T: (g_values, masks, labels)
T->>T: optimize_model()
Flax + Optax 最佳化
T->>M: detector 物件
Note over M: score() → [0, 1]
接近 1 = 浮水印文本
3. 安裝與環境設定
3.1 系統需求
| 項目 | 最低需求 | 建議配置 |
|---|---|---|
| Python | 3.9+ | 3.10 或 3.11 |
| GPU (Gemma 2B) | 16 GB VRAM (T4) | A10G / L4 |
| GPU (Gemma 7B) | 32 GB VRAM (A100) | A100 40GB |
| GPU (GPT-2) | 不需要 | 任意 GPU 加速 |
| RAM | 16 GB | 32 GB+ |
| 磁碟空間 | ~5 GB | ~15 GB (含模型權重) |
3.2 方法一:PyPI 安裝 (推薦快速上手)
1# 建立虛擬環境 (使用 uv 最佳)
2uv venv ~/.venvs/synthid
3source ~/.venvs/synthid/bin/activate
4
5# 安裝核心套件
6uv pip install synthid-text
7
8# 若需要執行 notebook
9uv pip install 'synthid-text[notebook]'
3.3 方法二:從原始碼安裝 (推薦研究用)
1# 建立虛擬環境
2uv venv ~/.venvs/synthid
3source ~/.venvs/synthid/bin/activate
4
5# 複製 repo 並安裝
6git clone https://github.com/google-deepmind/synthid-text.git
7cd synthid-text
8
9# 安裝含 notebook 相依套件
10uv pip install '.[notebook-local]'
11
12# 或安裝含測試相依套件
13uv pip install '.[test]'
3.4 關鍵相依套件
1torch==2.4.0 # PyTorch (嵌入階段)
2transformers==4.43.3 # Hugging Face Transformers
3flax # Flax (偵測器)
4jax[cuda] # JAX + CUDA (偵測器)
5numpy==1.26.0 # NumPy
6optax # Optax (最佳化器)
7scikit-learn # sklearn (交叉驗證)
8immutabledict==4.2.0 # 不可變字典
注意:
torch與jax[cuda]同時存在可能造成 CUDA 記憶體衝突。建議使用足夠 VRAM 的 GPU,或在 CPU 上執行偵測階段。
3.5 驗證安裝
1# 執行測試套件
2pytest .
3
4# 驗證匯入
5python -c "from synthid_text import synthid_mixin, logits_processing; print('OK')"
3.6 啟動 Jupyter Notebook
1# 從原始碼安裝後
2python -m notebook
3# 開啟 notebooks/synthid_text_huggingface_integration.ipynb
4. 使用教學與範例
4.1 Step 1:初始化模型與 Tokenizer
1import torch
2import transformers
3from synthid_text import synthid_mixin
4
5DEVICE = (
6 torch.device('cuda:0') if torch.cuda.is_available()
7 else torch.device('cpu')
8)
9MODEL_NAME = 'google/gemma-2b-it' # 或 'openai-community/gpt2'
10
11# 標準 Tokenizer
12tokenizer = transformers.AutoTokenizer.from_pretrained(MODEL_NAME)
13
14# SynthID 啟用的模型 (使用 Mixin 子類別)
15model = synthid_mixin.SynthIDGemmaForCausalLM.from_pretrained(
16 MODEL_NAME,
17 device_map='auto',
18 torch_dtype=torch.bfloat16,
19)
若使用 GPT-2,改用
synthid_mixin.SynthIDGPT2LMHeadModel。
4.2 Step 2:嵌入浮水印 (Watermark Embedding)
1INPUTS = [
2 "請說明深度學習在藥物開發中的應用",
3 "What are the key challenges in protein folding?",
4 "I enjoy walking with my cute dog",
5]
6TEMPERATURE = 0.5
7TOP_K = 40
8TOP_P = 0.99
9
10# 準備輸入
11inputs = tokenizer(
12 INPUTS,
13 return_tensors='pt',
14 padding=True,
15).to(DEVICE)
16
17# 生成帶浮水印的文字
18outputs = model.generate(
19 **inputs,
20 do_sample=True, # 必須啟用取樣 (非 greedy)
21 max_length=1024,
22 temperature=TEMPERATURE,
23 top_k=TOP_K,
24 top_p=TOP_P,
25)
26
27# 解碼
28generated_texts = tokenizer.batch_decode(outputs, skip_special_tokens=True)
29for text in generated_texts:
30 print(text)
31 print("---")
關鍵參數說明:
do_sample=True:必須使用取樣模式。Greedy decoding 無法嵌入浮水印temperature:必須在 (0.0, 1.0] 之間。溫度越高,浮水印信號越強但生成品質可能下降top_k:必須 >= 2。控制 vocabulary 中參與取樣的 token 數量
4.3 Step 3:偵測浮水印 (Watermark Detection)
方法 A:Weighted Mean Detector (無需訓練)
1from synthid_text import logits_processing, detector_mean
2import jax.numpy as jnp
3
4CONFIG = synthid_mixin.DEFAULT_WATERMARKING_CONFIG
5
6# 建立 Logits Processor (用於計算 G 值)
7logits_processor = logits_processing.SynthIDLogitsProcessor(
8 **CONFIG, top_k=TOP_K, temperature=TEMPERATURE
9)
10
11# 取得僅生成部分的 token
12inputs_len = inputs['input_ids'].shape[1]
13generated_only = outputs[:, inputs_len:]
14
15# 計算 EOS 遮罩 (End-of-Sequence mask)
16eos_token_mask = logits_processor.compute_eos_token_mask(
17 input_ids=generated_only,
18 eos_token_id=tokenizer.eos_token_id,
19)[:, CONFIG['ngram_len'] - 1:]
20
21# 計算上下文重複遮罩 (context repetition mask)
22context_repetition_mask = logits_processor.compute_context_repetition_mask(
23 input_ids=generated_only
24)
25
26# 合併遮罩
27combined_mask = context_repetition_mask * eos_token_mask
28
29# 計算 G 值
30g_values = logits_processor.compute_g_values(input_ids=generated_only)
31
32# 使用 Weighted Mean 評分
33scores = detector_mean.weighted_mean_score(
34 g_values=jnp.array(g_values.cpu().numpy()),
35 mask=jnp.array(combined_mask.cpu().numpy()),
36)
37
38# 輸出結果
39THRESHOLD = 0.5 # 需根據實際場景校準
40for i, score in enumerate(scores):
41 label = "AI 生成 (浮水印)" if score > THRESHOLD else "可能為人類撰寫"
42 print(f"文本 {i+1}: score={float(score):.4f} → {label}")
方法 B:Bayesian Detector (需訓練,最高準確度)
1import jax.numpy as jnp
2from synthid_text import detector_bayesian
3
4# 準備訓練資料 (需要浮水印文本 + 非浮水印文本)
5# train_g_values: shape [n_samples, seq_len, depth]
6# train_masks: shape [n_samples, seq_len]
7# train_labels: shape [n_samples] (1=浮水印, 0=非浮水印)
8
9# 訓練偵測器
10detector, loss = detector_bayesian.optimize_model(
11 jnp.squeeze(train_g_values),
12 jnp.squeeze(train_masks),
13 jnp.squeeze(train_labels),
14 jnp.squeeze(test_g_values),
15 jnp.squeeze(test_masks),
16 jnp.squeeze(test_labels),
17)
18
19# 使用訓練好的偵測器
20scores = detector.score(
21 g_values.cpu().numpy(),
22 combined_mask.cpu().numpy()
23)
24# scores: [0, 1] 之間,接近 1 = 高機率為浮水印文本
4.4 完整端到端流程圖
flowchart TD
subgraph 嵌入階段 Embedding
E1[載入 SynthID Model
SynthIDGemmaForCausalLM] --> E2[設定 WatermarkingConfig
keys, ngram_len, depth]
E2 --> E3[model.generate
do_sample=True]
E3 --> E4[帶浮水印的 token 序列]
end
subgraph 偵測階段 Detection
D1[建立 SynthIDLogitsProcessor
相同 CONFIG] --> D2[compute_g_values]
D2 --> D3[compute_eos_token_mask
+ context_repetition_mask]
D3 --> D4{選擇偵測器}
D4 -->|無訓練| D5[mean_score /
weighted_mean_score]
D4 -->|有訓練| D6[bayesian detector.score]
D5 --> D7[Score ∈ 0~1]
D6 --> D7
D7 --> D8{閾值比較}
end
E4 --> D1
style E1 fill:#4285f4,color:#fff
style D6 fill:#ea4335,color:#fff
5. 進階功能與最佳實踐
5.1 自訂浮水印金鑰 (Custom Keys)
預設設定使用 30 個硬編碼的 key。在實際部署中,必須使用密碼學安全的隨機金鑰:
1import secrets
2
3# 產生密碼學安全的金鑰
4num_layers = 30 # depth = 30
5custom_keys = [secrets.randbelow(1000) for _ in range(num_layers)]
6
7custom_config = {
8 "ngram_len": 5,
9 "keys": custom_keys,
10 "context_history_size": 1024,
11 "device": torch.device("cuda:0"),
12}
重要:嵌入與偵測必須使用完全相同的金鑰。金鑰遺失 = 無法偵測。
5.2 Distortionary vs. Non-Distortionary Watermarking
logits_processing.py 提供兩種模式:
| 模式 | 函數 | num_leaves | 特性 |
|---|---|---|---|
| Non-distortionary | update_scores() | N/A | 對輸出分布影響最小 |
| Distortionary | update_scores_distortionary() | 2 或 3 | 信號更強但可能影響品質 |
Distortionary 模式透過 num_leaves 參數控制 tournament tree 的分支數。理論期望 G 值:
num_leaves=2:E[G] = 0.5 + 0.25 * (1 - 1/V) ≈ 0.75 (大詞彙表)num_leaves=3:E[G] = 7/8 - 3/(8V) ≈ 0.875 (大詞彙表)
5.3 遮罩策略 (Masking Strategy)
正確的遮罩對偵測準確率至關重要:
flowchart LR
A[原始輸出序列] --> B[EOS Token Mask
移除 padding/EOS 後的 token]
B --> C[Context Repetition Mask
移除重複上下文的 token]
C --> D[Combined Mask
最終有效 token]
D --> E[G 值計算]
- EOS Token Mask:跳過
ngram_len - 1個開頭 token(不足以形成完整 n-gram),並在 EOS token 後停止 - Context Repetition Mask:過濾重複出現的 n-gram 上下文,避免重複模式造成偏差
- Combined Mask:兩者的交集,確保只使用有意義的 G 值
5.4 閾值校準 (Threshold Calibration)
偵測閾值的選擇直接影響 false positive rate (FPR; 偽陽性率) 和 true positive rate (TPR; 真陽性率):
1# 建議方法:在已知標籤的資料集上計算 ROC 曲線
2from sklearn.metrics import roc_curve, auc
3
4fpr_list, tpr_list, thresholds = roc_curve(true_labels, scores)
5roc_auc = auc(fpr_list, tpr_list)
6
7# 選擇特定 FPR 下的閾值
8target_fpr = 0.01 # 1% 偽陽性率
9idx = next(i for i, f in enumerate(fpr_list) if f >= target_fpr)
10optimal_threshold = thresholds[idx]
11print(f"At FPR={target_fpr}: threshold={optimal_threshold:.4f}, TPR={tpr_list[idx]:.4f}")
5.5 不同 Token 長度的閾值處理
論文 Appendix A.3.1 建議:使用 Weighted Mean detector 跨不同長度文本時,應針對特定 token 長度區間經驗性計算閾值或使用 weighted frequentist approach:
1# 依 token 長度分桶校準
2length_bins = [(50, 100), (100, 200), (200, 500), (500, 1024)]
3thresholds_by_length = {}
4
5for low, high in length_bins:
6 mask_lengths = combined_mask.sum(axis=1)
7 bin_mask = (mask_lengths >= low) & (mask_lengths < high)
8 bin_scores = scores[bin_mask]
9 bin_labels = labels[bin_mask]
10 # 在每個 bin 獨立校準
11 fpr, tpr, thresh = roc_curve(bin_labels, bin_scores)
12 thresholds_by_length[(low, high)] = thresh[next(
13 i for i, f in enumerate(fpr) if f >= 0.01
14 )]
5.6 批次處理效能建議
| 建議 | 說明 |
|---|---|
使用 torch.bfloat16 | 嵌入階段減半記憶體用量 |
設定合理的 top_k | top_k=40 是效能與品質的平衡點 |
| 偵測階段用 CPU | G 值計算不需要 GPU;JAX 偵測器可純 CPU 跑 |
| 批次大小 | 嵌入:受 VRAM 限制;偵測:可大批次 |
context_history_size | 預設 1024 足夠多數場景,增大會增加記憶體 |
6. 合規應用
6.1 AI 內容標記法規概覽
全球主要法規對 AI 生成內容標記的要求日益嚴格:
| 法規/標準 | 適用範圍 | 相關要求 |
|---|---|---|
| EU AI Act (2024) | 歐盟 | 高風險 AI 系統須具備可追溯性;生成式 AI 輸出須可標記 |
| 中國《生成式人工智慧服務管理暫行辦法》 | 中國 | 深度合成內容須添加標識 |
| 美國 Executive Order 14110 (2023) | 美國聯邦 | 聯邦機構須發展 AI 內容認證標準 |
| C2PA (Content Authenticity) | 全球產業標準 | 內容來源與歷程的技術規範 |
| 台灣《人工智慧基本法》(研議中) | 台灣 | 研議中的 AI 治理框架 |
6.2 SynthID Text 的合規定位
flowchart TD
subgraph 合規需求
R1[AI 內容可追溯]
R2[AI 內容可辨識]
R3[AI 內容不誤導]
end
subgraph SynthID Text 提供
S1[嵌入不可見浮水印]
S2[統計偵測 + 信心分數]
S3[低失真文字生成]
end
R1 --> S1
R2 --> S2
R3 --> S3
subgraph 不提供
N1[文字內容可見標記
如 disclaimer 聲明]
N2[密碼學驗證
數位簽章]
N3[防竄改保護]
end
style N1 fill:#ffcccb
style N2 fill:#ffcccb
style N3 fill:#ffcccb
6.3 醫藥文件合規場景 (Pharmaceutical Document Compliance)
在製藥產業中,AI 生成文字的合規標記尤為重要:
場景一:臨床試驗報告 AI 輔助撰寫
1情境:使用 LLM 輔助撰寫 CSR (Clinical Study Report; 臨床試驗報告)
2法規:ICH E3 guideline、各國 GCP
3需求:標記哪些段落由 AI 生成,確保可追溯
4SynthID 角色:嵌入浮水印 → 後續審計時可偵測 AI 生成段落
場景二:法規提交文件 (Regulatory Submissions)
1情境:AI 輔助準備 IND/NDA/BLA submission 文件
2法規:FDA 21 CFR Part 11、EMA eSubmission
3需求:確保文件來源可驗證、AI 貢獻可追蹤
4SynthID 角色:作為多層標記策略的一環
場景三:藥物安全報告 (Pharmacovigilance)
1情境:AI 自動生成 ICSR (Individual Case Safety Report; 個別案例安全報告)
2法規:ICH E2B(R3)、FDA MedWatch
3需求:區分人工審核 vs. AI 自動生成的內容
4SynthID 角色:嵌入浮水印作為內部追蹤機制
6.4 實務建議
- 多層標記策略:SynthID 浮水印應搭配可見標記 (visible labels) 與 metadata 記錄使用,而非作為唯一標記手段
- 金鑰管理:將浮水印金鑰視為 organization secret,納入 key management system
- 定期校準:隨模型更新 (fine-tuning、版本升級),偵測閾值需重新校準
- 保留偵測紀錄:偵測結果 (score、threshold、版本) 應作為文件元資料保留
- 法律審查:在正式合規場景使用前,應諮詢法律與合規團隊對技術限制的評估
7. 常見問題與限制
7.1 技術限制
| 限制 | 說明 |
|---|---|
| 僅限取樣模式 | Greedy decoding (do_sample=False) 無法嵌入浮水印 |
| 短文本偵測困難 | Token 數少於 50 時偵測準確率顯著下降 |
| 金鑰依賴 | 偵測必須持有嵌入時使用的完全相同金鑰 |
| 非密碼學安全 | accumulate_hash() 使用 LCG,不具備密碼學安全性 |
| 不防竄改 | 浮水印可能因文字修改(同義詞替換、重組)而損毀 |
| 模型特定 | 目前僅支援 Gemma 與 GPT-2 的 mixin;Production 用途應改用 HF Transformers 整合 |
| 跨實作差異 | 與論文數據存在微小偏差,因 Gemma/Mistral 跨實作的數值差異 |
7.2 常見錯誤與解決
Q1:ValueError: Invalid temperature ... when sampling with watermarking
1原因:temperature 超出 (0.0, 1.0] 範圍
2解法:確保 temperature 為正浮點數且 <= 1.0
Q2:ValueError: top_k has to be > 1
1原因:top_k 設為 1 或 0
2解法:top_k 必須 >= 2,建議使用 40
Q3:JAX 與 PyTorch CUDA 衝突
1原因:兩個框架同時佔用 GPU 記憶體
2解法:
3 (a) 嵌入階段用 GPU,偵測階段用 CPU JAX
4 (b) 設定 JAX_PLATFORMS=cpu 強制 JAX 使用 CPU
5 (c) 使用足夠 VRAM 的 GPU (如 A100 40GB)
1# 強制 JAX 使用 CPU
2export JAX_PLATFORMS=cpu
Q4:Bayesian detector 訓練資料不足
1原因:訓練集太小或不平衡
2解法:
3 - 浮水印 vs. 非浮水印文本至少各 1000 筆
4 - 使用相同 prompt 分布產生兩組
5 - 文本長度分布應與 production 場景一致
Q5:偵測分數偏低但確實使用了浮水印
1原因:可能的因素包括——
2 (a) 文本太短 (< 50 tokens)
3 (b) 遮罩設定不正確
4 (c) 嵌入與偵測的 CONFIG 不一致
5 (d) temperature / top_k 與嵌入時不同
6解法:逐項檢查 CONFIG 一致性,確認 combined_mask 有效
7.3 與 Production 方案的比較
graph LR
subgraph 本 Repo Reference Implementation
R1[研究重現]
R2[演算法理解]
R3[自訂實驗]
end
subgraph HF Transformers 整合
H1[Production Ready]
H2[更多模型支援]
H3[社群維護]
end
subgraph Google SynthID API
G1[Gemini / Vertex AI 內建]
G2[零設定]
G3[Google 維護]
end
R1 -.->|升級路線| H1
H1 -.->|雲端替代| G1
| 面向 | 本 repo | HF Transformers | Google SynthID API |
|---|---|---|---|
| 適用 | 研究 | 自架部署 | 雲端服務 |
| 模型 | Gemma, GPT-2 | 多數 HF 模型 | Gemini 系列 |
| 維護 | DeepMind (research) | HF 社群 | |
| 自訂性 | 最高 | 高 | 低 |
7.4 引用方式
如在學術論文中使用本工具或引用相關方法,請使用以下 BibTeX:
1@article{Dathathri2024,
2 author={Dathathri, Sumanth and See, Abigail and Ghaisas, Sumedh and ...},
3 title={Scalable watermarking for identifying large language model outputs},
4 journal={Nature},
5 year={2024},
6 volume={634},
7 number={8035},
8 pages={818-823},
9 doi={10.1038/s41586-024-08025-4},
10}
附錄:快速參考卡
1嵌入:SynthIDGemmaForCausalLM.generate(do_sample=True, temperature=0.5, top_k=40)
2偵測:SynthIDLogitsProcessor.compute_g_values() → detector_mean.weighted_mean_score()
3金鑰:30 個整數,嵌入與偵測必須一致
4分數:0.0 (人類) ← → 1.0 (AI 浮水印)
5限制:短文本 (<50 tokens) 偵測不可靠;非密碼學安全
6Production:改用 HF Transformers 整合或 Google SynthID API
Comments