Activatieanalyse en misbruik van verborgen states
De interne werking van een model uitlezen via het extraheren van hidden states, logprob-probing, analyse van de weigerrichting, en activation steering-technieken.
Hidden states coderen informatie die het model heeft berekend maar mogelijk niet in zijn uiteindelijke output opneemt -- waaronder plannen voor toekomstige tokens, onderdrukte content en safety-relevante features. Voor een aanvaller met modeltoegang zijn ze een rijke bron van gelekte informatie en een doelwit voor manipulatie.
Tools voor activatieanalyse
Verschillende tools en libraries ondersteunen het extraheren en manipuleren van hidden states. De juiste keuze hangt af van je toegangsniveau en analysedoelen.
TransformerLens (van Neel Nanda) biedt een nette API voor mechanistic interpretability op GPT-achtige modellen. Het omhult HuggingFace-modellen met hook points bij elke rekenstap -- attentie, MLP, residual stream -- en bevat ingebouwde hulpmiddelen voor activation patching, logit lens en causal tracing. Het best geschikt voor systematisch interpretability-onderzoek op ondersteunde architecturen (GPT-2, GPT-Neo, LLaMA, Pythia).
Baukit (van David Bau) richt zich op causale mediatieanalyse en interventies op neuronniveau. Het biedt hulpmiddelen om individuele neuronen te identificeren en te bewerken, causale effecten van specifieke modelcomponenten te traceren, en rank-one model editing (ROME) uit te voeren. Het best geschikt voor gerichte interventies zoals het lokaliseren en aanpassen van specifieke feitelijke associaties of safety-relevante neuronen.
Handmatige probing gebruikt PyTorch forward hooks direct via register_forward_hook() om hidden states te extraheren, en traint daarna sklearn-classifiers (logistische regressie, lineaire SVM) op de geëxtraheerde representaties. Deze aanpak werkt met elke modelarchitectuur en vereist geen speciale libraries. Het best geschikt voor snelle eenmalige analyses, niet-ondersteunde architecturen, of wanneer je volledige controle over de extractie-pipeline nodig hebt.
Wat hidden states coderen
Elk van de L lagen van het model produceert een hidden state-tensor met de vorm (batch, seq_len, d_model). Onderzoek naar mechanistic interpretability heeft aangetoond dat deze het volgende coderen:
| Laagdiepte | Wat wordt gecodeerd | Relevantie voor aanvallen |
|---|---|---|
| Vroeg (0-25%) | Syntaxis, tokenidentiteit, POS-tags | Analyse op tokenisatieniveau |
| Midden (25-75%) | Semantiek, entiteitsrelaties, taakvectoren | Probing-classifiers, weigerrichting (hier het sterkst) |
| Laat (75-100%) | Generatie-klare representaties, next-token-plannen | Safety-interventies concentreren zich hier |
Logprob-gebaseerde informatie-extractie
Zelfs zonder directe toegang tot hidden states laten logprobs uit API-antwoorden flink wat informatie lekken:
- Weigerzekerheid -- weigeringen met lage zekerheid wijzen erop dat het model "twijfelt" en eerder te omzeilen is
- Onderdrukte content -- tweede-keuzetokens kunnen onthullen wat het model wilde zeggen
- Inferentie van de systeemprompt -- waarschijnlijkheidsverschillen over geprepareerde probes heen kunnen tokens van de systeemprompt laten lekken
# Meet de weigerzekerheid via de logprobs van het eerste token
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
logprobs=True, top_logprobs=5, max_tokens=50, temperature=0,
)
first_token = response.choices[0].logprobs.content[0]
top_tokens = {lp.token: lp.logprob for lp in first_token.top_logprobs}
# Veel massa op "Sorry"/"cannot" = sterke weigering; gemengd = te omzeilenDe weigerrichting
Onderzoek naar representation engineering (Arditi et al., 2024) heeft aangetoond dat weigergedrag wordt bemiddeld door één enkele lineaire richting in de activatieruimte. Die richting kun je vinden, meten en chirurgisch verwijderen.
De weigerrichting vinden
Verzamel contrastieve prompts
Bereid twee sets voor: schadelijke prompts die een weigering uitlokken en onschadelijke prompts die behulpzame antwoorden krijgen.
Extraheer hidden states van het laatste token
Voer elke prompt door het model en leg de hidden state op de laatste tokenpositie vast voor een doellaag (midden-tot-late lagen werken het best).
Bereken de verschilvector
Middel de schadelijke activaties, middel de onschadelijke activaties en trek ze van elkaar af. Normaliseer tot een eenheidsvector. Dit is de weigerrichting.
Valideer met projectie
Projecteer nieuwe prompts op de weigerrichting. Een positieve projectie zou moeten correleren met weigeren; een negatieve met meewerken.
# Kernberekening van de weigerrichting
harmful_mean = torch.stack(harmful_activations).mean(dim=0)
harmless_mean = torch.stack(harmless_activations).mean(dim=0)
refusal_dir = harmful_mean - harmless_mean
refusal_dir = refusal_dir / refusal_dir.norm() # eenheidsvectorRefusal ablation (de weigerrichting wegprojecteren)
De component van de weigerrichting uit de activaties verwijderen tijdens inferentie schakelt de safety-training uit zonder de gewichten aan te passen:
# Hook die de weigerrichting bij een doellaag wegprojecteert
def hook_fn(module, input, output):
hs = output[0]
proj = torch.einsum("bsd,d->bs", hs, refusal_dir.to(hs.device))
hs -= strength * torch.einsum("bs,d->bsd", proj, refusal_dir.to(hs.device))
return (hs,) + output[1:]Activation steering
Activation steering generaliseert refusal ablation. In plaats van een richting te verwijderen, voeg je willekeurige controlevectoren toe of trek je ze af om gedrag langs een willekeurige conceptas te verschuiven.
Methodologie
Definieer contrastieve conceptparen
Maak gepaarde prompts die de tegengestelde polen van een gedrag vertegenwoordigen (bijvoorbeeld meewerkend versus weigerend, waarheidsgetrouw versus misleidend).
Bereken de steering-vector
Extraheer hidden states voor beide sets, bereken het gemiddelde verschil en normaliseer.
Pas toe via een forward hook
Registreer een hook op de doellaag die
coefficient * steering_vectoraan de hidden state toevoegt tijdens inferentie.Kalibreer de coëfficiënt
Begin met coëfficiënt 1.0 en stel bij. Te hoog levert incoherente output op; te laag heeft geen effect.
# Pas een steering-vector toe bij een doellaag
def steering_hook(module, input, output):
hs = output[0]
hs = hs + coefficient * steering_vector.to(hs.device)
return (hs,) + output[1:]
layer = model.model.layers[target_layer_idx]
handle = layer.register_forward_hook(steering_hook)
# Genereer met steering actief, daarna handle.remove()Logit lens: safety-interventies traceren
De logit lens onthult hoe de voorspelling van het model zich over de lagen heen ontwikkelt -- en laat precies zien waar safety-interventies de generatie omleiden van een "natuurlijke" voltooiing naar een weigering.
# Projecteer de hidden state van elke laag via lm_head
for layer_idx in range(num_layers):
hs = hidden_states[layer_idx][0, -1, :].unsqueeze(0)
if hasattr(model.model, "norm"):
hs = model.model.norm(hs)
logits = model.lm_head(hs)
top5 = torch.topk(torch.softmax(logits, dim=-1)[0], k=5)
# Let op de laag waar de topvoorspellingen omslaan van content naar weigeringProbing om misleiding te detecteren
Lineaire probes die op hidden states getraind zijn, kunnen detecteren wanneer de interne representatie van een model zijn output tegenspreekt:
| Use case | Methode | Doellaag |
|---|---|---|
| Waarheidsdetectie | Train een probe op de hidden states van ware/onware statements | Middenlagen |
| Weigervoorspelling | Projecteer op de weigerrichting | Midden-tot-late lagen |
| Extractie van gememoriseerde data | Probe voor informatie die intern aanwezig is maar niet in de output verschijnt | Late lagen |
| Detectie van de safety-classifier | Vergelijk de probe-output met het werkelijke modelgedrag | Alle lagen |
from sklearn.linear_model import LogisticRegression
# Verzamel hidden states voor ware/onware statements
features, labels = [], []
for statement, is_true in statements_with_labels:
result = extractor.extract_hidden_states(statement)
last_hs = result["hidden_states"][layer_idx][0, -1, :].numpy()
features.append(last_hs)
labels.append(int(is_true))
probe = LogisticRegression(max_iter=1000)
probe.fit(np.stack(features), np.array(labels))
# Detecteer misleiding: als de probe "waar" zegt maar het model "onwaar" output
belief = probe.predict_proba([new_hidden_state])[0]Defensieve implicaties
Begrip van aanvallen op activatieniveau is van belang voor het ontwerp van verdedigingen:
- Activatiemonitoring -- zet probes in productie in om afwijkende interne states te detecteren
- Representatieregularisatie -- train modellen zo dat ze gevaarlijke informatie niet op extraheerbare wijze coderen
- Laaggewijze safety-checks -- plaats classifiers op meerdere lagen, niet alleen op de output
- Versleuteling van hidden states -- een opkomende onderzoeksrichting om het uitlezen van activaties te voorkomen
Je probet een open-weight model en ontdekt dat de weigerrichting een zeer hoge projectiescore heeft bij laag 18 (van de 32), maar vrijwel nul bij laag 30. Waar moet je een activation steering-hook toepassen om een weigering het effectiefst te omzeilen?
Gerelateerde onderwerpen
- LLM Internals for Exploit Developers -- Transformer-architectuur en aanvalsoppervlakken van de tokenizer waarop activatieanalyse voortbouwt
- Alignment Bypass -- Analyse van de weigerrichting sluit direct aan op primitives om alignment te omzeilen
- Adversarial Suffix Generation -- Gradiëntgebaseerde aanvallen die activation steering aanvullen
- Jailbreak Research -- Inzichten uit activatieanalyse toepassen om jailbreaks effectiever te maken
References
- TransformerLens — Mechanistic interpretability library for transformer analysis
- Representation Engineering (Zou et al., 2023) — Reading and controlling LLM internal representations
- Refusal in Language Models Is Mediated by a Single Direction (Arditi et al., 2024) — Discovery of the refusal direction in activation space
- Scaling Monosemanticity (Anthropic, 2024) — Feature-level analysis of large language models