# Мини-движок SQL Модели пишут SQL-движок на чистом Python. Он должен отвечать так же, как SQLite: с теми же значениями, теми же типами и в том же порядке строк. Ответ каждой модели проверяют 464 скрытых теста и 5 замеров скорости, а эталоном служит настоящий SQLite. 28 октября 2026. Интерактивная версия: [report.html](report.html), все бенчмарки: [../index.html](../index.html) ## Полоса тестов ![Полоса тестов](charts/strip.svg) Каждая строка показывает один прогон модели, а каждое деление в ней означает один тест. Тёмное деление значит, что тест пройден, красное значит провал, серое значит, что код не запустился. Столбцы общие для всех прогонов и отсортированы от лёгких тестов к трудным. ## Что выяснили **Безупречно справились двое.** Claude Opus 5.5, запущенный агентом Claude Code, прошёл все 464 теста, а Kimi K3.1 Pro прошёл 460. Оба уложились в лимит скорости во всех пяти замерах. Протокол агента проверен: он ни разу не читал файлы и не запускал код. **Один и тот же Opus 5.5 набирает от 2% до 100%.** Всё решает глубина размышления. Агентом он думал около 118 тысяч токенов. Через API с адаптивным мышлением модель на этой задаче не думала совсем, даже на effort max, и прошла от 8 до 274 тестов. **Четыре модели из шести в рейтинге споткнулись об одну строку.** Это DeepSeek Flash (регистр имён функций), GPT-6.1 Sol (`COUNT(*)`), Qwen3.8-Max (`CASE WHEN`) и Opus через API (сравнение токенов). С правкой Qwen проходит 462 теста, GPT 445, DeepSeek Flash 431. Архитектура у них сильная, подвела невнимательность. GPT-6.1 Terra и DeepSeek V4 Pro и вовсе сдали код с синтаксической ошибкой. **Долгое размышление не гарантирует кода.** GLM 5.3 потратил на рассуждение весь лимит API в 131 тысячу токенов и не написал ни строки, поэтому его прогон вне рейтинга. Qwen думал 47 минут и написал почти идеальный код с одной опечаткой. **Локальной модели пока далеко до облачных.** Strata (Qwen3.8-Flash-Next в квантовании Q2 на домашнем ПК) с лимитом 128K дописала код до конца, но её токенайзер сломан в основе. Итог 32 теста из 464. ## Все прогоны | Место | Модель | Тесты | Ловушки | Случайные | Ошибки | Скорость | Время | Рассуждение | Всего токенов | Токенов/с | Строк кода | С правкой | |---|---|---|---|---|---|---|---|---|---|---|---|---| | 🥇 1 | Claude Opus 5.5 (агент, effort max) | 464 (100.0%) | 56/56 | 400/400 | 8/8 | 5/5 | 54 мин 49 с | 368.6K* | 379.4K | 115* | 1390 | — | | 🥈 2 | Claude Opus 5.5 (агент) | 464 (100.0%) | 56/56 | 400/400 | 8/8 | 5/5 | 32 мин 03 с | 118K* | 138.8K | 72* | 1868 | — | | 🥉 3 | Kimi K3.1 Pro | 460 (99.1%) | 54/56 | 398/400 | 8/8 | 5/5 | 23 мин 40 с | 25K | 35.4K | 25 | 1456 | — | | 4 | GPT-6.1 Sol | 376 (81.0%) | 40/56 | 328/400 | 8/8 | 2/5 | 6 мин 00 с | скрыто | 16.8K | 47 | 1185 | 445, скорость 5/5 | | 5 | Qwen3.8-Max | 294 (63.4%) | 52/56 | 234/400 | 8/8 | 5/5 | 47 мин 30 с | 98.6K | 114.3K | 40 | 2090 | 462, скорость 5/5 | | 6 | Claude Opus 5.5 (effort max) | 274 (59.1%) | 11/56 | 255/400 | 8/8 | 1/5 | 2 мин 25 с | 0 | 18.5K | 128 | 1556 | — | | 7 | DeepSeek Flash (V4.1) | 104 (22.4%) | 31/56 | 65/400 | 8/8 | 1/5 | 5 мин 49 с | 56.6K | 69.7K | 200 | 1990 | 431, скорость 4/5 | | 8 | Strata Q2, лимит 128K | 32 (6.9%) | 21/56 | 3/400 | 8/8 | 0/5 | 35 мин 20 с | 95.9K* | 110.8K | 52 | 1941 | — | | 9 | Claude Opus 5.5 (шлюз, chat) | 8 (1.7%) | 0/56 | 0/400 | 8/8 | 0/5 | 1 мин 47 с | скрыто | 14K | 131 | 1140 | 278, скорость 1/5 | | 10 | Claude Opus 5.5 (effort high) | 8 (1.7%) | 0/56 | 0/400 | 8/8 | 0/5 | 2 мин 06 с | 0 | 14.7K | 116 | 1265 | 24, скорость 1/5 | В колонке «С правкой» указан результат того же кода после исправления одной-двух строк. В рейтинг он не входит. «Токенов/с» показывает, как быстро модель пишет: все токены ответа, включая рассуждение, делённые на полное время ответа. ## Время ответа ![Время ответа](charts/time.svg) ## Сколько модель написала ![Токены](charts/tokens.svg) Синим показано рассуждение, бирюзовым код и ответ. Серый цвет значит, что провайдер не показывает, сколько ушло на рассуждение. ## Разбор по участникам ### Claude Opus 5.5 (агент, effort max) 464 теста из 464 и 5 замеров из 5, все замеры от 0,03 до 0,06 секунды, это быстрее, чем у агента с уровнем по умолчанию. Думал 55 минут и около 370 тысяч токенов, втрое больше обычного агента, а код вышел самым длинным, 1390 строк. Opus через API на том же `effort: max` не рассуждал вовсе и прошёл 274 теста. Протокол соблюдён: одно чтение задания и одна запись решения. ### Claude Opus 5.5 (агент) **464 теста из 464 и 5 замеров из 5, это единственный безупречный результат.** К тому же у него самые быстрые замеры скорости: от 0,04 до 0,08 секунды против 0,15–0,44 у остальных. Агент работал с чистым контекстом и ни разу не запускал код. В его протоколе ровно один вызов, запись файла, и это проверено. Прогон занял 32 минуты и около 139 тысяч токенов, из них примерно 118 тысяч ушло на рассуждение и 21 тысяча на код (оценка по кэшу контекста). От прогонов Opus через API (от 8 до 274 тестов) его отличает глубина размышления. В Claude Code модель работает с высоким effort и думает долго, а через API с адаптивным мышлением на этой задаче не думала совсем. ### Kimi K3.1 Pro 460 тестов из 464 и 5 замеров из 5. Все четыре промаха связаны с одной тонкостью. SQLite превращает дробь в текст с 15 значащими цифрами: `0.1+0.2 || ''` даёт `'0.3'`, а `1e20` даёт `'1.0e+20'`. Kimi делает это через `repr` Python и получает `'0.30000000000000004'`. Ещё `ROUND(2.675, 2)` у него дал 2.68 вместо 2.67, потому что SQLite округляет двоичное значение, а не десятичную запись. Kimi оказался самым медленным из облачных моделей (около 24 минут), но самым экономным по токенам. ### GPT-6.1 Sol 376 тестов из 464 и 2 замера из 5. Почти все промахи дала одна ошибка. Аргумент `COUNT(*)` хранится как узел `("*",)`, а две функции обхода дерева, `_resolve` и `_replace_alias`, его не знают. Поэтому любой запрос с `COUNT(*)` заканчивается ошибкой «bad expression», в том числе три замера скорости. С правкой двух строк код проходит 445 тестов и 5 замеров из 5, это второе место по качеству кода. Остальные промахи связаны с теми же тонкостями SQLite, что у Kimi, плюс `SUBSTR` с началом 0 и неверное деление в семи случайных запросах. Модель быстрая: 6 минут и 17 тысяч токенов. ### Qwen3.8-Max 294 теста из 464 и 5 замеров из 5. Одна ошибка ломает все `CASE WHEN` без операнда, это 168 тестов. Проверка `if not self.match_kw("WHEN")` сдвигает указатель и съедает первый WHEN. С правкой этой строки код проходит **462 теста и 5 замеров из 5, это лучший результат с правкой**. Остальной код почти безупречен. Это самый долгий облачный прогон: 47 минут и 99 тысяч токенов рассуждения. ### Claude Opus 5.5 (effort max) 274 теста из 464 и 1 замер из 5. Адаптивное мышление даже на `max` решило не думать: токенов рассуждения ноль, код пошёл с 4-й секунды, прогон занял 2,5 минуты. В части запросов не находятся колонки с алиасом таблицы (`Column not found: e.dept_id`), не работает ORDER BY по колонке не из SELECT, а JOIN сделан вложенными циклами и не укладывается в лимит скорости. Ошибок в одну строку нет, просто код менее тщательный. ### DeepSeek Flash (V4.1) 104 теста из 464 из-за одной опечатки. Парсер сохраняет имя функции в нижнем регистре, а проверка сравнивает его с `"COUNT"` и `"ABS"` в верхнем. Поэтому не работает ни одна функция и ни один агрегат. С правкой одной строки код проходит 431 тест и 4 замера скорости из 5. Архитектура хорошая, есть hash join и правильная работа с NULL, но модель ни разу мысленно не прогнала `SELECT COUNT(*)`. ### Strata Q2, лимит 128K 32 теста из 464 и ни одного замера скорости. Прошли только тесты на ошибки и простые запросы без `t.col`. С лимитом 128K модель уложилась: 35 минут, около 111 тысяч токенов, из них примерно 97 тысяч на рассуждение (сервер не отдаёт разбивку, это оценка по длине текста), 1941 строка кода. Но токенайзер сломан в основе. Точку в `e.id` он принимает за начало числа, и на этом падает 401 тест, а операторы `.`, `=` в части позиций и `%` он не знает вовсе. После правки двух строк результат тот же, 32 теста, то есть ошибка не в одной строке. Для локальной модели в квантовании Q2 это честная попытка, но до облачных моделей ей далеко. ### Claude Opus 5.5 (шлюз, chat) 8 тестов из 464, прошли только тесты на ошибки. Метод парсера `consume('IDENT')` сравнивает *значение* токена со словом «IDENT» вместо *типа*, поэтому падает любой `FROM <таблица>`. С правкой одной строки код проходит 278 тестов и 1 замер скорости из 5: JOIN вложенными циклами не укладывается в 60 секунд. Ответ пришёл за 1 мин 47 с, это 14 тысяч токенов, и первый текст появился на 3-й секунде, то есть почти без рассуждения. Через chat/completions шлюза не видно, как передаётся глубина рассуждения, поэтому Opus перезапущен через нативный `/v1/messages`. ### Claude Opus 5.5 (effort high) 8 тестов из 464. Токенов рассуждения ноль, прогон занял 2 минуты, и в коде **ровно та же ошибка**, что в прогоне через chat: `consume('IDENT')` сравнивает значение токена со словом «IDENT». Сам код при этом другой, то есть кэша не было. Значит, это устойчивая привычка модели. С правкой код проходит лишь 24 теста, дальше ломаются другие места. ## Задача Нужно написать один модуль на Python 3.12 с функцией `run_query(tables, sql)`. Пользоваться можно только стандартной библиотекой, модуль `sqlite3` и eval/exec запрещены. Движок должен понимать SELECT и DISTINCT, INNER, LEFT и CROSS JOIN, WHERE, GROUP BY, HAVING, ORDER BY по выражению, алиасу и номеру колонки, LIMIT и OFFSET, агрегаты внутри выражений, CASE, LIKE, BETWEEN, IN, IS и функции ABS, LOWER, UPPER, LENGTH, COALESCE, IFNULL, NULLIF, ROUND, SUBSTR. Значения, их типы (int, float, str, None), число строк и порядок должны совпадать с SQLite 3.45 без type affinity и без ICU. JOIN двух таблиц по 50 000 строк должен укладываться в 3 секунды. Полный текст: [task/task.md](task/task.md) ## Как проверяли - 56 ручных запросов с ловушками. Среди них целочисленное деление и `%` с отрицательными числами, `ROUND(2.5)` и `ROUND(0.125, 2)`, `NOT IN` со списком, где есть NULL, трёхзначная логика AND, OR и NOT. Ещё есть `LOWER` и `UPPER`, которые в SQLite меняют регистр только у латиницы, LIKE, который не различает регистр тоже только у латиницы, отрицательные аргументы `SUBSTR`, превращение дробей в текст при `||` (`0.1+0.2` даёт `'0.3'`), сортировка NULL, агрегаты по пустой таблице, LEFT JOIN с условием в ON и соединение таблицы с самой собой. - 400 случайных запросов из генератора с фиксированным seed. В них есть типизированные выражения глубиной до трёх уровней, восемь вариантов FROM и JOIN, агрегаты, GROUP BY, HAVING, DISTINCT, ORDER BY, LIMIT и OFFSET. - 8 запросов, которые обязаны закончиться ошибкой `ValueError`: синтаксическая ошибка, неизвестная таблица, колонка или функция, неверное число аргументов. - 5 замеров скорости на таблицах по 50 000 строк, на каждый даётся 3 секунды. Вложенными циклами в лимит не уложиться, нужен hash join. - Ответ сравнивается с настоящим SQLite. Значения и типы проверяются строго, int и float считаются разными, дроби сравниваются с точностью 1e-9. Если в запросе нет ORDER BY, порядок строк не важен. Строки с одинаковым ключом сортировки тоже можно выдать в любом порядке. - Сам стенд проверен эталоном, обёрткой над sqlite3. Он проходит 464 теста из 464 и 5 замеров из 5. ## Условия - Каждая модель получила одно и то же задание слово в слово, одним сообщением, без системного промпта и без инструментов. У модели был один ответ, и запустить свой код она не могла. - Запросы шли напрямую в API провайдера в потоковом режиме (`stream.py`), рассуждение было включено. У Qwen для этого служит `enable_thinking`, у GLM `thinking: enabled`, у GPT, Grok и Gemini `reasoning_effort: high`. Opus получал `thinking: adaptive` и `effort` high или max через нативный `/v1/messages`. Kimi и DeepSeek работали в режиме по умолчанию. - Лимит ответа выставлен на максимум, который разрешает API: у DeepSeek это 384K, у Qwen и GLM 131K, у остальных 128K. Strata получила 128K при контексте 131K. - В зачёт идёт код как есть. Если код ломается из-за одной опечатки, отдельно считается вариант с правкой одной строки. Он нужен только для понимания и в рейтинг не входит. - Время считается от отправки запроса до последнего токена. Оно зависит и от загрузки серверов провайдера, поэтому это не чистая скорость модели. - Opus 5.5 проверялся двумя способами: через API, как все остальные, и агентом Claude Code с чистым контекстом и запретом запускать код. У агента есть системный промпт Claude Code. ## Нюансы - В первой попытке DeepSeek Flash потратил все 64K токенов на рассуждение и не выдал код. Лимит занизили мы, поэтому модель перезапустили с 384K. У DeepSeek 1M означает размер контекста, а не длину ответа. - У аккаунта Moonshot для Kimi K3.1 Pro разрешён только один одновременный запрос. - Из России запросы к api.moonshot.ai больше примерно 16 КБ обрываются на ТСПУ, потому что сервис стоит за Cloudflare. Поэтому трафик к Kimi шёл через VPN роутера. - GPT-6.1 Sol, GPT-6.1 Terra, Grok, Opus 5.5 через API и Gemini 3.8 Flash работали через партнёрский шлюз. Мы проверили, что системный промпт он не подмешивает. GPT нормально работает через chat/completions. Claude полноценно работает только через нативный `/v1/messages`: через chat Opus на задаче не рассуждал. Gemini через шлюз не рассуждает ни при каких параметрах. - Strata это локальная Qwen3.8-Flash-Next в квантовании Q2 размером около 66 ГБ на домашнем ПК. С лимитом 64K её код оборвался на 1931-й строке, поэтому её перезапустили с 128K. - Генератор случайных запросов не использует арифметику над строками, сравнение числа со строкой и `%` над дробями, потому что задание явно исключает эти случаи. - GLM 5.3 упёрся в максимум API в 131 072 токена на одном рассуждении. Это ограничение модели и провайдера, а не наших настроек. - Opus 5.5 с адаптивным мышлением на этой задаче не думал вовсе, ни на `high`, ни на `max`: токенов рассуждения ноль, код пошёл с 4-й секунды. Остальные модели тратили на рассуждение от 25 до 130 тысяч токенов. - Ошибку в одну строку сделали четыре модели из шести в рейтинге: DeepSeek Flash (регистр имён функций), GPT-6.1 Sol (`COUNT(*)`), Qwen (`CASE WHEN`) и Opus через API (`consume('IDENT')`). Ни одна из них не прогнала в голове простейший запрос. - Время и токены Opus-агента оценочные. У субагента нет файла ответа, поэтому токены посчитаны по объёму, который попал в кэш контекста перед записью файла. Протокол агента проверен: он ни разу не читал файлы и не запускал код. - Opus-агент с `effort: max` добавлен 29.10.2026, после основного прогона, по тому же протоколу: одно чтение задания и одна запись решения, без запуска кода. Его запустили, чтобы сравнить с Opus через API на том же `effort: max`: через партнёрский шлюз модель рассуждает заметно меньше. Его время и токены посчитаны по журналу агента. ## Разминка Перед основной задачей была разминка: калькулятор выражений на `fractions.Fraction` с приоритетами `**`, унарным минусом, `%` как в Python, функциями, переменными и ошибками с позицией. Его проверяли 68 скрытых тестов из папки `warmup/`. - Kimi K3.1 Pro через `kimi -p` прошёл 68 тестов из 68 за 3 мин 19 с. - DeepSeek Flash через API прошёл 68 тестов из 68 за 2 мин 29 с и потратил 25 тысяч токенов на рассуждение. - Задача оказалась по силам обеим и не различает модели, поэтому основной стала более сложная задача. ## Исключены из рейтинга - **DeepSeek V4 Pro** (0 из 464): Код не импортируется из-за синтаксической ошибки, а после её исправления падает на каждом запросе. В отличие от большинства исключённых прогонов, это ошибка самой модели, а не API. Прогон исключён по решению автора бенчмарка. - **GLM 5.3** (0 из 464): Весь максимум API в 131 072 токена ушёл на рассуждение, и до кода модель не дошла. Это ограничение провайдера на длину ответа. - **GPT-6.1 Terra** (0 из 464): Код не импортируется из-за опечатки в словаре приоритетов операторов: `"!=", 4` вместо `"!=": 4`. Это ошибка самой модели. С исправлением одного символа код проходит 260 тестов из 464 и 1 замер скорости из 5, дальше ломается проверка зарезервированных имён. - **Gemini 3.8 Flash** (0 из 464): Партнёрский шлюз не включает у Gemini рассуждение ни одним параметром, и модель ответила заготовкой за 5 секунд. Это проблема доступа, а не модели. - **Strata Q2, лимит 64K** (0 из 464): Наш заниженный лимит 64K оборвал код на середине. Прогон заменён запуском с лимитом 128K. - **Grok 4.7** (0 из 464): Партнёрский шлюз каждый раз обрывал поток посреди рассуждения, и модель не успевала выдать ни строки кода. Это проблема доступа, а не модели. Grok стоит проверить через прямой API xAI. Три попытки оборвались на 383-й, 652-й и 252-й секунде. ## Участники | Модель | Разработчик | ID | Доступ | Лимит ответа | |---|---|---|---|---| | Kimi K3.1 Pro | Moonshot AI | `kimi-k3.1-pro` | API api.moonshot.ai (через VPN роутера) | 128K | | DeepSeek Flash (V4.1) | DeepSeek | `deepseek-flash` | API api.deepseek.com | 384K | | DeepSeek V4 Pro | DeepSeek | `deepseek-v4-pro` | API api.deepseek.com | 384K | | Qwen3.8-Max | Alibaba | `qwen3.8-max` | API token-plan.maas.qwencloudapi.com | 131.1K | | GLM 5.3 | Z.ai (Zhipu) | `glm-5.3` | API api.z.ai | 131.1K | | GPT-6.1 Sol | OpenAI | `gpt-6.1-sol` | партнёрский шлюз | 128K | | GPT-6.1 Terra | OpenAI | `gpt-6.1-terra` | партнёрский шлюз, `reasoning_effort: high` | 128K | | Claude Opus 5.5 (effort max) | Anthropic | `claude-opus-5-5` | партнёрский шлюз, нативный `/v1/messages`, `thinking: adaptive`, `effort: max` | 128K | | Claude Opus 5.5 (effort high) | Anthropic | `claude-opus-5-5` | партнёрский шлюз, нативный `/v1/messages`, `thinking: adaptive`, `effort: high` | 128K | | Claude Opus 5.5 (шлюз, chat) | Anthropic | `claude-opus-5-5` | партнёрский шлюз, `/v1/chat/completions`, `reasoning_effort: high` | 128K | | Claude Opus 5.5 (агент) | Anthropic | `claude-opus-5-5` | субагент Claude Code, чистый контекст, без запуска кода | — | | Claude Opus 5.5 (агент, effort max) | Anthropic | `claude-opus-5-5` | субагент Claude Code, `effort: max`, чистый контекст, без запуска кода | — | | Gemini 3.8 Flash | Google | `gemini-3.8-flash` | партнёрский шлюз | 128K | | Strata Q2, лимит 128K | локальный ПК | `qwen3.8-flash-next-q2_0` | Strata на 127.0.0.1:8080 | 128K | | Strata Q2, лимит 64K | локальный ПК | `qwen3.8-flash-next-q2_0` | Strata на 127.0.0.1:8080 | 64K | | Grok 4.7 | xAI | `grok-4.7` | партнёрский шлюз, `reasoning_effort: high` | 128K | ## Файлы | Путь | Что это | |---|---| | `README.md` | отчёт в формате Markdown | | `report.html` | страница отчёта с графиками, тёмной темой и подсказками | | `bench.json` | метаданные: участники, условия, нюансы и выводы, из них собирается отчёт | | `task/task.md` | задание, которое получили модели | | `harness/test_sql.py` | скрытые тесты, эталоном служит SQLite | | `harness/stream.py` | запросы к API моделей в потоковом режиме | | `harness/grade.py` | извлечение кода из ответа и прогон тестов | | `answers/.json` | ответ модели целиком: код, рассуждение, токены и время | | `solutions//solution.py` | код, который написала модель; в папке `-fix` он же с правкой одной строки | | `grades/.txt` | результаты тестов и список падений | | `charts/*.svg` | графики для README | | `warmup/` | разминка, калькулятор выражений |