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", "пятизначное на пятизначное - обычно десятизначное". По этим закономерностям он угадает края. Середину - нет.
Принципиальное отличие от калькулятора: калькулятор выполняет алгоритм - цепочку детерминированных шагов, где каждый зависит от предыдущего. Запустите его тысячу раз - тысячу одинаковых ответов. Модель выбирает вероятное продолжение текста. Каждый раз - потенциально немного другое.
Она не видит символы - она видит куски
Вторая фундаментальная проблема - и именно она объясняет фиаско со 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 л.с. не может вскипятить чайник. Мощность есть, но приложена не туда.
Часть 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.
Общее: модель не считает - делегирует. И все три метода добавляются после претрейна. Модель сначала годами учится угадывать арифметику, потом получает инструмент. Старые "привычки угадывания" мешают.
Часть 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 добавляет ей арифметику, а не учит общаться.
Три компонента
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, модель работает как раньше.
Как обучается
Модифицированный 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". Стандартный формат представления - выравнивание по правому краю (единицы справа). Проблема: при таком формате позиция цифры внутри токена зависит от длины числа. Это нелокальная информация.
Авторы развернули: старшая цифра - на фиксированной позиции (слева), хвост заполняется заглушкой "*". При этом четвёртая по старшинству цифра всегда во втором токене, шестая - в третьем - независимо от длины числа.
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.
Часть 5. Сравнение подходов
| Свойство | Обычная LLM | CoT | Tool Use | IGC |
|---|---|---|---|---|
| Сложение/вычитание | - | + | + | + |
| Умножение/деление | - | ~ | + | + |
| Один шаг | + | - | - | + |
| Всё на GPU | + | + | - | + |
| Нет побочных эффектов | - | - | - | + |
| Можно в претрейн | + | - | - | + |
| Произвольная длина чисел | + | + | + | - |
Часть 6. За пределами арифметики
Самое интересное. Калькулятор в IGC - чёрный ящик. Обучаемые компоненты не знают, как он работает. Они учатся подавать входы и использовать выходы.
Что, если заменить чёрный ящик?
- Поиск по базе данных. Input Mapping извлекает ключ, блок ищет, Output Mapping встраивает. RAG без промежуточных токенов, в один проход.
- Граф знаний. Обход графа вместо поиска.
- Любая детерминированная операция. Конвертация, валидация, справочник.
Паттерн "обучаемый вход -> недифференцируемый блок -> обучаемый выход с вентилями" - универсален.
Часть 7. Ограничения
Фиксированная длина. Максимум задаётся при обучении. Авторы: в датасете MATH 99% чисел четырёхзначные и короче. Для остатка - tool use как fallback.
Только арифметика, не word problems. IGC считает, но не извлекает задачу из текста - это работа LLM. Авторы разграничивают: бывает, модель правильно рассуждает, но ошибается в арифметике внутри рассуждения. А бывает - арифметика тривиальная, но модель не может извлечь числа. IGC решает первую проблему.
Код не опубликован. Статья на ревью, код будет при принятии.
Одна операция за раз. Цепочки вычислений - через несколько проходов.
Итого
Работа из Саарландского университета - не про арифметику как таковую. Она про архитектурный паттерн: недифференцируемую операцию можно обернуть обучаемыми "переходниками" с вентилями и встроить в трансформер. Без промежуточных токенов, без внешних вызовов.
17 миллионов параметров побеждают 535 миллиардов - не потому что нейросеть научилась считать, а потому что ей дали настоящий калькулятор и научили им пользоваться.
Для агентных систем сигнал: tool use через MCP - рабочий, но архитектурно неэлегантный подход. Задержка, разрыв контекста, невозможность учиться на результатах при претрейне. IGC показывает альтернативу - инструменты как часть архитектуры, а не как внешние костыли.
Ссылки:
- Dietz and Klakow, 2025 - IGC: Integrating a Gated Calculator into an LLM (arxiv:2501.00684) - оригинальная статья
- TechCrunch - Why AI can't spell 'strawberry' - про проблему strawberry
- TechCrunch - Why is ChatGPT so bad at math? - систематические тесты арифметики
- Loeber, 2024 - Notes on Arithmetic in GPT-4 - детальные эксперименты с умножением