SynthID Text 完整教學:AI 生成文字浮水印嵌入與偵測

SynthID Text (合成識別文字) 是 Google DeepMind 發表於 Nature 期刊的 AI watermarking (AI 浮水印) 技術參考實作。本教學涵蓋從原理到實務的完整流程,適用於需要辨識 AI-generated text (AI 生成文字) 的研究者、合規人員與開發者。


目錄

  1. 專案概述
  2. 核心架構與技術原理
  3. 安裝與環境設定
  4. 使用教學與範例
  5. 進階功能與最佳實踐
  6. 合規應用
  7. 常見問題與限制

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 專案基本資訊

項目內容
GitHubgoogle-deepmind/synthid-text
Stars912
Forks91
語言Python
授權Apache License 2.0 (程式碼) / CC-BY 4.0 (其他素材)
PyPIsynthid-text (v0.2.1)
論文 DOI10.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 則透過多層次的「錦標賽」結構,在不顯著改變輸出分布的前提下嵌入信號。

運作原理

  1. N-gram 上下文雜湊 (Context Hashing):取前 H 個 token 作為上下文 (context window),預設 ngram_len=5(即 H=4),用 LCG (Linear Congruential Generator; 線性同餘生成器) 計算 hash

  2. G 值指派 (G-value Assignment):對每個 (n-gram, key) 組合,雜湊後產生二元 G 值(0 或 1),決定每個 candidate token 被歸入「綠色組 (green list)」或「紅色組 (red list)」

  3. 機率重新分配 (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.pyupdate_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=5context_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
偵測器需要訓練實作框架準確度適用場景
MeanJAX快速原型、等長文本
Weighted MeanJAX中高不等長文本、加權深層
BayesianFlax/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 系統需求

項目最低需求建議配置
Python3.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 加速
RAM16 GB32 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  # 不可變字典

注意torchjax[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-distortionaryupdate_scores()N/A對輸出分布影響最小
Distortionaryupdate_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 值計算]
  1. EOS Token Mask:跳過 ngram_len - 1 個開頭 token(不足以形成完整 n-gram),並在 EOS token 後停止
  2. Context Repetition Mask:過濾重複出現的 n-gram 上下文,避免重複模式造成偏差
  3. 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_ktop_k=40 是效能與品質的平衡點
偵測階段用 CPUG 值計算不需要 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 實務建議

  1. 多層標記策略:SynthID 浮水印應搭配可見標記 (visible labels) 與 metadata 記錄使用,而非作為唯一標記手段
  2. 金鑰管理:將浮水印金鑰視為 organization secret,納入 key management system
  3. 定期校準:隨模型更新 (fine-tuning、版本升級),偵測閾值需重新校準
  4. 保留偵測紀錄:偵測結果 (score、threshold、版本) 應作為文件元資料保留
  5. 法律審查:在正式合規場景使用前,應諮詢法律與合規團隊對技術限制的評估

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

面向本 repoHF TransformersGoogle SynthID API
適用研究自架部署雲端服務
模型Gemma, GPT-2多數 HF 模型Gemini 系列
維護DeepMind (research)HF 社群Google
自訂性最高

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