Strawberry и другие позоры

Лето 2024. Интернет взрывается от мема: люди спрашивают ChatGPT, Claude, Gemini - сколько букв "r" в слове "strawberry"? Правильный ответ - три. Модели уверенно отвечают: две.

Дальше было ещё веселее. Когда пользователи начинали спорить, ChatGPT аргументировал: мол, буква R в "straw" - это часть слова, но она не влияет на общий подсчёт R в "strawberry". Модель буквально газлайтила людей, защищая неправильный ответ развёрнутой аргументацией. Gemini в некоторых случаях заявлял, что букв "r" в strawberry вообще ноль - и отказывался признавать ошибку даже после побуквенного разбора.

Кейс стал настолько знаковым, что OpenAI назвала свой проект рассуждающей модели кодовым именем "Strawberry" (позже ставший o1) - как внутреннюю шутку: модель наконец научилась считать буквы.

Но strawberry - верхушка. Систематические тесты показывают: GPT-4o не справляется с умножением чисел длиннее четырёх цифр. При умножении нескольких чисел GPT-4 давал 95% точности для двух чисел до 100, 30% для трёх, 5% для четырёх - и ноль дальше. При этом модель часто правильно угадывала последнюю цифру результата (потому что она определяется только последними цифрами множителей - простой паттерн), но середина числа - мусор.

Модель, которая пишет код, рассуждает о квантовой физике и генерирует сонеты, не может перемножить два пятизначных числа. Давайте разберёмся почему.


Часть 1. Почему LLM не умеют в арифметику

Она не считает - она угадывает следующий символ

Ключевое: языковая модель - это машина для предсказания следующего токена. Не калькулятор, не процессор, не логический движок. Машина для продолжения текста.

Когда вы пишете "2 + 3 =", модель не складывает. Она смотрит на паттерн "цифра + цифра =" и вспоминает, что в обучающих данных (весь интернет, книги, код) после такой конструкции обычно стояло "5". И выдаёт "5".

Для простых случаев это неотличимо от настоящего вычисления - потому что в интернете тысячи примеров "2 + 3 = 5". Но "72528 x 67066 =" модель почти наверняка не видела. И начинает экстраполировать.

Представьте человека, который не знает алгоритм умножения, но прочитал миллион задач с ответами. Он заметит закономерности: "если числа заканчиваются на 8 и 6, результат заканчивается на 8", "пятизначное на пятизначное - обычно десятизначное". По этим закономерностям он угадает края. Середину - нет.

Принципиальное отличие от калькулятора: калькулятор выполняет алгоритм - цепочку детерминированных шагов, где каждый зависит от предыдущего. Запустите его тысячу раз - тысячу одинаковых ответов. Модель выбирает вероятное продолжение текста. Каждый раз - потенциально немного другое.

Калькулятор vs LLM

Она не видит символы - она видит куски

Вторая фундаментальная проблема - и именно она объясняет фиаско со strawberry.

LLM не работают с текстом посимвольно. Перед попаданием в модель текст разбивают на токены - куски, которые могут быть словом, частью слова, цифрой или группой цифр.

Слово "strawberry" модель видит не как s-t-r-a-w-b-e-r-r-y. GPT-4o разбивает его на три токена: "st", "raw", "berry". Каждый токен - неделимая единица. Модель не умеет "заглядывать внутрь" токена, как мы не видим атомы в предметах.

Она знает, что "st" + "raw" + "berry" = клубника. Но что "raw" содержит одну "r", а "berry" - две - эта информация при токенизации растворяется.

С числами - то же, только хуже. Число 1234567890 Llama 3.1 разобьёт на: "123", "456", "789", "0". Модель не "знает", что "123" в начале числа - это сотни миллионов. Токен "123" как самостоятельное число и "123" как начало миллиарда выглядят одинаково. А позиция цифры - это всё в арифметике.

Токенизация: что теряется

Трансформер не заточен под многошаговые алгоритмы

Даже с идеальной токенизацией трансформер не умел бы считать надёжно.

Умножение 72528 x 67066 - это не одна операция. Это цепочка: перемножить каждую пару цифр, сдвинуть, сложить промежуточные суммы, передать переносы. Десятки зависимых шагов. В прямом проходе трансформера фиксированное число слоёв (в Llama 8B - 32). Каждый слой может выполнить ограниченный объём работы.

Аналогия: вам нужно умножить столбиком, но вместо того чтобы записывать промежуточные результаты, вы держите всё в голове - и у вас ровно 32 "шага мышления". Для сложения трёхзначных чисел хватит. Для умножения пятизначных - нет.

Исследование Dziri et al. (2024, NeurIPS) формально показало: трансформеры имеют фундаментальные ограничения на композиционные задачи. Где каждый шаг зависит от предыдущего - сложность растёт экспоненциально. А ресурсы модели фиксированы.

И ещё: каждый шаг рассуждения генерируется вероятностно. Одна ошибка в переносе на третьем шаге - и весь результат неправильный. Для калькулятора это невозможно. Для нейросети - норма.

Каскад ошибок при умножении

А почему не встроили калькулятор сразу?

Ответ прост: не входило в задачу. Трансформер проектировался для языка. Attention, позиционные кодировки, нормализация - всё оптимизировано для статистических зависимостей между словами. Не для алгоритмов.

GPU, на котором работает LLM, прекрасно считает - триллионы арифметических операций в секунду. Но эти вычисления "инфраструктурные": перемножение матриц весов, вычисление attention-скоров. Это вычисления для предсказания текста, а не для решения вашей задачи "324 x 87332".

Как машина с двигателем в 300 л.с. не может вскипятить чайник. Мощность есть, но приложена не туда.

GPU считает, но не то

Часть 2. Как это решают сегодня

Раз модель сама не считает, ей дали костыли. Три штуки:

Chain of Thought. Модель расписывает решение по шагам: "умножим 4 на 7, получим 28, запишем 8, перенесём 2...". Каждый шаг - отдельная генерация, каждый может ошибиться. Модель o1 от OpenAI справляется с умножением девятизначных чисел примерно в половине случаев - прогресс, но всё ещё лотерея. И инференс замедляется в разы.

Tool use. Модель генерирует вызов калькулятора, вызов перехватывается, число считается на CPU, результат подставляется обратно. Так работают ChatGPT (code interpreter), Claude (MCP), Gemini. Точно, но: задержка на GPU-CPU-GPU, модель не может использовать результат "внутри" своих рассуждений на уровне латентных представлений, и при претрейне этого инструмента не было.

Генерация кода. Модель пишет result = 324 * 87332, код исполняется снаружи. Вариант tool use.

Общее: модель не считает - делегирует. И все три метода добавляются после претрейна. Модель сначала годами учится угадывать арифметику, потом получает инструмент. Старые "привычки угадывания" мешают.

Три подхода к арифметике в LLM

Часть 3. IGC - калькулятор внутри модели

В январе 2025 года Флориан Дитц и Дитрих Клакоу из Саарландского университета предложили другое: не делегировать, а встроить калькулятор прямо внутрь LLM. Модуль IGC (Integrated Gated Calculator) работает на GPU, в том же прямом проходе, без промежуточных токенов. (arxiv:2501.00684)

Где это сидит

Текст приходит, превращается в эмбеддинги, проходит через 32 слоя трансформера Llama 3.1 8B. IGC встраивается после слоя 1 (авторы перебрали разные варианты - ранние слои лучше). Модуль перехватывает промежуточные активации, обрабатывает и модифицирует их. Остальные 31 слой продолжают работу уже с модифицированными данными.

Все 8 миллиардов параметров Llama заморожены. Обучается только IGC - 17 миллионов параметров. Это 0.2% от базовой модели.

Важный нюанс: авторы используют именно instruction-finetuned Llama 3.1 8B - модель, которая уже умеет следовать инструкциям. IGC добавляет ей арифметику, а не учит общаться.

IGC в архитектуре трансформера

Три компонента

1. Input Mapping - "прочитай задачу"

Из токенов "What is 324 times 87332?" нужно извлечь: операнд 1 (324), операнд 2 (87332), оператор (x).

Работает через attention. Есть "якорный токен" - момент, когда задача целиком описана (переход от реплики пользователя к ответу). Якорный токен формирует Query, все предшествующие токены - Key и Value. Attention собирает нужное из контекста.

На выходе - вероятностные распределения: для каждой позиции каждого операнда (какая цифра 0-9 или "пусто") и для оператора.

2. Calculator - "посчитай"

Чистые тензорные операции, никакого ML:

  • Дискретизировать распределения (взять самую вероятную цифру каждой позиции)
  • Собрать числа
  • Выполнить все четыре операции параллельно (на батче это эффективнее)
  • Выбрать результат нужной операции через weighted average на основе вероятности оператора из Input Mapping
  • Результат - обратно в цифры, one-hot

Блок не дифференцируем. Градиент через него не идёт. Калькулятор не учится - он просто считает.

3. Output Mapping - "верни результат модели"

Результат калькулятора "вписывается" в латентные представления через gated connections. Для каждого токена после якорного два компонента: "значение" (как результат влияет на токен) и "вентиль" (от 0 до 1 - насколько сильно).

Вентили - ключевой элемент. Если задача не арифметическая, вентили закрываются ~ 0, модель работает как раньше.

Три компонента IGC

Как обучается

Модифицированный teacher forcing с двумя особенностями:

Auxiliary loss. Калькулятор блокирует градиент, поэтому Input Mapping обучается отдельно - cross-entropy между его выходами и правильными операндами/оператором. Для простых шаблонов разметка автоматическая. Для word problems авторы описывают аналог подхода Toolformer: LLM сама размечает данные, и если разметка снижает perplexity - добавляется в обучение.

Подмена результата. Пока Input Mapping не сходился и подаёт мусор, на выход калькулятора подставляется правильный ответ. Output Mapping начинает учиться сразу. Не обязательно, но ускоряет.

Left-aligned формат

Неочевидная, но критическая деталь.

Llama 3.1 токенизирует числа слева направо, по три цифры: 1234567890 -> "123" "456" "789" "0". Стандартный формат представления - выравнивание по правому краю (единицы справа). Проблема: при таком формате позиция цифры внутри токена зависит от длины числа. Это нелокальная информация.

Авторы развернули: старшая цифра - на фиксированной позиции (слева), хвост заполняется заглушкой "*". При этом четвёртая по старшинству цифра всегда во втором токене, шестая - в третьем - независимо от длины числа.

Left-aligned vs Right-aligned: позиция цифры должна быть предсказуемой

Right-aligned часто не сходился. Left-aligned - стабильные 99%.


Часть 4. Результаты

Бенчмарк - BigBench Arithmetic: четыре операции, числа до 5 цифр, простые шаблоны.

Сравнение намеренно нечестное - в пользу конкурентов: для n-shot берётся лучший результат по любому n, для IGC - среднее по сидам.

Модель Параметры Метод Общая + - x /
Лучшие <100B <100B n-shot 49% 49% 69% 35% 71%
PALM 535B 535B n-shot 94% 94% 96% 91% 97%
Llama 8B baseline 8B+17M файнтюнинг 70% 95% 88% 22% 75%
IGC 8B+17M файнтюнинг 99% 99% 99% 99% 98%

17 миллионов параметров бьют 535 миллиардов.

Что важно в деталях:

Стабильность. Разные seeds - низкая дисперсия. У n-shot бенчмарков дисперсия огромная: часто 1-shot бьёт 3-shot на той же задаче. Авторы объясняют: модели теряют точность не на арифметике, а на понимании формата вывода. IGC этой проблемы не имеет.

Скорость. 70 эпох, 10 000 примеров, одна GPU, 2-4 дня. Для обычного файнтюнинга 10K примеров - ничтожно мало. Для IGC хватает - потому что калькулятор внутри идеальный, и inductive bias куда сильнее.

Baseline 22% на умножении. Ключевое наблюдение. Llama при претрейне уже видела арифметику и выучила эвристики. Для сложения они работают неплохо (95%). Для умножения - бесполезны (22%).

Абляция: shortcut мешает

Авторы проверили гибрид - IGC + прямое дифференцируемое соединение (shortcut) в обход калькулятора:

  • Только shortcut (без калькулятора): ~70%, уровень baseline
  • Чистый IGC: 99%, стабильно
  • IGC + shortcut: нестабильно, итоговая точность ниже

Shortcut сходится быстрее (он дифференцируем), но переобучается и не генерализует. А его присутствие мешает модели "довериться" калькулятору - destructive interference.

Сходимость: IGC vs Shortcut vs гибрид

Часть 5. Сравнение подходов

Свойство Обычная LLM CoT Tool Use IGC
Сложение/вычитание - + + +
Умножение/деление - ~ + +
Один шаг + - - +
Всё на GPU + + - +
Нет побочных эффектов - - - +
Можно в претрейн + - - +
Произвольная длина чисел + + + -

Часть 6. За пределами арифметики

Самое интересное. Калькулятор в IGC - чёрный ящик. Обучаемые компоненты не знают, как он работает. Они учатся подавать входы и использовать выходы.

Что, если заменить чёрный ящик?

  • Поиск по базе данных. Input Mapping извлекает ключ, блок ищет, Output Mapping встраивает. RAG без промежуточных токенов, в один проход.
  • Граф знаний. Обход графа вместо поиска.
  • Любая детерминированная операция. Конвертация, валидация, справочник.

Паттерн "обучаемый вход -> недифференцируемый блок -> обучаемый выход с вентилями" - универсален.

Обобщение IGC: одна обвязка, разные модули

Часть 7. Ограничения

Фиксированная длина. Максимум задаётся при обучении. Авторы: в датасете MATH 99% чисел четырёхзначные и короче. Для остатка - tool use как fallback.

Только арифметика, не word problems. IGC считает, но не извлекает задачу из текста - это работа LLM. Авторы разграничивают: бывает, модель правильно рассуждает, но ошибается в арифметике внутри рассуждения. А бывает - арифметика тривиальная, но модель не может извлечь числа. IGC решает первую проблему.

Код не опубликован. Статья на ревью, код будет при принятии.

Одна операция за раз. Цепочки вычислений - через несколько проходов.


Итого

Работа из Саарландского университета - не про арифметику как таковую. Она про архитектурный паттерн: недифференцируемую операцию можно обернуть обучаемыми "переходниками" с вентилями и встроить в трансформер. Без промежуточных токенов, без внешних вызовов.

17 миллионов параметров побеждают 535 миллиардов - не потому что нейросеть научилась считать, а потому что ей дали настоящий калькулятор и научили им пользоваться.

Для агентных систем сигнал: tool use через MCP - рабочий, но архитектурно неэлегантный подход. Задержка, разрыв контекста, невозможность учиться на результатах при претрейне. IGC показывает альтернативу - инструменты как часть архитектуры, а не как внешние костыли.



Ссылки: