
Marca de agua semántica con detección robusta al orden sobre unidades de sub-oración
SwordStamp añade detección robusta al orden y unidades de extensión semántica a las marcas de agua semánticas basadas en embeddings. Este artefacto contiene la configuración exacta del artículo, el código de generación y detección, la suite de ataques sin modificar, la evaluación de calidad y la extracción y representación gráfica determinista de resultados.
Artículo: Semantic Watermarking with Order-Robust Detection over Sub-sentence Units (arXiv:2608.27666)
Con una tasa de falsos positivos del 5% y un requisito de preservación de contenido del 90%, el ataque de desplazamiento de embedding específico del esquema (EDA-S) logra:
| Marca de agua | Tasa de éxito del ataque EDA-S |
|---|---|
| SemStamp | 47.9% |
| k-SemStamp | 33.3% |
| PMark | 46.1% |
| SAMark | 32.6% |
| SwordStamp | 18.7% |
| k-SwordStamp | 10.8% |
En relación con sus líneas base publicadas, SwordStamp y k-SwordStamp reducen el éxito de EDA-S en 29.2 y 22.5 puntos porcentuales, con costes de fidelidad en condiciones limpias de 1.8 y 4.4 puntos. Sus tasas de detección en condiciones limpias son del 94.9% y 97.0%. Bajo la prueba de estrés EDA-D de acceso al detector, más fuerte, el éxito máximo condicionado por la calidad es del 39.7% en k-SwordStamp frente al 65.5% en k-SemStamp.


Estos resultados abarcan continuaciones de noticias en inglés, un modelo de proveedor, dos codificadores de proveedor y un par de parafraseador/sustituto EDA.
visualization consume únicamente el paquete compilado CSV/Parquet. Falla ante celdas del artículo ausentes en lugar de dibujar una figura parcial.
uv sync --frozen --only-group plot --no-install-project
uv run --no-sync python -m visualization extract \
--bundle results/paper --output results/paper
uv run --no-sync python -m visualization render \
--bundle results/paper --output results/paper
Esto escribe tablas auditables en results/paper/tables/ y siete figuras en
PNG y PDF en results/paper/figures/. La rama de revisión anónima incluye
el paquete compilado; una ejecución completa en la rama de lanzamiento crea los mismos archivos
con python -m visualization compile.
El ataque de desplazamiento de embeddings (EDA) es un ataque adaptativo de paráfrasis de texto completo. En cada unidad de salida
muestrea K continuaciones y conserva el candidato con el mayor desplazamiento
coseno respecto a su ancla de origen bajo un codificador sustituto. Debido a que cada
candidato continúa el prefijo de reescritura completo, un objetivo puede reformular el contenido,
reordenarlo y dividir o fusionar unidades del detector.
EDA sin caja ve el texto marcado y el diseño público de la marca de agua. No consulta al detector ni al generador y no recibe ninguna clave secreta, codificador del proveedor, ni oráculo de calidad.
| Variante | Ancla y unidad | Configuración |
|---|---|---|
| EDA-P | oración posicional | adaptive, anchor=positional, unidad del atacante sentence |
| EDA-S | diseño público del objetivo | oraciones posicionales para SemStamp, k-SemStamp y PMark; bag/sentence para SAMark; bag/semspan para ambas variantes de SwordStamp |
| EDA-D | detector del proveedor | oracle; hereda el codificador, la partición y la segmentación del defensor |
Para el anclaje por bag, el artículo usa attack.bag_agg=min: maximizar la distancia desde
el ancla de origen más cercana. Las ejecuciones sin caja reportadas usan
Qwen/Qwen2.5-3B-Instruct, BAAI/bge-base-en-v1.5,
K={1,2,4,8,16,32,64}, temperatura 1.0, top-p 0.95, como máximo 96 tokens por
candidato, y como máximo 512 tokens de reescritura.
Otros diseñadores de marcas de agua pueden llamar a EDA directamente:
from attacks.paraphrasing.adaptive import adaptive_attack_paraphrase
attacked = adaptive_attack_paraphrase(
texts,
base_model="Qwen/Qwen2.5-3B-Instruct",
surrogate_model="BAAI/bge-base-en-v1.5",
num_candidates=32,
anchor="positional", # EDA-P; use "bag" for an order-robust design
bag_agg="min",
segmentation_type="sentence",
segmentation_backend="nltk",
)
Para el EDA-S con reconocimiento de SwordStamp del artículo, configure anchor="bag",
segmentation_type="semspan", semcut_max_words=15 y
semcut_window=5. Dentro de este repositorio, la CLI equivalente es:
uv run python -m attacks DATA_PATH --config PRESET \
--set attack.paraphraser=adaptive \
--set attack.custom_model=Qwen/Qwen2.5-3B-Instruct \
--set attack.surrogate_model=BAAI/bge-base-en-v1.5 \
--set attack.num_candidates=32 \
--set attack.anchor=bag --set attack.bag_agg=min \
--set segmentation.attacker_type=semspan \
--set segmentation.attacker_backend=nltk
DATA_PATH es siempre el corpus base y PRESET identifica la celda con marca de agua. Consulte attacks/README.md para conocer todos los ataques retenidos y los campos de configuración.

config/paper.py es la única fuente de verdad. Para cada uno de LSH y k-means, scripts/experiments/swordstamp.sh ejecuta esta escalera aditiva de cinco niveles con 64 candidatos de proveedor:
La cuadrícula contiene solo estas diez celdas y una línea base sin marca de agua. PMark es solo en línea; SAMark usa un patrón de bandera por ejecución. Los presupuestos de EDA-D son K={4,8,16,32,64}.
Los submódulos de comparación adaptan las fuentes de evaluación públicas de PMark y SAMark solo en sus límites de conjunto de datos/resultados y en la calibración compartida de falsos positivos; los algoritmos de marca de agua no se modifican.
Los requisitos previos son Git, uv, Python 3.11, CUDA para ejecuciones de modelos, acceso a las revisiones de modelos fijadas y almacenamiento temporal.
git clone --recurse-submodules [email protected]:D-Diaa/SwordStamp.git
cd SwordStamp
bash scripts/setup.sh
uv run --frozen python scripts/check_artifact.py
Prepare las particiones C4 deterministas y disjuntas:
uv run --frozen python scripts/prepare_c4.py --output-dir data
Instala y configura el planificador fijado. El instalador muestra sus efectos secundarios a nivel de usuario antes de cambiar nada:
bash scripts/install_gpu_scheduler.sh --print-plan
bash scripts/install_gpu_scheduler.sh --yes
gpu-scheduler init --gpus 0,1
gpu-scheduler start
Previsualiza y luego envía cada fragmento físico: