メインコンテンツへ移動
AIチュートリアル

watermarks-removerでテキストとファイルからAI由来情報マークを削除

自分が所有するコンテンツでwatermarks-removerを使用する方法を紹介します。このチュートリアルでは、ローカル環境とDockerのセットアップ、テキストとファイルのクリーニング、HTTPリクエスト、オプションの検出と書き換え、バッチ処理、認証、高度な画像ツールについて説明します。

watermarks-removerでテキストとファイルからAI由来情報マークを削除

watermarks-removerとは?

watermarks-removerは、テキストやファイルを検査し、対応するAI由来情報マークを除去するためのPythonサービスおよびエージェントスキルです。自身が所有する素材のプライバシー保護とコンテンツの衛生管理を目的としています。

このプロジェクトでは、クリーニングを複数のレイヤーに分けています。レイヤーAでは、不可視Unicode文字、特殊な空白、双方向制御文字、タグ文字など、関連するテキストアーティファクトを決定論的に除去します。レイヤーBでは、エージェントによる書き換え、またはオプションのrewrite_text.pyフックを使って、統計的なトークンサンプリング型ウォーターマークに対処します。ファイルクリーナーは、C2PA、EXIF、XMP、オフィス文書のメタデータなど、対応するメタデータや文書プロパティを処理します。

このプロジェクトは、自身が所有している、または変更する権限を持つコンテンツにのみ使用してください。検出とクリーニングは別々の操作であり、一部のオプション検出器は研究用ツールで、ベンダーによる正式な検証システムではありません。

主な機能

  • 標準ライブラリを中核に採用: ローカルHTTPサービスとコアスクリプトにはPython 3.10以降が必要で、必須のPython依存関係はありません。
  • 幅広いファイル振り分け: 対応形式には、テキスト、HTML、Markdown、PNG、JPEG、WebP、AVIF、HEIC、BMP、GIF、TIFF、SVG、PDF、DOCX、XLSX、PPTX、EPUB、ODT、MP4、MOV、M4A、M4V、WAV、MP3が含まれます。
  • 統一コマンド: inspect_file.pyとclean_file.pyが対応形式を検出し、適切なパイプラインを選択します。
  • HTTP連携: Python実装を同梱しなくても、検査、検出、クリーニング、一括処理のエンドポイントを利用できます。
  • 安全性を高めた形式処理: テキストツールはバイナリファイルの可能性が高いファイルを拒否し、認識されない形式はunknownとして分類され、自動的にはクリーニングされません。
  • オプションの検出: 設定済みのテキスト検出器とSynthID画像スコアリングを、単独で、またはクリーニングの前後に実行できます。
  • オプションの高度なバックエンド: 別途インストールすることで、MarkLLM検証ハーネス、reverse-SynthIDスコアリング、CtrlRegenによるピクセル領域の画像処理に対応します。

サービスのインストールと起動

1. リポジトリをクローンする

git clone https://github.com/guillaumemeyer/watermarks-remover.git
cd watermarks-remover

2. 標準ライブラリHTTPサーバーを起動する

最も簡単なセットアップは、ローカルPythonサービスを使用する方法です。デフォルトではループバックで待ち受けます。

make serve

直接起動することもできます。

python3 service/scripts/server.py --host 127.0.0.1 --port 8765

サービスが利用可能か確認します。

curl -s http://127.0.0.1:8765/health

レスポンスにはok: trueとサービスのバージョンが含まれます。GET /capabilitiesで利用可能なオプションツールとバックエンドを確認できます。また、GET /openapi.jsonでは生成されたOpenAPI 3.0.3仕様を取得できます。

3. オプションのエージェントスキルをインストールする

エージェントスキルにはサービスの実装は含まれていません。HTTPサーバーを呼び出す薄いクライアントなので、スキルを使用する前にサービスを起動してください。

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

ユーザー全体で使うGrokをインストールする場合は、ホームディレクトリの下にリンクを作成します。

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

/remove-ai-marksで呼び出すか、対応するAIウォーターマークや来歴メタデータを除去するようエージェントに依頼します。サービスがhttp://127.0.0.1:8765にない場合は、WATERMARKS_SERVICE_URLを設定してください。

4. オプションのCursorテキスト専用スキルをインストールする

このリポジトリには、権限のある原稿、ドキュメント、Webコピー向けの自己完結型Cursorスキルも含まれています。ファイルメタデータ、画像、C2PA、HTTPサービス、外部モデルツールは対象外です。

python3 install_skill.py

Windowsではpy install_skill.pyを使用してください。--forceを指定しない限り、既存のインストールは保持されます。

コマンドラインからファイルを検査・クリーニングする

統一ファイルツールを使用する

スクリプトディレクトリ用の短い変数を設定し、対応ファイルを検査またはクリーニングします。

SCRIPTS=service/scripts

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
python3 "$SCRIPTS/clean_file.py" notes.docx -o notes.cleaned.docx

inspect_file.pyは、入力を変更せずに検出した種類と疑わしい内容を報告します。clean_file.pyはファイルを適切なクリーナーに振り分け、-oで指定したパスに結果を書き込みます。

レイヤーAのテキストアーティファクトをクリーニングする

既知のテキストファイルには、専用のテキストコマンドを使用します。

python3 "$SCRIPTS/inspect_text.py" draft.md
python3 "$SCRIPTS/clean_text.py" draft.md -o draft.cleaned.md --stats

--statsオプションを指定すると、決定論的なテキストクリーニングによって変更された内容が報告されます。

バイナリファイルをテキストツールに渡さない

テキストスクリプトは、ZIPコンテナ、PDF、画像、その他のバイナリデータと見られるファイルを拒否します。これにより、圧縮バイト列がテキストとしてデコードされ、破損したテキストとして書き戻されるのを防ぎます。

python3 "$SCRIPTS/inspect_text.py" report.docx

このようなファイルにはinspect_file.pyまたはclean_file.pyを使用してください。--force-textで保護を解除することもできますが、 rawバイト列を意図的にスキャンする場合にのみ使用してください。

同様に、統合クリーナーは unknown に分類されたファイルを拒否します。適切な場合は認識可能なファイル名拡張子を指定するか、--as text または --force-text を使ってテキスト処理を明示的に選択してください。

Layer B の書き換えフックを使用する

統計的テキスト透かしには、Unicode のクリーンアップではなく書き換えが必要です。デフォルトでは、書き換えスクリプトはプロンプトを表示するだけで、モデルを呼び出しません。

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

ループバックエンドポイントはデフォルトで許可されています。リモートモデルのエンドポイントには、WATERMARKS_REWRITE_ALLOW_REMOTE=1 または --allow-remote が必要です。API 認証情報は、コマンドライン引数ではなく、WATERMARKS_REWRITE_API_KEY を通じて指定してください。

HTTP API を呼び出す

1 つのファイルをクリーニングする

API は Base64 でエンコードされたファイルバイト列を受け取り、形式の振り分けを補助するために指定されたファイル名を使用します。

WM="http://127.0.0.1:8765"
curl -s -X POST "$WM/clean" \
  -H 'Content-Type: application/json' \
  -d "{\"file\": \"$(base64 < notes.md | tr -d '\n')\", \"name\": \"notes.md\"}"

成功したレスポンスには、検出された kind、Base64 エンコードされた cleaned ファイル、およびクリーニングの report が含まれます。

クリーニングせずに検査または検出する

構造検査には POST /inspect を、設定済みの透かし検出器には POST /detect を使用します。検出はオプトイン方式で、クリーニングとは別に実行されます。要求して設定しない限り、サービスがベンダーや外部の検出器 API を呼び出すことはありません。

curl -s -X POST "$WM/inspect" \
  -H 'Content-Type: application/json' \
  -d "{\"file\": \"$(base64 < notes.md | tr -d '\n')\", \"name\": \"notes.md\", \"detect\": true}"

前後の測定を行うには、クリーニングオプションで detect_before と detect_after を指定します。

{"file":"BASE64_DATA","name":"notes.md","options":{"detect_before":true,"detect_after":true}}

検出器の障害は fail-soft で処理されます。検出器が利用できない場合、タイムアウトした場合、またはエラーを返した場合、レポートには available: false が記録され、クリーニングは継続されます。

バッチを処理する

POST /inspect/batch と POST /clean/batch は、ファイルごとの同じパイプラインを通じて複数のエントリを処理します。デフォルトのリクエスト上限は 50 ファイルで、WATERMARKS_MAX_BATCH_FILES で変更できます。

{"files":[
  {"file":"BASE64_DATA_1","name":"notes.md"},
  {"file":"BASE64_DATA_2","name":"photo.png","options":{}}
]}

不正なバッチエントリには ok: false とエラーメッセージが返されますが、残りのエントリの処理は中止されません。

Docker でプロジェクトを実行する

公開されている core イメージには、サービス、クリーナー、ExifTool、qpdf、c2patool が含まれています。ローカルの core イメージをビルドし、ループバック経由でのみ公開します。

make docker-core-build
docker run --rm \
  -p 127.0.0.1:8765:8765 \
  --read-only \
  --tmpfs /tmp \
  watermarks-remover

コンテナ内でクリーナーを直接実行することもできます。

docker run --rm -v "$(pwd):/data" watermarks-remover \
  /app/scripts/clean_file.py /data/notes.md \
  -o /data/notes.cleaned.md

Docker Compose はデフォルトで core サービスのみを起動します。オプションのプロファイルを追加すると、研究用ハーネスや大容量画像バックエンドを起動できます。

docker compose up -d
docker compose --profile harness up -d
docker compose --profile heavy up -d
docker compose --profile harness --profile heavy up -d

make compose-check で実行中のスタックを検証できます。core のヘルスエンドポイントを確認し、有効化されたオプションサービスがヘルプコマンドを実行できることを検証します。

設定とセキュリティ

通常のテキストクリーニングに環境変数は必要ありません。オプション設定はリポジトリルートの .env ファイルにコピーできます。Docker Compose はこのファイルを自動的に読み込みます。

cp .env.example .env
docker compose up -d

このファイルは gitignore 対象であり、決してコミットしないでください。主な設定は次のとおりです。

  • WATERMARKS_SERVER_API_KEY は HTTP API にベアラー認証を要求します。
  • WATERMARKS_SERVICE_URL は、クライアントがサービスに接続する場所を指定します。
  • WATERMARKS_REWRITE_BACKEND、WATERMARKS_REWRITE_MODEL および関連変数は、Layer B モデルの直接呼び出しを設定します。
  • WATERMARKS_SYNTHID_SCORER_URL は、core サービスをオプションの SynthID 画像スコアリングサイドカーに接続します。
  • HF_TOKEN は、ゲート付きモデルを使用するオプションのバックエンドに、環境変数のみで Hugging Face トークンを提供します。

サーバーはデフォルトでループバックにバインドされ、信頼できるネットワークでの使用を想定しています。--host を変更してローカルマシンの外部に公開する場合は、WATERMARKS_SERVER_API_KEY を設定し、適切なネットワーク保護を追加してください。

高度なヒント

ホスト側で実行するためのオプションのメタデータツールをインストールする

core の Python スクリプトは標準ライブラリを使用しますが、外部ツールによって特定のワークフローを改善できます。c2patool は C2PA マニフェストを検査し、exiftool は特に PDF から残存メタデータを削除し、qpdf は実際に PDF の構造を除去するために必要です。これらのツールはすでに core Docker イメージに含まれています。

SynthID クラスの画像シグナルをスコアリングする

オプションの reverse-SynthID 統合では、ピクセル領域の信頼度スコアを生成できます。これは検出専用であり、ピクセルウォーターマークを除去するものではありません。上流のチェックアウトは非商用の研究ライセンスを使用しているため、同梱されていません。

SCRIPTS=service/scripts
"$SCRIPTS/setup_synthid.sh"

REVERSE_SYNTHID_DIR=~/reverse-SynthID \
~/reverse-SynthID/.venv/bin/python \
"$SCRIPTS/inspect_image.py" shot.png

Heavy Compose プロファイルでは、このスコアラーを HTTP サイドカーとして実行できます。WATERMARKS_SYNTHID_SCORER_URL と共有の WATERMARKS_SYNTHID_SCORER_API_KEY を設定し、クリーニングの前後に検出をリクエストしてください。

ピクセル領域の処理には CtrlRegen を使用する

CtrlRegen は、SynthID 系、StegaStamp、Tree-Ring、StableSignature のピクセル領域マークに対応する、オプションの外部バックエンドです。上流リポジトリにライセンスファイルがないため、同梱も公開もされていません。セットアップでは、研究用途向けの固定された依存関係を使用する分離環境が作成されます。

SCRIPTS=service/scripts
"$SCRIPTS/setup_ctrlregen.sh"

NOAI_WATERMARK_DIR=~/noai-watermark \
~/noai-watermark/.venv/bin/python \
"$SCRIPTS/clean_image.py" shot.png \
-o shot.cleaned.png --remove-pixel ctrlregen

デフォルトの強度は控えめな 0.25 です。文書化されているプリセットの範囲は、最小限の再生成向けの 0.15 から、最大強度向けの 0.7 までです。値を大きくすると信号をより多く除去できますが、画像コンテンツの再生成量も増えます。

CtrlRegen は 512 × 512 ピクセルでネイティブに動作します。大きな入力は自動的にタイル分割されるため、処理時間とメモリ使用量はタイル数に応じて増加します。GPU を強く推奨します。モデルのダウンロード容量は約 10 GB を見込んでください。また、可能な場合は非常に大きな画像を先に縮小してください。

MarkLLM で制御されたテキスト実験を検証する

オプションの MarkLLM ハーネスでは、対応する KGW または SynthID スキーム設定を使用して、テスト用テキストを生成し、再検出できます。制御された実験には便利ですが、ベンダーの判定結果を保証するものではなく、書き換えられたテキストをベンダーの検出器が拒否することを証明することもできません。

SCRIPTS=service/scripts
"$SCRIPTS/setup_markllm.sh"

意味のある結果を得るには、生成と検出で同じスキーム設定とキーを使用してください。

まとめ

watermarks-remover は、認可されたコンテンツから、サポート対象の来歴情報の付加領域を慎重に、形式を考慮しながらクリーニングするワークフローを提供します。まず統合インスペクションコマンドを使用し、可能な場合は決定論的な Layer A クリーニングを行い、必要な場合にのみ Layer B の書き換えを追加し、外部検出器やピクセルバックエンドは選択的に有効化してください。アプリケーション統合には、ローカル HTTP API と生成された OpenAPI 仕様が最も柔軟なインターフェースを提供します。