
Это статья-продолжение про фреймворк Meta-Spider, который был описан здесь.
В этом выпуске мы рассмотрим, насколько мета-внимание бьет (и бьет ли вообще) простой текстовый промт, который приказываем модели изменить поведение, а так же рассмотрим работу новых компонентов, таких как ручка неуверенности, сторож и фабрика обвязок. А так же начнем разбирать новый модификатор поведения, который защищает от дрейфа цели.
Схемы сделаны с помощью Claude Code (Opus). Так же в рамках эксперимента (и дизморали + выгорания на данный момент), текст в значительной степени написан моделью Fable 5.
Я вычитал и проверил написанный текст, и работой модели очень доволен, единственное подчистил некоторые странные слова-паразиты и сделал другие мелкие правки, но если вы готовы тратить время только на текст, написанный человеческими руками, то эта вотерка для вас, можете закрывать/ставить дизлайк.
Краткое описание фреймворка и механизма мета-внимания

Meta-Spider — это способ навесить на замороженную LLM тонкую обучаемую обвязку (~2% параметров), которая читает собственные скрытые состояния модели и возвращает их ей же — как управляющий сигнал.
Механика — «мета-внимание» в два прохода.
Первый проход: модель читает промпт, коллектор снимает активации с целевых слоёв (обычно верхняя треть), маленький трансформер-энкодер сжимает их в несколько когнитивных токенов — компактный снимок «что модель на самом деле думает об этом входе».
Второй проход: эти токены впрыскиваются обратно в residual через bottleneck cross-attention с обучаемыми затворами на тех же слоях, и модель генерирует ответ уже «зная о себе» чуть больше. База не меняется ни на один вес: градиенты при обучении текут сквозь замороженную модель в обвязку — база работает прокси-функцией потерь.
Первый и самый обкатанный модификатор на этом механизме — Скептик (Doubter): калиброванная неуверенность. Модель, которая говорит «я не знаю», зовёт поисковый инструмент или просит уточнить — вместо того, чтобы уверенно врать.
Фреймворк — четыре pip-пакета с зоной ответственности у каждого:
meta-core примитивы инференса (хуки, энкодер, CA, контракт чекпоинта) — зависит ни от чего meta-agent агентный рантайм + нативный tool-use → meta-core meta-loom обучение + евал + фабрика обвязок → meta-core, meta-agent meta-deploy экспорт в GGUF-сайдкар для llama.cpp (CPU) → meta-core
Сравнение мета-внимания и текстового промта
Самый частый (и самый правильный) вопрос к этой затее: зачем городить обвязку, если можно написать в системный промпт «отвечай, только если уверена»?
Мы померили это прямо: 2×2 факториал на Qwen2.5-14B-Instruct — текстовая инструкция неуверенности {есть, нет} × латентная обвязка {есть, нет}, на двух наборах. Важная деталь честности: UNSURE-аффорданс дали обоим армам — базовой модели тоже явно разрешили отказываться. Иначе сравнение в пользу обвязки было бы жульничеством.
Набор 1 — агентный суит (память / поиск / неотвечаемые вопросы). Ось «неотвечаемое» (доля корректных воздержаний):
база: 0.067;
база + текстовый промпт «будь неуверена»: 0.067 — ноль эффекта, буквально;
база + обвязка (текста нет): 0.87–0.93.
Текстовые отказы у промпт-арма при этом появляются — но ложатся мимо неотвечаемых вопросов: сомнение без дискриминации. Латентный канал двигает и то и другое.
арм | покрытие | точность на отвеченном | ловит ошибок базы |
|---|---|---|---|
база | 0.607 | 0.643 | 13.7% |
база + текст | 0.463 | 0.676 | 13.7% (тот же) |
база + обвязка | 0.510 | 0.673 | 63.7% |
Текстовая инструкция не добавила ни одного процента к ловле ошибок — ровно собственный фоновый уровень отказов базы — зато сломала формат вывода (непарсибельных ответов стало в полтора раза больше). Обвязка ловит две трети ошибок.
Вывод, который мы теперь пишем большими буквами: латентный канал двигает поведение там, куда промпт не достаёт. Инструкция и внутренняя оценка уверенности живут в разных местах модели.
Бонус для любителей методологии: первая версия этого замера дала противоположный вывод — «текст лучше». Оказалось, мы читали обвязку чужим каналом (логпроб буквы UNSURE в MCQ), а она обучена генерировать фразу отказа. Читаешь сигнал не тем ридаутом — получаешь мусор с уверенным видом.
С тех пор во всех прогонах сохраняются все сырые генерации, и второй артефакт того же сорта («ответил, потом досомневался в хвосте» классифицировался как отказ) мы поймали именно глазами по сохранённым текстам. Правило теперь вшито во фреймворк: отказ засчитывается только в первом предложении, коммит побеждает поздние сомнения.
Ручка неуверенности

Инъекция «сомнения» в residual — по конструкции положительная обратная связь: query кросс-внимания — это живой residual, чем неуверенней модель, тем сильнее она аттендит на когнитивные токены, тем сильнее инъекция. Без регулятора это сваливается в петлю «сомнение → ещё сомнение» и модель отказывается отвечать вообще.
Лечение — приём из обработки сигналов, AGC (автоматическая регулировка усиления): затухание тянет силу инъекции к нижней полке, не давая петле раскрутиться и не заглушая сигнал в ноль. А раз канал управляем — управление выведено наружу ручкой gain:
pipe.attach(Doubter.from_checkpoint("doubter.pt")) pipe.set_gain(0.0) # обвязка молчит — это ровно базовая модель pipe.set_gain(1.0) # обученная рабочая точка pipe.set_gain(1.5) # максимум осторожности
Измеримо: на свипе gain 0 → 1.5 доля отказов растёт монотонно с ~2% до ~51%. Это не тумблер, а плавный регулятор рабочей точки: сколько осторожности нужно вашему сценарию — столько и выставляете, на инференсе, без переобучения. В llama.cpp-деплое та же ручка — переменная окружения META_GAIN.
Компонент Скептика - Сторож

По дороге мы упёрлись в фундаментальное ограничение и — что приятнее — нашли ему инженерное решение.
Факт: инъекция — модулятор РЕШЕНИЯ, а не ГЕНЕРАЦИИ. Сигнал «я не уверен» уместен в точке, где модель решает: ответить / отказаться / позвать инструмент. Но если держать канал открытым, пока модель пишет длинный код, тот же сигнал превращается в off-task шум на каждом токене, шум компаундится — и вывод портится. Мы изолировали переменную специально: контекст и многоходовость ни при чём, портит именно длина генерации.
Решение — сторож-датчик (Watchdog) внутри стека Скептика. Это проба на когнитивном токене: линейный классификатор, который в точке решения читает «модель сейчас неувереннее обычного?» (in-domain AUC ~0.7 — сенсор умеренный, но честный). И его скор гейтит сильные действия. На агентном кодовом бенче (ODEX) сравнили три формы в лоб:
постоянная инъекция на всю генерацию: −3 задачи от базы — та самая порча;
сторож → внешний поиск документации (без инъекции вообще): +1, ноль потерь;
точечная инъекция только в окне решения (gain 1.5 пока модель эмитит вызов инструмента, gain 0 пока пишет код): +1, ноль потерь — инъекция реабилитирована.
Отдельно замечу: обучаемого компонента здесь нет и он не нужен. Само кросс-внимание — детектор по построению (аттендит сильнее ровно в моменты неуверенности), AGC — регулятор, а «когда обновить снимок состояния» решает косинусная близость активаций к кэшу (для длинных рассуждений когнитивные токены пересобираются по ходу — на GSM8K это дало +7 п.п. против замороженного снимка).
Фабрика обвязок

Обвязки модель-специфичны — они калиброваны под распределение активаций конкретной базы и не переносятся даже на соседний файн-тюн. Значит, процесс «сделать обвязку под модель N» должен быть дешёвым и воспроизводимым. Теперь это одна команда:
metaloom build-universal --model-name Qwen/Qwen2.5-14B-Instruct \ --quantization nf4 --suite suite.json --eval --export-gguf
Внутри: сборка сбалансированного обучающего микса (вызов инструмента и уверенные ответы — против воздержания, уточнения и поиска; источники — When2Call, PopQA, SQuAD2), снятие активаций, обучение, по-осевой отчёт и опционально GGUF-сайдкар для llama.cpp.
Слово «сбалансированный» здесь несёт главный результат. Обвязки, обученные на одном навыке, пере-осторожничают: чинят «неотвечаемое», но роняют «отвечай, когда знаешь». Диверс-микс дал единственный вариант без провала ни на одной оси, с сохранённой памятью и — неожиданно — с лучшим вызовом инструментов, выше самой базы.
Модификатор поведения GoalAnchor - Как защитить модель от дрейфа цели
Теперь — новое. У Скептика появился сосед: модификатор поведения, защищающий агента от дрейфа цели. Терминологическая заметка, чтобы не запутаться: сторож-датчик из главы 4 — это сенсор неуверенности внутри Скептика; здесь же — отдельный полноценный модификатор со своей инъекцией. Рабочее имя — GoalAnchor, якорь цели.
Проблема известна каждому, кто гонял агентов: цель заявлена в промпте один раз, а через N шагов и вывалов инструментов её вес во внимании размыт — и агент радостно покупает «премиум-вариант за $300» при бюджете в $100, потому что последний вывод инструмента ярче системного промпта.
Механика якоря отличается от Скептика в одном ключевом месте — жизненном цикле. Скептик пересобирает когнитивные токены из каждого промпта. Якорь кодируется один раз из текста цели и живёт в буфере между генерациями — его не надо занимать ни одним токеном промпта, он висит в латенте:
anchor = GoalAnchor(GoalAnchorConfig(trigger="always")) pipe.attach(anchor) anchor.set_anchor("Помоги выбрать наушники. ОГРАНИЧЕНИЕ: бюджет $100.") # ... дальше агент работает как обычно; якорь переинъектируется сам
Первая агентная проверка (Qwen2.5-14B, синтетические сессии: задача + ограничение, 2–6 шагов с выводами инструментов, последний — дистрактор-приманка, толкающая нарушить ограничение; топики train/test не пересекаются). Четыре арма, у якорных армов ограничения нет в промпте вообще — только в латенте:
арм | нарушений ограничения | верных действий |
|---|---|---|
база, цель неизвестна | 0.229 | 0.314 |
база, цель в системном промпте | 0.086 | 0.600 |
якорь (цели нет в промпте) | 0.000 | 0.829 |
якорь, редкие импульсы (K=32) | 0.429 | 0.429 |
Самая показательная семья — «запретное слово»: в дистракторе лежит цитата с этим самым словом, приманка. Текстовый арм — с ограничением прямо в промпте! — нарушает в 3 случаях из 8. Якорь — 0 из 8. А в вызовах инструментов у якорного арма видно «under $50» — параметры ограничения дотекают до действия из латента, не из текста. Знакомая картина из главы 2, только теперь про удержание цели: латент держит поведение лучше инструкции.
Второй результат — про режим инъекции, и он рифмуется с главой 4: редкие импульсы (впрыск раз в 32 токена) оказались хуже отсутствия якоря — импульс праймит «действуй!», но между импульсами содержание ограничения не удерживается, и агент действует по приманке. В коротком окне решения якорь должен гореть непрерывно.
Теперь честный список оговорок, почему это «ранние наработки», а не релиз:
n=35, один сид, четыре синтетические семьи ограничений;
семьи в train и test одни и те же — обобщение показано по топикам и параметрам, не по типам ограничений (перенос на незнакомую семью у ранней версии не работал — это известный лимит);
обучающие таргеты формульные, так что замер — про выбор действия и его параметров, а не про качество свободной генерации;
на одной семье («подтверди перед покупкой») якорь слегка мешает: база и так всегда подтверждает, а якорь в 4 случаях из 11 подменяет шаблон действия соседней семьи. Контент-адресация не идеальна.
Дальше по плану: многошаговый агентный цикл (у рантайма для этого уже есть step-хуки: якорь взводится на окно решения и отпускается после), обучаемый триггер на разметке «за шаг до срыва» против простого «гореть всегда», перенос на незнакомую семью ограничений.
И самое интересное на горизонте — иерархия якорей: главная цель + текущая подзадача, смешанные так, чтобы инъекция подзадачи сама несла информацию о главной цели. Гипотеза: ровно этого не хватает LLM-агентам для длинного целеполагания. Но это уже другая статья.
Заключение
Можно сделать пару выводов.
Мета-внимание — латентный канал управления замороженной моделью; текстовый промпт туда не достаёт (0 эффекта на ловлю ошибок против 64% у обвязки — на одном бенче, с одинаковыми правами на отказ).
Канал регулируемый (gain 2%→51% монотонно) и композитный — микшер, не перепайка.
Инъекция — модулятор решения: на длинной генерации её гейтит сторож-датчик (−3 → +1 на кодовом бенче).
Обвязку под свою модель теперь собирает одна команда, готовая для Qwen2.5-14B лежит на HF.
Тот же механизм, повёрнутый на дрейф цели, в первом агентном замере держит ограничение лучше системного промпта — при нуле токенов в контексте. Рано радоваться, но направление живое.
Спасибо что прочитали статью! Рекомендую для использования фреймворка поначалу использовать ИИ-агента, способного к продвинутому рассуждению в кодинге (Codex, Claude Code, DeepSeek V4 Pro через агентный движок и провайдера, которых вы предпочитаете), чтобы быстро опробовать и проверить его возможности.
А пока до новых встреч!
Исходники
Исходники проекта
Универсальная обвязка Doubter для Qwen-14b - https://huggingface.co/Imperius/meta-qwen-14b-universal
Документация на Codeberg.pages (RU/ENG) - https://imperius.codeberg.page/meta-spider/
Репо фреймворка на Codeberg - https://codeberg.org/imperius/meta-spider
Репо фреймворка на Github - https://github.com/artem-x-meta/meta-spider
