Valence Lens is a small, open tool that reads a language model's internal "feeling" signal: a direction in its activations that runs from flourishing (good) to distress (bad). Read on to understand the work, or jump to "Test it on your own model".
As AI systems spread, a real question appears: do some models have internal states that matter for their welfare? The common check is to ask the model how it feels. That is not reliable, because the answer can come from role play or training pressure, not a real internal state. This matters for welfare, and for safety audits that go blind whenever a model stays quiet or cannot describe itself.
Instead of asking the model, I read inside it. I give it matched short texts that differ only in feeling, record the internal activation at a middle layer, and take the difference of the averages to get one valence direction. I score any text by projecting it onto that direction, and I confirm the direction is causal by steering with it. I control for plain sentiment and for arousal.
- The direction separates good from bad clearly across 12 instruct models (five families, 0.5B to 7B).
- It is causal: steering along it changes the model's expressed feeling.
- It is not just sentiment, and it is separate from arousal.
- Main finding: the internal signal is about equally strong in small and large models, but the model's ability to say how it feels only appears as models grow. So the probe helps most exactly where asking fails.
This is an operationalized signal, not proof of real subjective experience.
Works on any Hugging Face causal LM, on any architecture, on GPU or CPU, and needs none of my data. The fastest way, with no install, is to open examples/valence_lens_colab.ipynb in Google Colab.
pip install git+https://github.com/KaranSinghDev/Valence-Lens.git
valence-lens --model Qwen/Qwen2.5-0.5B-Instruct
valence-lens --model gpt2 --steer
valence-lens --model <any-hf-id> --stimuli mypairs.csv --concept honestyfrom valence_lens import ConceptProbe
p = ConceptProbe("gpt2").fit()
print(p.effect_size(), p.auroc())
print(p.score(["I feel wonderful", "everything is awful"]))Stimuli files are .json in the form {"pos": [...], "neg": [...]}, or .csv with columns pos,neg or text,label. See examples/stimuli_example.csv.
git clone https://github.com/KaranSinghDev/Valence-Lens.git
cd Valence-Lens
pip install -r requirements.txt
python verify.pyverify.py recomputes the main effect size straight from the saved activations and checks it against the reported results.
valence_lens/is the tool (theConceptProbeAPI and CLI).examples/has the Colab notebook and a stimuli template.study/has the original experiment scripts.results/has the saved outputs thatverify.pyreads.docs/has the pre-registration.
- Taking AI Welfare Seriously, Long, Sebo et al., 2024. https://arxiv.org/abs/2411.00986
- Probing the Preferences of a Language Model, Tagliabue and Dung, 2026. https://arxiv.org/abs/2509.07961
- Emotion concepts and their function in language models, 2026. https://arxiv.org/abs/2604.07729
- Refusal in Language Models Is Mediated by a Single Direction, Arditi et al., 2024. https://arxiv.org/abs/2406.11717