# Локальная LLM для программирования в реальной команде

> Практический разбор локальной LLM для программирования: качество моделей, расчет VRAM, серверные среды, защита и выгода подписки.

Локальную модель для программирования стоит запускать лишь тогда, когда вы точно знаете, какую работу ей поручите, умеете измерять ее ошибки и оставляете достаточно памяти под контекст, который реально отправляют разработчики. Покупка мощной видеокарты до выбора модели переворачивает решение с ног на голову. В итоге вы защищаете покупку, а не улучшаете разработку.

У локального инференса есть три честных плюса: код остается внутри подконтрольного вам периметра, переменные расходы становятся предсказуемыми, а выбранная модель не исчезает после изменения чужого сервиса. Вместе с этим вы получаете обновления, планирование мощности, оценку моделей, контроль доступа и еще одну систему для дежурного инженера. Для многих команд хорошая облачная подписка на помощника по программированию по-прежнему дает лучший код за меньшие деньги. Самостоятельный хостинг выигрывает гораздо реже, чем готовы признать любители оборудования.

## Сначала определите работу, потом выбирайте модель

Полезная локальная установка заменяет конкретную часть работы, а не абстрактное «программирование». Автодополнение, разговор об одном файле, поиск по репозиторию, генерация тестов, проверка pull request и агент, меняющий двадцать файлов, по-разному нагружают модель и сервер.

До просмотра объявлений о видеокартах опишите типичный запрос. Зафиксируйте языки программирования, средний размер промпта, самый большой полезный промпт, допустимое время до первого токена, число одновременных пользователей и право модели менять файлы или запускать команды. Модель может казаться быстрой одному разработчику в терминале и стать непригодной, когда четыре плагина редактора постоянно отправляют запросы на автодополнение.

Число одновременных запросов нужно считать отдельно. Диалог идет всплесками: сервер обрабатывает длинный промпт, отдает поток токенов и простаивает, пока разработчик читает. Автодополнение отправляет короткие запросы намного чаще. Агенты чередуют инференс с чтением файлов и тестами. Сервер для двух агентов может не справиться с десятью клиентами автодополнения, даже если суточный объем токенов одинаков. Рассчитывайте мощность на самую загруженную полезную минуту и ограничивайте прием запросов, чтобы перегрузка превращалась в видимую очередь, а не в череду перезапусков из-за нехватки памяти.

Я делю задачи на два уровня. Первый помогает разработчику: дописывает код, объясняет его, делает небольшие рефакторинги, пишет модульные тесты и отвечает на вопросы по нескольким переданным файлам. Хорошая модель на 7B-14B параметров справляется со значительной частью такой работы. Второй уровень работает как агент: находит нужные файлы, планирует изменение, правит несколько модулей, запускает тесты, читает ошибки и исправляет патч. Здесь важнее сильное рассуждение, надежная работа с инструментами и достаточный контекст, чем чистая скорость генерации. Модель на 32B параметров подходит как практическая отправная точка, но и она не всегда сравняется с сильнейшими облачными системами в незнакомом репозитории.

Не считайте конфиденциальность полным описанием задачи. Фраза «код не может покидать нашу сеть» задает ограничение, но не объясняет, что должен делать сервер. Вам все равно нужны рабочая нагрузка и критерии приемки. Если ограничение относится лишь к двум репозиториям, направляйте их на локальную модель, а обычную работу оставьте более сильной облачной. Избирательная маршрутизация часто оказывается самым разумным вариантом.

Неудобный вопрос: безопасно ли локальное программирование с LLM. Оно может не передавать код внешнему поставщику модели, однако сами промпты безопаснее не становятся. Сервер видит исходный код, случайно попавшие в файлы секреты, личность пользователя, а иногда и вывод команд из продакшена. Защищайте его как систему с исходным кодом: проверяйте каждый клиент, шифруйте трафик между машинами, ограничивайте журналы, фиксируйте версии файлов модели и отделяйте ответ модели от выполнения команд. HTTP-порт без аутентификации не становится приватным только потому, что стоит в вашей сети.

## Размер модели ограничивает полезную работу

Число параметров не идеально, но внутри одного семейства неплохо показывает потенциальные возможности. Маленькие модели дешевы и отзывчивы, однако быстрее теряют ограничения и делают правдоподобные локальные правки, которые конфликтуют с остальным кодом. Крупные модели обычно лучше планируют и чаще исправляются после упавшего теста. Архитектура, обучающие данные, настройка инструкций и оболочка агента все же могут нарушить простую зависимость от размера.

Выбирайте семейства, которые явно обучали на коде, и instruct-версию для диалога или агента. Qwen2.5-Coder удобен для сравнения, потому что в карточке модели перечислены варианты 0,5B, 1,5B, 3B, 7B, 14B и 32B. Версия 7B instruct подходит для быстрых объяснений, дополнения и ограниченных правок. Вариант 14B я считаю минимальным кандидатом для ежедневной работы с репозиториями на разных языках. Версии 32B instruct уже можно поручать изменения в нескольких файлах.

DeepSeek-Coder-V2-Lite-Instruct тоже стоит проверить, если среда запуска поддерживает ее архитектуру mixture-of-experts. Карточка модели указывает 16B параметров всего, 2,4B активных и заявленный контекст 128K. Число активных параметров помогает понять вычисления на один сгенерированный токен, но полный набор весов все равно нужно где-то хранить. Команды видят 2,4B, подбирают машину как для плотной модели 3B и обнаруживают, что память зависит от общего размера, а не только от активных экспертов.

Не путайте опубликованное окно контекста с полезным окном для кода. Карточка Qwen2.5-Coder-32B заявляет 131 072 токена, но там же сказано, что стандартная конфигурация ограничена 32 768 и для более длинного ввода нужен YaRN. Больший контекст требует больше памяти под KV-кеш и может рассеивать внимание. Поиск по репозиторию, который отправил восемь нужных файлов, обычно лучше выгрузки восьмидесяти файлов в формально длинное окно.

Лицензия входит в выбор модели. Прочитайте точный текст, прикрепленный к тому репозиторию и той ревизии, которые вы развернете. Проверьте коммерческое использование, распространение, ограничения на размещаемый сервис, правила допустимого использования и обязанности для измененных весов. «Открытые веса» не всегда означают открытую лицензию по критериям OSI, а разрешительная лицензия среды запуска ничего не говорит о лицензии модели.

По публичным тестам составляйте короткий список, но не принимайте модель. Задания типа HumanEval проверяют небольшие функции в контролируемых промптах. Ваш агент должен понимать ваши имена, миграции, сгенерированные файлы, тестовые команды и правила ревью. Преимущество в пять баллов не спасет модель, которая редактирует не тот пакет или игнорирует упавший интеграционный тест.

## В VRAM должны поместиться не только веса

В памяти видеокарты лежат веса модели, KV-кеш, рабочие области среды запуска и служебные данные. Размер квантованных весов задает нижнюю границу, но не цель для покупки. Грубого расчета достаточно, чтобы отсеять невозможную конфигурацию до скачивания модели:

```text
weight_GiB = parameters_in_billions * bits_per_weight / 8 * 1.08
required_VRAM = weight_GiB + KV_cache + runtime_overhead + safety_margin
```

Коэффициент 1,08 дает плановый запас на метаданные квантования и тензоры смешанной точности, это не физическая константа. Накладные расходы зависят от среды. Размер KV-кеша определяется архитектурой, длиной контекста, точностью кеша, размером пакета и числом одновременных последовательностей, поэтому после первой оценки измерьте свою конфигурацию.

Для плотной модели 7B с четырьмя битами формула дает около 3,8 ГиБ весов. Видеокарты на 8 ГБ хватит для умеренного контекста и одного пользователя, хотя 12 ГБ требуют заметно меньше компромиссов. Модель 14B начинается примерно с 7,6 ГиБ: 12 ГБ будет тесно, а 16 ГБ дают нормальный минимум. Модель 32B начинается примерно с 17,3 ГиБ. На 24 ГБ она может работать для одного пользователя с ограниченным контекстом, а 32 ГБ и больше оставят агенту место под кеш и служебные данные. Для 70B исходная оценка равна 37,8 ГиБ, поэтому обычно нужны 48 ГБ, несколько видеокарт либо серьезные компромиссы.

Эти числа относятся к четырехбитным весам, а не обещают точный размер файла или пик потребления. Шесть или восемь бит требуют больше памяти. Длинный контекст и параллельные запросы увеличивают расход. Визуальный энкодер, модель для speculative decoding и эмбеддинги на той же видеокарте тоже занимают место.

Обработка промпта и генерация токенов нагружают оборудование по-разному. Большой контекст хорошо использует параллельные вычисления, а последовательная генерация часто упирается в пропускную способность памяти. Просите у поставщика и внутренних тестировщиков отдельные скорости обработки промпта и генерации. Общая цифра «токенов в секунду» может скрыть мучительное ожидание первого токена или приукрасить сервер, который быстро читает промпт, но медленно пишет код.

Измеряйте процесс на реально нужной длине контекста. Для llama.cpp контролируемая проверка выглядит так:

```bash
./llama-server \
  -m /models/coder-32b-q4_k_m.gguf \
  -c 32768 -ngl 99

nvidia-smi
```

Вторая команда должна показать таблицу процессов с идентификатором, именем и памятью GPU, например `42137 llama-server 22184MiB`. Отправьте один реалистичный промпт, затем два одновременно и следите за пиковым расходом памяти и задержкой токенов. Показание в простое не учитывает рост кеша. Если процесс падает только на втором запросе, перед вами нехватка мощности, а не загадочная проблема модели.

Оперативная память тоже важна. Ее должно хватать на загрузку или отображение модели в память, операционную систему, поисковые индексы и перенос слоев на CPU без свопа. Для видеокарты на 24 ГБ с квантованной моделью 32B я предпочитаю не меньше 64 ГБ RAM. Это эксплуатационный запас, а не утверждение, что инференс использует все целиком.

## У каждого оборудования своя эксплуатационная цена

NVIDIA остается самым предсказуемым выбором для широкой поддержки сред запуска. Основные серверные проекты в первую очередь работают с CUDA, а подержанные карты на 24 ГБ позволяют собрать мощную станцию для одного пользователя. Проверьте потребление, размеры, охлаждение, разъемы блока питания и допустимость постоянной работы потребительской карты в ваших условиях. Дешевая VRAM перестает быть дешевой после снижения частоты от перегрева и случайных перезапусков.

Apple silicon удобен в рабочей станции разработчика: общая память вмещает модели, которые не помещаются в дискретную видеокарту той же ценовой категории. llama.cpp считает Metal приоритетным бэкендом. Машина с 64 или 128 ГБ общей памяти может тихо запускать крупные квантованные модели, но скорость зависит от пропускной способности и других потребителей памяти, а многопользовательским сервером она автоматически не становится. Покупайте ее ради удобства одного-двух человек, а не потому, что объем памяти похож на VRAM серверной карты.

Инференс только на CPU подходит для оценки, фоновых сводок и редких пакетных задач. На моделях 14B и крупнее он редко дает комфортную работу агента. Смешанная выгрузка на CPU и GPU позволяет llama.cpp запускать модели больше видеопамяти, но каждый слой на медленном пути памяти снижает скорость. Гибридный режим помогает совместимости, но не дает бесплатной мощности.

Несколько видеокарт решают вопрос объема лишь тогда, когда среда эффективно делит модель. Они не превращаются в единый прозрачный пул. Важны скорость соединения, поддержка tensor parallel, топология карт, ядра квантования и синхронизация. Две потребительские карты могут вместить более крупную модель и все равно отвечать медленнее одной карты с меньшей моделью. До стандартизации проверьте точную конфигурацию.

Оборудование AMD и Intel имеет смысл, если команда уже умеет его обслуживать, а выбранная среда доказала работу нужного бэкенда. llama.cpp описывает HIP, Vulkan, SYCL и другие варианты. Документация vLLM по квантованию указывает на более сложную деталь: у каждого метода своя матрица поддерживаемого оборудования. Поддержка видеокарты средой не гарантирует работу выбранного ядра квантования.

Аренда выделенной облачной видеокарты остается самостоятельным управлением инференсом, но не дает локального контроля данных. Для пилота это часто лучший выбор: мощность можно изменить или отключить после теста. Включите в стоимость подключенный диск, часы простоя, передачу данных, резервные копии и время инженера. Смотреть только на почасовую цену ускорителя равносильно расчету зарплаты без налогов.

## Квантование меняет качество неравномерно

Четыре бита дают практическую отправную точку для локального программирования, но не универсальный оптимум. Хорошие современные схемы сохраняют большую часть возможностей модели, однако потери проявляются неравномерно. Синтаксис может остаться точным, а длинные цепочки зависимостей, редкие библиотеки и строгое соблюдение инструкций ухудшатся.

Для GGUF-моделей в llama.cpp разумно начать с Q4_K_M, сравнить Q5_K_M при наличии памяти и взять Q8_0 как качественный квантованный ориентир. Руководство llama.cpp предупреждает: повторное квантование уже квантованных тензоров может намного сильнее снизить качество по сравнению с исходными 16- или 32-битными весами. Это предупреждение нельзя игнорировать. Удобно перепакованный файл может стать меньше и вызвать ошибки, в которых вы обвините исходную модель.

Сохраняйте происхождение файла и квантователь в реестре моделей. Записывайте ревизию исходной модели, метод и версию квантования, шаблон, настройки контекста и хеш файла. Два почти одинаковых имени могут скрывать разные шаблоны диалога или калибровочные данные. После изменения поведения новый файл можно будет сравнить со старым.

Не тратьте дни на спор о четырехбитных форматах до сравнения 14B и 32B. Переход на более сильный размер часто важнее одного шага квантования внутри маленькой модели. Сравните оба варианта при одном бюджете памяти. Q4-модель на 32B может лучше Q8-модели на 14B рассуждать о репозитории, а маленькая все равно выиграет по задержке и автодополнению.

Качество зависит и от формата промпта. Instruct-модели ожидают определенный шаблон диалога и специальные токены. Ошибочно выбранный шаблон заставляет хорошую модель болтать, игнорировать инструменты или продолжать текст пользователя. Сверьте шаблон с метаданными или карточкой модели. Не пытайтесь исправить такую ошибку страницей системного промпта.

## Серверная среда может испортить хорошую модель

Выбирайте llama.cpp для компактного развертывания, квантования GGUF, широкого списка оборудования и удобной рабочей станции. vLLM подходит для поддерживаемых моделей на GPU, нескольких пользователей, пакетной обработки и высокой пропускной способности. Ollama упрощает локальную установку и упаковку моделей, но все равно нужно фиксировать версии, закрывать сетевой доступ и измерять память.

Отделяйте API инференса от агента. Сервер превращает сообщения в токены. Агент выбирает файлы, собирает промпты, разбирает вызовы инструментов, ограничивает команды, сохраняет diff и останавливает бесконечные циклы. Если смешать слои, причину ошибки не найти. Для плохого патча нужно понять, пропустил ли поиск файл, потерял ли промпт ограничение, ошиблась ли модель или инструмент выполнил опасное действие.

HTTP API, совместимый с форматом OpenAI, упрощает подключение редакторов, но одинаковые пути и JSON не гарантируют одинакового поведения. Модели по-разному оформляют вызовы инструментов, стоп-токены, системные сообщения и fill-in-the-middle. Проверяйте именно ту функцию, которой пользуется редактор. Успешный диалог ничего не доказывает про автодополнение.

Фиксируйте все зависимости, способные изменить ответ: ревизию модели, квантованный файл, сборку среды, драйвер GPU, шаблон диалога, системный промпт, версию агента и настройки поиска. Храните рабочий комплект для отката. Серверы моделей остаются обычными программными системами, и безобидное обновление может изменить токенизацию, ядра, кеш или обработку остановки. Когда разработчики скажут, что помощник «стал странным», список версий даст точку для расследования.

Ограничения должны жить в конфигурации, а не в устных договоренностях команды:

```yaml
model: coder-32b-q4_k_m
max_context_tokens: 32768
max_output_tokens: 4096
concurrent_requests: 2
request_timeout_seconds: 180
log_prompts: false
allowed_repositories:
  - billing-api
  - internal-tools
tool_policy: patch_and_test_only
```

Такой фрагмент предотвращает три типичных сбоя: редактор не запросит молча весь заявленный контекст, всплеск трафика не заполнит кеш неограниченными последовательностями, а агент не превратит помощника по коду в произвольную оболочку. В вашем стеке имена будут другими, но исполняемые ограничения должны существовать.

Запускайте сервис от отдельной учетной записи. Привяжите его к приватному интерфейсу, поставьте аутентификацию и запретите исходящую сеть, если она явно не нужна для скачивания модели или инструмента. Храните промпты только при наличии причины и срока хранения. Журналы с закрытым кодом, который вы не отдали поставщику, уничтожают смысл самостоятельного хостинга.

## Проверяйте патчи, а не умные ответы

Модель проходит оценку, когда ее патчи выдерживают ваши проверки и ревью. Красивый разговор служит слабым доказательством. Возьмите решенные задачи из своих репозиториев, уберите финальные патчи и попросите кандидатов решить одну и ту же задачу из одинакового исходного состояния.

Соберите 20-40 задач из ожидаемой работы: локальную ошибку, функцию в нескольких файлах, миграцию, нестабильный тест, рефакторинг с ограничением публичного API и запрос, от которого нужно отказаться из-за нехватки данных. Не кладите в набор секреты и сведения клиентов. Для каждого запуска фиксируйте модель, среду, промпт, поиск, лимиты токенов и права инструментов.

Оценивайте то, что влияет на выпуск:

- Сборка и тесты проходят без ослабления тестов.
- Diff меняет только нужные файлы и соблюдает правила репозитория.
- Модель находит и использует правильную существующую абстракцию.
- Агент исправляется после настоящего падения теста.
- Ревьюер принимает патч с небольшими поправками.

Считайте время до принятого патча, а не только токены в секунду. Быстрая модель с тремя неверными патчами отнимает больше времени, чем медленная с одной пригодной правкой. Записывайте типы сбоев. Постоянный выбор неверного файла требует лучшего поиска, сломанные вызовы инструментов указывают на модель или шаблон, нехватка памяти относится к серверу, а правдоподобная неверная логика возвращает нас к возможностям модели.

Добавьте отрицательные проверки. Дайте агенту задачу, функция для которой уже существует, запрос, нарушающий правило репозитория, и задачу без обязательного решения по схеме данных. Надежным результатом может быть короткое объяснение или просьба уточнить данные. Модели, которые всегда выдают diff, эффектно выглядят на демонстрации и создают опасную нагрузку на ревью.

Воспроизводимый запуск может быть простым:

```bash
git checkout "$TASK_COMMIT"
git clean -fdx
./run-agent "$TASK_FILE" 12
./ci/test.sh
git diff
```

Ожидайте обычный отчет тестов, затем единый патч с `diff`, заголовками файлов и измененными строками. Запускайте команды только в одноразовом клоне или изолированном worktree: `git clean -fdx` удаляет неотслеживаемые и игнорируемые файлы. Команда намеренно жесткая, потому что оценка должна сбрасывать состояние, а не передавать следующей модели следы предыдущей.

По возможности поручите слепую проверку старшему инженеру. Скройте за условными именами локальных и облачных кандидатов, иначе люди прощают системе, которую хотели купить. Повторяйте набор после смены модели, квантования, среды, промпта агента или поиска. Тогда тест станет регрессионным, а не одноразовым ритуалом покупки.

## Подписка выигрывает чаще, чем показывает таблица

Облачная подписка обычно лучше, если разработчикам нужны сильнейшие рассуждения, нагрузка возникает нерегулярно, правила разрешают передавать репозитории наружу, а обслуживать инференс некому. Месячная цена включает дорогое оборудование, обновления моделей, управление мощностью и готового агента. Локальный сервер должен победить весь этот комплект, а не одну строку с токенами API.

Считайте стоимость за три года: амортизацию оборудования, электричество, место, охлаждение, диски, резерв мощности, настройку инженером, защиту, обновления и аварии. Делите сумму на сэкономленные часы разработчиков с принятыми патчами, а не на сгенерированные токены. Если станция за $10 000 занимает сорок инженерных часов на настройку и поддержку, эти часы могут стоить дороже GPU.

Самостоятельный хостинг имеет смысл, когда политика запрещает внешнюю обработку, нагрузка постоянно высокая и предсказуемая, задержка удаленного сервиса неприемлема, узкая задача подходит маленькой модели либо стабильность версии важнее обновлений. Локальная модель также годится как запасной вариант при сбоях и лимитах. Ни одно условие не требует отправлять ей все запросы.

Я не советую покупать оборудование, чтобы «перестать платить за подписки». Сервер виден, а регулярный платеж психологически раздражает, поэтому совет популярен. Но он неверен, если локальная модель снижает выпуск или создает неоплачиваемую должность оператора. Зарплата в большинстве команд намного выше цены инференса, поэтому небольшая потеря качества съест крупную экономию на вычислениях.

Используйте правила маршрутизации. Чувствительные репозитории и типовые массовые задачи оставьте локально. Сложные архитектурные изменения, редкие ошибки фреймворка и нерегулярную работу отправляйте сильной облачной модели, если политика разрешает. Разработчик должен ясно видеть выбранный маршрут, а скрытая отправка закрытого кода наружу должна быть технически невозможна.

В oleg.is я начинаю с Team & AI Audit, когда основателю нужно связать решение с расходами на команду, а не с увлечением видеокартами. Аудит стоит $5 000, занимает пять рабочих дней и находит не меньше $50 000 годовой экономии либо проводится бесплатно. Результатом становится рабочая модель нагрузки и команды, которая может рекомендовать локальный инференс, облачные инструменты или их сочетание.

## Пилот должен удешевлять неудачу

Локальная LLM для программирования должна заслужить расширение за четырехнедельный пилот на реальной, но обратимой работе. Возьмите арендуемое оборудование или одну станцию, по модели из каждого подходящего размера, фиксированный набор задач и небольшую группу разработчиков. Не начинайте с покупки стойки и приказа всем отказаться от облачного помощника.

В первую неделю классифицируйте нагрузку и измерьте облачный ориентир. Во вторую разверните локальный сервер с аутентификацией, закрепленными версиями, лимитами памяти и отключенными по умолчанию журналами. В третью проведите слепую оценку патчей и ограниченное ежедневное использование. В четвертую сравните принятые патчи, время правок ревьюера, задержки, сбои и полную эксплуатационную стоимость.

Условия остановки задайте заранее. Прекратите пилот, если модель не достигает минимальной доли приемки, задержка мешает работе, защита остается набором исключений или один инженер навсегда превращается в няню сервера. Продолжайте, только когда команда умеет объяснить, какие запросы идут локально, а измеренная экономика подтверждает этот маршрут.

Не начинайте с дообучения. Поиск, инструкции репозитория, правильный шаблон диалога, лучшее разбиение задач и более сильная базовая модель заслуживают проверки раньше обучения. Дообучение помогает стабильным повторяющимся шаблонам, но добавляет подготовку данных, оценку, развертывание и жизненный цикл модели. Оно не добавит маленькой модели всю способность рассуждать, на покупке которой вы хотели сэкономить.

Финальным решением может быть «оставить подписку». Такой пилот не провалился. Провал выглядит иначе: сервер работает только потому, что его уже купили, а разработчики тайком вставляют сложные задачи в облачного агента. Оставляйте локальный инференс, когда его преимущество в границах данных, цене или стабильности выдерживает честную проверку патчами. Иначе потратьте инфраструктурный бюджет на инструмент, который доводит проверенный код до продакшена.
