Сладкая ложь о маленьких моделях
«Скачай 7B-модель, запусти на своём ноуте, и получишь агента, который напишет тебе микросервис на Go». Звучит как реклама чудо-таблетки. В 2026 году таких обещаний стало ещё больше — Hugging Face пестрит моделями под 7-12 миллиардов параметров, а в блогах пишут, что OpenCode 12B «почти догоняет GPT-4». Я провёл десятки часов, пытаясь заставить малые модели работать как полноценных coding-агентов. Результат — сборник катастроф.
Эта статья — не ещё один обзор «лучших локальных моделей». Это анатомия провалов. Я разберу пять конкретных failure points, из-за которых малые агенты превращаются в дорогой генератор мусора. И дам рабочие костыли — потому что идеального решения пока нет.
Failure Point #1: Markdown fences — модель не знает, где начинается её код
Самая частая и бесячая проблема. Агент должен выдать код в формате Markdown fences (```python ... ```). Малые модели регулярно:
- Забывают закрыть fence — ответ обрывается на середине.
- Вставляют код без fences — агент не может распарсить результат.
- Генерируют вложенные fences — ``` внутри ``` ломают всё.
- Пишут ````python```` (четыре бектика) — кэп.
С OpenCode 12B (квант Q4_K_M) я получил 40% ответов с битыми fences. Каждый второй вызов агента заканчивался ошибкой парсинга.
! Почему так происходит
Модели обучаются на сырых данных с GitHub, где форматирование кода хаотичное. Маленькая ёмкость (7-12B) не позволяет хорошо выучить паттерны Markdown. В результате модель «срезает углы» — генерирует fence только когда вероятность высока, а в середине ответа теряет нить.
Что делать? Не надейтесь на сырой текст. Используйте форсированный JSON или грамматику. В статье о настройке стека агентов я описывал, как принудительно ограничить вывод через грамматики llama.cpp. Для малых моделей это спасение:
# Пример грамматики для forced JSON
./llama-cli -m model.gguf --grammar-file code_action.gbnf \
-p "Generate code action"
Но даже это не гарантия — модель может начать галлюцинировать поля внутри JSON.
Failure Point #2: Потеря контекста в мультифайловых задачах
Агент должен отредактировать три файла. Он открывает первый, пишет изменения. Потом второй — и забывает, что писал в первом. К третьему файлу модель уже не помнит имя проекта. Знакомо?
В реальных кейсах с моделями 30-100B та же проблема, но с меньшими масштабами. У малых моделей «рабочая память» в разы меньше.
Решение: Не давайте модели весь контекст сразу. Разбивайте задачу на шаги и подкладывайте только релевантные фрагменты. Примерно так работают системы RAG. Для агента — используйте «план действий» в промпте, где каждый шаг явно перечислен, и модель видит только текущий файл.
Failure Point #3: Галлюцинации несуществующих библиотек
«Импортируй библиотеку super-fs, она есть на PyPI». Нет, не существует. Малые модели с удовольствием выдумывают имена пакетов, особенно если в трейне были старые версии Python. Отсюда:
import asyncioвместоimport asyncio(но это ещё ладно).from pytorch_lightning import Trainer— давно переименовано, но модель не знает.api.super_method()— метода нет, код падает в RuntimeError.
Бенчмарки SWE-bench Verified показывают, что модели <15B набирают ~15-25% pass rate, причём половина ошибок — именно галлюцинации API.
Костыль: Добавьте в системный промпт строгий запрет на выдуманные библиотеки. Ещё лучше — дайте модели список доступных пакетов и их актуальные сигнатуры. Этот подход описан в готовых промптах для opensource моделей.
Failure Point #4: Агент зацикливается — не может выйти из инструмента
Типичный сценарий: агент получает задачу «отрефакторить функцию». Он вызывает инструмент read_file, потом edit_file, потом опять read_file, потом edit_file той же строчки, потом снова read_file... И так 20 раз. Контекст забивается, лимит шагов исчерпан, результата ноль.
Малые модели плохо понимают, когда задача решена. У них нет встроенного «чувства завершённости». Особенно это проявляется, когда рефакторинг касается нескольких файлов — модель не может сопоставить изменения.
Что реально помогает:
- Жёсткий лимит на количество вызовов инструментов (максимум 5-7).
- Промпт с требованием «после каждого редактирования запусти тесты и, если они проходят, прекрати работу».
- Использование модели-супервизора (пусть даже 1.5B) для оценки прогресса.
Ещё один совет из практики: если модель не останавливается — заставьте её выводить специальный токен в конце. Проверяйте наличие этого токена и обрывайте агента. Дешёво и сердито.
Failure Point #5: Квантование убивает качество кода
У вас 8GB VRAM? Вы скачиваете OpenCode 12B в Q4_K_M. Или Qwen3.5-7B в Q3_K_S. И получаете модель, которая в 30% случаев пишет ерунду. Потому что квантование для малых моделей критичнее, чем для больших. Чем меньше модель, тем чувствительнее её веса к округлению.
| Квантование | Качество кода (pass@1) | VRAM (12B) |
|---|---|---|
| FP16 | 100% (базовый уровень) | 24 GB |
| Q8_0 | ~98% | 12 GB |
| Q4_K_M | ~85% | 6 GB |
| Q3_K_S | ~70% | 4 GB |
Какой вывод? Если у вас 8GB — выбирайте модель 7B в Q8_0, а не 12B в Q4. Качество будет выше, даже при меньшем размере. Проверено на личных тестах с GLM-4.7-Flash 32B (в облегчённой версии) — но это уже не малая модель.
Про то, как правильно выбирать квантование для конкретного железа, я писал в обзоре стека агентов.
Резюме: когда малые модели всё-таки можно использовать
Я не говорю, что малые модели бесполезны. Есть задачи, где они справляются: генерация однострочных функций, написание тестов, рефакторинг изолированных файлов. Но как только появляется мультиагентская логика, длинный контекст или требовательный тулинг — начинаются проблемы.
Лучшая стратегия на 2026 год — гибрид: малая модель (12-14B в Q8) для быстрых черновиков и агентских циклов, а финальную верификацию и сложные правки пересылать на более крупную модель (30B+) через API очередей. Такой подход используют в рецептах сборки локальных агентов.
И не верьте рекламе. Маленькая модель — не дешёвая копия большой. Это отдельный зверь со своими привычками. Иногда он кусается.
FAQ по failure points малых моделей
Почему модель пишет код не в том файле?
Потому что малые модели плохо связывают имя файла со своим содержимым. Решение — вставлять перед каждым вызовом инструкцию: «Сейчас ты будешь редактировать файл /src/main.py. Его содержимое: ...». И чётко ограничивать контекст одним файлом.
Какой минимальный размер модели для coding-агента?
Мой опыт показывает, что 7B — это нижняя граница, и то для простых задач. Для реальных проектов — начинайте с 12-14B в Q8. Если железо позволяет, лучше 30B+ в Q4.
Можно ли дообучить малую модель на своих промптах?
Да, LoRA-дообучение на корпусе агентских логов работает. После 500-1000 шагов модель начинает лучше следовать формату fences. Но это требует качественного датасета и времени.
Если у вас есть свои грабли — пишите в комментариях. Я соберу из них отдельный пост.