Сравнение локальных LLM для разных задач: кодинг, саппорт, аналитика
Один из самых частых вопросов, которые прилетают в IT-отдел после запуска локального AI-сервиса: «а почему модель плохо пишет код» или «почему она такая тупая в аналитике». Обычно ответ прост — для задачи выбрана не та модель. Open-source LLM сегодня развились настолько, что универсального победителя на все случаи жизни не существует: одна модель отлично пишет код, но слабовата в свободном диалоге, другая прекрасно поддерживает разговор, но путается в математике. Разберём, какие модели на практике стоит ставить на srv-ai01 под конкретные задачи компании — кодинг, поддержку клиентов и аналитику данных.
Кодинг: Qwen2.5-Coder и DeepSeek-Coder
Для задач, связанных с генерацией и ревью кода, специализированные кодовые модели стабильно обходят модели общего назначения того же размера. Два лидера в open-source сегменте на конец 2025 года:
- Qwen2.5-Coder-32B-Instruct — сильный выбор для смешанных стеков (Python, JS/TS, Go), хорошо держит длинный контекст при код-ревью, разумно себя ведёт при рефакторинге больших файлов;
- DeepSeek-Coder-V2 — особенно силён в алгоритмических задачах и competitive-programming стиле, чуть тяжелее по требованиям к VRAM, но даёт заметно более точные ответы на сложные архитектурные вопросы.
# для команды разработки на srv-ai01
vllm serve /models/qwen2.5-coder-32b-instruct \
--port 8000 \
--max-model-len 32768 \
--gpu-memory-utilization 0.85 \
--served-model-name coding-assistant
Если GPU-ресурсы ограничены, квантованная версия Qwen2.5-Coder-14B в GPTQ или AWQ формате даёт неплохой компромисс между качеством и объёмом VRAM — разница в качестве с 32B заметна в основном на сложных многофайловых задачах, для точечных вопросов «почему падает этот тест» разницы почти нет.
Поддержка клиентов: Llama 3.1/3.3 и Mistral
Для саппорта важнее не глубина рассуждений, а естественность диалога, следование тону компании и устойчивость к попыткам вывести модель за рамки скрипта (см. статью про prompt injection). Здесь хорошо себя показывают:
- Llama 3.3-70B — качественный follow-instructions, стабильно держит заданный тон и формат ответа, хорошо работает с RAG поверх базы знаний компании;
- Mistral Small / Mistral Large — заметно быстрее по латентности при сопоставимом качестве диалога, что важно для интерактивного чата, где пользователь ждёт ответ здесь и сейчас, а не через 15 секунд;
- Qwen2.5-32B-Instruct — неплохой универсальный вариант, если нужно и немного кода в ответах поддержки (например, помощь с настройкой API), и обычный диалог.
Для саппорта латентность часто важнее пиковой точности, поэтому здесь имеет смысл жертвовать размером модели ради скорости первого токена — клиент, ждущий ответ 20 секунд, воспринимает сервис как медленный, даже если сам ответ отличный.
# для отдела поддержки — приоритет на латентность
vllm serve /models/mistral-small-24b-instruct \
--port 8001 \
--max-model-len 16384 \
--gpu-memory-utilization 0.4 \
--served-model-name support-assistant
Аналитика данных: DeepSeek-V3 и Qwen2.5-72B
Для задач аналитики — интерпретация таблиц, построение выводов из отчётов, работа с числами и логическими цепочками — критична способность к рассуждению (reasoning) и устойчивость при работе с большим объёмом структурированных данных в контексте.
- DeepSeek-V3 — один из сильнейших open-source вариантов по качеству рассуждений на момент выхода, особенно хорош там, где нужно несколько шагов логического вывода поверх табличных данных;
- Qwen2.5-72B-Instruct — надёжный выбор при работе с длинными отчётами и большим контекстом, стабильно следует структуре запроса (например, «выведи ответ строго в виде таблицы»);
- DeepSeek-R1 (или его дистиллированные версии) — если аналитика требует явного пошагового рассуждения перед ответом, reasoning-модели этого типа заметно снижают число фактических ошибок ценой более медленного ответа.
Для аналитики почти всегда стоит связывать модель с code-интерпретатором (см. статью про плагины Open WebUI) — вместо того чтобы модель «в уме» считала агрегаты по таблице, она должна писать и выполнять код, который считает точно.
Как выбирать, если ресурсы srv-ai01 ограничены
Если железо не позволяет держать три полноценные модели одновременно в памяти, практичная стратегия — держать одну сильную универсальную модель (например, Qwen2.5-32B-Instruct) как модель по умолчанию, и догружать специализированные модели по требованию через динамическую загрузку vLLM или llama.cpp с выгрузкой неиспользуемых моделей по таймауту простоя.
# пример конфигурации с ленивой загрузкой в LiteLLM
model_list:
- model_name: coding-assistant
litellm_params:
model: openai/qwen2.5-coder-32b
api_base: http://srv-ai01.itpages.lab.local:8000/v1
- model_name: support-assistant
litellm_params:
model: openai/mistral-small-24b
api_base: http://srv-ai01.itpages.lab.local:8001/v1
- model_name: analytics-assistant
litellm_params:
model: openai/deepseek-v3
api_base: http://srv-ai01.itpages.lab.local:8002/v1
Такая настройка позволяет пользователям и интеграциям обращаться к моделям по смысловому имени (coding-assistant, support-assistant), не зная деталей о том, какая конкретно модель и на каком порту стоит за этим именем — это также упрощает будущие обновления моделей по схеме blue-green.
Методика сравнения моделей на своих данных
Общие бенчмарки (MMLU, HumanEval, MT-Bench) полезны для первичного отбора кандидатов, но плохо предсказывают, как модель поведёт себя на специфичных задачах твоей компании. Разумная методика — собрать 30-50 реальных примеров запросов из каждой категории (код, поддержка, аналитика) и прогнать через каждого кандидата с одинаковыми параметрами генерации.
# упрощённый скрипт сравнения моделей на своём наборе примеров
import json
candidates = ["qwen2.5-coder-32b", "deepseek-coder-v2", "llama3.3-70b"]
test_set = json.load(open("test_prompts/coding_tasks.json"))
results = {}
for model in candidates:
correct = 0
for task in test_set:
response = query_model(model, task["prompt"])
if evaluate_response(response, task["expected_criteria"]):
correct += 1
results[model] = correct / len(test_set)
print(results)
Оценку ответов лучше не полностью автоматизировать — для кода можно проверять автотестами, но для поддержки и аналитики финальную оценку 20-30 ответов стоит поручить живому эксперту из соответствующего отдела, который знает, что такое «хороший ответ» в контексте конкретных задач компании.
Требования к железу для разных моделей
Перед тем как выбирать модель по качеству, стоит трезво оценить, помещается ли она в VRAM srv-ai01. Ориентировочные требования при использовании квантования (4-bit AWQ/GPTQ):
Модель Параметры VRAM (4-bit) Скорость (примерно)
Mistral Small 24B ~16 GB быстрая
Qwen2.5-Coder / Qwen2.5 14B ~10 GB быстрая
Qwen2.5-Coder / Qwen2.5 32B ~20 GB средняя
Llama 3.3 70B ~40 GB средняя-медленная
DeepSeek-V3 (MoE, активных ~37B) 671B total ~40-45 GB средняя за счёт MoE
Модели с архитектурой Mixture-of-Experts (как DeepSeek-V3) особенно интересны для ограниченного железа — при огромном общем числе параметров на каждый конкретный запрос активируется лишь часть экспертов, что даёт качество, близкое к куда более крупной плотной модели, при разумных требованиях к VRAM и вычислениям.
Обновление модельного ландшафта: план ревью
Open-source модели развиваются быстро — то, что было лучшим выбором для кодинга полгода назад, может уже уступать новому релизу. Разумно не гнаться за каждым новым релизом, но и не консервировать выбор навсегда. Практичный ритм — ежеквартальный обзор доступных моделей с прогоном того же набора тестов, что использовался при первоначальном выборе, и решением, стоит ли мигрировать.
# чек-лист квартального ревью моделей
1. Есть ли новая версия текущей модельной линейки (например,
Qwen3 вместо Qwen2.5)?
2. Прогнать новую версию на своём test_set из статьи выше
3. Сравнить с текущими метриками качества и латентности
4. Если прирост качества > 10% или прирост скорости > 20% -
планировать миграцию через blue-green
5. Если прироста нет - оставить текущую версию, зафиксировать
дату следующего ревью
Такой процесс защищает от двух крайностей — от бесконечной гонки за самой свежей моделью, которая требует постоянных миграций без ощутимой пользы, и от застревания на устаревшей версии просто потому, что «и так работает», когда рынок за это время ушёл заметно вперёд по качеству или эффективности.
Частые ошибки и как их избежать
- Одна модель на все задачи «для простоты». Экономит время на настройке, но заметно снижает качество там, где нужна специализация — особенно в коде и аналитике. Начни хотя бы с двух моделей: кодовой и универсальной.
- Выбор модели по бенчмаркам без проверки на своих задачах. Общие лидерборды не отражают специфику твоих промптов и данных компании. Всегда прогоняй кандидатов на реальных примерах из своих задач, прежде чем катить в прод.
- Игнорирование латентности при выборе модели для интерактивного чата. Самая точная модель бесполезна, если сотрудники перестают ей пользоваться из-за долгого ожидания ответа. Для чата в реальном времени латентность first-token часто важнее пары процентов точности.
Специализация внутри одной категории задач
Даже внутри одной широкой категории вроде «кодинг» разумно учитывать более узкую специализацию под стек технологий компании. Модель, отлично справляющаяся с Python и JavaScript, не обязательно так же хороша в узкоспециализированных языках или фреймворках — например, в написании Terraform-конфигураций, PL/SQL или встраиваемого C для микроконтроллеров.
# пример специализированного теста под конкретный стек
test_prompts_terraform = [
"Напиши модуль Terraform для VPC с публичной и приватной подсетью",
"Исправь ошибку в этом ресурсе aws_security_group: ...",
"Объясни разницу между count и for_each в этом файле",
]
# прогони через кандидатов и сравни с ожидаемым результатом от senior-инженера
Если основной стек компании — что-то нишевое, иногда практичнее взять модель среднего размера с хорошими общими навыками кода и до-обучить (fine-tune) её на внутренней кодовой базе компании через LoRA, чем искать готовую модель, идеально закрывающую именно эту нишу. Это отдельная, более сложная тема, но её стоит держать в уме как альтернативу бесконечному перебору готовых моделей.
Гибридный подход: маршрутизация запросов между моделями
Продвинутый вариант использования нескольких моделей — не просто дать пользователю выбор, а автоматически маршрутизировать запрос к нужной модели на основе его содержания, определяемого небольшой классифицирующей моделью или простыми правилами.
def route_request(user_message: str) -> str:
if contains_code_block(user_message) or re.search(r"(?i)напиши код|debug|исправь ошибку", user_message):
return "coding-assistant"
if re.search(r"(?i)посчитай|проанализируй таблицу|сводка по данным", user_message):
return "analytics-assistant"
return "support-assistant"
Такой роутинг снижает нагрузку на самую тяжёлую модель (аналитическую или кодовую), направляя туда только действительно релевантные запросы, а рутинные вопросы обрабатывает более лёгкая и быстрая модель по умолчанию.
Что дальше
Безопасность и эксплуатация AI-инфраструктуры — вот с чем ещё стоит разобраться: