Рубрики
Технологии

Пост @azTotMD — Искусственный интеллект (+1) — 07.09.2026 00:31

Современные LLM выдают вектор с вероятностями для каждого слова из словаря, а затем внешний алгоритм выбирает один из них (сэмплирует с температурой или берёт наивероятнейшний). Выбранный токен добавляется к входной последовательности и процесс повторяется, генерируя ответ токен за токеном.

Сложно ожидать, что такой подход даст приемлемое качество для вычисления арифметических выражений. Ситуация усугубляется тем, что чисел бесконечно много, а размер словаря ограничен. Т.е. надо ограничится цифрами и, возможно, рядом наиболее часто встречающихся чисел типа 42, 100, 666.

Можно, конечно, при обучении закидать модель синтетическими примерами. Но там ведь, наверное, не дураки сидят? Наверняка, инженеры добавили в контур к LLM какой-нибудь калькулятор, назовём его «арифметический сопроцессор». Цель языковой модели (или какой-нибудь другой, более легковесной) обнаружить арифметическое выражение внутри запроса пользователя, распарсить его и передать в «сопроцессор», а его результат уже подмешать в ответ. Кстати, что-то подобное существует в API и называется «вызов функций«, только функции выполняются на стороне клиента, а эта штука должна выполнятся в ифраструктуре провайдера модели.

Я поставил простенький эксперимент: отправлял в Gemini просьбу выполнить арифметическую операцию, причем для простоты задачи числа писал цифрами:

REQUESTS := {
    "+": ("Add {a} and {b}. Return only the answer as an integer.", operator.add),
    "-": ("Subtract {b} from {a}. Return only the answer as an integer.", operator.sub),
    "*": ("Multiply {a} by {b}. Return only the answer as an integer.", operator.mul)
}
OPERATIONS := list(REQUESTS)
for i in range(N):
    operation := random.choice(OPERATIONS)
    request, operator_func := REQUESTS[operation]
    a := random.randint(2352342, 988790923)
    b := random.randint(90835, 235221921)
    expected = operator_func(a, b)
    prompt := request.format(a=a, b=b)
    response := client.interactions.create(model=MODEL, input=prompt)
    print(f"{a} {operation} {b} | {expected} | {response}")

Модель gemini-3.6-flash справилась со всеми примерами, а вот результаты для gemini-3.1-flash-lite сильно удивили, пара примеров:

609522274 * 150089725 | 91483030486034650 | 91484542308365250

407417556 + 155449057 | 562866613 | 562866613

Все примеры на умножение — провалены, все примеры на сложение/вычитание — пройдены. Неужели она в самом деле пытается считать их LLM-ным способом и заваливается, когда длина последовательности становится слишком большой?

Читать дальше →