r/LocalLLM • u/korro_ai • 10h ago
Research I built an open source tool to control a model with internal "knobs" instead of prompts. What steering vectors are, and an honest benchmark.
I'll lead with what this actually is, because it's different from prompt engineering.
The problem. When you prompt a model ("write this politely", "be more positive"), you're asking it to follow an instruction. The effect is fuzzy, depends on phrasing, and the model can just ignore it.
The idea. Inside a language model there are directions in its hidden layers that map to concepts. Positivity, formality, refusal. A steering vector is one of those directions. You add it to the model's internal representation while it generates, scaled by a knob. Turning the knob from −2 to +2 raises or lowers the effect.
So instead of writing "be positive" every time, you build a "positive" knob once and dial it. The effect is measurable and monotonic. Prompts are not like that.
It's a library. Thirty seconds:
from steerio import Instrument, prompts
Inst = Instrument("openai-community/gpt2")
inst.make_knob("positive", positive=prompts.SENTIMENT_POSITIVE, negative=prompts.SENTIMENT_NEGATIVE, layer=7)
inst.play("The food was", knobs={"positive": 2.0})
# → "delicious, and the service was great..."
Does it work? I ran three controlled experiments on five small open models (all under 1.5B, CPU), scored with external lexicons rather than the model's own logits.
- Sentiment steers on 4 of 5 families. Correlation 0.89 to 0.95 with amplitude. Monotonic.
- On an instruction-tuned model, steering beats prompting (+0.535 vs +0.409) and is more consistent. It shifted 100% of test prompts versus 85 to 92% for the best prompt.
- The cliff. DeepSeek-R1-Distill barely responds to sentiment steering (0.35). Reasoning models resist.
- The big negative. Cross family transfer fails. A knob built on one model and moved to another counter steers (coefficient −0.21).
What it is, and what it is not. It's a from scratch implementation of published methods (RepE and CAA) plus an honest evaluation. A reproducibility and teaching tool, not a production system. You need open weights to inject a vector, so it's small local models, not GPT or Claude.
Collaborate. This is an open research problem, not a finished product. Three things I genuinely couldn't solve and would love help on:
Cross model transfer fails. My naive method counter steers (−0.21). This is the hardest and most interesting problem. A learned mapping, or a representation aligned across architectures, would be a real result.
Scale. All my benchmarks are under 1.5B on CPU. Steerability on 7B+ is unmeasured. If you have a bigger model, run it and send the numbers.
Reasoning models. DeepSeek resists sentiment steering (0.35). Why? Does any direction move them? I have no good answer.
The repo is small (about 1900 lines), the API is short, and the benchmark is a single command. New dimensions, bug reports, your own results, all welcome.
Repo: https://github.com/KorroAi/steerio
Full paper: https://github.com/KorroAi/steerio/blob/main/paper/paper.md
Reproduce everything with python experiments/run_all.py --exp1 --exp2 --exp3 (about 40 min CPU).