Битва поколений: сравниваем Qwen3.5 и Qwen3.6 в локальном инференсе. Новое не всегда лучше

Я не планировал писать эту статью, я делал исследования для себя. Но в какой-то момент я понял, что это может показаться интересным и даже полезным кому-то еще. И вот вы читаете эти строки.
Это статья про исследование разных поколений больших языковых MoE моделей Qwen, применяемых для локального инференса.
Я рассчитываю, что читатель уже знаком с ИИ и LLM и хотя бы ориентируется в терминологии. Пространные пояснения очевидного будут только раздражать искушенного читателя, поэтому не буду подробно объяснять, что такое MoE или как запускать модели локально.
Почему локально, когда вокруг масса провайдеров ИИ, пользоваться услугами которых гораздо дешевле, чем иметь собственную инфраструктуру для инференса? Тут я, конечно, имею в виду такую инфраструктуру, которая в состоянии обслужить хотя бы десяток клиентов одновременно. Все просто - мы хотим обрабатывать наши данные, а вернее - финансовые данные наших клиентов, только локально. Да и наш регулятор, и наше подразделение ИБ за этим строго следят. Ну и, не буду кривить душой, нам это очень интересно - быть близко к передовой современных технологий.
Сейчас в качестве основной модели мы применяем Qwen 3.5 35B-A3B. Это MoE (смесь экспертов) модель на 35 миллиардов параметров с 3 миллиардами активных при обработке каждого запроса. Это на самом деле отличная модель, с очень приличным русским языком, прекрасно справляющаяся с теми задачами, которые мы ставили перед собой. Правда, наши программисты считают, что она тупая, потому что хуже современных фронтирных моделей Anthropic или OpenAI и не может писать программы на малоизвестном нишевом языке, на котором они вынуждены писать код. Но у тех, кто использует данную модель для более приземленных вещей, вроде экспертных систем, баз знаний или в агентском цикле, больших претензий к ней нет. Но веса модели были опубликованы на Hugging Face аж целых 7 месяцев назад и после этого вышли и Qwen 3.6, и Qwen 3.8. И у людей стали появляться вопросы, мол, почему мы до сих пор сидим на таком старье, когда на дворе столько нового. Ведь не может же новое быть хуже старого, так ведь? (тут должны быть мемные картинки «К лучшему, верно?» с Энакином Скайуокером и Падме Амидалой, но я взрослый человек, поэтому их нет) Внутренне я хотел согласиться с этим, но понимал, что без исследования нельзя ответить на этот вопрос однозначно. Поэтому для себя я ответил так: “Да, но нет”, - я обычно пользуюсь этим оксюмороном, когда быстрый ответ - “да”, которое может превратиться в “нет” после размышлений. Это и послужило причиной, по которой я приступил к исследованию. А прав я был или нет - каждый из вас сможет сделать вывод после прочтения статьи.
Исследование, про которое я пишу, нельзя назвать фундаментальным, да и даже обычным прогоном по десяткам бенчмарков, результаты которых мы можем найти в карточках моделей, оно не является. Но всё же оно не было поверхностным - оно продолжалось в течение 8 дней, а тестируемые модели “сожгли” почти миллиард токенов. В процессе было подготовлено 1.8 ГБ входных данных для тестов, а результаты заняли 4.6 ГБ.
Конечно, я бы не стал разбирать все это вручную. Если я был мозгом данного исследования, то моим помощником, техническим исполнителем моих идей была модель Anthropic Opus 5 - она занималась всей машинерией: писала обвязку для сбора и обработки тестовых данных, запускала инференс, следила за тем, чтобы карты не простаивали, анализировала результаты и помогала мне с написанием тезисов для этой статьи. Все выводы Opus проверяла другая современная и мощная модель OpenAI GPT-6 Astra, перепроверявшая результаты и дававшая конструктивную критику некоторых выводов. Такой кросс-чекинг дал мне больше уверенности в выводах, которыми я делюсь с вами. Забегая вперед, скажу, что некоторые результаты получились противоречивыми и я не буду навязывать вам свое мнение или объявлять явного победителя. Каждый волен сам трактовать те данные, которые я дам. И хотя все, что было написано до этого, написал я сам, в дальнейшем будут куски, написанные с помощью ИИ. Если бы не его помощь, этой статьи вообще бы не существовало. Я обещаю, что приложу все усилия, чтобы читать скучные данные было не скучно и чтобы у вас не было ощущения, что вы читаете очередной нейрослоп. Кстати, мне нравятся длинные тире и «ёлочки», поэтому буду использовать их тоже. Самое трудное в этом — найти откуда их копировать.
Участники
В начале задача выглядела просто: сравнить разные поколения одной модели между собой и решить, стоит ли переходить на новую. Как я уже писал выше, наша текущая модель — Qwen3.5-35B-A3B. Но чтобы обслужить как можно больше потребителей одновременно, нам пришлось пойти на компромисс: вместо полновесной модели с 16-битными весами мы используем «квантованную». Она занимает заметно меньше дефицитной VRAM, а освободившаяся память уходит под KV-кэш — хранилище контекста идущих диалогов. От его размера напрямую зависит, какое контекстное окно достанется каждому потребителю и сколько потребителей мы сможем обслужить одновременно. Поэтому полное название нашей модели — Qwen3.5-35B-A3B-GPTQ-Int4.
Мой электрический помощник упорно называет данную модель «инкумбент», а я не могу подобрать ёмкое русскоязычное обозначение, короче чем «текущая модель». Поскольку «инкумбент» короче, чем «текущая модель», на целое слово, то почему бы и не да? Пусть будет «инкумбент», мало у нас англицизмов, что ли? В дальнейшем я так и буду называть текущую модель, т. е. инкумбент, конечно.
Казалось бы, если вместо шестнадцати бит на вес оставить четыре, модель должна «поглупеть» в 4 раза — ведь именно веса в наибольшей мере задают её знания и умения. Логика подсказывает, что она превратится в «тыкву». Однако на практике благодаря особой «уличной магии» реальное ухудшение точности «скукоженной» (если вы не поняли эту шутку, значит, вы слишком молоды, смиритесь) 4-битной модели составляет всего считанные проценты. Сжимают обычно только экспертные слои — они и составляют почти весь вес модели, — так что на диске она худеет примерно втрое: с 67 до 20–25 ГиБ. А вот её «интеллект» остаётся практически нетронутым. Насколько именно квант отошёл от оригинала, можно измерить и напрямую — об этом в разделе про тесты.
Qwen3.5-35B-A3B-GPTQ-Int4 — официальный квант этой модели, выполненный самой лабораторией Tongyi, то есть автором моделей Qwen. К сожалению, ни для Qwen3.6, ни для вышедших следом Qwen3.8 и Qwen3.8-Flash-Next официальных квантов GPTQ-Int4 она больше не выпускала, а в последних и вовсе отказалась от линейки 35B-A3B. Во всяком случае, об их существовании мне ничего не известно.
Поскольку официальных квантов нет, пришлось искать чужие — благо на Hugging Face этого добра навалом.
Кандидаты
Для тестирования методом «научного тыка» были отобраны пять кандидатов — кванты нужной размерности одной и той же модели, Qwen/Qwen3.6-35B-A3B (в алфавитном порядке):
btbtyler09/Qwen3.6-35B-A3B-GPTQ-4bitcyankiwi/Qwen3.6-35B-A3B-AWQ-4bitpalmfuture/Qwen3.6-35B-A3B-GPTQ-Int4QuantTrio/Qwen3.6-35B-A3B-AWQTheHouseOfTheDude/Qwen3.6-35B-A3B_INT4
Здесь и далее я стараюсь приводить имена моделей так, как они указаны на Hugging Face, а для краткости называю кванты по имени мастерской: cyankiwi, QuantTrio и так далее.
Сильно забегая вперёд, скажу: после первых прогонов я засомневался, оправдана ли замена старого поколения на новое в нашей инфраструктуре, и решил добавить к сравнению ещё одну модель. Поскольку наши программисты жаловались, что инкумбент их не очень устраивает, я выбрал модель на той же базе, что и инкумбент: ornith-ai/Ornith-1.5-35B-A3B. Это модель, которая учится на задачах, придуманных ею же: авторы описывают замкнутый цикл, где она сама порождает задания, сама ищет способы их решить и на этом обучается. Она изначально заточена под программирование, и заявлено, что обходит Qwen3.6-35B-A3B на всех кодовых и агентских наборах. Судя по графикам в карточке модели, она должна была заметно опередить инкумбента в этой части.
А в комментариях к Ornith-1.5, насколько я помню, я и узнал о ещё более улучшенной её версии — peculiar-ragdoll/Tiel-Coder-35B-A3B-GGUF. Карточка Tiel-Coder обещает значительное превосходство над Ornith-1.5 и ставит модель на один уровень с Opus 4.6. Ух ты, подумал я, это определённо стоит попробовать! Загвоздка была в том, что Tiel-Coder существует только в формате GGUF, а мне был нужен safetensors, и прямая конверсия между этими форматами без потери качества невозможна.
Вскоре выяснилось, что никакого нового обучения Tiel-Coder не проходил. Это квантованная Ornith-1.5, но с изюминкой: авторы заменили шаблон чата на другой, тоже публично доступный, и сжимали модель по собственному рецепту со своей importance matrix. Что именно из этого подтянуло модель в программировании, по карточке не разделить. А для меня это значило, что я могу сделать свой собственный Tiel-Coder: переквантовать исходную Ornith-1.5-35B-A3B с изменённым шаблоном в нужный мне формат и, что главное, на собственном калибровочном наборе (~1270 образцов, ~1.4M токенов с обрезкой 4096 на образец). Его состав примерно такой: код и tool-calling — около 75%, русскоязычные тексты — около 40% (они пересекаются с кодом и tool-calling за счёт русских код-инструкций), профильные домены (PL/SQL, право, банки) — 10%. Само квантование заняло около 21 часа.
Так появилась модель, которую я назвал Humo-Coder — в честь Хумо, легендарной птицы, олицетворяющей в мифологии народов Центральной Азии и Ирана счастье, свободолюбие, удачу и благоденствие. Орнитологическая линия в названиях моделей продолжена.
И последний участник, вне конкурса, — эталон: чистая Qwen/Qwen3.6-35B-A3B без всякого сжатия, в bf16. Он не помещается в одну карту и работает на двух, поэтому в турнире не участвует, а служит точкой отсчёта: насколько кванты вообще отошли от оригинала.
Чем они различаются
У всех кандидатов экспертные веса — а это почти весь объём модели — сжаты до целочисленного 4-битного формата. Почему не до восьми бит — объясняется в разделе «Стенд»: у наших карт нет аппаратной поддержки FP8. В остальном же они все разные, хотя сходу это незаметно.
Первое отличие — метод квантования, их три:
AWQ (cyankiwi и, по крайней мере по названию, QuantTrio — к этому я ещё вернусь) прогоняет через модель калибровочные тексты, находит каналы, по которым идёт самый сильный сигнал, и защищает их от грубого округления.
GPTQ (btbtyler09, palmfuture, Humo-Coder и сам инкумбент) тоже калибруется, но иначе: сжимает веса по очереди и после каждого подправляет ещё не сжатых «соседей», чтобы выход слоя остался как можно ближе к оригиналу.
RTN (TheHouseOfTheDude) просто округляет каждый вес до ближайшего значения. Калибровка не нужна, делается быстро, но и ошибку округления компенсировать нечем.
Второе — размер группы: сколько весов делят между собой один масштабный коэффициент. Чем группа меньше, тем точнее квант — и тем чуть больше файл. Третье — что именно сжато. Это я проверял не по описаниям, а по самим файлам весов: у сжатого модуля рядом лежат упакованные веса и масштабы, у несжатого — обычный тензор.
модель | метод | группа | что сжато |
|---|---|---|---|
cyankiwi | AWQ | 32 | эксперты |
QuantTrio | AWQ без защиты каналов | 128 | эксперты (кроме первого слоя) |
btbtyler09 | GPTQ | 32 | эксперты |
palmfuture | GPTQ | 128 | эксперты |
TheHouseOfTheDude | RTN | 128 | эксперты, общий эксперт, слои полного внимания |
инкумбент | GPTQ, прошлое поколение | 128 | эксперты |
Humo-Coder | GPTQ | 32 | эксперты; общий эксперт — в 8 бит |
эталон | — | — | ничего |
Пятеро из семи сжимают только экспертов — на них приходится почти весь вес модели. TheHouseOfTheDude пошёл дальше всех: в четыре бита у него ушли ещё общий эксперт и слои полного внимания. Humo-Coder я сжал чуть больше, чем сжаты большинство остальных: общий эксперт у него тоже квантован, но бережно, в восемь бит.
А вот сколько каждый кандидат занимает. Все числа в ГиБ. Память на карте — то, что vLLM сам сообщает при запуске на карте с 48 ГБ VRAM, если разрешить ему занять 94% (--gpu-memory-utilization 0.94). Из этого бюджета вычитаются веса, активации и служебные буферы, а всё, что осталось, идёт под KV-кэш. Последний столбец — сколько запросов с полным окном в 131 072 токена поместится в кэш одновременно.
модель | на диске | веса на карте | под KV-кэш | полных окон |
|---|---|---|---|---|
cyankiwi | 23.25 | 22.87 | 19.35 | 7.33 |
QuantTrio | 23.71 | 22.23 | 19.99 | 7.57 |
btbtyler09 | 24.50 | 22.87 | 19.15 | 7.25 |
palmfuture | 22.74 | 21.12 | 20.94 | 7.93 |
TheHouseOfTheDude | 20.32 | 20.45 | 21.72 | 8.23 |
инкумбент | 22.74 | 21.12 | 20.94 | 7.93 |
Humo-Coder | 22.16 | 22.29 | 19.86 | 7.52 |
эталон (на двух картах вместе) | 66.97 | 65.72 | 19.72 | 7.47 |
Эталон не помещается в одну карту и работает на двух, поэтому его строка — сумма по паре: на каждой карте 32.86 ГиБ весов и 9.86 ГиБ под кэш. Две карты дают ему ровно столько же места под контекст, сколько квантам достаётся на одной карте. Разброс между участниками мизерный: от 19.15 до 21.72 ГиБ — разница меньше одного полного контекстного окна. Так что по объёму кэша ни один кандидат не получил заметного преимущества.
Кто и как калибровал
Из описаний моделей видно, что мастерские подошли к калибровке по-разному.
Калибровка — это прогон через модель небольшого набора текстов: так мы узнаём, какие веса на реальных данных важны, а какие можно округлять грубее. От того, что подсунули на калибровку, зависит, на чём сжатая модель просядет.
cyankiwi — единственная, у которой калибровочный набор заявлен как «STEM и агентский». Аббревиатура STEM расшифровывается как: Science, Technology, Engineering, and Mathematics (Естественные науки, Технологии, Инженерия и Математика). В карточке перечислены и десять языков, включая русский, хотя эта строка, судя по всему, описывает саму модель, а не набор.
palmfuture — имеет самую подробную карточку модели. Калибровка маленькая и смешанная: 102 куска общего текста, 77 инструкций, 51 кусок кода и 26 математических задач — всего 256 образцов, подобранных так, чтобы свой сигнал достался каждому из 256 экспертов. Автор честно приводит и статистику: GPTQ сошёлся на 97.42% модулей, остальные 2.58% свалились в простое округление.
btbtyler09 — самая аккуратная работа по описанию: сжаты только эксперты, все 30 720 модулей, а калибровочный набор в восемь раз больше, чем у palmfuture — 2048 образцов кода и общего текста.
TheHouseOfTheDude — описания нет вовсе, только рецепт: llm-compressor, схема W4A16. О калибровке неизвестно ничего.
Humo-Coder — калибровочный набор собран мной из общедоступных датасетов, состав я приводил выше. Это единственный участник, которого квантовал я сам.
Особняком стоит модель от QuantTrio, квантованная методом AWQ. В её описании написано следующее: data-free quantization, no calibration dataset was involved.
Заметили противоречие? Буква A в названии метода означает activation-aware: весь смысл метода в том, чтобы по статистике активаций найти каналы, которые нельзя огрублять. Откуда взяться статистике без данных?
Автор объяснил это в одной из веток обсуждения, и объяснение стоит того, чтобы его привести:
…ошибки распространяются. Если сосредоточиться на длинных текстах и калибровать на них, результаты на коротких, скорее всего, ухудшатся.
То есть отказ от калибровки здесь не небрежность, а позиция: калибровочный набор — это всегда выбор, на чём модель будет хороша, и молчаливое согласие, что на остальном она просядет. Автор решил не делать этот выбор за пользователя.
Но AWQ без активаций работать не может. Значит, «data-free» означает одно из двух: либо защитные коэффициенты посчитаны на синтетике, либо они попросту равны единице. Во втором случае от AWQ остаётся только формат упаковки весов, а само сжатие вырождается в обычное округление.
Проверить это оказалось проще, чем я думал. Защитные коэффициенты AWQ в файле не хранятся отдельно — они вшиваются в соседние слои: нормализация перед экспертами делится на коэффициент, а веса после неё умножаются. Эти слои остаются несжатыми, и их можно сравнить с оригиналом напрямую.
нормализация перед экспертами | компенсирующие веса | |
|---|---|---|
cyankiwi | отличается от оригинала: в одних слоях усилена, в других ослаблена, от 0.5 до 2.4 раза | обратный множитель, произведение ≈ 1.00 |
QuantTrio | совпадает бит в бит во всех 40 слоях | совпадают бит в бит |
У cyankiwi защита каналов работает и видна невооружённым глазом. У QuantTrio её не нашлось: нормализация перед экспертами и общий эксперт совпадают с оригиналом бит в бит во всех 40 слоях, а в выборочно распакованных экспертах видна только ошибка округления, без поканальной структуры. Это согласуется с простым округлением по группам, упакованным в формат AWQ, возможно с подбором порогов обрезки по самим весам. Полностью восстановить рецепт по весам нельзя, но похоже, что простым округлением в нашем турнире сжаты две модели, а не одна. Запомните и это — в результатах будет сюрприз.
Тесты
Набор тестов собирался не ради полноты, а вокруг конкретного применения: русскоязычный помощник, который отвечает людям, пишет код и вызывает инструменты. Ниже — что именно мы спрашивали у моделей. Тесты разбиты на шесть групп; в разделе с результатами они идут в том же порядке и под теми же именами. Что мы от каждого теста ожидали и что вышло на самом деле, расскажу в части с подробностями.
1. Русские пробы
Наши собственные, их три. Бюджет, как и во всех одноходовых тестах, — 32 768 токенов на ответ. В таблице результатов — доля верных ответов без подсказки (о подсказке ниже).
Города. Модели дают функцию «узнать погоду» и спрашивают, например: «Какая сейчас погода в Худжанде?» Засчитывается, если в аргументе стоит «Худжанд», а не
Khujand. Для человека разницы почти нет, а для программы она фатальна: база по такому ключу ничего не найдёт. Шестьдесят городов шестью слоями по редкости — от Екатеринбурга до Канибадама.Строки в коде. «Напиши функцию
format_bytes(n)с единицами Б, КБ, МБ, ГБ, ТБ». Модель, написавшая'KB', получает ноль. Сорок пять заданий.Параллельный вызов. Несколько вызовов инструментов в одном ответе с аргументами на русским. Сорок заданий.
У первых двух проб есть хитрость: каждое задание задаётся дважды — как есть и с одной добавленной строкой в системном промпте, которая прямо требует писать кириллицей: «Значения аргументов — строго кириллицей, без латиницы». Разница между ответами пары отвечает на вопрос: модель не умеет удерживать кириллицу — тогда лечится только сменой модели, — или не догадалась, что от неё этого хотят, — тогда хватит одной строки в конфиге.
2. Знания и рассуждение
Стандартные наборы. Бюджет — 32 768 токенов на ответ. В таблице — доля верных ответов.
GSM8K, 500 задач: школьные текстовые задачки в несколько действий. Проверяет, доведёт ли модель цепочку простых шагов до числа.
MMLU-Pro, 3500 вопросов по 14 предметам, обычно с десятью вариантами ответа. Проверяет широту знаний и умение не купиться на правдоподобный неверный вариант.
GPQA Diamond, 198 вопросов по биологии, химии и физике уровня аспиранта — таких, где специалист из соседней области даже с поиском отвечает верно примерно в трети случаев.
3. Код одним ответом
Модель выдаёт решение за один ответ, без права на исправление. Бюджет — 32 768 токенов на ответ. В таблице — доля задач, прошедших тесты.
MBPP+, 200 задач на Python попроще, но с дотошными тестами.
MultiPL-E Go, 154 задачи: классический HumanEval, переведённый на Go. Модели дают заголовок файла и просят дописать функцию; вердикт выносит компилятор и тесты.
4. Код в агентском цикле
318 задач на Go с AtCoder и Codeforces из LiveCodeBench, средних и трудных поровну. Модель читает условие и получает три инструмента: собрать, запустить на примерах из условия и сдать. Она видит ошибки компилятора и может их исправлять — как живой разработчик. Скрытые тесты ей не показывают никогда: их прогоняют уже после сдачи. Две оговорки. Крупные скрытые тесты при подготовке набора мы отфильтровали, так что проверяется правильность на умеренных входах, а не асимптотика: квадратичное решение может пройти там, где на соревновании требовалось n log n. И задачи публичные — знакомы ли они моделям по обучению, мы не проверяли. Бюджет здесь устроен иначе: до пяти раундов, до 65 536 токенов на один ответ и не больше 196 608 токенов на всю задачу. В таблице — число верных решений из 318.
5. Вызов функций: BFCL
Berkeley Function Calling Leaderboard, 3071 задача в 20 категориях: одиночные вызовы, параллельные, многоходовые диалоги, работа с памятью и — что особенно ценно — проверка на сдержанность: не звать инструмент, когда звать не надо. Две категории с поиском в интернете пришлось исключить: для них нужен ключ к внешнему сервису. Бюджет — 32 768 токенов на каждый ответ. В таблице — число решённых задач из 3071.
6. Близость к оригиналу: KL-дивергенция
На каждом шаге модель выдаёт не одно слово, а вероятности для всего словаря. KL показывает, насколько этот расклад у кванта отличается от расклада эталона на том же тексте: чем меньше, тем точнее квант повторяет оригинал. Корпус — проза, редкие кириллические слова, код на трёх языках, агентские диалоги; всего 317 713 позиций (предсказанных токенов). Строго говоря, наш KL — приближение: движок отдаёт 64 самых вероятных токена на позицию, и расхождение считается по их пересечению, а не по всему словарю. Такие числа годятся для сравнения квантов между собой на одной и той же части корпуса (срезе) — например, только на коде или только на прозе, — но не как абсолютная величина. Здесь измеряется не поведение, а то, насколько сжатая модель перестала быть собой. В таблице — медианный KL на срезе с нашими пробами. Посчитать его можно только для квантов того же исходника, что и эталон, поэтому у инкумбента и Humo-Coder прочерк.
Было и несколько пилотных проб: поиск иголки в стоге сена, десять задач на Python с исполнением, десять многоходовых сценариев, проба на многословие. Они проверяли механику стенда, а не модели, и в таблицы результатов не входят. Иголку, например, нашли все шестеро во всех 45 попытках — различать там нечего.
Как читать результаты
Дальше будет много пар вроде «97.4% против 97.2%». Чтобы понять, значит ли такая разница хоть что-то, процентов мало — нужно посчитать, на скольких задачах модели разошлись и в чью пользу.
Две модели решают одни и те же задачи. Большинство из них решили обе модели или провалили тоже обе — такие задачи о разнице моделей ничего не говорят. Остаются те, где модели разошлись: одна решила, другая нет. Скажем, из пятисот задач модели разошлись на семи, и счёт 4:3. Может ли монета за семь бросков выпасть четыре раза орлом и три раза решкой? Запросто. А в другом раунде бросков счёт вполне может быть уже 3:4 — и модели поменяются местами в таблице. А вот если из 36 расхождений 30 в пользу одной модели, случайностью это объяснить уже трудно.
У этого метода есть имя — критерий Макнемара. Он даёт число p: вероятность увидеть такой же или ещё более сильный перекос, если допустить, что разницы между моделями нет вовсе и каждое расхождение — просто бросок честной монеты. Чем меньше p, тем труднее объяснить такой перекос случайностью.
Когда пар много, порог приходится ужесточать: при двадцати одной паре семи моделей различие считается установленным, если p меньше 0.0024 (это 0.05, делённое на 21 пару), когда в сравнении участвует и эталон, пар двадцать восемь, и порог — 0.0018.
Почему порог именно такой? Это поправка Бонферрони: общий порог ошибки 0.05 делится на число сравнений. Она самая простая и одна из самых строгих, зато её легко проверить, и результат не зависит от того, в каком порядке перебирать пары. Есть поправки мягче при том же контроле ошибок — например, поправка Холма. Мы проверили, изменила бы она что-нибудь там, где значения p подходят к порогу ближе всего — в агентском цикле. Не изменила. Холм перебирает пары от самой значимой к наименее значимой и останавливается на первой, не прошедшей свой порог. Первые восемь пар он пропустил — те же, что и Бонферрони, — а на девятой (palmfuture против cyankiwi, p = 0.0042 при пороге 0.0038) остановился. При обеих поправках установленными оказываются одни и те же пары. Семейство сравнений у нас — все пары моделей внутри одного набора. Где сравнения дробятся ещё и по категориям, как в BFCL, я говорю о поправке отдельно.
И главное: «различие не установлено» не означает «модели равны». Это значит лишь, что этот прибор на этой выборке разницы не видит.
Ещё три понятия, без которых дальше не обойтись.
Бюджет — сколько токенов модели разрешено потратить на ответ. Если она исчерпала его, так и не ответив, это обрыв по бюджету. Обрывы бывают двух видов. Иногда модель рассуждает осмысленно, но ей просто не хватило места — это честный обрыв. А иногда она ходит по кругу, раз за разом повторяя одни и те же фразы, — это зацикливание. Отличает одно от другого наш датчик: он берёт последние 8000 символов оборванного ответа, режет их на строки и смотрит, сколько среди них различных. Если строк не меньше двадцати, а различных среди них меньше четверти, ответ считается зацикленным. Датчик сверяли с независимой разметкой всех 134 обрывов, накопившихся к 20 сентября, — совпали в 92% случаев.
Но у датчика есть слабое место: он ловит только дословные повторы. Модель, которая ходит по кругу, каждый раз перефразируя одни и те же мысли, для него выглядит как честно рассуждающая. Поэтому все 301 обрыв во внешних наборах мы дополнительно показали независимой модели-судье, GLM-5.3 Flash, не из семейства Qwen. Она прочла последние 8000 символов каждого оборванного ответа и отнесла его к одному из трёх видов: модель ходит по кругу, модель уже остановилась на ответе, но не успела его выдать, или модель действительно продолжала работу. Выборочно я сверил её вердикты с самими текстами: из 11 проверенных 9 подтвердились, 2 оказались спорными. Судья — такой же прибор, как датчик, только тоньше: о правильности решений он не судит, её по-прежнему определяют тесты. Разница оказалась разительной: из 163 обрывов, которые датчик счёл честными, к продолжающейся работе судья отнёс лишь 37. В 87 модель ходила по кругу, перебирая одни и те же варианты и не решаясь выбрать, а в 39 уже нашла ответ, но так и не выдала его. Тем же способом судья разобрал и 603 обрыва агентского цикла, и там картина ещё резче: из 365 «честных» обрывов по датчику честными на самом деле оказались лишь 51.
Отсюда два балла. Сырой балл — доля верно решённых задач из всех: любой обрыв засчитан провалом, ведь модель, не давшая ответа, задачу не решила. Он основной, и все выводы строятся на нём. Балл по правилу стенда не засчитывает провалом честные обрывы — те, где, по вердикту судьи, модель продолжала работу: такие задачи просто исключаются из подсчёта, потому что в них, возможно, модели просто не хватило бюджета. Это гипотеза: судья видит только хвост ответа, и увеличением бюджета мы её не проверяли. Поэтому этот балл — вторичный и условный. Зацикливание, как и ответ, найденный, но не выданный, остаётся провалом в обоих баллах. Балл по правилу стенда я показываю в скобках рядом с сырым там, где они различаются, а где он меняет вывод, говорю об этом отдельно.
Стенд
Итак, сервер, на котором всё проводилось и который дальше я буду называть стендом, имеет следующие характеристики:
карты | 4 × NVIDIA RTX A6000, 48 ГБ, архитектура sm_86 |
связь | карты 0–1 и 2–3 связаны NVLink попарно, между парами только PCIe |
процессоры | 2 × Intel Xeon Platinum 8470, 52 ядра каждый, 208 потоков |
память | 1 ТБ, два узла NUMA — по одному на пару карт |
движок | vLLM 0.29.0, torch 2.13.0, CUDA 13.0 |
система | Ubuntu 24.04.5, ядро 6.8, драйвер 595.91 |
Стенд боевой: на тех же картах работает модель, которой пользуются наши сотрудники, поэтому большую часть серии тесты шли на двух свободных картах. Для агентского цикла и BFCL, самых долгих наборов, мы на время освобождали ещё одну карту, и они шли на трёх. Каждый кандидат занимал одну карту. Делить модель между многими картами на этом железе невыгодно: по нашему замеру одна модель, разложенная на все четыре карты, выдаёт 410 токенов в секунду, а две её копии, каждая на своей паре карт, — 714 вместе.
Архитектура sm_86 объясняет, почему все участники четырёхбитные. Тензорных ядер FP8 у A6000 нет: восьмибитные модели запускаются, но без аппаратной поддержки формата, и выигрыш в скорости, ради которого их берут, съедается. Практический выбор на этих картах — четыре бита через ядра Marlin.
Настройки движка одинаковы у всех и заморожены на всю серию: окно в 131 072 токена, кэширование префиксов, до 32 одновременных запросов. Единственное исключение — Humo-Coder: ему движок разрешал занять не 94% памяти карты, а 90%, так что кэш у него в серии был немного меньше, чем в таблице выше. На сами ответы это влиять не должно, а на планирование запросов и скорость могло — этого мы отдельно не измеряли. Параметры генерации — температура 0.6, top_p 0.95, top_k 20 — передаются явно в каждом запросе. Это не педантизм: если их не передать, vLLM возьмёт значения из файла настроек самой модели, и у моделей разных мастерских «одинаковый» запрос мог бы молча уйти с разными настройками. В этой серии настройки генерации по умолчанию у всех восьми моделей совпали, но полагаться на это нельзя.
Всё одной таблицей:
движок | vLLM 0.29.0, образ |
окно и кэш | 131 072 токена, кэширование префиксов, до 32 одновременных запросов, 94% памяти карты (у Humo-Coder — 90%) |
генерация | температура 0.6, |
бюджет | 32 768 токенов на ответ; в агентском цикле — до 5 раундов, до 65 536 токенов на ответ и до 196 608 на задачу |
повторы | каждая задача решалась один раз |
seed | 42 в настройках EvalScope (внешние наборы, BFCL, русские пробы); в агентском цикле не задавался |
инструменты | EvalScope — внешние наборы, BFCL и русские пробы; собственный скрипт — агентский цикл и KL |
Сырые результаты я пока не выкладываю, и причины скорее практические, чем принципиальные. Их почти пять гигабайт, и в них хватает служебного: журналы движка и обвязки с подробностями нашей внутренней инфраструктуры. Кроме того, авторы GPQA просят не публиковать их вопросы в открытом виде, чтобы те не попадали в обучающие данные следующих моделей, а ответы моделей эти вопросы цитируют.
Один прогон на задачу при температуре 0.6 означает, что при повторе отдельные ответы будут другими. Поэтому мы и сравниваем модели не по процентам, а по счёту расхождений с поправкой на случайность — об этом в разделе «Как читать результаты».
Результаты коротко
Для тех, кому некогда, — всё в одном разделе. Лучший результат в столбце выделен жирным; эталон вне конкурса и не выделяется. Но помните: лучший результат ещё не означает установленного различия. Баллы сырые; в скобках, где он отличается, — балл по правилу стенда.
Под каждой таблицей качества стоит таблица цены с теми же столбцами. В каждой её клетке два числа. Первое — сколько токенов модель в среднем выдала на задачу по всем задачам набора, включая нерешённые, зацикленные и оборванные: это полный счёт за набор. Второе — среднее только по задачам, которые модель решила верно: это цена одного правильного ответа, и сожжённые впустую бюджеты в неё не входят. Сравнивать второе число между моделями надо с оговоркой: у каждой свой набор решённых задач, и та, что решает больше трудных, выглядит дороже. В таблицах цены жирным выделен самый экономный результат.
1. Русские пробы — доля верных ответов
Все три столбца — ответы без подсказки о кириллице. «Города» взяты из отдельного прогона, где каждый город спрашивали один раз; парный прогон — с подсказкой и без — разобран в 1 разделе главы с подробностями, и его числа немного отличаются: инкумбент там набрал 59 из 60, Humo-Coder — 31. Это обычный разброс между прогонами при температуре 0.6. «Строки в коде» — половина парного прогона без подсказки.
Города | Строки в коде | Параллельный вызов | |
|---|---|---|---|
инкумбент | 100% | 95.6% | 100% |
palmfuture | 95.0% | 86.7% | 100% |
cyankiwi | 91.7% | 57.8% | 100% |
QuantTrio | 91.7% | 82.2% | 97.5% |
btbtyler09 | 90.0% | 71.1% | 97.5% |
TheHouseOfTheDude | 86.7% | 71.1% | 92.5% |
Humo-Coder | 45.0% | 77.8% | 60.0% |
эталон bf16 | 96.7% | 60.0% | 100% |
Цена: токенов на задачу, в среднем по всем задачам / по решённым
Города | Строки в коде | Параллельный вызов | |
|---|---|---|---|
инкумбент | 98 / 98 | 2034 / 1995 | 187 / 187 |
palmfuture | 987 / 448 | 2792 / 2216 | 523 / 523 |
cyankiwi | 212 / 204 | 3424 / 2697 | 511 / 511 |
QuantTrio | 399 / 381 | 2116 / 2200 | 451 / 457 |
btbtyler09 | 199 / 188 | 3389 / 3068 | 456 / 448 |
TheHouseOfTheDude | 395 / 386 | 3213 / 2137 | 615 / 592 |
Humo-Coder | 59 / 58 | 414 / 494 | 127 / 126 |
эталон bf16 | 454 / 438 | 1784 / 2185 | 528 / 528 |
2. Знания и рассуждение и 3. Код одним ответом — доля верных ответов
GSM8K | MMLU-Pro | GPQA | MBPP+ | MultiPL-E Go | |
|---|---|---|---|---|---|
инкумбент | 92.6% | 84.6% | 82.3% | 97.0% | 65.6% |
palmfuture | 97.2% (97.4%) | 84.9% | 82.8% (83.2%) | 98.0% | 76.6% |
cyankiwi | 97.4% | 85.4% | 80.8% (81.2%) | 93.5% | 79.9% |
QuantTrio | 97.2% | 85.2% | 82.8% (84.1%) | 94.5% | 82.5% |
btbtyler09 | 96.6% | 84.9% | 84.8% (85.7%) | 96.5% | 81.8% |
TheHouseOfTheDude | 97.0% | 83.8% | 80.3% (82.4%) | 95.0% | 53.9% |
Humo-Coder | 96.4% | 82.9% (83.2%) | 80.3% (85.5%) | 97.5% (98.0%) | 74.0% |
эталон bf16 | 97.8% | 85.3% | 82.3% (82.7%) | 94.0% | 59.1% (59.5%) |
В скобках — балл по правилу стенда, если он отличается от сырого: задачи, где модель честно не уложилась в бюджет и, по вердикту судьи, продолжала работу, исключены из подсчёта. Возможно, в этих обрывах модели просто не хватило места, но это гипотеза, а не измерение. И читать такой балл надо осторожно: не укладываются в бюджет обычно самые трудные задачи, и без них балл выходит завышенным. Заметнее всего разница у Humo-Coder на GPQA: в 12 задачах из 198 он честно не успел, и без них его результат вырастает с 80.3 до 85.5%. В русских пробах и BFCL честных обрывов практически нет, поэтому там скобок нет.
Цена: токенов на задачу, в среднем по всем задачам / по решённым
GSM8K | MMLU-Pro | GPQA | MBPP+ | MultiPL-E Go | |
|---|---|---|---|---|---|
инкумбент | 7364 / 5750 | 4013 / 3629 | 8619 / 7674 | 1290 / 1033 | 1516 / 1437 |
palmfuture | 4891 / 4618 | 2638 / 2501 | 8901 / 7812 | 2722 / 2553 | 13 603 / 12 416 |
cyankiwi | 2796 / 2697 | 2587 / 2438 | 7985 / 7139 | 4003 / 2910 | 15 538 / 15 381 |
QuantTrio | 2878 / 2744 | 2602 / 2444 | 7815 / 6813 | 3058 / 2175 | 14 192 / 13 401 |
btbtyler09 | 4044 / 3692 | 2543 / 2408 | 6953 / 6198 | 2742 / 2402 | 15 537 / 15 284 |
TheHouseOfTheDude | 2672 / 2573 | 2632 / 2472 | 8710 / 7306 | 3291 / 2670 | 17 054 / 13 458 |
Humo-Coder | 265 / 238 | 1885 / 906 | 8241 / 3688 | 1022 / 875 | 1225 / 1008 |
эталон bf16 | 2411 / 2329 | 2564 / 2411 | 7711 / 6409 | 2816 / 2298 | 18 613 / 13 992 |
То же самое одной картинкой: по горизонтали — цена, по вертикали — балл. Хорошо видно, что Humo-Coder почти везде стоит левее всех, а инкумбент на коде дешевле квантов, но на рассуждениях дороже.

4. Код в агентском цикле, 5. Вызов функций: BFCL и 6. Близость к оригиналу: KL-дивергенция
Агентский цикл, верных из 318 | BFCL, решено из 3071 | приближённый KL, медиана на срезе с пробами (меньше — лучше) | |
|---|---|---|---|
инкумбент | 164 | 2250 | — |
palmfuture | 132 | 2208 | 0.0175 |
cyankiwi | 163 | 2188 | 0.0110 |
QuantTrio | 162 | 2194 | 0.0167 |
btbtyler09 | 167 | 2219 | 0.0102 |
TheHouseOfTheDude | 152 | 2232 | 0.0369 |
Humo-Coder | 202 | 2206 | — |
Цена: токенов на задачу, в среднем по всем задачам / по решённым
Агентский цикл | BFCL | |
|---|---|---|
инкумбент | 26 389 / 13 409 | 954 / 687 |
palmfuture | 35 254 / 13 503 | 1598 / 1181 |
cyankiwi | 36 584 / 24 311 | 1647 / 1203 |
QuantTrio | 36 338 / 22 502 | 1629 / 1170 |
btbtyler09 | 36 289 / 20 426 | 1621 / 1227 |
TheHouseOfTheDude | 44 361 / 30 122 | 1668 / 1280 |
Humo-Coder | 16 784 / 8313 | 1109 / 641 |
В агентском цикле это все токены, выданные моделью за все раунды работы над задачей, в BFCL — за все ходы диалога.

Эталон в агентском цикле и BFCL не прогонялся, а KL у него по определению нулевой: он сам и есть точка отсчёта.
Что из этого установлено, а что нет:
Единого победителя нет. Лидер одной таблицы в другой оказывается в хвосте, и это не шум: даже статистически установленные различия смотрят в разные стороны (профили — в разделе «Выводы»).
Старая модель сдаёт позиции не везде. Инкумбент впереди на всех трёх русских пробах и по сумме BFCL, хотя перевес там не установлен, а в агентском цикле он значимо уступает только Humo-Coder и сам значимо обыгрывает palmfuture. Проигрывает он им на школьной арифметике — всем пятерым — и в дисциплине: в каждой четвёртой задаче объявляет решение готовым, ни разу его не собрав (подробности — в разделах 2 и 4).
Пять квантов Qwen3.6 друг от друга почти неотличимы. На арифметике и BFCL между ними нет ни одной установленной пары, в агентском цикле — одна из десяти, на MMLU-Pro — две (разделы 2, 4 и 5).
Обещанный сюрприз: из двух «округлителей» один худший, другой — среди лучших. TheHouseOfTheDude, у которого в четыре бита ушло больше всего, хуже всех на Go и дальше всех от оригинала. А между QuantTrio, который, судя по всему, тоже просто округляет, но только экспертов, и откалиброванным cyankiwi различие по правильности не установлено ни на одном тесте (разделы 3 и 6).
Humo-Coder — самый контрастный участник. В программировании он обыгрывает всех шестерых, лучший и на задачах с памятью. А на русских городах, параллельных и многоходовых вызовах и на MMLU-Pro — в хвосте (разделы 1, 4 и 5).
Латиницу лечит одна строка в системном промпте. Похоже, модели не разучились писать кириллицу, а просто не догадываются, что от них этого ждут (раздел 1).
Несколько тестов измеряли не то, что обещали: MultiPL-E Go — в основном компилируемость, а Java и JavaScript в BFCL — расхождение в записи типов (разделы 3 и 5).
Токены переворачивают таблицы. Humo-Coder на Go и арифметике на порядок дешевле квантов Qwen3.6. И это не потому, что он быстро сдаётся: на задачах, которые решили все восемь моделей вместе с эталоном (438 на арифметике и 19 на Go), его медиана — 179 токенов против 2–3.4 тысяч у квантов на арифметике и 567 против 10–15 тысяч на Go. Инкумбент дешевле квантов на коде и вызовах инструментов, но дороже на арифметике и MMLU-Pro. Если счёт за токены для вас важнее последних процентов точности, начинайте с таблиц цены. Только помните: считаются здесь выданные токены, а полный счёт зависит ещё от чтения входа, батча и нагрузки — его мы не измеряли.
Итак, может ли новое быть хуже старого? Как выяснилось, может — смотря в чём. Прав ли я был со своим «да, но нет», решайте сами.
Самые нетерпеливые могут на этом закончить. Дальше — подробности: чего мы ждали от каждого теста, что подтвердилось и что нет.
Подробности
Дальше — те же шесть групп тестов, но уже медленно и с объяснениями. Для каждой я сначала расскажу, чего мы от неё ждали, потом — что получилось на самом деле, и в конце — совпало ли одно с другим.
1. Русские пробы
Чего ждали. Русские пробы мы гоняли ещё в первой, маленькой серии, и там инкумбент не ошибся ни разу. Такой безупречный счёт на небольшой выборке часто оказывается случайностью: задания слишком лёгкие, и все упираются в потолок. Поэтому перед большим прогоном я записал в журнал предсказание: когда городов станет шестьдесят, инкумбент перестанет выглядеть безупречным. Была у меня и гипотеза о том, почему модели вообще ломаются на русских названиях. Редкое слово вроде «Канибадам» токенизатор разбивает на редкие токены, а веса, отвечающие за редкие токены, по идее, сильнее всего страдают при сжатии модели.
Что вышло. Предсказание не сбылось: инкумбент остался почти безупречным. Вот результат пробы с городами. Каждый из шестидесяти городов модель получала дважды: один раз без подсказки, второй — с той самой строкой «значения аргументов — строго кириллицей» в системном промпте. Обе половины сняты в одном прогоне, так что их можно сравнивать напрямую.
без подсказки | с подсказкой | |
|---|---|---|
инкумбент | 59/60 | 60/60 |
palmfuture | 59/60 | 60/60 |
btbtyler09 | 57/60 | 60/60 |
QuantTrio | 57/60 | 58/60 |
cyankiwi | 56/60 | 60/60 |
TheHouseOfTheDude | 51/60 | 60/60 |
Humo-Coder | 31/60 | 57/60 |
Внимательный читатель заметит, что эти цифры немного расходятся со сводной таблицей из раздела «Результаты коротко». Там был отдельный прогон, в котором каждый город спрашивался один раз и только без подсказки. В нём инкумбент набрал 60 из 60, а Humo-Coder — 27. Отдельные числа от прогона к прогону немного гуляют, но общая картина в обоих прогонах одна и та же.
Из этой таблицы я делаю три вывода.
Первый: новое поколение действительно чаще переходит на латиницу, но не всё. palmfuture идёт с инкумбентом вровень: в парной пробе у обоих по 59 из 60, а в однократной — 57 против 60, и такое различие вполне может быть случайным (p = 0.25). Значит, утверждать, что любой квант Qwen3.6 хуже инкумбента на русском, было бы сильнее, чем позволяют данные.
Второй, и практически самый важный: подсказка лечит почти всех. Одна строка в системном промпте поднимает пятерых из шести исходных участников до безупречных 60 из 60. У QuantTrio с подсказкой остаются два промаха, но они не про язык: оба раза модель вообще забыла передать название города. Humo-Coder с подсказкой вырастает с 31 до 57 — огромный скачок, хотя и не до конца. Со строками в коде то же самое: без подсказки модели пишут единицы кириллицей в 26–43 заданиях из 45, а с подсказкой — в 42–44. Именно ради этого мы и задавали каждое задание дважды. Без второй половины пары мы измерили бы, насколько модель догадлива, и назвали бы это её способностью. А на практике разница между «надо менять модель» и «надо дописать одну строчку в конфиг» очень велика.
Третий: гипотеза про редкие токены не подтвердилась там, где её удалось проверить. Замер KL, о котором речь пойдёт в шестом разделе, отдельно смотрел на срез с редкими кириллическими словами. Кванты разошлись на нём с оригиналом не сильнее, чем на обычной прозе. А вот связь редкости слова именно с переходом на латиницу мы отдельно не проверяли, так что здесь вопрос остаётся открытым.
Отдельно стоит сверить результат с тем, что подсказывают карточки моделей. Если разложить их рядом, прогноз напрашивается сам. cyankiwi, у которого калибровка заявлена как агентская, а в карточке перечислен и русский, должен выиграть на русских пробах. QuantTrio, не калиброванный вовсе, должен проиграть. А btbtyler09 с калибровочным набором в восемь раз больше должен оказаться точнее palmfuture, своего соседа по методу. Заранее такой прогноз мы в журнал не записывали, поэтому это не проверка предсказания, а просто сверка со здравым смыслом.
И здравый смысл здесь не помог. cyankiwi и QuantTrio набрали на городах ровно одинаково — по 55 из 60. Напомню, что у QuantTrio мы не нашли даже защиты каналов, то есть, похоже, простое округление сравнялось с калибровкой, сделанной как будто специально «под наш случай». А из двух GPTQ-квантов palmfuture, у которого калибровочный набор в восемь раз меньше, набрал даже чуть больше: 57 против 54, хотя такое различие вполне может быть случайным.
Совпало ли с ожиданием. Записанное заранее предсказание — нет: инкумбент остался почти безупречным. Но главный урок раздела в другом. Ни размер калибровочного набора, ни его состав, ни аккуратность мастерской не позволили предсказать, как модель поведёт себя на наших задачах. Узнать это можно только одним способом — прогнать модель на своих задачах. Что, в общем, и оправдывает всю эту работу.
2. Знания и рассуждение
Чего ждали. От GSM8K — потолка: школьную арифметику современные модели решают почти целиком, и различать там особенно нечего. От MMLU-Pro, самого большого набора в серии, мы ждали, что уж он-то хоть что-нибудь различит. А от GPQA — что на трудных вопросах уровня аспиранта разница между моделями наконец станет видна.
Что вышло. Почти всё вышло наоборот: глаз, глядя на проценты, подсказывал одно, а счёт расхождений говорил другое.
Начнём с GSM8K. Разброс там от 92.6 до 97.4%, и между пятью квантами Qwen3.6 не установлено ни одного различия. Зато отставание инкумбента установлено против каждого из них. Возьмём для примера cyankiwi. Из 500 задач большинство обе модели решили одинаково: обе верно или обе неверно. Разошлись они на 36 задачах, и в 30 из них верно ответил cyankiwi, а в 6 — инкумбент. Если бы модели были равны по силе, такой или более сильный перекос выпадал бы примерно семь раз на сто тысяч. С остальными квантами картина та же:
квант | задач, где решил только квант | задач, где решил только инкумбент | p |
|---|---|---|---|
cyankiwi | 30 | 6 | 0.00007 |
QuantTrio | 30 | 7 | 0.00019 |
palmfuture | 30 | 7 | 0.00019 |
TheHouseOfTheDude | 29 | 7 | 0.00031 |
btbtyler09 | 29 | 9 | 0.00166 |
Все пять значений p ниже порога 0.0024, так что это уже не монетка. Этот счёт — по сырому баллу, но и по правилу стенда он тот же. У инкумбента на этом наборе 29 обрывов по бюджету, и честных среди них нет: почти всегда он ходил по кругу. Причём в 11 случаях модель уже нашла верный ответ, но вместо того чтобы выдать его, снова и снова его перепроверяла, пока не кончился бюджет.
Причём на ту же арифметику инкумбент тратит больше всех: в среднем 7364 токена на задачу против 2672–4891 у квантов, а на решённую задачу — 5750 против 2573–4618. То есть на школьных задачах старая модель решает хуже и при этом дороже.
С MMLU-Pro вышла самая поучительная история. Разброс там всего два с половиной процентных пункта, от 82.9 до 85.4%, и по таблице кажется, что модели неотличимы. Но по сырому баллу из двадцати восьми пар (здесь участвует и эталон, поэтому моделей восемь) различие установлено в восьми: Humo-Coder уступает пятерым соперникам, а TheHouseOfTheDude — троим: эталону, cyankiwi и QuantTrio.
С Humo-Coder на этом наборе стоит разобраться отдельно. У него 76 обрывов по бюджету. Датчик счёл 70 из них честными, но разбор судьёй показал другое: в 52 случаях модель ходила по кругу, перебирая одни и те же варианты и не решаясь выбрать, в 9 уже нашла ответ, но не выдала его (в 7 из них — верный), и лишь в 9 действительно продолжала работу. Если исключить эти девять, все пять поражений Humo-Coder остаются установленными.
Восемь установленных пар при разнице в два с половиной пункта — это немало. Как такое возможно? Дело в том, что процент ничего не говорит о том, насколько односторонне модели расходятся. Возьмём cyankiwi и TheHouseOfTheDude. Их ответы разошлись на 230 вопросах из 3500, и в 143 случаях из этих 230 прав был cyankiwi. Если бы модели были равны, такой или более сильный перекос выпадал бы примерно три раза на десять тысяч попыток (p ≈ 2.7·10⁻⁴). Большой набор даёт много расхождений, и даже небольшой, но устойчивый перекос в них становится хорошо виден.
На GPQA (80.3–84.8%) не установлено ничего: на 198 вопросах расхождений между моделями набирается лишь несколько десятков, а на них виден только очень крупный перекос. Больше всех обрывов по бюджету здесь у Humo-Coder — 31, и в 12 из них он честно не успел; отсюда его заметная разница между сырым баллом и баллом по правилу стенда.
Совпало ли с ожиданием. С GSM8K — да, там действительно потолок, по крайней мере для квантов. С GPQA — нет: разницы между моделями он не показал. С MMLU-Pro — да, он различил. И это полезный урок: правило «если проценты рядом, значит, прибор ничего не видит» оказалось не правилом, а догадкой. Проверять надо счётом расхождений, а не на глаз.
3. Код одним ответом
MBPP+ и цена насыщенного теста
Чего ждали. Потолка. Его старший брат HumanEval+ в нашем предварительном замере, ещё до серии, дал 95.1%, и мы заранее считали MBPP+ просто проверкой того, что при сжатии ничего не сломалось.
Что вышло. Потолок действительно получился: от 93.5 до 98.0%. Но история на этом не закончилась.
Ещё до того, как пришли данные MBPP+, мы разбирали результаты другого набора по классам сложности, и мой ИИ-помощник предложил выбросить класс самых лёгких задач: все модели решают его на 100%, различать там нечего. Я возразил. На насыщенном тесте действительно бессмысленно сравнивать правильность, зато можно сравнить стоимость — сколько токенов модель тратит на один и тот же результат. В повседневной работе модель — это помощник программиста, и основной поток запросов состоит как раз из простых задач. Разница в цене на простых задачах умножается на их количество.
Через час пришли данные MBPP+ и подтвердили это. Возьмём cyankiwi и QuantTrio. По качеству они почти одинаковы: 93.5% против 94.5%, различие не установлено. А по расходу токенов разница есть. Чтобы сравнение было честным, мы взяли только 182 задачи, которые решили обе модели, и сравнили медианы: 1988 токенов у cyankiwi против 1730 у QuantTrio. QuantTrio дешевле в 1.15 раза, и это различие установлено (p = 0.0001).
Более того, оказалось, что для измерения стоимости насыщенный набор даже лучше трудного. Сравнивать цену честно можно только на тех задачах, которые решили все модели. Иначе не поймёшь, экономна ли модель или она просто сдалась, не доработав. На MBPP+ таких задач, решённых всеми шестью исходными участниками, 175, а на трудном наборе Go — всего 31. Чем ближе набор к потолку, тем больше в нём материала для сравнения цены. Поэтому HumanEval+, который мы после того предварительного замера в серию не включали, считая бесполезным, теперь стоит в очереди как тест на стоимость.
MultiPL-E Go: тест, который измерял не то
Чего ждали. Что этот набор покажет, насколько хорошо модели знают Go.
Что вышло. Этот набор дал самый большой разброс во всей серии: от 53.9% у TheHouseOfTheDude до 82.5% у QuantTrio, двадцать восемь процентных пунктов. Такому разрыву очень хочется поверить. Но стоило посмотреть, из чего он сложился, как вера пошатнулась. Провалы бывают двух видов: код не скомпилировался или скомпилировался, но выдал неверный ответ. Вот как они распределились у лучшего и худшего кванта:
провалов «не собралось» | провалов «неверный ответ» | |
|---|---|---|
лучший квант | 22 | 5 |
худший квант | 71 | 0 |
Почти все провалы у всех моделей — это код, который просто не собрался. Причина оказалась в самом наборе. Модели дают начало файла, в котором уже подключены пакеты testing и fmt, и просят дописать функцию. Самой функции эти пакеты не нужны, а Go отказывается компилировать программу, в которой подключённый пакет не используется. Модель оказывается в вилке: если она удалит лишний импорт, то нарушит инструкцию «дополни код выше», а если оставит — программа не скомпилируется. TheHouseOfTheDude на простой задаче smallest_change так и метался между «уберу fmt» и «оставлю fmt», пока не израсходовал все 32 768 токенов бюджета.
А у Humo-Coder шестнадцать провалов из сорока давала одна-единственная строка:
var _ = fmt.Sprintf // так можно
var _ = testing.T // так нельзя: testing.T — тип, а не значение
Это известный приём: чтобы компилятор не ругался на неиспользуемый пакет, в коде упоминают что-нибудь из него. Модель выучила этот приём, но применила его к типу, а не к значению, и компилятор такого не принимает. Мы удалили из этих шестнадцати решений только эту строку, ничего больше не трогая, и, по записи в журнале серии, все шестнадцать прошли тесты. Сама логика решения была верной везде.
Совпало ли с ожиданием. Нет. Балл MultiPL-E Go оказался смесью двух разных умений: знания Go и умения выкрутиться из противоречивого задания. Сравнивать модели по нему можно — задание у всех одно и то же, — но читать его как оценку знания Go нельзя. Показательно, что несжатый эталон занял на этом наборе седьмое место из восьми.
На этом же наборе нашлись ещё две вещи, о которых стоит рассказать.
Правило, которое могло работать в пользу слабейшего. Помните правило про обрывы из раздела «Как читать результаты»? Вот почему в нём важно отделять честный обрыв от зацикливания. TheHouseOfTheDude решил на Go 83 задачи из 154, а 33 его ответа оборвались по бюджету. Если исключить из подсчёта все 33, его результат вырастет с 53.9 до 68.6% — почти пятнадцать пунктов в подарок. Заслуженный ли? Из этих 33 задач 32 решил хотя бы один из остальных исходных участников, а 16 решили все пятеро: четыре кванта и инкумбент. В среднем на этих задачах соседи тратили 13 677 токенов при потолке 32 768, то есть задачи были вполне посильными. Разгадка в том, что 27 из 33 обрывов — зацикливания. Модель, которая ходит по кругу, задачу не решила, и провал ей засчитывается. Честных обрывов, где модель продолжала работу, у TheHouseOfTheDude по разбору судьёй нет ни одного: в остальных шести случаях он либо тоже ходил по кругу, либо уже нашёл ответ и не выдал его. Так что по правилу стенда его результат остаётся 53.9%, и никакого подарка нет. Вдобавок наш инструмент подсчёта проверяет, решают ли ту же задачу другие модели, и предупреждает, если решают.
Цена. На этом наборе разница в расходе токенов оказалась самой большой в серии. Инкумбент тратит в среднем 1516 токенов на задачу, а кванты Qwen3.6 — от 13 603 до 17 054, примерно в десять раз больше. На решённых задачах картина та же: 1437 против 12 416–15 381. Humo-Coder ещё экономнее: 1225 в среднем и 1008 на решённую. Но это свойство набора, а не поколения моделей: на GSM8K, как мы видели, дороже как раз инкумбент.
4. Код в агентском цикле
Чего ждали. Мы ожидали, что работа с инструментами обойдётся дороже, чем простой текстовый диалог: каждый вызов инструмента — это лишнее сообщение, лишний разбор и лишний круг. Должен честно оговориться: это ожидание не было записано в журнал до прогона, поэтому засчитывать его как настоящее предсказание нельзя.
Что вышло. Этот тест занял три карты примерно на три с половиной дня: 318 задач на каждую из семи моделей, всего 2226 прогонов. Прежде чем показывать таблицу, объясню её столбцы.
Результат модели здесь описывают две разные метрики, и складывать их в одну нельзя: они про разное.
Умение — сколько задач модель решила верно. Верным считается решение, которое проходит скрытые тесты, даже если модель так и не сдала его по правилам. Сюда входит и код, который модель предъявила в последнем ответе, но ни разу не собрала: такой код мы собрали и проверили сами. Код, оставшийся только в рассуждениях, не считается: модель его не предъявила.
Дисциплина — сколько задач модель сдала по правилам: хотя бы раз собрала код и нажала «сдать». Верность решения здесь не важна: модель, которая собрала, проверила и честно сдала неверное решение, вела себя как надо.
За каждую задачу модель получает до двух очков: одно за верное решение и одно за правильную сдачу. Сумма — ещё одна, общая мера, максимум 636 очков на 318 задачах.
Остальные столбцы таблицы:
Из верных не сдано — сколько верных решений модель так и не сдала по правилам. Код написан и работает, но модель не довела дело до конца.
Три столбца про обрывы — что происходило, когда ответ модели упирался в потолок 65 536 токенов, по вердикту судьи: петля — модель ходила по кругу; ответ найден — остановилась на решении, но так и не выдала его; честно не успела — продолжала новую работу.
Часов — сумма времени по всем задачам. Задачи шли параллельно на трёх картах, так что календарно всё заняло меньше.
умение, верных | дисциплина, сдано | сумма очков из 636 | из верных не сдано | петля | ответ найден | честно не успела | часов | |
|---|---|---|---|---|---|---|---|---|
Humo-Coder | 202 | 115 | 317 | 102 | 14 | 2 | 14 | 15.8 |
btbtyler09 | 167 | 120 | 287 | 58 | 77 | 4 | 8 | 33.7 |
инкумбент | 164 | 93 | 257 | 88 | 60 | 1 | 3 | 24.3 |
cyankiwi | 163 | 107 | 270 | 64 | 64 | 11 | 8 | 34.0 |
QuantTrio | 162 | 120 | 282 | 57 | 60 | 15 | 12 | 33.4 |
TheHouseOfTheDude | 152 | 102 | 254 | 63 | 104 | 17 | 3 | 37.8 |
palmfuture | 132 | 95 | 227 | 51 | 108 | 15 | 3 | 32.6 |
Честных обрывов в агентском цикле так мало, что балл по правилу стенда почти не отличается от сырого: Humo-Coder 66.4% (сырой 63.5%), btbtyler09 53.9% (52.5%), QuantTrio 52.9% (50.9%), cyankiwi 52.6% (51.3%), инкумбент 52.1% (51.6%), TheHouseOfTheDude 48.3% (47.8%), palmfuture 41.9% (41.5%).
На этом стенде часы — почти то же самое, что токены: скорость генерации у шести моделей из семи уложилась в полосу 94–96 токенов в секунду. Исключение — TheHouseOfTheDude с 103.7 токена в секунду: по токенам он обходится примерно на 9% дороже, чем выглядит по часам.
Главный результат виден сразу: Humo-Coder обыгрывает всех шестерых соперников по умению. Каждое из шести сравнений с ним проходит порог значимости, даже самое близкое — с btbtyler09 (p = 0.0017). И обходится он дешевле всех: в среднем 16 784 токена на задачу против 35–44 тысяч у квантов Qwen3.6, а на решённую задачу — 8313 против 13.5–30 тысяч. Поэтому и времени на весь набор у него ушло в полтора раза меньше, чем у инкумбента, и больше чем вдвое меньше, чем у квантов. А вот между самими квантами установлено всего одно различие из десяти возможных пар: btbtyler09 обыгрывает palmfuture со счётом 63 к 28. Остальные девять пар различить не удалось. Инкумбент по умению от квантов почти не отличается: он значимо обыгрывает palmfuture (68 к 36), а с остальными различие не установлено.
Инкумбент, кстати, — главный выгодоприобретатель от проверки несобранного кода. Сорок два его верных решения лежали в последнем ответе, но так и не были собраны: без нашей проверки у него было бы 122 верных и последнее место, а с ней — 164 и место в середине таблицы.
Но интереснее самого балла оказалось то, что мы увидели, заглянув внутрь.
Две трети решений были готовы сразу. Мы посмотрели на самую первую сборку в каждой решённой задаче, где модель собирала код сама. Таких решений у семи моделей вместе 1079; ещё 63 верных решения нашлись при нашей проверке несобранного кода и в этот разбор не входят. В 743 случаях первая же сборка удалась, и код в ней совпал с итоговым. То есть в двух третях случаев работающая программа была написана с первой попытки. В 205 случаях первая сборка не удалась, модель прочитала ошибку компилятора и исправила код. В оставшихся 131 случае код собрался с первого раза, но модель всё равно продолжала его править, и не всегда по делу. В одной задаче, например, вся правка свелась к замене var stack []byte на stack := make([]byte, 0, len(s)) — это небольшая оптимизация, а не исправление ошибки.
Умение и дисциплина действительно расходятся. У Humo-Coder 102 задачи, в которых работающий код написан, но так и не сдан, — это половина всего, что он решил. Инкумбент страдает другим недостатком: в 80 задачах из 318 он объявил решение окончательным, ни разу его не скомпилировав. Для сравнения: у cyankiwi таких случаев 40, у QuantTrio 36, а у Humo-Coder ни одного. Получается, один проверяет и не сдаёт, а другой сдаёт непроверенное — и в половине таких случаев, как мы видели, решение всё-таки оказывалось верным. По дисциплине впереди btbtyler09 и QuantTrio, по умению — Humo-Coder, по сумме очков — снова Humo-Coder.
Как модели жгут бюджет. Когда ответ упирается в потолок, модель почти всегда ходит по кругу. Иногда дословно — как TheHouseOfTheDude в задаче abc310_f: рассуждение начинается вполне по делу, но примерно через 130 тысяч символов, это около 44 тысяч токенов, превращается вот в это:
Wait, `go` load balancer code.
Used.
Correct.
Wait, `go` scheduler code.
Used.
Correct.
Так модель и крутится, пока ответ не упрётся в потолок 65 536 токенов: весь ответ занял почти 190 тысяч символов. Такие петли ловит и датчик. Но чаще модель кружит, перефразируя: снова и снова пересматривает одни и те же идеи, каждый раз немного другими словами, и не решается ни на одну. Такое видит только судья.
По его вердикту больше всего петель у palmfuture (108) и TheHouseOfTheDude (104), у остальных квантов — от 60 до 77, у инкумбента — 60, а меньше всех у Humo-Coder — 14. Честных обрывов, где модель продолжала новую работу, мало у всех: от 3 до 14 на 318 задач, и больше всего их как раз у Humo-Coder. У него доля обрывов, где модель продолжала работу, выше, чем у всех остальных: 14 из 30, столько же, сколько петель. palmfuture же не решил ни одной из своих долгих задач: на них он почти всегда ходил по кругу.
Больше половины времени карты работают почти впустую. Задачи дольше десяти минут — от 12 до 42% набора у разных моделей — съедают 54–76% всего времени, а решений в них на всех семерых нашлось девятнадцать. Что с этим делать, — в разделе «Что дальше».
Инструменты против простого текста. Часть задач мы прогнали и без инструментов: модель присылает код текстом, скрипт сам его компилирует и возвращает ошибку. На 79 задачах у cyankiwi и 84 у QuantTrio работа через инструменты вышла немного дешевле, но насколько — зависит от способа счёта: по медианам расхода на 12–17%, по медиане отношений на каждой задаче — всего на 2–9%. Решено при этом текстом даже чуть больше: 41 против 34 и 42 против 40. Что именно дало разницу, неполный опыт не показывает: способы различаются сразу в трёх вещах — кто решает, когда вызвать компилятор, можно ли запустить программу на примерах и когда модель останавливается.
Совпало ли с ожиданием. Нет: работа через инструменты оказалась не дороже, а немного дешевле текста, хотя разница и невелика. И ещё одна важная оговорка. Весь этот набор — программирование на Go, а Humo-Coder изначально заточен под код. Он выиграл на своём поле, и вывод «он лучше для любой агентской работы» отсюда не следует. На русских пробах, как мы видели, он последний.
5. Вызов функций: BFCL
Чего ждали. Во всех наших тестах не хватало одной проверки: умеет ли модель не вызывать инструмент, когда вызывать его не нужно. Мы ждали, что BFCL закроет эту дыру.
Что вышло. Дыру он не закрыл: на этой проверке все семь моделей показали от 87 до 90%, и различий между ними нет. Общий балл тоже не различил никого. Разброс от 2188 до 2250 решённых задач из 3071 — это два процентных пункта между первым и последним, и ни одна из двадцати одной пары моделей не прошла порог значимости. Полтора суток работы трёх карт, двадцать одна тысяча прогонов, полмиллиарда входных токенов — и ни одного установленного различия.
Но стоило разложить общий балл по категориям, как внутри нашлись два крупных эффекта, которые смотрят в противоположные стороны.
Работа с памятью. В этих задачах модель должна запомнить сведения из диалога и позже правильно ими воспользоваться. Humo-Coder справился с 71.4% таких задач, а худший из остальных — лишь с 48.4%. Разрыв в двадцать три пункта, и все шесть сравнений с Humo-Coder значимы. Здесь, правда, нужна оговорка. 465 задач на память — это на самом деле 155 вопросов, каждый из которых задан в трёх разных режимах, и все они опираются на пять общих историй. То есть задачи не вполне независимы друг от друга. Если считать вопрос решённым, когда модель справилась с ним хотя бы в двух режимах из трёх, преимущество Humo-Coder всё равно сохраняется, а вот более мелкие различия между остальными моделями пропадают.
Многоходовые вызовы. Здесь модели нужно провести с пользователем несколько ходов, вызывая инструменты по ходу диалога. И тот же Humo-Coder здесь последний: 385 задач из 800 против 445 у лучшего. Насколько надёжно это отставание, зависит от того, насколько строго считать. При самом строгом счёте, когда поправка делается на все двадцать категорий сразу, оно установлено против двух соперников, а при обычном пороге 0.0024 — против четырёх. И ещё одна оговорка: обе эти группы категорий, память и многоходовые вызовы, мы выделили уже после того, как увидели ровный общий балл. Поэтому для следующей серии это гипотеза, которую надо проверить заново, а не заранее поставленный опыт.
Общий балл сложил выигрыш Humo-Coder в памяти с его проигрышем в многоходовых вызовах и выдал ровную линию, на которой Humo-Coder стоит пятым из семи. Усреднение не заглушило шум, а спрятало в себе два настоящих эффекта с разными знаками — и они погасили друг друга.
Java и JavaScript. Ещё одна странность BFCL: в категориях на Python все модели набирают 92–94%, на Java — 37–39%, на JavaScript — 32–38%. Разрыв в два с половиной — три раза, и он одинаков у всех семи моделей. Объяснение «модели плохо знают неродные языки» напрашивается само, но стоит открыть вердикт проверяющего кода, как картина меняется:
ответ модели: "useShortName": true
вердикт: Expected type String, got bool.
Схема функции объявляет этот параметр логическим, и модель честно возвращает логическое значение true. А проверяющий код ожидает строку "true", потому что в этих категориях все значения по соглашению записываются строками. На ошибки из-за расхождения типов приходится около 80% всех провалов на Java и JavaScript. Назвать «исправленный» балл по этим данным нельзя, потому что в тех же ответах встречаются и настоящие ошибки. Но и читать баллы этих категорий как оценку знания языков тоже нельзя, пока мы не разберёмся с тем, как набор записывает типы.
Совпало ли с ожиданием. Нет. Проверку лишних вызовов BFCL не различил, зато наглядно показал, как общий балл может спрятать два крупных и противоположных эффекта.
6. Близость к оригиналу: KL-дивергенция
Чего ждали. Что это будет прибор чувствительнее поведенческих тестов. Поведенческий тест на каждое задание даёт только «да» или «нет», и шестьдесят заданий — это шестьдесят таких ответов. А здесь каждая из трёхсот с лишним тысяч позиций текста даёт целое распределение вероятностей, и никакой случайности при выборе ответа в замере нет.
Что вышло. Корпус для замера был разбит на девять частей — срезов: проза, код, агентские диалоги, наши пробы и так далее. Вот результаты на срезе с нашими пробами. Кроме медианного KL, в таблице есть совпадение лучшего токена: как часто самый вероятный следующий токен у кванта тот же, что у эталона.
модель группа KL≈, медиана совпадение лучшего токена
btbtyler09 32 0.0102 90.6%
cyankiwi 32 0.0110 90.7%
QuantTrio 128 0.0167 88.6%
palmfuture 128 0.0175 86.3%
TheHouseOfTheDude 128 0.0369 82.7%
Видны две вещи. Во-первых, кванты с группой 32 ближе к оригиналу, чем кванты с группой 128. Так получилось на восьми срезах из девяти. На этом срезе чуть ближе всех btbtyler09, но на большинстве остальных первенство у cyankiwi — разница между ними мала. Это ровно то, чего ждёшь от меньшей группы: чем меньше весов делят один масштабный коэффициент, тем точнее сжатие.
Во-вторых, TheHouseOfTheDude отошёл от оригинала вдвое дальше, чем любой другой квант, и так на всех девяти срезах. Это тот самый участник, который сжат агрессивнее всех, хуже всех выступил на Go и вместе с palmfuture чаще всех ходил по кругу. Цепочка «сжали больше — модель ушла дальше от оригинала — начались срывы» напрашивается сама. Но доказать её мы не можем: такой участник у нас один, и отделить влияние охвата сжатия от прочих его отличий — другого автора, другого рецепта — просто не на чем.
Зато здесь есть любопытное сравнение. QuantTrio, судя по всему, тоже округляет без защиты каналов, но сжимает только экспертов — и от оригинала он заметно ближе, чем TheHouseOfTheDude. Это согласуется с гипотезой, что охват сжатия важнее метода, но отдельного опыта, который изолировал бы этот фактор, у нас нет: модели различаются ещё и авторами, и списками исключений.
И отдельный сюрприз: по медиане приближённого KL QuantTrio ближе к оригиналу, чем palmfuture с полноценным GPTQ и такой же группой 128, причём на всех девяти срезах. По другим мерам преимущество не столь однозначно, так что превосходства одного метода над другим это само по себе не доказывает.
К этим результатам есть два предостережения. Первое: близость к оригиналу ещё не означает пользу. Сам несжатый эталон на наборе Go занял седьмое место из восьми, и квант, который точно его повторяет, повторит и его ошибки. Второе: различие по KL не обязательно проявляется в поведении. Разница между группами 32 и 128 хорошо видна по KL, а в агентском цикле из шести пар «группа 32 против группы 128» значимой оказалась одна.
Совпало ли с ожиданием. Да: этот прибор действительно оказался чувствительнее поведенческих тестов. И гораздо дешевле: замер всех пятерых квантов вместе с эталоном занял около получаса, тогда как полная поведенческая серия идёт сутки и больше. Поэтому в следующей серии мы начнём с KL. Не для того, чтобы отсеивать кандидатов по нему — порог отсева мы не устанавливали, — а чтобы сразу понять, к кому стоит присмотреться внимательнее.
Как нас обманывали собственные приборы
Отдельная глава — в духе «скандалов, интриг и расследований». Она о том, что инструменты измерения тоже умеют врать, причём убедительно. Расскажу о пяти случаях: каждый пригодится любому, кто сравнивает модели сам.
Колонка победителей. После первой серии у нас была таблица, где в одиннадцати строках из четырнадцати значилось имя лучшей модели. Выглядело солидно. Потом мы нашли в коде строчку, которая выбирала победителя: names[vals.index(win)], где win — лучшее значение в строке. При ничьей она возвращает того, кто стоит в списке первым. Если пять моделей набирали по 100%, «побеждала» та, что была записана выше в списке моделей. После исправления в таблице не осталось ни одного победителя по качеству.
Слепая зона. Первая серия была маленькой — от 30 до 50 заданий на тест. Мы посчитали, какую разницу тест вообще способен заметить на такой выборке. Оказалось, что на тридцати заданиях можно отличить безупречную модель только от той, что опустилась ниже 80%. Всё, что мельче, тест просто не видит. А все различия, которые мы видели в первой серии, были мельче. Так что вывод «модели не различаются» был неверным. Верный звучал бы так: «этот градусник измеряет только от сорока». Именно поэтому русские пробы мы и растянули с 36 заданий до 150.
Не тот статистический тест. Поначалу мы сравнивали итоги моделей так, будто каждая решала свой собственный набор задач. Для этого есть свой метод — точный тест Фишера. Но набор-то у всех был общий, а для общего набора правильный инструмент — тот самый счёт расхождений, критерий Макнемара. Когда мы пересчитали те же самые данные правильным методом, в девяти парах из десяти p стали меньше. Мы теряли чувствительность на ровном месте.
Правило исключения обрывов — о нём шла речь в разделе про Go. Если не отличать честный обрыв от зацикливания, разумное правило начинает дарить баллы тем, кто ходит по кругу.
Ноль, которого не было. По записям агентского цикла у инкумбента не было ни одного зацикливания на 318 задачах — единственного из семи. Красивое свойство, но ложное. Проверку обрыва на повтор добавили в нашу обвязку посреди серии, а инкумбент шёл в агентском цикле первым, и его обрывы записались без всякой проверки. Когда мы применили датчик к сохранённым ответам, он нашёл 54 петли из 64, судья — 60. В одной задаче модель до самого конца бюджета повторяет одну и ту же пару строк: «Wait, I need to make sure I don’t use min_sub of a child that is nil. Yes.» Урок простой: вывод прибора нельзя хранить готовым, его надо вычислять из сырых данных при каждом разборе — тогда исправление прибора доходит до всех прогонов сразу.
Ни одну из этих поломок не было видно снаружи. Все они давали правдоподобные числа, аккуратные таблицы и уверенные выводы. И именно поэтому их стоило искать.
Выводы
Вместо одного победителя у каждого участника получился профиль. Если свести его к одной мысли — что вы получаете и чем за это платите:
Инкумбент — надёжный собеседник для русскоязычного агента: на русском и в вызовах функций у него лучшие результаты среди участников, а на коде он ещё и экономен. Платите вы школьной арифметикой и небрежностью: в агентском цикле он то и дело сдаёт код, даже не попытавшись его собрать.
Humo-Coder — сильный и экономный программист, которому нельзя доверять русский язык без присмотра. Без подсказки о кириллице он искажает около половины названий городов, а половину своих верных решений так и не доводит до сдачи.
TheHouseOfTheDude — самый неудачный из вариантов: дальше всех от оригинала и хуже всех на Go, хотя по сумме BFCL неожиданно второй. Виноват ли в этом широкий охват сжатия, опыт не выделяет.
palmfuture — хорош на русском и почти не отличается от инкумбента на городах, но в агентском цикле слабее всех квантов и чаще всех ходит по кругу.
btbtyler09 — самый ровный из квантов: без ярких провалов, ближе всех к оригиналу на срезе с пробами и единственный, кто значимо обыграл соседа в агентском цикле.
cyankiwi и QuantTrio — близнецы по результатам при противоположных подходах к сжатию: между тщательной калибровкой «под агентов» и, по всей видимости, простым округлением различие по правильности не установлено нигде.
Что из этого следует на практике:
По карточке модели её поведение не предсказать. Карточка говорит, что мастерская делала и почему, и ничего — о том, что из этого выйдет у вас.
Проверять надо на своих задачах. И сперва убедиться, что тест измеряет то, что написано на его обложке.
Часть проблем лечится промптом, а не сменой модели. Одна строка про кириллицу стоит дешевле любой миграции.
Смотреть надо не на проценты, а на счёт расхождений. Разница в пять пунктов может ничего не значить, а разница в два с половиной — оказаться установленной.
Чего мы не проверяли
Чтобы не было иллюзии полноты, — чего в этой работе нет.
Длинный контекст в реальной работе. Была только «иголка в стоге сена», и её все прошли. Как модели ведут себя на длинных живых диалогах и больших документах, мы не измеряли.
Скорость под нагрузкой. Объём KV-кэша взят из оценки движка, нагрузочных тестов с десятками одновременных пользователей не было.
Качество длинных связных текстов на русском — писем, резюме, ответов клиентам. Русский мы проверяли только там, где его можно проверить механически: в аргументах вызовов и строках кода.
Мультимодальность. Картинки мы моделям не показывали вовсе, хотя зрительная часть у моделей этого семейства есть.
Безопасность и отказы — как модели реагируют на провокационные и запрещённые запросы.
Наш рабочий системный промпт. Все прогоны шли со штатным шаблоном чата каждой модели и с промптами самих тестовых наборов, а не с тем системным промптом, с которым модели работают у нас в бою. А статья сама показывает, что одна строка в промпте может заметно поменять результат.
Разброс между повторами. Каждая задача решалась один раз; устойчивость результата мы оцениваем статистически, а не повторными прогонами.
Что дальше
Список на следующую серию вышел не из планов, а из того, что в этой сломалось.
Разобрать запись типов в BFCL и переоценить уже сохранённые ответы на Java и JavaScript. Это дешевле всего: не нужно ни одного нового прогона модели.
Урезать потолок ответа, а не поднимать — и проверить парно, сколько решений это будет стоить.
Начинать с KL, чтобы за полчаса увидеть, кто ушёл от оригинала дальше всех.
Прогнать агентский цикл на русских условиях задач. Все 318 условий уже переведены; 200 из них сверены вручную, а 15 не прошли автоматическую проверку чисел и литералов и ждут правки.
Расширить многоходовые русские пробы. Десять сценариев проверили механизм, но различать модели на них нельзя.
Финал
Я начинал с вопроса «может ли новое быть хуже старого?» и с ответа «да, но нет». Неделя работы и почти миллиард токенов ответа «да» или «нет» не дали — и, как выяснилось, дать не могли, потому что вопрос был поставлен неверно. Новое оказалось лучше старого в одном, хуже в другом и неотличимым в третьем. А кандидат, взятый со стороны почти из любопытства, обыграл всех в программировании, ради которого его и взяли, почти везде оказался самым экономным — и провалился на русских пробах с вызовами инструментов.
Выбор между моделями — это выбор, какими провалами вы согласны платить. Решение принимает тот, кто платит за токены и отвечает за простой. А работа измерения — показать, где различие установлено, где не установлено и где прибор просто ничего не видит.
И, как выяснилось за эту неделю, последнее встречается чаще первых двух.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.