
تنفيذ مرجعي لمخطط علامة مائية متعددة البتات لنماذج اللغة الكبيرة (LLM) باستخدام نشر الحمولة المشفّرة، وإعادة التوزين غير المتحيزة، وفك ترميز تصحيح الأخطاء (ECC) بالقرار الناعم لتضمين الرسائل واكتشافها في النص المُولَّد.
التنفيذ المرجعي لـ العلامة المائية متعددة البتات القوية والقابلة للتوسع لنماذج LLM عبر نشر الحمولة المشفرة.
يقوم WeaveMark بتضمين رسالة من k بت في النص المولّد بواسطة LLM مع الحفاظ على توزيع الرموز غير متحيز. يجمع بين نشر الحمولة المشفرة (κ بت من كلمة الشيفرة لكل رمز عبر ℓ طبقات، مع تعيين طبقة→بت يتم خلطه حسب السياق)، وفك تشفير ECC بالقرار الناعم من هوامش التصويت لكل بت، وإعادة وزن متعددة الطبقات غير متحيزة (كل اتجاه يُخضع لعملية XOR مع رمي عملة حسب السياق). الطبقات المخصصة ذات الصفر بت، المعزولة عن السياق بدلاً من الرسالة، تعطي كشفًا عن الوجود مستقلاً عن الرسالة.
weavemark/ مكتبة
watermark.py معالج logits الخاص بـ WeaveMark (التضمين)
extraction.py extract_bits, detect_zerobit
prf.py PRF بمفتاح (مشترك بين التضمين/الاستخراج)
data.py تحميل مجموعات البيانات، تجهيز المطالبات، سجلات JSONL
device.py فحص CUDA
ecc/ أجهزة فك ترميز Golay وReed-Muller والقرار الناعم
generate.py توليد نص بعلامة مائية / نص عادي
detect.py الاستخراج + درجة z للصفر بت + PPL
evaluate_downstream.py جودة التلخيص / الترجمة
perplexity.py مُقيّم PPL
attacks/ الاستبدال، DIPPER
run_*.py خطوط الأنابيب (توليد+كشف، هجمات، مهام لاحقة)
data/OpenGen.jsonl مطالبات OpenGen (--dataset opengen)؛ انظر الملاحظة أدناه
data/OpenGen.jsonl (معيار OpenGen العام القياسي) مستبعد من هذا الأرشيف بسبب الحجم؛ ضعه تحت data/ لاستخدام --dataset opengen. مجموعتا c4 وopenwebtext تُبثّان من Hub ولا تحتاجان إلى ملف محلي.
شغّل جميع البرامج النصية من جذر المستودع حتى يتم حل import weavemark.
يتطلب Python 3.10–3.12 وGPU من نوع CUDA (تُحمَّل النماذج بدقة 4-bit عبر bitsandbytes؛ لا يوجد مسار CPU). نموذج LLaMA-3-8B بدقة 4-bit يتسع في حوالي 16 جيجابايت.
cd WeaveMark
python -m venv .venv && source .venv/bin/activate # أو: conda create -n weavemark python=3.11
ثبّت إصدار CUDA من PyTorch قبل requirements.txt — فالأمر pip install torch العادي يعطي حزمة CPU فقط على Windows، ويجب أن تحتوي الحزمة على نوى (kernels) لبطاقة GPU الخاصة بك (سلسلة RTX 50 / sm_120 تتطلب torch ≥ 2.7 على CUDA ≥ 12.8؛ حزم cu121 الأقدم تتوقف عند sm_90 وتفشل وقت التشغيل). اختر الأمر المطابق من https://pytorch.org.
pip install torch --index-url https://download.pytorch.org/whl/cu128 # مثال: Blackwell
pip install -r requirements.txt
تحقق من أن GPU تشغّل النوى فعليًا (is_available() وحدها غير كافية — فهي تُرجع True حتى عندما تفتقر الحزمة إلى نوى للبنية):
python -c "import torch; t=torch.zeros(8).cuda().normal_(); print(torch.__version__, torch.cuda.get_device_capability(), (t*t).sum().item())"
LLaMA-3 وC4 مقيدان بالوصول: نفّذ huggingface-cli login واقبل شروطهما. يأتي OpenGen مع المستودع. اختر GPU باستخدام CUDA_VISIBLE_DEVICES=<i>.
python generate.py --method weavemark --ecc_method rm --random_message \
--dataset c4 --num_test 100 --max_new_tokens 200 \
--bpt 10 --num_layers 10 --window_size 2 --prob_delta 1.0 \
--num_zerobit_layers 0 --do_sample
python detect.py --data_dir output_dump/<run_folder> --detect --stride 25
يكتب detect.py ملفات detailed_eval_*.csv وsummary_eval_*.csv؛ الأعمدة الرئيسية هي success_rate ومع --zerobit_threshold، z_success_rate. يربط run_main.py بين التوليد والكشف (عدّل الثوابت في أعلاه).
مجموعات البيانات: c4 / openwebtext تُبثّان من Hub وتُقتطع إلى عدد كلمات --prompt_len؛ بينما يقرأ opengen ملف data/OpenGen.jsonl ويقتطع كل بادئة إلى عدد رموز --prompt_len.
ECC رسالة→كلمة شيفرة: golay 12→24، rm 16→32، dual_golay 24→48، dual_rm
32→64. none يضمّن --message بدون ترميز.
إعدادات الورقة: تتبع متعدد البتات يستخدم --bpt 10 --num_layers 10 --window_size 2 --prob_delta 1.0 --num_zerobit_layers 0، مع ECC حسب طول الرسالة؛ أضف
--num_zerobit_layers 2 --enable_zerobit للإعداد المدمج؛ الصفر بت النقي هو
--bpt 0 --num_layers 0 --num_zerobit_layers 10 --enable_zerobit.
python attacks/substitution.py --data_dir output_dump/<run> --ratios 0.1 0.2 0.3
python attacks/dipper_attack.py --data_dir output_dump/<run> --lex_diversity 20 --order_diversity 20
python detect.py --data_dir output_dump/<run> --text_file attacked_text_10.jsonl --detect --stride 999
يربط run_substitution.py / run_dipper.py بين الهجوم وكشف النص الكامل
(--stride 999 يقيّم كل مقطع كاملًا). يشغّل run_downstream.py
التلخيص (CNN/DailyMail) والترجمة (WMT16 en→ro) مع BERTScore +
ROUGE/BLEU.
window_size = 2: التصميم غير المتحيز يمنع إعادة استخدام سياق، لذا فإن نافذة
أكبر تقلل فقدان التخطي (انظر الملحق).no_watermark تعيد استخدام نفس المفاتيح/المعاملات لقياس معدل
الإيجابيات الكاذبة.@inproceedings{weavemark,
title = {Robust and Scalable Multi-bit LLM Watermarking via Coded Payload Spreading},
author = {Anonymous},
year = {2026},
note = {Under review}
}
attacks/dipper.py مُكيَّف من
martiansideofthemoon/ai-detection-paraphrases
(ينطبق ترخيصه على ذلك الملف). صدر بموجب MIT (انظر LICENSE)؛ عيّن
صاحب حقوق النشر قبل النشر.
| Flag | Symbol | المعنى | القيمة النموذجية |
|---|
--bpt | κ | بت لكل رمز | 10 |
--num_layers | ℓ | طبقات متعددة البتات | 10 |
--window_size | h | نافذة السياق | 2 |
--prob_delta | δ | قوة إعادة الوزن | 1.0 |
--ecc_method | — | none/golay/dual_golay/rm/dual_rm | rm |
--num_zerobit_layers | ℓ_z | طبقات الصفر بت | 0 أو 2 |
--top_k | K | أخذ العينات top-k | 50 |