Посреди обычной рабочей переписки AI-агент прислал мне сообщение:
Аԥсны
Одно слово. Без точки, пояснений и продолжения.
До этого агент выполнял длинную техническую задачу: запускал команды, получал ошибки, менял способ выполнения и сообщал о ходе работы. После странного слова он как ни в чём не бывало продолжил.
Сначала я решил, что это какой-то служебный маркер. Может быть, обломок внутренней разметки, часть команды или случайно показанное рассуждение модели. На знакомый мне русский язык слово не походило, но выглядело слишком осмысленно для битой кодировки.
Я спросил агента, что это было.
Он уверенно ответил:
Это служебный артефакт форматирования. В черновике ответа оказался лишний технический маркер.
Звучало правдоподобно. И было неправдой.
Как агент придумал объяснение собственному сбою
Меня не устроил ответ про «технический маркер». Если в системе действительно есть такой маркер, его можно найти в коде, документации, журнале сессии или протоколе обмена с моделью.
Я поручил другому агенту провести расследование.
Он проверил переписку, системные инструкции, файлы проекта, документацию, память агента и результаты выполненных команд. Раньше Аԥсны нигде не встречалось.
Первое появление слова нашлось в сохранённом исходном ответе модели. Запись выглядела примерно так:
{
"type": "message",
"role": "assistant",
"phase": "commentary",
"content": [
{
"type": "output_text",
"text": "Аԥсны"
}
]
}
commentary — канал коротких промежуточных сообщений. В нём агент обычно пишет что-то вроде «Проверяю конфигурацию» или «Ищу полный путь к Node.js». Такая реплика не завершает задачу: после неё агент продолжает вызывать инструменты.
В этот раз модель вместо нормального комментария выдала Аԥсны. Hermes получил текст и переслал его в Telegram. Обработчик форматирования его не создавал, Telegram ничего не исказил.
А первое объяснение агент придумал уже после события. Он увидел собственный странный ответ и подобрал к нему убедительно звучащую причину.
Это оказалось интереснее самого сбоя.
Что такое Аԥсны
Аԥсны читается примерно как «Апсны́». Это абхазское название Абхазии. У слова есть популярное поэтическое толкование — «страна души».
Для меня нашлось и другое, гораздо более бытовое значение. «Апсны» называется красное полусладкое абхазское вино. Вполне неплохое, кстати.
Получилась занятная цепочка. AI-агент выполнял техническую операцию, внезапно написал по-абхазски «Абхазия», а расследование привело меня к бутылке красного вина.
Так ИИ надоумил меня выпить вина, хотя сам об этом не подозревал.
Почему модель выбрала именно это слово
Точного ответа у меня нет. Путь сообщения удалось восстановить по журналам, но внутренние вероятности модели в момент выбора следующего токена недоступны.
Зато обнаружилась любопытная деталь.
Языковые модели работают не с буквами и не всегда с целыми словами. Они делят текст на токены. Распространённое слово может занимать один токен, а редкое сочетание символов — несколько.
В токенизаторе o200k_base, который использовался этим маршрутом модели, всё слово Аԥсны представлено одним токеном:
62842 → Аԥсны
То есть модель не сочиняла его по буквам. Она один раз выбрала элемент словаря под номером 62842, после чего закрыла промежуточное сообщение.
Почему в словаре есть целое абхазское слово, по доступным данным установить нельзя. Оно попало туда при построении токенизатора, но конкретный исходный текст нам неизвестен.
Само присутствие слова в словаре ещё не означает, что модель хорошо научилась им пользоваться. Редкий токен может быть слабо представлен в обучающих данных самой модели. С такими элементами связывают часть аномалий, которые называют glitch tokens.
Я не могу доказать, что 62842 относится именно к ним. Это мог быть обычный единичный сбой выбора. Однако появление целого осмысленного слова выглядит уже не таким мистическим, если понимать: для модели это была одна операция, а не пять случайно угаданных букв.
Может ли такое слово попасть в код
Да.
Модель одним и тем же способом генерирует обычный текст, команды и аргументы инструментов. Когда агент меняет файл, содержимое патча тоже сначала создаёт языковая модель.
Если странный токен попадёт в имя инструмента или сломает JSON, вызов просто не выполнится. Если он окажется в пути к файлу, инструмент, скорее всего, вернёт ошибку.
Но возможны менее очевидные варианты:
const Аԥсны = getStatus()
Во многих языках Unicode разрешён в именах переменных. Такой код может пройти синтаксическую проверку.
Ещё проще случайному слову спрятаться в комментарии или строке:
logger.info('Аԥсны')
Сборка завершится успешно. Линтер тоже может ничего не заметить.
При этом экзотическое слово — не самая серьёзная опасность. Его хотя бы видно. Гораздо хуже, если модель заменит 3 на 30, перепутает имя таблицы или напишет правдоподобное, но неверное условие. Такой код выглядит нормально и иногда проходит поверхностные проверки.
Поэтому я не считаю успешное применение патча доказательством правильности. После работы AI-агента всё равно нужны просмотр diff, тесты, сборка и проверка фактического поведения.
Глюк закончился, а история осталась
В этом случае ничего опасного не произошло. Странное слово появилось только в промежуточном сообщении. Следующая команда была правильной, и агент продолжил работу.
Но эпизод хорошо показал две особенности AI-агентов. Модель способна выдать совершенно посторонний токен внутри связной и в целом корректной работы. А если попросить её объяснить случившееся, она может не исследовать событие, а сразу придумать удобную версию.
Поэтому мне всё меньше интересны уверенные ответы агентов и всё больше — сохранённые исходные данные, журналы, реальные вызовы инструментов и возможность восстановить цепочку событий.
А слово Аԥсны теперь напоминает мне сразу об Абхазии, редких токенах и красном полусладком.
Не самый плохой результат отладки.
Наблюдения об AI-агентах, разработке и странных поворотах между ними я продолжаю собирать в Telegram-канале «Струны, мысли».
