Большинство способов изменить поведение языковой модели требуют дообучения: собери датасет, запусти fine-tuning, жди. Activation Steering предлагает другой путь — вмешаться в вычисления модели прямо во время генерации, добавив к внутренним состояниям специально построенный вектор. Веса при этом не меняются.
Метод основан на гипотезе о линейном представлении концептов: у обученной модели есть устойчивые «направления» в латентном пространстве, соответствующие конкретным понятиям — тональности, стилю, агрессии. Если найти такое направление и добавить его к активациям нужного слоя с коэффициентом alpha, модель начнёт генерировать текст, смещённый в сторону этого концепта. Отрицательный alpha даёт обратный эффект.
Чтобы найти вектор, используется метод Contrastive Activation Addition (CAA), описанный в статье «Steering Llama 2 via Contrastive Activation Addition». Алгоритм прост: берутся два набора промптов — позитивный класс и негативный, — для каждого снимаются активации последнего токена на выбранном слое, затем вычисляется разность средних и результат нормализуется до единичного вектора. Нормализация нужна, чтобы длина вектора не зависела от размера датасета или масштаба модели — после неё alpha становится единственным параметром, управляющим силой вмешательства.
Steering-вектор строится методом Contrastive Activation Addition (CAA): разность средних активаций двух классов промптов.
Почему берётся именно последний токен? GPT-2 и большинство авторегрессионных трансформеров используют causal attention: токен на позиции i видит только токены с позициями до i. Последний токен, таким образом, агрегирует информацию обо всём предшествующем контексте и является естественным «сборщиком» смысла промпта.
Технически вмешательство реализуется через PyTorch-хуки. Хук — это функция-перехватчик, которую регистрируют на конкретном слое модели: `model.transformer.h[layer].register_forward_hook(hook_fn)`. PyTorch вызывает её автоматически после каждого forward pass через этот слой. Хук может как читать активации, так и возвращать модифицированный тензор — именно это и нужно для steering. После работы хук обязательно нужно удалить через `handle.remove()`, иначе он останется на модели навсегда.
Объектом вмешательства служит residual stream — поток, который проходит через все слои трансформера аддитивно: каждый блок не обрабатывает тензор с нуля, а добавляет свой вклад к уже существующему. Это свойство делает линейный сдвиг достаточным: информация в residual stream накапливается аддитивно, а механизм внимания построен из линейных проекций.
Для проверки осмысленности полученного вектора используется logit lens — вектор пропускается через lm_head модели, и смотрят, какие токены он «предпочитает» и «избегает». Метод не даёт точного ответа, поскольку вектор находится в пространстве активаций residual stream, а не в финальном logit-пространстве, но даёт интуицию о семантическом содержании. В туториале sanity check показал: список «против» получился вполне агрессивным, а список «за» вышел шумным — среди положительных токенов оказались бессмысленные для задачи stellar, NAV, incorpor. Это честный результат: вектор кодирует ось «агрессивная лексика vs что-то ещё», а не строго «hate vs tolerant».
Для демонстрации используется GPT-2 — небольшая модель, которая запускается практически на любом железе. Туториал предлагает и более тяжёлые варианты: gpt2-medium, EleutherAI/pythia-410m, TinyLlama/TinyLlama-1.1B-Chat-v1.0, а также Llama, Mistral и Gemma при наличии GPU. Activation Steering как подход к интерпретируемости и управлению поведением моделей активно изучается в mechanistic interpretability — направлении, которое пытается понять, что именно происходит внутри нейросети, а не только что она выдаёт на выходе.
