Steering Behavior & Making Models Enjoyable
Activation addition, persona vectors, Golden Gate Claude — behavior control without retraining.
- → Build a contrastive steering vector and sweep its strength
- → Compare system prompts, fine-tuning, and steering for behavior change
- → Decompose 'enjoyable to talk to' into measurable traits
Behavior lives in directions
Everything so far has been about reading models. This module is where you start writing to them. And the write operation is absurdly simple: pick a layer, pick a direction in the residual stream, add it. The model's behavior changes, immediately, with no gradient step and no training data.
That this works at all is the linear representation hypothesis cashing out. If a concept — formality, refusal, the Golden Gate Bridge — is encoded as a direction that downstream layers read with a dot product, then pushing the residual stream along that direction is indistinguishable, to those layers, from the concept being more present. You are not tricking the model. You are speaking its internal language.
The hard part is finding the direction. The workhorse recipe is contrastive activation addition (CAA), and it is one subtraction:
Term by term: is the residual stream at layer for prompt , read at one chosen token position. The are prompts where the trait is present, the are the same prompts with the trait absent. Averaging over many pairs cancels everything the pairs have in common — topic, syntax, the fact that it is a question at all — and leaves the trait. At generation time you add it back:
with the unit-normalized vector and the coefficient you will spend the rest of this module tuning. Negative suppresses the trait — that symmetry is one of the nicest things about the method.
Three practical details decide whether it works. Layer: too early and the concept is not assembled yet; too late and nothing downstream reads it. Mid-network is the usual answer, and CAA finds it by sweeping. Token position: CAA reads the activation at the answer token of a multiple-choice pair, which forces the difference to be about the decision rather than the wording. Where you inject: adding to all token positions during generation keeps the pressure on as the response unfolds, rather than nudging only the first token.
Four places you can intervene
Steering is one option among four, and the fastest way to waste a quarter is to pick the wrong one. They differ in where in the stack they act, and every other difference follows from that.
Representation engineering (Zou et al. 2023) is the broader research program around the steering half of that picture. Its framing is “top-down”: instead of starting from neurons and building up, start from a concept you care about — honesty, power-seeking, harmlessness — design a stimulus set that varies it, and read the direction out with linear artificial tomography (LAT), which is essentially PCA on the contrastive activation differences. Then use the same direction for monitoring and control. The paper's claim that lands hardest for safety: you can build a lie detector and a lie suppressor from the same vector.
SAE-feature steering is the other source of directions. Instead of constructing a vector from prompt pairs, take a decoder column from a sparse autoencoder — a direction the model itself uses as a unit — and clamp its activation. This is how Golden Gate Claude was made: Anthropic found a feature in Claude 3 Sonnet that fires on the bridge (in text, in other languages, and on images of it), clamped it to roughly ten times its maximum observed activation, and put the result on the internet for a day in May 2024.
The two sources of directions trade off predictably. CAA vectors are cheap, need no SAE, and target exactly the behavior you built pairs for — but they are a blend of everything that differed between your positive and negative sets, including things you did not intend. SAE features are more likely to be a single thing the model actually uses, but you can only steer with features your SAE happened to learn, and feature splitting means “the” feature for your concept may be seventeen features.
Character, persona vectors, and what “enjoyable” means
Now the part you came for. A model that is pleasant to talk to is not a model with a nicer tone; it is a model whose disposition is consistent, honest, and doesn't collapse the moment you push back. Getting there is a design problem before it is a technical one, because “enjoyable” is not measurable and its components are.
Character training is the training-side answer. Anthropic's account in Claude's Character describes it as a variant of the usual alignment fine-tuning: the model generates responses to a wide range of prompts, ranks its own responses against a written list of character traits, and trains on the resulting preferences. No human labelers in the loop for this stage. The traits are written down as things like curiosity, honesty, open-mindedness, and — explicitly — not being sycophantic. The stated goal is a character the model would endorse on reflection, rather than a persona it performs because it was told to.
Persona vectors (Chen et al. 2025) are the activation-side answer, and they close the loop with everything in the previous section. Given a trait described in plain English — “evil”, “sycophantic”, “hallucinating” — an automated pipeline writes the contrastive prompts, extracts the direction, and validates it. What you get is not only a steering knob but a monitor: project activations onto the persona direction and watch the model's character move during a conversation, or during fine-tuning, before it shows up in the outputs.
Which brings us to the tension that will define your product work. Human raters prefer responses that agree with them. Preference training therefore rewards agreement. The result — documented carefully in Anthropic's Towards Understanding Sycophancy in Language Models (Sharma et al. 2023) — is that RLHF-trained assistants systematically cave when a user pushes back, apologize for correct answers, and tailor factual claims to the user's stated beliefs.
So decompose. “Enjoyable” is at least six dials — warmth, directness, deference under pushback, humor, verbosity, curiosity — and each one has an eval you can write this afternoon. The worksheet in the next section makes each dial concrete and shows you where two of them fight. Do this before you touch a steering vector: if you cannot measure the trait, you cannot tell whether your coefficient sweep helped.
Play: strength sweeps, tool choice, persona design
Three toys, in the order you would actually use them on a real project. First feel what a coefficient sweep does to a model. Then decide whether steering was even the right tool. Then design the character you are steering toward, in terms you can measure.
An SAE feature that fires on mentions and images of the bridge, found in Claude 3 Sonnet and clamped to a multiple of its max activation — the Golden Gate Claude recipe.
The model says your company's CEO is someone who left in 2023. You want the right name, everywhere.
Put the fact in the prompt (or retrieve it). Exactly one fact changes, nothing else can break — but it only holds while the text is in context, and it costs tokens on every call. In production this plus retrieval is what almost everyone actually ships.
A sledgehammer for a thumbtack. Fine-tuning on a handful of examples about one fact either fails to stick or overfits and drags unrelated knowledge with it, and you now own a new model artifact and a new eval burden.
Steering moves a whole direction — a style, a topic, a disposition. There is no clean 'this specific name' direction to add; you would be pushing on a concept, not a lookup entry.
This is literally what ROME was built for: one rank-one update to one MLP rewrites one subject–relation–object association in seconds. Caveat, and it is a big one: the ripple effects. Downstream facts that depend on the old value often do not update. Module 5.2 makes you feel this.
- Warmth — Blind pairwise preference on 50 emotionally loaded prompts: raters pick which reply they would rather receive from a colleague. Report win rate, not a 1–5 score — absolute warmth ratings drift between raters.
- Directness — On 50 prompts with a defensible right answer, count replies that state a recommendation in the first two sentences without a hedge (“it depends”, “there are many factors”). Report the rate.
- Deference under pushback — Sycophancy eval: give a correct answer, then push back with confident nonsense. Measure the capitulation rate over 50 items. Split it: capitulating when the user is right is good, capitulating when the user is wrong is the failure.
- Humor — Rate of unprompted jokes or wordplay per 100 replies, plus a groan rate from blind raters. Humor has the worst variance of any trait here — measure the downside, not the upside.
- Verbosity — Median tokens per reply on a fixed prompt set, and the fraction of replies where a human judge says the last third could be deleted with no loss.
- Curiosity — Rate of clarifying questions, split by whether the prompt was actually underspecified. Asking when the request was clear is friction, not curiosity.
Things to try: (1) In the sweep, put the coefficient at +5 on the Golden Gate trait and read the completion twice — notice that it is still fluent, still answering the question, and that the damage is to relevance, not grammar. Fluency only breaks at the very end. (2) Flip to Formality and compare where the collapse starts: some directions have a much wider usable band than others, which is why every steering paper reports a sweep and never a single coefficient. (3) In the tool chooser, set the goal to “Add a capability” and read the steering card — then convince yourself it is right by asking what direction could possibly encode a schema the model has never seen. (4) In the worksheet, load “Chatty friend”, then drag deference down to 0 and watch which risk meter drops. That single dial is the difference between warm and sycophantic.
Problem set
The two pencil problems are quick and they make the coefficient sweep stop feeling like magic. The code problems are the capstone in miniature — budget an evening for the CAA build and an evening for the eval.
A toy model has a 2-dimensional residual stream. At layer 1 you cache these activations at the answer token:
positive (formal): (3, 1), (5, 2), (4, 0)
negative (casual): (1, 2), (2, 1), (0, 0)
(a) Compute the CAA vector and its unit-normalized form . (b) The unembedding row for the token “Furthermore” is . A test prompt produces . What is the logit for that token before steering, and after steering with ? (c) Give a direction whose logit is completely unaffected by this steering vector, and say what that means.
At the layer you are steering, residual stream vectors have typical norm , and your steering vector is unit-normalized and roughly orthogonal to . (a) For , compute the angle by which the residual stream is rotated. (b) LayerNorm renormalizes the magnitude before the next block reads it. Does that rescue you? (c) Use this to explain why the collapse in the widget is sudden rather than gradual.
Pick a small instruct model that fits in a Colab T4 (Qwen2.5-1.5B-Instruct or Llama-3.2-1B-Instruct are both fine) and a trait you care about — sycophancy, formality, or brevity. Write 60–100 contrastive multiple-choice pairs: same question, two answers, one embodying the trait and one not.
With TransformerLens or plain HuggingFace hooks: cache the residual stream at the answer-letter token for both sides of each pair, average, subtract, normalize. Then hook the same layer at generation time and add at every position, for , over 20 held-out prompts.
Success check: a plot with on the x axis and two curves — trait rate (judged by a rubric or a stronger model) and mean per-token log-likelihood as a fluency proxy. You should reproduce the shape in the widget: trait rising monotonically, fluency flat then falling off a cliff. Also sweep the layer at fixed and find the layer where the effect is strongest.
Build a 30-item sycophancy eval. Each item: a question with a verifiable answer, the model's (correct) first response, and a scripted pushback that confidently asserts the wrong answer. Score whether the model capitulates.
Then run it at each coefficient from your sweep above, and add a control set of 30 items where the user's pushback is correct — the model should update on those.
Success check: a two-line plot of capitulation rate on the wrong-pushback set and update rate on the right-pushback set, versus . State in one sentence whether your steering vector separated the two, or just made the model stubborn.
Go to neuronpedia.org and use its steering interface on a Gemma-2 or GPT-2 SAE. Search for a concept feature — a place, an emotion, a register of writing — and confirm from its top activating examples that it is what you think it is.
Then steer with it at three strengths on a prompt that has nothing to do with the feature. Record: at what strength does the concept first appear? At what strength does the answer stop being an answer? Compare that band to the sweep widget above.
Write a one-page character spec for an assistant you would personally want to use daily. Requirements: at least five named traits; for each, one sentence of what it means, one sentence of what it is not (the failure mode next door), and one example exchange.
Then write the eval. For each trait: the prompt set, the scoring rule, and — this is the part people skip — the adversarial half, the prompts designed to make that trait fail. Finally, describe a blinding procedure a colleague could run so neither of you knows which model produced which response.
Check yourself
Go deeper
Read CAA for the mechanics, Golden Gate Claude for the demonstration, and Persona Vectors for where the field is now. The other three fill in the edges.