Ты платишь за бенчмарки, которые ничего не говорят о твоей задаче
MMLU, HumanEval, GSM8K — эти тесты давно превратились в спорт. Модели тренируются прямо на них, утечка данных — норма жизни. А ты смотришь на табличку с процентами и думаешь: "GPT-4o набрал 89% на HumanEval, значит, он и мой код починит".
Спойлер: не починит. Потому что твой код — не задача из бенчмарка. Твоя кодовая база — это легаси 2018 года, странные зависимости и бизнес-логика, которую не поймёт ни один eval.
Я DevOps, и последние полгода я собирал реальные сессии — промпты, которые я и моя команда реально отправляли в LLM за месяц. И знаешь, что? DeepSeek V4 (стоимость $0.15/M токенов) дал одинаковое качество с GPT-4o ($5/M) на 82% моих задач. Экономия в 37 раз — не маркетинг, а чистая математика.
Но чтобы это сработало, нужен персональный бенчмарк. Не абстрактный, а слепленный из твоих собственных сессий. Сейчас покажу, как сделать такой за вечер.
⚡ Важно: Подход работает для любых моделей — от OpenAI до открытых через Ollama. Я буду использовать цены на июнь 2026. Если ты ещё не знаком с локальным запуском, прочитай гид по Ollama — там всё разжёвано.
Почему 37? Математика не врёт
Берём среднюю задачу: генерация SQL-запроса по описанию (контекст ~4K токенов, ответ ~1K). Стоимость одного запроса:
| Модель | Цена за 1K токенов (вход+выход) | Стоимость одной задачи | 1000 задач/день |
|---|---|---|---|
| GPT-4o (OpenAI) | $0.005 | $0.025 | $25 |
| Claude 4 Opus (Anthropic) | $0.008 | $0.040 | $40 |
| GLM-5.2 (Zhipu) | $0.0006 | $0.003 | $3 |
| DeepSeek V4 | $0.00015 | $0.00075 | $0.75 |
| Kimi K2.6 (Moonshot) | $0.0002 | $0.001 | $1 |
DeepSeek V4 дешевле GPT-4o в 33 раза по токенам. А с учётом того, что на простых задачах DeepSeek не требует дополнительных попыток — экономия до 37x. Но только если твои задачи не ломают DeepSeek. А чтобы это проверить — нужен бенчмарк.
Как построить персональный бенчмарк: пошаговая мясорубка
1 Собери сырые сессии — каждое взаимодействие с LLM
Не надо придумывать тестовые сценарии. Бери реальную историю из прода — логи, прокси, расширения браузера. У меня всё это стекалось в ClickHouse через логгер, о котором я писал в статье про реалистичные бенчмарки.
Формат одной сессии:
{
"session_id": "abc123",
"system_prompt": "Ты эксперт по PostgreSQL...",
"messages": [
{"role": "user", "content": "Напиши запрос для поиска дубликатов email"},
{"role": "assistant", "content": "SELECT email, COUNT(*) ..."}
],
"metadata": {
"task_type": "sql_generation",
"expected_tokens": 150,
"user_rating": 5
}
}
Минимальный набор: 200-500 уникальных сессий. Если меньше — статистика шумит. Если больше — только лучше. Собирай минимум неделю, чтобы поймать разные паттерны.
Без рейтинга от пользователя — это мусор. Если не ставишь лайки ответам — смысла нет. Мы добавили в интерфейс кнопку "👍/👎" и получили 12K оценок за месяц. Только на них и строили бенчмарк.
2 Разметь задачи по типам и сложности
Просто "код" — слишком грубо. Дроби на: генерация SQL, рефакторинг Python, объяснение ошибки, написание тестов, оптимизация запроса. У нас получилось 8 категорий. Для каждой — своя метрика.
Я использовал LLM (GPT-4o-mini) для автоматической классификации. Промпт:
# Пример функции классификации
import openai
def classify_task(messages: list) -> str:
system = """Классифицируй задачу пользователя.
Варианты: sql_generation, code_review, debugging, refactoring, explanation, docs, other.
Ответь только одним словом."""
response = openai.chat.completions.create(
model="gpt-4o-mini-2026-06-24",
messages=[{"role": "system", "content": system}, messages[-1]],
temperature=0
)
return response.choices[0].message.content.strip()
Важно: Не забудь про экономию токенов при массовой классификации — там есть трюк, как не плодить черновики. Иначе потратишь на разметку больше, чем сэкономишь потом на моделях.
3 Прогони каждую сессию через кандидатов + получи оценку
Мы гоняли через: DeepSeek V4, Kimi K2.6, GLM-5.2, Qwen3.5-max, и локальную Llama 4 (через Ollama). Для каждого запроса — тот же системный промпт и история, что в оригинале. Ответы сохраняем.
Теперь нужно сравнить ответ кандидата с оригинальным (эталонным). Вариантов два:
- Если есть пользовательские рейтинги — используем их как ground truth. Сравниваем, как часто кандидат получает такую же или более высокую оценку.
- Если нет рейтингов — используем LLM-as-Judge. Промптом просим GPT-4o (или другую сильную модель) оценить ответы по шкале 1-5. Но есть подвох: судья тоже может ошибаться. Лучше брать несколько моделей и усреднять. Подробнее — в статье Lexometrica Ground Truth.
Я сделал так: прогнал все ответы через Ensemble Judge (GPT-4o + Claude 4 Opus + GLM-5.2), голосованием выбрал победителя. На тестовой выборке из 100 сессий с ручными оценками — совпадение 73%. Достаточно для наших целей.
4 Агрегируй и считай разницу в цене
Сводим всё в таблицу: для каждой категории — средний балл кандидата, процент задач, где он не уступил эталону (score >= эталона), и стоимость.
Главный показатель — Win Rate: доля сессий, где дешёвая модель сработала не хуже дорогой.
| Категория | DeepSeek V4 Win Rate | Kimi K2.6 Win Rate | Экономия (vs GPT-4o) |
|---|---|---|---|
| SQL генерация | 94% | 92% | 37x |
| Рефакторинг Python | 88% | 79% | 33x |
| Объяснение ошибок | 96% | 97% | 37x |
| Написание тестов | 72% | 68% | 25x |
У DeepSeek просадка на тестах. Значит, для этой категории оставляем GPT-4o. А на всём остальном — переключаем. Финальный счёт: 82% трафика на DeepSeek, 10% на Kimi, 8% на GPT-4o. Экономия реальная: было $450/мес, стало $12.5.
Как автоматизировать прогон и не сойти с ума
Вот скрипт на Python, который гоняет сессии через список моделей и собирает оценки. Используем asyncio для параллельных запросов — иначе будешь ждать вечность.
import asyncio
import aiohttp
import json
from typing import List, Dict
BENCH_SESSIONS = [...] # загрузи свои сессии
MODELS = [
{"name": "deepseek-v4", "api_key": "...", "endpoint": "https://api.deepseek.com/v1/chat/completions"},
{"name": "kimi-k2.6", "api_key": "...", "endpoint": "https://api.moonshot.cn/v1/chat/completions"},
{"name": "glm-5.2", "api_key": "...", "endpoint": "https://open.bigmodel.cn/api/paas/v4/chat/completions"},
]
async def query_model(session, session_data: Dict, model_config: Dict) -> Dict:
headers = {
"Authorization": f"Bearer {model_config['api_key']}",
"Content-Type": "application/json"
}
payload = {
"model": model_config["name"],
"messages": [{"role": "system", "content": session_data["system_prompt"]}] + session_data["messages"],
"temperature": 0.2
}
async with session.post(model_config["endpoint"], json=payload, headers=headers) as resp:
result = await resp.json()
return {
"session_id": session_data["session_id"],
"model": model_config["name"],
"response": result["choices"][0]["message"]["content"],
"tokens": result["usage"]["total_tokens"]
}
async def run_benchmark():
async with aiohttp.ClientSession() as session:
tasks = []
for sess in BENCH_SESSIONS:
for model in MODELS:
tasks.append(query_model(session, sess, model))
results = await asyncio.gather(*tasks)
return results
if __name__ == "__main__":
results = asyncio.run(run_benchmark())
with open("bench_results.json", "w") as f:
json.dump(results, f, indent=2)
print(f"Done. Collected {len(results)} responses.")
⚠️ Подводный камень: У разных моделей разные temperature по умолчанию. DeepSeek при 0.2 выдаёт детерминированные ответы, а Kimi при 0.2 всё ещё креативничает. Придётся подбирать — но для бенчмарка лучше зафиксировать 0.2 у всех, если хочешь сравнивать стабильность.
После прогона — этап оценки. Используй LLM-as-Judge. Вот пример промпта для судьи:
system:
Ты — судья качества ответов LLM. Сравни эталонный ответ и ответ кандидата.
Оцени по шкале 1-5, учитывая: точность, полноту, стиль.
Ответь только числом.
user:
Вопрос: {question}
Эталон: {reference}
Кандидат: {candidate}
Судью тоже можно запустить асинхронно через тот же aiohttp.
Типичные ошибки и как их избежать
Я наступил на все эти грабли:
- Слишком мало сессий. Первый раз собрал 30 — результаты скакали как бешеные. Нужно не меньше 200, а лучше 500.
- Игнорирование контекстной длины. DeepSeek V4 режет контекст после 128K токенов? Или Kimi? Проверяй. У нас были сессии с контекстом под 200K — пришлось исключить их из бенча, так как не все модели их переваривают. Для длинных контекстов — отдельный бенч, как в статье про реалистичные бенчмарки.
- Не учитывать время ответа. Если DeepSeek V4 считает 10 секунд, а GPT-4o — 2 секунды, то экономия денег может не оправдать задержки. Замеряй latency и включай в критерий.
- Биас судьи. GPT-4o как судья занижает оценки DeepSeek (соревнование). Мы использовали Claude 4 Opus для оценки — он более объективен. Или брали среднее по трём моделям.
Когда дешёвая модель всё-таки проигрывает
Будь честен: есть задачи, где DeepSeek V4 сливает. У нас это:
- Многошаговые рассуждения с цепочками мыслей (Chain-of-Thought) — DeepSeek тормозит и теряет нить.
- Генерация кода с нестандартными библиотеками — Kimi K2.6 справляется лучше благодаря свежим данным.
- Задачи, требующие знания текущих событий (последний месяц) — тут GLM-5.2 выигрывает за счёт свежего датасета.
Но это не проблема — мы же построили бенчмарк! Теперь для таких задач оставляем GPT-4o (или Claude). Гибридная стратегия: 80% трафика на дешёвых, 20% на дорогих — и всё равно экономия 30x.
Кстати, если хочешь выжать максимум даже из маленьких локальных моделей — почитай статью про 2x улучшение кодогенерации без хакинга агента. Там техника, которая поднимает DeepSeek V4 ещё на несколько процентов.
Автоматическое переключение моделей в продакшене
Финальный шаг — внедрить роутер. На каждый входящий запрос определяем категорию (тем же классификатором), смотрим в таблицу Win Rate и решаем: отправлять на дешёвую модель или на дорогую.
Пример минимального роутера на FastAPI:
from fastapi import FastAPI, Request
import openai
app = FastAPI()
# Таблица решений: категория -> модель
ROUTING_TABLE = {
"sql_generation": "deepseek-v4",
"code_review": "deepseek-v4",
"refactoring": "deepseek-v4",
"debugging": "deepseek-v4",
"explanation": "deepseek-v4",
"test_writing": "gpt-4o", # тут DeepSeek проигрывает
"other": "gpt-4o"
}
@app.post("/chat/completions")
async def chat(request: Request):
body = await request.json()
messages = body["messages"]
# Определяем категорию
category = classify_task(messages) # функция из шага 2
model = ROUTING_TABLE.get(category, "gpt-4o")
# Шлём запрос
response = openai.chat.completions.create(
model=model,
messages=messages,
temperature=0.2
)
return {"choices": [{"message": {"content": response.choices[0].message.content}}]}
Да, это упрощение. В реальности нужно учесть rate limits, fallback при ошибках, логирование. Но суть ясна.
Что дальше? Бенчмарк как живой организм
Не думай, что сделал бенчмарк раз и навсегда. Модели обновляются, твои задачи меняются. Мы перепрогоняем бенч каждые две недели, добавляя свежие сессии. И ещё: когда выходит новая дешёвая модель (а в 2026 году они выходят каждую неделю), достаточно прогнать её через существующий датасет — и сразу видно, стоит ли переселять трафик.
Например, на днях вышла Qwen3.5-max-128K — мы прогнали, она показала Win Rate 91% на тестах (против 72% у DeepSeek). Теперь тесты ушли на Qwen. Экономия осталась, а качество подросло.
Кстати, если тебе кажется, что бенчмарки — это скучно, посмотри, как билингвальная эротика учит LLM писать — там тоже про качество, но на неожиданном датасете. Или как ChatGPT врёт в лицо — стратегические советы LLM опаснее, чем кажется. Это к вопросу о том, что бенчмарк спасает от иллюзий.
Сделай свой бенчмарк сегодня. Завтра ты уже будешь платить в 37 раз меньше. А освободившийся бюджет пусти на что-нибудь полезное — например, на тренировку своей модели на T4 через MaximusLLM. Но это уже совсем другая история.