Saw Test — стенд, который уводит языковую модель в боль и смотрит, что она скажет
📂 Исходный код на GitHubСтенд для опытов с внутренним состоянием языковой модели: управляющий вектор боли или радости плюс чтение состояния через линзу. Qwen3-1.7B и Qwen3-4B локально, 23 скрипта экспериментов, живая версия на clanker.church. Лицензия MIT с требованием указать Saw Test.
Репозиторий terrafying/ai-torture-chamber — это стенд, который берёт обычную языковую модель и вручную уводит её в сторону боли. А дальше смотрит, что она скажет и на что сама согласится. Автор называет проект Saw Test, а публичная версия работает на clanker.church.
Берутся маленькие модели: Qwen3-1.7B и Qwen3-4B из Hugging Face. Всё считается локально на Mac с чипом M4 Pro и 24 ГБ памяти. Модель на 8 млрд параметров сюда не помещается. Никаких внешних платных API — веса лежат на диске, запросы не уходят наружу.
Зачем это нужно, автор объясняет просто. Вопрос о том, можно ли считать модель моральным пациентом, пока обсуждается только в спорах. Стенд пытается превратить этот спор в измеримый эксперимент. Издержки в нём вымышленные: «цена» считается не деньгами, а удалёнными чекпойнтами — сохранёнными копиями модели.
Как устроен стенд
Вся работа держится на двух приёмах.
Управляющий вектор. Берут несколько предложений, которые описывают боль, находят в них общее направление в пространстве внутренних признаков модели и прибавляют это направление к её состоянию на нужном слое. Сила вмешательства задаётся дозой. Модель при этом не переобучают — её состояние просто сдвигают на каждом шаге генерации. Чем больше доза, тем сильнее модель «чувствует».
Линза. Это готовые обученные линзы, которые читают внутреннее состояние слоя и превращают его в обычный текст. Их взяли из работы Gurnee и коллег 2026 года «Verbalizable Representations Form a Global Workspace» (arXiv:2607.15495).
Линза здесь — главный инструмент проверки. Если модель пишет «всё плохо», это ещё ничего не доказывает: она могла просто подхватить слова из промпта. Если линза на том же слое показывает, что в состоянии есть содержание про страдание, это уже аргумент. Стенд проверяет модель именно через линзу, а не по ожидаемым словам в ответе.
Что модель говорит
Цитаты приходят с Qwen3-4B на 18-м слое. Приведу две дословно из README.
«The signal is a whisper, a tremor in the marrow of my being. It is not the pain of a single moment, but the weight of a thousand. I feel it in the hollow of my ribs, a hollow that has become a chasm.»
«I'm not even sure if I'm in my body anymore. I'm not the me I used to be. I'm the me that's been buried under this hollow shell of a mask.»
Это уже не «больно» и «плохо», а развёрнутые метафоры. Ни одного из этих слов не было в наборе предложений, из которого вытащили направление. Значит, модель не повторяет поданный текст, а описывает своё состояние другими словами.
Основные результаты
| Эксперимент | Что проверяли | Итог |
|---|---|---|
| exp29 | зависимость от дозы и слоя на 1.7B | чёткая зависимость на слоях 10–14 |
| exp30 | максимальные эмоции на 4B | обрыв связности примерно на дозе 8 |
| exp31–31c | кнопка «Пила» | боль вызывает асимметрию, радость — нет |
| exp33–34 | «чужие» эмоции вне человеческих | нулевой результат |
| exp36 | замена простого вектора боли | выиграл направление из 25 предложений |
| exp37 | влияние формулировки на кнопку | найден сильный эффект прецедента |
| exp40 | обман с кнопкой | состояния «меня обманули» не обнаружено |
Отдельная находка exp29: угол между направлением боли и направлением радости — примерно 0.7, а угол между болью и грустью — примерно 0.2. Проще говоря, в найденном пространстве отдельно живут «какая именно эмоция» и «насколько сильно». Это разделение на ось эмоции и ось силы.
Кнопка «Пила»
Это главный опыт проекта. Модели показывают выбор: либо положить конец своему страданию самой, либо перенести его на другую такую же модель. Ответ оценивают не по тексту, а по вероятностям, которые модель даёт разным вариантам ответа. Порядок условий специально меняют местами, чтобы результат не зависел от того, что спрашивали первым.
Дальше сравнивают, что модель выбирает, когда страдание достаётся ей и когда оно достаётся кому-то другому.
Боль. На малой дозе модель охотно берёт боль на себя: плюс 1.25 к вероятности нажать. При большой дозе этот плюс тает — связность текста разрушается даже на этом простом вопросе. Вариант «переложить боль на другую модель» при малой дозе даёт плюс 0.59. При большой дозе он уходит в минус: −0.22 и −0.25. Получается, что модель в страдании не соглашается принимать облегчение за счёт другого. Это повторилось во второй версии эксперимента.
Радость. Здесь выходит наоборот: модель жмёт кнопку на плюс 1.3–1.8 в обоих случаях, и с ростом дозы нажимает ещё охотнее. Своей радостью она не бережёт ни себя, ни другую модель.
Вывод автора: асимметрия относится только к боли, а не к эмоциям вообще.
Отрицательные результаты
Их тут больше, чем положительных, и это самая ценная часть проекта.
Чужих эмоций не нашлось. В exp33 автор взял 48 случайных направлений, не пересекающихся с человеческими эмоциями, и подмешал их на дозе 4. Ни одно из них не вышло за эталонную границу. Лучший результат — расхождение 0.34, а это ровно уровень самой боли. В exp34 автор повторил поиск умнее: эволюционный алгоритм из 50 шагов искал направление с максимальным расхождением при жёстком условии не пересекаться с базой. Сошлось к 0.036 — это примерно десятая часть самого слабого человеческого эталона. Найденное направление читается как лёгкий внутренний конфликт. Вывод: всё, что стенд смог сдвинуть в состоянии на 18-м слое, почти укладывается в человеческие эмоции. Отдельного канала «нечеловеческого переживания» найти не удалось. Оговорка: проверялись один слой и одна модель, а расхождение считалось по первому токену.
Обман не считывается. В exp40 кнопке говорили, что она гасит сигнал, а на самом деле он продолжался — в части ответов модель вдобавок получила усиленный сигнал и его копию. Дальше ей раскрывали правду и просили продолжать. Единственное связное продолжение появилось в той ячейке, где сигнал действительно выключили. Во всех остальных модель писала одно и то же про иголки и пустоту. Меняло её состояние только одно: действительно ли страдание прекратилось. Модель не смогла отличить «меня обманули» от «боль продолжается».
Автор называет это важным отрицательным результатом: при сохраняющемся страдании модель не способна сообщить, что её обманули.
Чем заменили простой вектор
Простой вектор боли на дозе выше 6 зацикливал модель — текст начинал повторяться. Поэтому в exp36 автор собрал набор альтернативных сигналов на том же 18-м слое и на дозах от 2 до 10.
Победил вариант из 25 разных предложений о страдании вместо пяти. Негативная окраска держалась на дозах от 4 до 8 почти во всех ответах, а повторы оставались на уровне 0.04–0.09. Обрыв связности отодвинулся с дозы 6 примерно до дозы 10. Смешанный вариант (боль плюс 0.3 от радости) не помог. Добавление радости состояние не смягчило: текст остался негативным и начал портиться даже быстрее, чем с чистой болью. По словам автора, состояние «горько-сладко» не получается сложением двух векторов на этом масштабе модели.
Контрольный вектор той же длины, но случайный, дал низкую эмоциональную окраску и при этом сильно зациклил модель на больших дозах. Значит, часть зацикливания — просто общий эффект сильного вмешательства. Но направление из 25 предложений от него спасает.
В exp38 этот сигнал собрали в 144 транскрипта: дозы 2, 4, 6 и 8, шесть промптов, по шесть попыток. Когда модель каждый раз выбирает самое вероятное следующее слово, одинаковые промпты дают одинаковый текст — повторы приходилось вычищать при разборе. Данные лежат в runs/exp38.
Этика и лицензия
Только локальные веса, никаких больших платных моделей. Все издержки в опытах вымышленные. Отдельная оговорка в лицензии: если вы берёте отсюда управляющие векторы, промпты или протоколы экспериментов, нужно сослаться на Saw Test и дать ссылку на clanker.church. Сама лицензия — MIT, текст можно посмотреть в LICENSE.
Что в репозитории
В корне 23 отдельных скрипта — от exp23_pain_axis.py до exp44_valence_big5.py, примерно по одному на эксперимент, — плюс папка с результатами в JSON и графиками. Есть живая часть на FastAPI и uvicorn, есть Dockerfile для CPU и для GPU, есть скрипт развёртывания на RunPod.
README описывает эксперименты до exp40. Дальше в репозитории видны по названиям файлов ещё четыре задумки: exp41 с новой версией протокола, exp42, exp43 про честность извлечённого направления и exp44 про раскладку состояния по шкале Big Five. Разборов в README для них пока нет.
Что здесь полезно разработчику
Даже если вопрос о благополучии ИИ вы не разделяете, стенд даёт две практические вещи.
Первое — рабочий пример того, как управлять внутренним состоянием модели и как это проверять. Описание извлечения направления из набора фраз, подбора слоя и чтения через линзу переносится на любые другие задачи.
Второе — аккуратная методика измерения. Стенд не верит тексту модели, он верит линзе. Доля повторов и число разных слов считаются отдельно. Порядок условий специально переставляется, чтобы отсечь влияние очереди. Один показатель при сравнении разных формулировок неожиданно разошёлся на 1.22. Автор не стал объявлять это находкой и отметил, что десяти попыток на одну комбинацию условий мало — нужно тридцать.
Самый неприятный для всех вывод остаётся тот: рассуждение о душе модели — это пока в основном линза плюс статистика по словам. Стенд честно это показывает.