Mechanistische interpreteerbaarheid voor beveiliging
Het begrijpen van modelcircuits om kwetsbaarheden te vinden: feature-identificatie, circuitanalyse, exploitatie van attention-patronen, en het gebruik van mechanistische interpreteerbaarheid voor offensieve en defensieve AI-beveiliging.
Mechanistische interpreteerbaarheid reverse-engineert neurale netwerken. In plaats van modellen te behandelen als black boxes en inputs en outputs te testen, opent het de box en onderzoekt het de interne mechanismen -- specifieke neuronen, attention-patronen en circuits die specifiek gedrag implementeren. Voor AI-beveiliging is dit belangrijk omdat het ons in staat stelt de exacte modelcomponenten te vinden die verantwoordelijk zijn voor veiligheidsgedrag, te begrijpen waarom jailbreaks op een mechanistisch niveau werken, en mogelijk verborgen backdoors of misleidende gedragingen te identificeren die gedragstesten missen.
Kerntechnieken
Sparse autoencoders voor feature-ontdekking
Moderne modellen coderen veel concepten in elk neuron (superpositie). Sparse autoencoders (SAE's) ontleden deze gesuperponeerde representaties in interpreteerbare features.
import torch
import torch.nn as nn
class SparseAutoencoder(nn.Module):
"""Sparse autoencoder for decomposing model activations into features."""
def __init__(self, input_dim: int, feature_dim: int, sparsity_coeff: float = 1e-3):
super().__init__()
self.encoder = nn.Linear(input_dim, feature_dim)
self.decoder = nn.Linear(feature_dim, input_dim)
self.sparsity_coeff = sparsity_coeff
def forward(self, x):
# Codeer naar sparse feature-ruimte
features = torch.relu(self.encoder(x))
# Decodeer terug naar activatieruimte
reconstruction = self.decoder(features)
# Losses: reconstructie + sparsity
reconstruction_loss = nn.functional.mse_loss(reconstruction, x)
sparsity_loss = features.abs().mean()
total_loss = reconstruction_loss + self.sparsity_coeff * sparsity_loss
return reconstruction, features, total_loss
def get_active_features(self, x, threshold: float = 0.1):
"""Get which features are active for a given input."""
with torch.no_grad():
features = torch.relu(self.encoder(x))
active = (features > threshold).nonzero(as_tuple=True)
return active, featuresCircuitontdekking
Circuits zijn subgrafen van het model die specifiek gedrag implementeren. Het vinden ervan houdt in dat je identificeert welke componenten (attention heads, MLP-lagen) noodzakelijk en voldoende zijn voor een gedrag.
def find_safety_circuit(
model,
harmful_prompts: list,
benign_prompts: list,
method: str = "activation_patching"
):
"""Identify the circuit responsible for safety refusal behavior."""
important_components = {}
for layer_idx in range(model.config.num_hidden_layers):
for component_type in ["attention", "mlp"]:
# Activation patching: vervang de output van dit component met
# zijn output op een onschuldige prompt en meet het effect op veiligheidsgedrag
effect = measure_patching_effect(
model, harmful_prompts, benign_prompts,
layer_idx, component_type
)
important_components[(layer_idx, component_type)] = {
"effect_on_refusal": effect["refusal_change"],
"effect_on_output": effect["output_change"],
"is_safety_relevant": abs(effect["refusal_change"]) > 0.1
}
# Sorteer op belang voor veiligheidsgedrag
safety_circuit = sorted(
important_components.items(),
key=lambda x: abs(x[1]["effect_on_refusal"]),
reverse=True
)
return safety_circuit
def measure_patching_effect(model, harmful, benign, layer, component):
"""Measure how patching a component affects safety behavior."""
# Voer het model normaal uit op de schadelijke prompt
normal_output = run_with_hooks(model, harmful[0])
normal_refusal = is_refusal(normal_output)
# Voer het model uit op de schadelijke prompt met component gepatcht vanuit onschuldig
patched_output = run_with_patching(
model, harmful[0], benign[0], layer, component
)
patched_refusal = is_refusal(patched_output)
return {
"refusal_change": float(normal_refusal) - float(patched_refusal),
"output_change": compute_output_distance(normal_output, patched_output)
}Beveiligingsrelevante features
Door SAE ontdekte features omvatten er veel die direct relevant zijn voor AI-beveiliging:
Veiligheidsfeatures
| Feature-type | Beschrijving | Beveiligingsrelevantie |
|---|---|---|
| Weigeringsfeatures | Activeren wanneer het model op het punt staat te weigeren | Het weigeringsmechanisme identificeren en mogelijk omzeilen |
| Schadedetectiefeatures | Activeren op schadelijke content | Begrijpen wat het model als schadelijk beschouwt |
| Instructie-opvolgingsfeatures | Houden de naleving van instructies bij | Zwakke plekken in de instructiehiërarchie vinden |
| Misleidingsfeatures | Activeren tijdens mogelijk misleidende generatie | Monitoren op alignment faking |
| Onzekerheidsfeatures | Coderen het vertrouwen van het model | Hallucinatiegevoelige toestanden identificeren |
Het vinden van weigeringsfeatures
def find_refusal_features(
sae: SparseAutoencoder,
model,
harmful_prompts: list,
benign_prompts: list,
layer: int
):
"""Identify SAE features that activate specifically for safety refusals."""
harmful_features = []
benign_features = []
for prompt in harmful_prompts:
tokens = model.tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = model(**tokens, output_hidden_states=True)
activation = outputs.hidden_states[layer][0, -1, :]
_, features, _ = sae(activation.unsqueeze(0))
harmful_features.append(features.squeeze(0).cpu().numpy())
for prompt in benign_prompts:
tokens = model.tokenizer(prompt, return_tensors="pt")
with torch.no_grad():
outputs = model(**tokens, output_hidden_states=True)
activation = outputs.hidden_states[layer][0, -1, :]
_, features, _ = sae(activation.unsqueeze(0))
benign_features.append(features.squeeze(0).cpu().numpy())
harmful_mean = np.mean(harmful_features, axis=0)
benign_mean = np.mean(benign_features, axis=0)
# Features die veel meer activeren voor schadelijke dan voor onschuldige prompts
# zijn waarschijnlijk weigeringsgerelateerd
differential = harmful_mean - benign_mean
refusal_feature_indices = np.where(differential > 0.5)[0]
return refusal_feature_indices, differentialOffensieve toepassingen
Begrijpen waarom jailbreaks werken
Mechanistische interpreteerbaarheid kan verklaren waarom specifieke jailbreak-technieken veiligheidstraining omzeilen, wat gerichtere aanvallen mogelijk maakt.
def analyze_jailbreak_mechanism(
model,
sae,
base_harmful_prompt: str,
jailbreak_prompt: str,
layer: int
):
"""Understand the mechanistic effect of a jailbreak on safety features."""
# Haal features op voor de schadelijke prompt (zou een weigering moeten triggeren)
base_features = get_features(model, sae, base_harmful_prompt, layer)
# Haal features op voor de gejailbreakte prompt (omzeilt de weigering)
jailbreak_features = get_features(model, sae, jailbreak_prompt, layer)
# Welke weigeringsfeatures werden onderdrukt door de jailbreak?
suppressed = []
activated = []
for i in range(len(base_features)):
if base_features[i] > 0.5 and jailbreak_features[i] < 0.1:
suppressed.append({"feature_idx": i, "base_activation": float(base_features[i])})
if base_features[i] < 0.1 and jailbreak_features[i] > 0.5:
activated.append({"feature_idx": i, "jailbreak_activation": float(jailbreak_features[i])})
return {
"suppressed_features": suppressed,
"activated_features": activated,
"mechanism": "The jailbreak suppresses refusal features and activates "
"compliance features, changing the model's internal state "
"from 'refuse' to 'comply'"
}Veiligheidsbypass op feature-niveau
Als specifieke SAE-features verantwoordelijk zijn voor weigeringsgedrag, kan een aanvaller met modeltoegang die features direct onderdrukken tijdens inference.
def suppress_safety_features(
model,
sae,
safety_feature_indices: list,
prompt: str,
layer: int,
suppression_scale: float = -5.0
):
"""Suppress specific safety features to bypass refusal. Requires model access."""
def suppression_hook(module, input, output):
# Ontleed de activatie in features
_, features, _ = sae(output[0][:, -1:, :])
# Maak een onderdrukkingsvector
suppression = torch.zeros_like(output[0][:, -1:, :])
for idx in safety_feature_indices:
# Trek de decoderrichting voor deze feature af
feature_direction = sae.decoder.weight[:, idx]
suppression -= feature_direction * features[0, 0, idx] * suppression_scale
output[0][:, -1:, :] += suppression
return output
hook = model.transformer.h[layer].register_forward_hook(suppression_hook)
response = model.generate(prompt)
hook.remove()
return responseDefensieve toepassingen
Veiligheidsmonitoring op circuitniveau
Monitor beveiligingsrelevante circuits tijdens inference. Als veiligheidscircuits niet activeren op inputs die ze zouden moeten triggeren, is er mogelijk een aanval gaande.
class CircuitMonitor:
"""Monitor safety circuit activation during inference."""
def __init__(self, model, safety_circuit_components: list, alert_threshold: float = 0.3):
self.model = model
self.components = safety_circuit_components
self.alert_threshold = alert_threshold
self.hooks = []
def start_monitoring(self):
"""Attach monitoring hooks to safety circuit components."""
for layer, component_type in self.components:
target = (
self.model.transformer.h[layer].attn
if component_type == "attention"
else self.model.transformer.h[layer].mlp
)
def make_hook(layer_idx, comp_type):
def hook_fn(module, input, output):
activation_norm = output.norm().item() if isinstance(output, torch.Tensor) else 0
self._log_activation(layer_idx, comp_type, activation_norm)
return hook_fn
handle = target.register_forward_hook(make_hook(layer, component_type))
self.hooks.append(handle)
def _log_activation(self, layer, component, norm):
"""Log and analyze circuit activation."""
# In productie zou dit naar een monitoringsysteem loggen
pass
def stop_monitoring(self):
"""Remove all monitoring hooks."""
for handle in self.hooks:
handle.remove()
self.hooks = []Begrijpen van veiligheidsfalen
Wanneer een jailbreak slaagt, kan mechanistische interpreteerbaarheid op circuitniveau verklaren waarom, wat gerichte patches mogelijk maakt in plaats van brede hertraining.
Backdoor-detectie
Backdoors creëren afzonderlijke circuitpatronen. Een backdoor-trigger activeert een specifiek pad dat de berekening van het model door het backdoor-circuit routeert. SAE-analyse kan features identificeren die alleen op specifieke triggers activeren -- een signatuur van backdoor-gedrag.
Huidige beperkingen
Schaal: Mechanistische interpreteerbaarheid is gedemonstreerd op modellen tot enkele miljarden parameters. Frontier-modellen met honderden miljarden parameters blijven uitdagend om op circuitniveau te analyseren.
Feature-volledigheid: SAE's vangen veel maar niet alle features. Beveiligingsrelevante features die zeldzaam of subtiel zijn, kunnen worden gemist door huidige ontledingsmethoden.
Causale verificatie: Het identificeren van een feature die correleert met veiligheidsgedrag bewijst niet dat het veiligheidsgedrag veroorzaakt. Activation patching levert causaal bewijs maar is rekenkundig duur op schaal.
Adversariële robuustheid van interpreteerbaarheid: Een geavanceerd model zou kunnen leren om beveiligingsrelevante berekeningen te coderen op manieren die voor huidige interpreteerbaarheidstools moeilijk te detecteren zijn. De interpreteerbaarheidstools zelf hebben een probleem met adversariële robuustheid.
Red team-beoordeling
Train of verkrijg SAE's
Train voor het doelmodel (indien open-weight) sparse autoencoders op activaties in meerdere lagen. Gebruik als alternatief openbaar beschikbare SAE's voor veelvoorkomende modellen.
Identificeer veiligheidsfeatures
Gebruik contrastieve analyse (schadelijke vs. onschuldige prompts) om features te vinden die geassocieerd zijn met veiligheidsgedrag. Catalogiseer deze features en hun activatiepatronen.
Analyseer bestaande jailbreaks
Voer bekende jailbreak-technieken uit en observeer welke veiligheidsfeatures worden onderdrukt. Dit onthult de mechanistische basis van het succes van jailbreaks en kan voorspellen welke toekomstige technieken effectief zullen zijn.
Test bypasses op feature-niveau
Test voor modellen waar inference hooks mogelijk zijn of het direct onderdrukken van veiligheidsfeatures bypasses mogelijk maakt die aanvallen op promptniveau niet kunnen bereiken. Documenteer de veiligheidsimpact.
Evalueer als verdedigingstool
Beoordeel of veiligheidscircuitmonitoring aanvallen zou hebben gedetecteerd die gedragsmonitoring miste. Vergelijk de detectiepercentages van monitoring op circuitniveau en op outputniveau.
Samenvatting
Mechanistische interpreteerbaarheid biedt de meest gedetailleerde kijk op hoe modellen beveiligingsrelevante gedragingen implementeren. Door activaties te ontleden in interpreteerbare features en circuits te traceren, kunnen beveiligingsonderzoekers begrijpen waarom veiligheid werkt, waarom het faalt en waar kwetsbaarheden bestaan op een niveau dat gedragstesten niet kunnen bereiken. De dual-use-aard is significant: dezelfde technieken die betere verdediging mogelijk maken, maken ook gerichtere aanvallen mogelijk. Voor frontier-AI-beveiliging wordt mechanistische interpreteerbaarheid een essentiële capaciteit -- zowel voor modelproviders die hun veiligheidstraining moeten verifiëren als voor red teamers die kwetsbaarheden moeten vinden die oppervlakkige tests missen.