课程目录

第 5 课 · 动手学大模型(上海交大)

Model Watermarking

模型水印:给生成文本盖一个看不见的章

这一章处理一个越来越现实的问题:一段文本是不是机器写的?做法是在生成时就把水印嵌进去——人读不出来,算法检测得到。

学习目标

  • 水印嵌入:在语言模型生成内容时嵌入水印。
  • 水印检测:检测给定文本的水印强度。
  • 水印评估:评估水印方法的检测性能。
  • 评估水印的鲁棒性(可选)。

核心概念

教程用 X-SIR 代码仓库,里面实现了三种文本水印算法(X-SIR、SIR、KGW)和两种水印去除攻击(改写 paraphrase 与翻译 translation)。实操从最经典的 KGW 入手。

KGW 的思路是在每一步解码时,用上文的哈希把词表切成绿名单和红名单,然后偏向绿名单采样。检测端不需要模型的原始输出,只要用同一套哈希规则数一数绿词比例,算出 z-score:有水印的文本 z-score 会显著偏高,无水印的文本则接近随机基线。

评估的关键在于同时看两端。只测有水印文本的 z-score 说明不了问题——必须拿无水印文本做对照,才知道在给定阈值下的误报率有多高。鲁棒性评估则是把生成结果先改写或翻译一遍再检测,看水印还剩多少。

实践步骤

  1. 装好 X-SIR 的依赖,requirements.txt 里的版本是建议值,不是硬性要求。
  2. 把待输入的提示组织成 jsonl 文件,每行一个 json 对象,至少包含 prompt 键。教程用 data/dataset/mc4/mc4.en.jsonl,共 500 条,嫌慢可以自行缩减。
  3. 选模型和算法:baichuan-inc/Baichuan-7B--watermark_method kgw
  4. gen.py 生成带水印的内容,输出仍是 jsonl,response 字段是模型输出。
  5. detect.py 分别计算有水印文本和无水印文本的 z-score,输出到各自的 z_score.jsonl。
  6. 用两组 z-score 画分布、定阈值,算检测性能。
  7. 可选:对生成结果做 paraphrase 或 translation 攻击后重新检测,量化鲁棒性。

常见误区

  • 只跑嵌入不跑对照。 没有无水印基线,z-score 是个没有刻度的数。
  • 把阈值当常数。 阈值取决于文本长度和采样温度,短文本的 z-score 天然不稳。
  • 忽略生成质量。 水印强度和文本质量是一对权衡,只报检测率不报困惑度或人工评分,结论是片面的。

动手练习

用同一批提示生成两份结果:一份开水印,一份关水印。各算 z-score,画两条分布曲线,选一个阈值使误报率低于 1%,记录此时的检出率。然后把带水印的那份整体做一次改写攻击,重新检测,看检出率掉了多少。最后把生成长度从默认值砍半再来一遍,观察短文本对水印的影响。

要点回顾

水印是可验证的机制,不是承诺。嵌入端要看质量损失,检测端要看两类错误,鲁棒性端要看它扛不扛得住最常见的改写与翻译。三样都测过,才谈得上「这个水印能用」。

参考来源

  • 上海交通大学《动手学大模型》系列编程实践教程,第五章「模型水印」:documents/chapter5,核验日期:2026-09-06。