今天在 GitHub Trending 上看到一个有意思的项目:watermarks-remover,一句话描述就是——一个纯 Python 标准库实现的多厂商 AI 水印清除工具,支持文本和文件的 Unicode 层、统计采样层、C2PA 元数据层等多层次水印去除。

一、项目概述

watermarks-remover 由开发者 guillaumemeyer 开源,定位是帮助用户清除自己拥有内容的 AI 生成痕迹。它的核心目标并非"伪造人工创作",而是隐私与内容卫生——当你拥有某段文本或文件的版权,却不想附带 AI provenance 信息时,这个工具可以帮你处理。

项目覆盖的 AI 厂商和生态系统包括:

  • Claude(Anthropic)
  • Gemini / SynthID-Text(Google)
  • OpenAI provenance surfaces
  • Open-LLM(Kirchenbauer 风格水印等开源模型)

支持的输入格式覆盖文本层和文件层:

通道覆盖内容
Unicode 隐匿字符层(Layer A)零宽字符、双向文本控制符、Tag 字符、特殊空格等
统计采样水印层(Layer B)基于 token 采样偏差的文本水印
文件元数据层C2PA / EXIF / XMP / Office 文档属性

支持的容器格式:PNG、JPEG、SVG、PDF、DOCX、ODT、HTML、Markdown。

最新版本为 v0.3.2,已在 GitHub 获得持续更新,聚焦安全加固和供应链加固。

二、技术原理

2.1 双层清除架构

watermarks-remover 采用业界标准的双层水印模型,这也是 Institute of AI PM 指南 中推荐的分析框架:

  • Layer A(确定性清除):针对基于编辑手段注入的水印,通过正则和字符串操作直接移除 Unicode 零宽字符、Bidi 控制符、Tag 字符等。这类水印有确定性的检测和清除方法。

  • Layer B(统计采样水印):针对分布在 token 选择中的采样偏差信号。由于信号分散在全篇文字中,没有万能清除手段,工具采用重写攻击(paraphrase attack)——通过让非原厂商模型对文本进行大幅度改写来稀释水印信号。这也是文献中的标准攻击方式。

工具在文档中坦诚指出:Layer B 是 best-effort 的,代价是内容质量退化。如果你本来就打算用更弱的模型重写,那直接用弱模型生成内容反而更简单。

2.2 核心脚本设计

项目以纯 Python stdlib(3.10+)为主,核心脚本位于 skills/remove-ai-marks/scripts/

统一文件处理入口:

# 统一 inspect / clean
python3 scripts/inspect_file.py draft.md
python3 scripts/clean_file.py draft.md -o draft.cleaned.md
python3 scripts/clean_file.py photo.png -o photo.cleaned.png

Layer A 文本检查与清除:

python3 scripts/inspect_text.py draft.md
python3 scripts/clean_text.py draft.md -o draft.cleaned.md --stats

Layer B 重写(可选,需外部模型):

# 默认仅打印 prompt(无需 API key)
python3 scripts/rewrite_text.py draft.md --backend print-prompt --strength paraphrase

# 可选接入 Ollama 本地模型
WATERMARKS_REWRITE_BACKEND=ollama WATERMARKS_REWRITE_MODEL=llama3.2 \
  python3 scripts/rewrite_text.py draft.md -o draft.rewritten.md

2.3 安全写入机制

v0.3.2 引入了原子写入(atomic write)机制,每次写入通过临时文件 + 重命名完成,拒绝符号链接目的地,防止预置符号链接攻击文件写入路径。同时通过 RLIMIT_AS/RLIMIT_FSIZE 对子进程(exiftool、c2patool、SynthID scorer)施加资源上限,防止恶意大文件耗尽系统资源。

# 安全写入示例(项目实际使用)
def safe_write_bytes(path: Path, data: bytes):
    tmp = path.with_suffix(path.suffix + '.tmp')
    tmp.write_bytes(data)
    tmp.rename(path)  # atomic on POSIX

2.4 可选 SynthID 像素评分

工具支持对图像进行 SynthID 置信度评分(来自 Google DeepMind),但仅用于检测/评分,不执行像素级水印移除。这需要额外 checkout 外部项目 aloshdenny/reverse-SynthID,通过 setup_synthid.sh 引导安装 venv 依赖:

./skills/remove-ai-marks/scripts/setup_synthid.sh
REVERSE_SYNTHID_DIR=~/reverse-SynthID \
  ~/reverse-SynthID/.venv/bin/python scripts/inspect_image.py shot.png

三、安装与快速开始

环境要求

  • Python 3.10+
  • 可选:c2patool(C2PA manifest 检查)
  • 可选:exiftool(PDF 元数据清除首选)
  • 可选:Ollama 或 OpenAI API key(Layer B 重写)

安装方式

作为 Agent Skill 安装(推荐用于 AI Agent):

mkdir -p ~/.grok/skills
ln -sfn "$(pwd)/skills/remove-ai-marks" ~/.grok/skills/remove-ai-marks

调用方式:对话中直接说 /remove-ai-marks 或"清除 AI 水印"。

作为独立脚本使用:

git clone https://github.com/guillaumemeyer/watermarks-remover.git
cd watermarks-remover
SCRIPTS=skills/remove-ai-marks/scripts

# 快速体验
python3 "$SCRIPTS/clean_text.py" tests/fixtures/sample_watermarked.txt \
  -o /tmp/cleaned.txt --stats

运行测试:

python3 -m venv .venv && .venv/bin/pip install pytest
.venv/bin/python -m pytest
# 或快速冒烟测试
make smoke

四、使用方法与实战

4.1 文本 Layer A 清除

# 检查文本中的 AI 水印
python3 scripts/inspect_text.py article.md

# 清除并查看统计
python3 scripts/clean_text.py article.md -o article.cleaned.md --stats

4.2 文件元数据清除

# 图像(PNG/JPEG)
python3 scripts/clean_file.py photo.png -o photo.cleaned.png

# PDF(需要 exiftool)
python3 scripts/clean_file.py document.pdf -o document.cleaned.pdf

# Office 文档
python3 scripts/clean_file.py report.docx -o report.cleaned.docx

4.3 Layer B 统计水印重写

# humanize 强度:消除 AI 风格措辞
python3 scripts/rewrite_text.py article.md \
  --strength humanize \
  -o article.rewritten.md

# code 强度:针对代码注释和文档字符串
python3 scripts/rewrite_text.py src.py \
  --strength code \
  -o src.clean.py

# 自定义 temperature 和候选数量
python3 scripts/rewrite_text.py article.md \
  --temperature 0.9 \
  --candidates 5 \
  -o article.rewritten.md

五、常见问题与解决方案

Q: Layer B 重写后内容质量下降明显?
这是不可避免的 trade-off。统计水印信号分布在 token 选择中,稀释信号需要实质性的词汇和句式改写。建议:如果你本来就打算用更弱的模型重写,直接生成即可,无需先让强模型生成再清除水印。

Q: PDF 清除效果不理想?
PDF 元数据清除强烈依赖 exiftool。未安装 exiftool 时,PDF 清除会降级。如果需要干净的 PDF,建议安装:brew install exiftool(macOS)。

Q: 如何避免重写时重新打上水印?
Layer B 应使用非原厂商模型重写。例如不要用 Claude 重写 Claude 生成的内容,这可能重新打上水印。项目推荐使用本地 open-weight 模型(Ollama)来避免这一问题。

Q: C2PA 硬绑定能否被清除?
不能。C2PA 的内容签名绑定在内容本身(而非元数据),仅移除元数据无法解除硬绑定的 Content Credentials。工具会报告已移除元数据,但不保证解除内容层的 provenance 链接。

Q: 项目支持 Docker 吗?
支持。SynthID scorer 有专用的 Dockerfile 构建:make docker-synthid-build

六、总结

watermarks-remover 是一款定位清晰、技术实现扎实的 AI provenance 清理工具。它的双层架构(确定性 Layer A + 统计 Layer B)对应了当前 AI 水印的两大技术路线,文档也诚实地说明了 Layer B 的局限性和质量代价。对于需要处理自己拥有内容的水印/元数据问题的开发者或研究者,这是一个值得关注的实用工具。

项目地址:github.com/guillaumemeyer/watermarks-remover