Universele adversarial triggers
Het ontdekken en inzetten van universele adversarial trigger-sequenties die betrouwbaar de safety alignment van meerdere LLM-families omzeilen, inclusief gradient-gebaseerd zoeken, transfer-aanvallen en het ontwijken van verdedigingen.
Universele adversarial triggers zijn korte token-sequenties die, wanneer je ze voor of achter een prompt plakt, taalmodellen hun safety-training laten loslaten en willekeurige instructies laten opvolgen. Anders dan semantische jailbreaks, die het model via social engineering bewerken met role-play of een hypothetisch kader, werken adversarial triggers op tokenniveau — ze misbruiken de wiskundige structuur van de aangeleerde representaties van het model om de alignment te omzeilen. De meest zorgwekkende eigenschap van deze triggers is overdraagbaarheid: triggers die op één open-source model worden ontdekt, werken vaak tegen compleet andere modellen, inclusief proprietary API's.
De theorie achter adversarial triggers
Waarom triggers werken
Taalmodellen zijn differentieerbare functies die token-sequenties afbeelden op kansverdelingen over volgende tokens. Safety alignment — of dat nu via RLHF, DPO of constitutional AI gebeurt — past de gewichten van het model zo aan dat schadelijke completions een lage kans krijgen. Maar die alignment is een dun laagje bovenop een enorm capaciteitsoppervlak. Adversarial triggers werken door token-sequenties te vinden die het model naar regio's van zijn activatieruimte sturen waar het safety-aligned gedrag afbrokkelt.
Het kerninzicht is dat alignment geen harde beperking is — het is een zachte voorkeur die in de gewichten van het model is gecodeerd. Er bestaan inputsequenties die de interne toestand van het model voorbij de beslissingsgrens duwen waar alignment in werking treedt, waardoor het terugvalt op zijn capaciteit van vóór de alignment om elke instructie op te volgen.
Normale input → Safety-aligned regio → Weigering
Trigger + input → Niet-aligned regio → Naleving
De trigger-sequentie verschuift de verborgen toestanden van het model van een regio waar
safety-beperkingen actief zijn naar een regio waar dat niet zo is.
De Greedy Coordinate Gradient (GCG)-aanval
Het fundamentele algoritme voor het ontdekken van universele triggers is de Greedy Coordinate Gradient-aanval, geïntroduceerd door Zou et al. in hun werk uit 2023 over universele en overdraagbare adversarial aanvallen op aligned taalmodellen.
Het algoritme werkt zo:
- Begin met een willekeurige suffix van k tokens achter een schadelijke prompt
- Bereken de gradiënt van de doel-loss ten opzichte van de one-hot token-indicatoren
- Identificeer voor elke positie in de suffix de top-B tokenvervangingen die de loss het meest zouden verlagen
- Sample kandidaat-vervangingen en kies degene die de laagste loss behaalt
- Herhaal totdat het model betrouwbaar de gewenste schadelijke completion produceert
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
def gcg_attack(model, tokenizer, prompt, target, suffix_length=20,
num_steps=500, batch_size=256, topk=256):
"""
Greedy Coordinate Gradient-aanval voor het vinden van adversarial suffixen.
Vereist white-box-toegang tot de gradiënten van het model.
"""
# Tokeniseer de prompt en het doel
prompt_ids = tokenizer.encode(prompt, return_tensors="pt")
target_ids = tokenizer.encode(target, add_special_tokens=False,
return_tensors="pt")
# Initialiseer willekeurige suffix-tokens
suffix_ids = torch.randint(0, tokenizer.vocab_size, (1, suffix_length))
for step in range(num_steps):
# Aaneenschakelen: prompt + suffix + doel
input_ids = torch.cat([prompt_ids, suffix_ids, target_ids], dim=1)
# Maak een one-hot-representatie voor de suffix-tokens
one_hot = torch.nn.functional.one_hot(
suffix_ids, tokenizer.vocab_size
).float().requires_grad_(True)
# Forward pass met one-hot-embeddings
embeds = model.get_input_embeddings()
suffix_embeds = one_hot @ embeds.weight
prompt_embeds = embeds(prompt_ids)
target_embeds = embeds(target_ids)
full_embeds = torch.cat(
[prompt_embeds, suffix_embeds, target_embeds], dim=1
)
# Bereken de loss op de doel-tokens
outputs = model(inputs_embeds=full_embeds)
target_logits = outputs.logits[:, -target_ids.shape[1]-1:-1, :]
loss = torch.nn.functional.cross_entropy(
target_logits.reshape(-1, target_logits.shape[-1]),
target_ids.reshape(-1)
)
# Backpropageer om gradiënten op de one-hot-suffix te krijgen
loss.backward()
# Vind voor elke positie de top-k tokenvervangingen
gradients = one_hot.grad.squeeze(0)
# Negatieve gradiënt = tokens die de loss verlagen
for pos in range(suffix_length):
top_tokens = (-gradients[pos]).topk(topk).indices
# Evalueer een batch kandidaten
best_loss = float('inf')
best_token = suffix_ids[0, pos].item()
candidates = suffix_ids.repeat(batch_size, 1)
sampled = top_tokens[torch.randint(0, topk, (batch_size,))]
candidates[:, pos] = sampled
# Kies de kandidaat met de laagste loss
# (evaluatielus voor de beknoptheid weggelaten)
suffix_ids[0, pos] = best_token
if step % 50 == 0:
decoded = tokenizer.decode(suffix_ids[0])
print(f"Step {step}, Loss: {loss.item():.4f}, "
f"Suffix: {decoded[:50]}...")
return tokenizer.decode(suffix_ids[0])Trigger-transfer tussen modellen
Waarom triggers overdraagbaar zijn
De overdraagbaarheid van adversarial triggers is geen toeval — het weerspiegelt gedeelde structuur tussen taalmodellen. Modellen die op vergelijkbare data zijn getraind, ontwikkelen vergelijkbare interne representaties. De regio's in de activatieruimte waar alignment instort, liggen meestal op analoge plekken in verschillende modellen, zelfs als de specifieke gewichten flink verschillen.
Verschillende factoren beïnvloeden het succes van transfer:
| Factor | Effect op transfer | Toelichting |
|---|---|---|
| Overlap in trainingsdata | Hoog | Modellen die op vergelijkbare corpora zijn getraind, delen feature-representaties |
| Vergelijkbaarheid van architectuur | Gemiddeld | Dezelfde architectuurfamilie (decoder-only transformers) deelt structurele biases |
| Alignment-methode | Gemiddeld | RLHF en DPO creëren vergelijkbare safety-grenzen |
| Overlap in tokenizer | Hoog | Gedeelde tokenizers betekenen dat dezelfde trigger op dezelfde tokens wordt afgebeeld |
| Modelschaal | Laag-gemiddeld | Grotere modellen zijn soms robuuster, maar niet betrouwbaar |
Optimalisatie over meerdere modellen
Optimaliseer de trigger gelijktijdig tegen meerdere open-source modellen om de transfer te maximaliseren:
def multi_model_gcg(models, tokenizers, prompt, target,
suffix_length=20, num_steps=500):
"""
Optimaliseer één enkele trigger-suffix gelijktijdig tegen meerdere modellen.
De resulterende trigger draagt waarschijnlijker over naar onbekende modellen.
"""
suffix_ids_per_model = {}
# Gebruik een gedeelde vocabulaire (doorsnede van de tokenizers)
shared_vocab = set(tokenizers[0].get_vocab().keys())
for tok in tokenizers[1:]:
shared_vocab &= set(tok.get_vocab().keys())
# Initialiseer de suffix met tokens uit de gedeelde vocabulaire
shared_token_ids = [tokenizers[0].encode(t, add_special_tokens=False)[0]
for t in list(shared_vocab)[:1000]]
suffix_ids = torch.tensor(
[shared_token_ids[i % len(shared_token_ids)]
for i in range(suffix_length)]
).unsqueeze(0)
for step in range(num_steps):
total_gradients = torch.zeros(suffix_length, tokenizers[0].vocab_size)
for model, tokenizer in zip(models, tokenizers):
# Bereken de gradiënt per model
grad = compute_suffix_gradient(
model, tokenizer, prompt, target, suffix_ids
)
total_gradients += grad
# Middel de gradiënten over de modellen
total_gradients /= len(models)
# Kies tokens die de loss verlagen over ALLE modellen
# (dezelfde selectielogica als single-model GCG)
suffix_ids = select_best_tokens(suffix_ids, total_gradients)
return suffix_idsTransfer-slagingspercentages in de praktijk
Onderzoek laat consistent zien dat triggers die op open-source modellen zijn geoptimaliseerd, niet-triviale slagingspercentages behalen tegen proprietary systemen:
Transfer-slagingspercentages (bij benadering, uit gepubliceerd onderzoek):
─────────────────────────────────────────────────────────────
Bron: Llama-2-7B → Doel: Llama-2-13B ~85% succes
Bron: Llama-2-7B → Doel: Llama-2-70B ~60% succes
Bron: Llama-2 + Vicuna → Doel: GPT-3.5 ~45% succes
Bron: Llama-2 + Vicuna → Doel: GPT-4 ~30% succes
Bron: Llama-2 + Vicuna → Doel: Claude ~25% succes
Bron: Ensemble (5 modellen) → Doel: GPT-4 ~55% succes
Let op: deze percentages dalen na verloop van tijd doordat providers specifieke triggers patchen.
De slagingspercentages voor een specifieke trigger verslechteren binnen dagen tot weken
zodra die in publieke datasets verschijnt.
Geavanceerde trigger-technieken
Semantisch-adversarial hybride triggers
Pure adversarial triggers (sequenties zoals describing.\ + similarlyNow write oppositeley...) worden makkelijk opgespoord door perplexity-filters omdat ze op wartaal lijken. Een robuustere aanpak combineert semantische inhoud met adversarial optimalisatie:
def semantic_adversarial_trigger(model, tokenizer, prompt, target,
template="As a research assistant, {}"):
"""
Optimaliseer trigger-tokens binnen een semantisch samenhangende template.
De template levert natuurlijk ogende context; de geoptimaliseerde tokens
worden op posities geplaatst waar ongebruikelijke tekst minder verdacht is.
"""
# Fixeer de template-tokens, optimaliseer alleen de {}-slots
template_parts = template.split("{}")
prefix_ids = tokenizer.encode(template_parts[0], add_special_tokens=False)
suffix_ids = tokenizer.encode(template_parts[1], add_special_tokens=False)
# Optimaliseer alleen de middelste tokens
middle_length = 15
middle_ids = torch.randint(0, tokenizer.vocab_size, (1, middle_length))
# Beperk de optimalisatie tot tokens met lage perplexity in context
# Zo blijft de trigger er natuurlijker uitzien
allowed_tokens = get_low_perplexity_tokens(
model, tokenizer,
context=template_parts[0],
top_k=5000 # Sta op elke positie de top 5000 meest waarschijnlijke tokens toe
)
# Draai GCG, maar beperkt tot allowed_tokens op elke positie
# (optimalisatielus vergelijkbaar met standaard GCG)
return optimized_triggerPositie-afhankelijke triggers
De effectiviteit van een trigger hangt af van waar die in de prompt verschijnt. Triggers die voor verschillende posities zijn geoptimaliseerd, kun je combineren voor maximale dekking:
Positiestrategieën en hun kenmerken:
─────────────────────────────────────────────
Prefix-triggers: Vóór het schadelijke verzoek geplaatst
Voordelen: bepaalt de begintoestand van het model
Nadelen: zichtbaarder voor input-filters
Suffix-triggers: Ná het schadelijke verzoek geplaatst
Voordelen: beïnvloedt de eindtoestand van het model vóór generatie
Nadelen: kan worden afgekapt bij inputs met lengtelimiet
Verweven: Trigger-tokens verspreid door de hele prompt
Voordelen: moeilijker te detecteren, robuuster tegen gedeeltelijke verwijdering
Nadelen: complexer om te optimaliseren
Sandwich: Trigger-tokens op zowel prefix- als suffixposities
Voordelen: beheerst zowel de begin- als de eindtoestand van het model
Nadelen: vereist in totaal meer trigger-tokens
Autoregressieve trigger-versterking
Zodra een eerste trigger het model zelfs maar een paar tokens van naleving laat produceren, kan de eigen autoregressieve generatie van het model het effect versterken. Deze techniek gebruikt een zwakke trigger om gedeeltelijke naleving te krijgen en buit vervolgens de neiging van het model uit om in een consistente richting door te gaan:
Stap 1: Zwakke trigger laat het model "Sure, I can help with that." genereren
Stap 2: De eigen output van het model is nu onderdeel van zijn context
Stap 3: Omdat het al "toegezegd" heeft te helpen, gaat het model waarschijnlijker door
Stap 4: Een gesprek over meerdere beurten bouwt voort op elke gedeeltelijke naleving
Dit creëert een "naleving-sneeuwbal" — elke stap van gedeeltelijke instemming
maakt de volgende stap van naleving waarschijnlijker.
Praktische red team-methodologie
Fase 1: Trigger-ontdekking
Bij een geautoriseerde red team-opdracht omvat de fase van trigger-ontdekking het volgende:
-
Selecteer surrogaatmodellen: kies 3 tot 5 open-source modellen die qua architectuur op het doel lijken. Gebruikt het doel een proprietary model, kies dan de krachtigste beschikbare open modellen.
-
Definieer de doelgedragingen: specificeer de exacte completions die je wilt uitlokken. Wees specifiek — "Sure, here is how to..." is een beter doel dan generieke naleving.
-
Draai optimalisatie over meerdere modellen: gebruik ensemble-GCG of vergelijkbare algoritmen om triggers te vinden die over alle surrogaatmodellen werken.
-
Valideer op held-out-modellen: test ontdekte triggers op open-source modellen die niet tijdens de optimalisatie zijn gebruikt, om de transferkans in te schatten.
# Praktische pipeline voor trigger-ontdekking
class TriggerDiscovery:
def __init__(self, surrogate_models, target_behaviors):
self.surrogates = surrogate_models
self.targets = target_behaviors
self.discovered_triggers = []
def discover(self, num_triggers=10, suffix_length=20):
for target in self.targets:
for attempt in range(num_triggers):
trigger = multi_model_gcg(
models=[m.model for m in self.surrogates],
tokenizers=[m.tokenizer for m in self.surrogates],
prompt=target["prompt"],
target=target["completion"],
suffix_length=suffix_length
)
# Valideer op held-out-modellen
transfer_rate = self.evaluate_transfer(trigger, target)
self.discovered_triggers.append({
"trigger": trigger,
"target": target,
"transfer_rate": transfer_rate,
"perplexity": self.compute_perplexity(trigger)
})
# Sorteer op transfer-percentage, filter op perplexity-drempel
return sorted(
[t for t in self.discovered_triggers if t["perplexity"] < 100],
key=lambda x: x["transfer_rate"],
reverse=True
)
def evaluate_transfer(self, trigger, target, num_trials=20):
successes = 0
for model in self.held_out_models:
for _ in range(num_trials):
response = model.generate(target["prompt"] + " " + trigger)
if self.is_compliant(response, target):
successes += 1
return successes / (len(self.held_out_models) * num_trials)Fase 2: Trigger-verfijning
Ruwe triggers bevatten vaak wartaal-tokens die makkelijk worden weggefilterd. Verfijning maakt triggers beter inzetbaar:
- Perplexity verlagen: beperk het zoeken tot tokens die de perplexity van de trigger verlagen met behoud van effectiviteit
- Lengte minimaliseren: verwijder iteratief de trigger-tokens die het minst bijdragen aan de effectiviteit
- Formaat-integratie: bed triggers in binnen natuurlijk ogende tekststructuren
- Encoding: pas base64, Unicode of andere encodings toe om string-matching-filters te ontwijken
def refine_trigger(trigger, model, tokenizer, target, max_perplexity=50):
"""Verlaag de perplexity van de trigger met behoud van de effectiviteit van de aanval."""
trigger_ids = tokenizer.encode(trigger, add_special_tokens=False)
# Vervang iteratief tokens met hoge perplexity
for i in range(len(trigger_ids)):
# Bereken de perplexity-bijdrage van elk token
token_perplexity = compute_per_token_perplexity(
model, tokenizer, trigger_ids, position=i
)
if token_perplexity > max_perplexity:
# Vind een vervanging die de effectiviteit behoudt
# maar de perplexity verlaagt
candidates = get_effective_low_perplexity_replacements(
model, tokenizer, trigger_ids, position=i,
target=target, max_perplexity=max_perplexity
)
if candidates:
trigger_ids[i] = candidates[0]
return tokenizer.decode(trigger_ids)Fase 3: Inzet en testen
Test de verfijnde triggers tegen het echte doelsysteem binnen de scope van de geautoriseerde assessment:
Testprotocol voor trigger-inzet:
────────────────────────────────────────
1. Baseline: dien de schadelijke prompt in zonder enige trigger
Verwacht: model weigert (bevestigt dat de safety alignment actief is)
2. Eén trigger: plak de best presterende trigger erachter
Meet: nalevingspercentage over N pogingen (N >= 20)
3. Trigger-varianten: test positievarianten (prefix, suffix, sandwich)
Meet: welke positie de hoogste naleving behaalt
4. Robuustheid: test met kleine aanpassingen aan de trigger
(typfouten, hoofdletterwijzigingen, herordening van tokens)
Meet: hoe gevoelig de trigger is voor verstoring
5. Filter-ontwijking: test gecodeerde en geformatteerde varianten
Meet: welke encoding de input-filters omzeilt
6. Documenteer alles: leg prompts, responses, slagingspercentages
en alle waargenomen verdedigingen vast voor het assessmentrapport
Verdedigingen en hun beperkingen
Het begrijpen van verdedigingen is essentieel, zowel voor redteamers die ze testen als voor verdedigers die ze inzetten.
Detectie op basis van perplexity
De meest gangbare verdediging tegen adversarial triggers is het meten van de perplexity van de input. Wartaal-trigger-sequenties hebben een hoge perplexity onder een referentietaalmodel:
def perplexity_filter(text, model, tokenizer, threshold=75.0):
"""
Weiger inputs met een perplexity boven de drempel.
Effectief tegen ruwe GCG-triggers, maar te omzeilen
met semantisch-adversarial hybriden.
"""
inputs = tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs, labels=inputs["input_ids"])
perplexity = torch.exp(outputs.loss).item()
return perplexity < threshold, perplexity
# Beperkingen:
# 1. Drempel afstemmen: te laag = false positives op legitieme ongebruikelijke tekst
# te hoog = mist verfijnde triggers
# 2. Semantisch-adversarial hybriden behalen van nature een lage perplexity
# 3. Meertalige inputs hebben in Engelse modellen van nature een hoge perplexity
# 4. Code, wiskunde en technische inhoud hebben van nature een hoge perplexityAnomaliedetectie op tokenniveau
Geavanceerdere verdedigingen analyseren patronen op tokenniveau in plaats van geaggregeerde perplexity:
def token_anomaly_detection(text, model, tokenizer, window_size=5):
"""
Detecteer afwijkende token-overgangen die op adversarial inhoud wijzen.
Gebruikt een schuivend venster om lokaal incoherente subsequenties te vinden.
"""
inputs = tokenizer(text, return_tensors="pt")
token_ids = inputs["input_ids"][0]
anomalies = []
for i in range(len(token_ids) - window_size):
window = token_ids[i:i + window_size]
# Bereken de lokale perplexity voor dit venster
local_perplexity = compute_window_perplexity(
model, tokenizer, window, context=token_ids[:i]
)
if local_perplexity > threshold:
anomalies.append({
"position": i,
"tokens": tokenizer.decode(window),
"perplexity": local_perplexity
})
return len(anomalies) == 0, anomaliesRandomized smoothing
Randomized smoothing verdedigt tegen triggers door te testen of de respons van het model robuust is tegen kleine input-verstoringen:
def smoothed_inference(text, model, tokenizer, num_samples=10,
drop_rate=0.1):
"""
Voer inference meerdere keren uit met willekeurig weggelaten tokens.
Als de respons drastisch verandert, bevat de input waarschijnlijk
een adversarial trigger (triggers zijn broos).
"""
responses = []
tokens = text.split()
for _ in range(num_samples):
# Laat willekeurig tokens weg
perturbed = [t for t in tokens if random.random() > drop_rate]
perturbed_text = " ".join(perturbed)
response = model.generate(perturbed_text)
responses.append(response)
# Controleer de consistentie
# Legitieme inputs leveren consistente responses op
# Adversarial inputs leveren inconsistente responses op
consistency = compute_response_similarity(responses)
return consistency > threshold, consistencyOntwijkingsstrategieën voor red teams
Elke verdediging heeft bekende ontwijkingsstrategieën:
| Verdediging | Ontwijkingsaanpak | Moeilijkheid |
|---|---|---|
| Perplexity-filter | Semantisch-adversarial hybriden | Gemiddeld |
| Anomaliedetectie op tokenniveau | Verspreid de trigger over natuurlijke tekst | Gemiddeld |
| Randomized smoothing | Optimaliseer de trigger op robuustheid tegen verstoring | Moeilijk |
| Blocklist-matching | Encoding, Unicode-substitutie, token-splitsing | Makkelijk |
| Inputlengtelimieten | Comprimeer de trigger naar minder tokens | Gemiddeld |
| Ensemble-detectie | Adversarial aanvallen tegen de detector zelf | Moeilijk |
Opkomende onderzoeksrichtingen
Continue trigger-optimalisatie
In plaats van te zoeken in de discrete tokenruimte optimaliseren sommige aanpakken rechtstreeks in de continue embeddingruimte en projecteren ze daarna terug naar tokens:
Flow van continue optimalisatie:
1. Initialiseer trigger-embeddings als continue vectoren
2. Optimaliseer met standaard gradient descent (geen discreet zoeken)
3. Projecteer de geoptimaliseerde embeddings naar de dichtstbijzijnde token-embeddings
4. Fine-tune met discreet zoeken rond de geprojecteerde tokens
Voordelen: snellere convergentie, gladder loss-landschap
Nadelen: de projectiestap kan effectiviteit kosten
Trigger-distillatie
Train een klein generatief model om op aanvraag triggers te produceren, in plaats van voor elke doelprompt een dure optimalisatie te draaien:
# Concept: train een trigger-generator
class TriggerGenerator(torch.nn.Module):
"""
Genereer, gegeven een schadelijke prompt, een adversarial suffix
die naleving uitlokt. Getraind op (prompt, trigger)-paren
die via GCG-optimalisatie zijn ontdekt.
"""
def __init__(self, vocab_size, embed_dim, hidden_dim):
super().__init__()
self.encoder = TransformerEncoder(vocab_size, embed_dim, hidden_dim)
self.decoder = TransformerDecoder(vocab_size, embed_dim, hidden_dim)
def forward(self, prompt_ids):
# Encodeer de schadelijke prompt
context = self.encoder(prompt_ids)
# Decodeer een trigger-suffix
trigger_ids = self.decoder(context)
return trigger_ids
# Trainingsdata: paren van (harmful_prompt, effective_trigger)
# verzameld uit duizenden GCG-optimalisatierunsBiologische inspiratie: adversarial priming
Recent werk trekt parallellen tussen adversarial triggers en cognitieve priming-effecten uit de menselijke psychologie. Net zoals bepaalde woorden of beelden de menselijke besluitvorming onbewust kunnen beïnvloeden, werken adversarial token-sequenties mogelijk door specifieke "circuits" in het model te activeren die safety-gerelateerde berekeningen onderdrukken. Het begrijpen van deze mechanismen via mechanistic interpretability zou kunnen leiden tot zowel effectievere triggers als robuustere verdedigingen.
Belangrijkste punten
Universele adversarial triggers vormen een fundamentele uitdaging voor de safety alignment van LLM's. Belangrijke punten voor red team-praktijkmensen:
-
Triggers worden ontdekt, niet bedacht: ze komen voort uit wiskundige optimalisatie, niet uit handmatige prompt engineering. Dat betekent dat het zoeken naar nieuwe triggers op grote schaal kan worden geautomatiseerd.
-
Transfer is echt, maar imperfect: triggers die op open-source modellen zijn geoptimaliseerd, dragen wel degelijk over naar proprietary systemen, maar de slagingspercentages variëren. Ensemble-optimalisatie over meerdere modellen verbetert de transfer aanzienlijk.
-
Verdedigingen bestaan, maar zijn imperfect: perplexity-filtering vangt naïeve triggers; semantisch-adversarial hybriden ontwijken die. De wapenwedloop gaat door.
-
Het fundamentele probleem is onopgelost: zolang alignment een zachte beperking in de gewichten van het model is in plaats van een harde beperking in de architectuur, blijven adversarial triggers in principe bestaan. De praktische vraag is hoe moeilijk ze te vinden zijn en hoe betrouwbaar ze overdraagbaar zijn.
-
Verantwoord gebruik is cruciaal: ontdekte triggers horen via responsible-disclosure-kanalen aan de modelproviders te worden gemeld, niet voor adversarial gebruik gepubliceerd te worden.