Облачная языковая модель — быстрый старт, но у него три цены: данные уходят за пределы сервера, оплата за каждый токен и зависимость от чужого аптайма. Для части задач — черновик маркетингового текста — это нормально. Для других — анализ логов с токенами доступа, разбор клиентских документов, приватный чат-бот на внутреннем сайте — нет: туда облако вести нельзя, и дело не только в GDPR, а в том, что, отправив текст в облако, вы больше не контролируете его копию.
Один из выходов — запускать модель на своей машине. Самый простой инструмент для этого на сегодня — Ollama: одна бинарная служба, которая скачивает модель и поднимает локальный API, совместимый с OpenAI. В этой статье — как поставить Ollama на VPS, что выбрать по размеру и языку (точные веса моделей сверены с официальной библиотекой на дату публикации), сколько памяти это ест и как воткнуть в PHP-код вместо облачного вызова.
Это четвёртая статья серии про ИИ-инструменты для контента и SEO. До этого разбирали форму запроса (Промпт-инжиниринг), массовую генерацию (Генерация мета-тегов) и retrieval по своему контенту (RAG на SQLite). RAG-контур из той статьи остаётся прежним — меняется только то, где живёт модель в call_model.
Часть I. Когда облако не подходит
Не всякую задачу надо тащить в локаль. Облачный API выигрывает, когда нужен максимум качества на редких сложных запросах, а данные нечувствительны. Но есть четыре сигнала, что стоит задуматься о своей модели:
- Приватность данных. Токены, персональные данные клиентов, коммерческая переписка, аналитика логов — всё, что нельзя копировать на чужой сервер. Юридически (152-ФЗ, GDPR, отраслевые требования) и практически: отправив текст в облако, вы теряете контроль над его копией.
- Цена на потоке. Чат-бот с высокой посещаемостью или автоматический разбор тысяч документов оплачивается за каждый миллион токенов. На определённом объёме своё железо окупается, и облако начинает стоить дороже.
- Автономность и офлайн. Сайт обязан работать, когда у вендора АPI сбой или канал до него лёг. Локальная модель живёт на том же VPS, что и остальной сервер.
- Латентность. Облачный запрос идёт через сеть; локальный — только через localhost. Для интерактива это может быть решающим.
Важная честная рамка: своя модель не бесплатна. Она стоит RAM и CPU/GPU вашего сервера и места на диске, и она слабее облачного флагмана по качеству. Локаль — это компромисс «приватность/контроль в обмен на мощность», и к нему стоит переходить осознанно, а не «потому что модно».
Часть II. Ollama на своём VPS: от установки до первого ответа
Ollama распространяется одним скриптом и работает как обычная служба. Установка на Linux-сервер:
curl -fsSL https://ollama.com/install.sh | shПосле установки Ollama поднимается как systemd-юнит ollama.service и слушает порт 11434 на localhost. Первый запуск модели (скачивание весов и ответ) — одной командой:
ollama run qwen2.5:7bНастройка доступа и юнита
Два решения после установки. Первое: по умолчанию служба слушает только 127.0.0.1 — это правильно, модель не должна торчать наружу. Если веб-код на том же сервере — оставляйте localhost; пробрасывать 11434 в интернет без аутентификации — дыра (об этом ниже, в граблях). Второе — как сервис переживает перезагрузку. Это ровно те же понятия, что разобраны на примере обычных сервисов: systemd: как сервис живёт на сервере. Типичный drop-in для автозапуска и лимита памяти:
# /etc/systemd/system/ollama.service.d/override.conf
[Service]
# старт после сети, рестарт при падении — базовая гигиена юнита
Restart=on-failure
# если сервер общий, ограничьте потребление, чтобы модель не «съела» PHP-FPM
MemoryMax=8G
systemctl daemon-reload && systemctl enable --now ollama
# проверить, что сервис поднялся и слушает:
systemctl status ollama --no-pager
ss -ltnp | grep 11434
Дальше всё управление моделями — через CLI: ollama list (что скачано), ollama pull <tag> (забрать версию), ollama rm <tag> (освободить диск). Никакой отдельной инфраструктуры: один процесс, один порт, папка с весами.
Часть III. Что выбрать по размеру и языку
Точные размеры моделей ниже взяты с официальной страницы библиотеки Ollama на дату подготовки статьи; линейка и кванты обновляются — перед pull сверяйте актуальные теги по адресу https://ollama.com/library.
Для VPS общего назначения рабочий диапазон — 7–8 миллиардов параметров, q4_K_M квантования. Это тот размер, который влезает в умеренную RAM и при этом связно говорит и пишет код. Что брать по задаче:
| Модель | Тег по умолчанию | Размер (q4_K_M) | Контекст | Чем хороша |
|---|---|---|---|---|
| Qwen2.5 | qwen2.5:7b (он же latest) | 4.7 GB | 32K | многоязычная, хорошо держит русский; размерность-многопрофильная |
| Llama 3.1 | llama3.1:8b | 4.9 GB | 128K | сильный английский и код; большой контекст |
| Mistral (v0.3) | mistral:7b | 4.4 GB | 32K | компактная, быстрая, «рабочая лошадка» |
Цифры — не маркетинговые «параметры», а фактический размер веса на диске (сверено: qwen2.5:7b=4.7 GB, llama3.1:8b=4.9 GB, mistral:7b=4.4 GB). Разница в контексте заметна сразу: Llama 3.1 на 128K помещает в окно за раз целый длинный документ, а Mistral на 32K — нет. Если задача — «ответь по огромному тексту целиком», это выбор в пользу Llama; если задача — много коротких запросов на потоке и важна скорость, Mistral дешевле по железу.
А если нужен русский покрепче
Qwen2.5 из таблицы уже хорошо работает с русским — это безопасный дефолт, не требующий экзотики. Существенно «заточенных под русский» моделей в официальной библиотеке Ollama на момент проверки — мало; отдельные русскоязычные семейства (например, GigaChat от Sber выпущен с открытыми весами и описанием архитектуры в arXiv:2506.09440) чаще доступны через собственный API или выкладываются в Hugging Face в формате GGUF, а не готовым тегом в Ollama. GGUF-файл можно подключить в Ollama через Modelfile — но точное наличие и название тега нужно сверять на библиотеке в момент установки, а не по памяти: модельный ряд меняется каждые месяцы, и выдуманный тег — самая частая причина «команда не работает». Для практического контура на русском безопаснее брать qwen2.5:7b, а редкие «строго-русские» модели заводить отдельным Modelfile, когда вы точно знаете, откуда качаете веса.
Часть IV. Квантование = память, и это не то же, что размер в параметрах
«7B-модель» говорит о числе параметров, но сколько она реально займёт RAM — определяет квантование: вес хранят с меньшей точностью, жертвуя каплей качества ради памяти и скорости. В Ollama квант — часть тега. Один и тот же Qwen2.5 на 7B:
qwen2.5:7b-instruct-q4_K_M → 4.7 GB (рабочий дефолт: качество/память в балансе)
qwen2.5:7b-instruct-q8_0 → 8.1 GB (выше качество, почти fp16, дороже по памяти)
qwen2.5:7b-instruct-fp16 → 15 GB (максимум качества, минимум потерь, тяжёлая)
(размеры те же, что и на странице библиотеки: q4_K_M 4.7 / q8_0 8.1 / fp16 15 GB). Практическое правило:
- q4_K_M — ставить по умолчанию. Это то квантование, под которое обычно хватает 8–16 GB VPS, и потеря качества против fp16 на бытовых задачах почти не заметна.
- q8_0 / fp16 — когда задача действительно просит максимум и есть запас памяти. Разница 4.7→15 GB в разы, а прирост — нет.
Но вес модели — ещё не вся память. Во время генерации живёт KV-кэш: чем больше контекст и чем длиннее диалог, тем больше RAM поверх файла весов. Поэтому ориентир по свободной памяти для комфортной 7–8B модели на q4_K_M — ~6–8 GB (вес + KV-кэш + служебное; это оценочный коридор, а не точная константа). Тот же MemoryMax из Части II стоит ставить выше этой цифры, иначе Ollama начнёт вытеснять PHP-FPM. Экономика памяти сервера под конфигурацию пула разобрана рядом — PHP-FPM: движок под WordPress: модель и пул делят один и тот же RAM, считать надо их вместе, не по отдельности.
Часть V. Интеграция с PHP: локальная модель — это другой base URL
Главное для программиста: Ollama отдаёт OpenAI-совместимый API. Значит, код, который уже умеет обращаться к облаку, переключается на локаль одной строкой — адресом. Точка входа — POST http://127.0.0.1:11434/v1/chat/completions.
<?php
// Локальный вызов модели вместо облачного: тот же OpenAI-формат тела.
function call_model_local( string $system, string $user, string $model = 'qwen2.5:7b' ): string {
$resp = wp_remote_post( 'http://127.0.0.1:11434/v1/chat/completions', array(
'timeout' => 120, // локальная генерация медленнее облака на CPU — таймаут крупнее
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( array(
'model' => $model,
'messages' => array(
array( 'role' => 'system', 'content' => $system ),
array( 'role' => 'user', 'content' => $user ),
),
'temperature' => 0.2,
'max_tokens' => 800,
'stream' => false,
) ),
) );
if ( is_wp_error( $resp ) ) return '';
$data = json_decode( wp_remote_retrieve_body( $resp ), true );
return (string) ( $data[ 'choices' ][0][ 'message' ][ 'content' ] ?? '' );
}Что меняется относительно облачного вызова и почему это удобно:
- Ключ не нужен вовсе. На
localhostмодель слушает без аутентификации — локальный хост «доверенный». Это не дыра, пока порт не торчит наружу; но и секрет в.envпрятать не от чего. Секретная гигиена с.envостаётся в силе только для облачных ключей — см. Три конфига WordPress. - Тот же контракт ответа.
choices[0].message.content— OpenAI-формат, поэтому RAG-контур из предыдущей статьи переключается на локаль без переделки логики — меняется толькоcall_modelнаcall_model_local. Подложка, порог score, guard — всё остаётся. stream= true для интерактива отдаёт SSE-поток (текст «прирастает» по мере генерации); механика работы с потоками в браузере — Потоки в браузере: SSE и WebSocket. На CPU генерация идёт заметно медленнее облака, поэтому для чата стриминг почти обязателен — иначе пользователь смотрит в пустой экран 20 секунд.
Если вместо прямой интеграции нужен «готовый помощник», на сайте есть живая страница чат-ассистента — поговорить с моделью можно там, а локальный endpoint подключается тем же OpenAI-совместимым обращением: https://codestack.space/ai-pomoshhnik-dlja-koda/.
Часть VI. Облако против локали: как считать компромисс
Нельзя просто «поставить Ollama и забыть» — вы меняете один набор ограничений на другой. Честная таблица, по чему они расходятся:
| Ось | Облако | Локаль (Ollama) |
|---|---|---|
| Приватность данных | текст уходит на сервер вендора | данные не покидают сервер ✅ |
| Пиковое качество | флагманские модели | локальная 7–8B слабее на сложном |
| Цена | оплата за токены | оплата за железо + электричество |
| Альтернативный сбой | зависит от вендора и сети | живёт на вашем сервере |
| Латентность | через сеть | через localhost ✅ |
| Масштаб | масштабирует вендор | упирается в ваше CPU/GPU |
Практический вывод: гибрид, а не «или/или». Чувствительное (логи с токенами, клиентские документы, внутренний чат-бот) — в локаль; сложное не-секретное (маркетинговый слоган, генерация по длинному общедоступному корпусу, где нужна вся мощность флагмана) — в облако. Тот же принцип локального против облачного наглядно демонстрирует интерактивная песочница, где один текст обрабатывают обе стороны и можно сравнить результат: https://codestack.space/sravnenie-ii/. Для приватных данных локаль — не «а может быть», а «надо»; для пикового качества — облако пока впереди, и наивно требовать от 7B-модели на CPU результата флагмана.
Инструменты под задачу
Самое полезное после установки — не код, а калибровка ожиданий: задайте локально запущенной модели реальный вопрос своей предметной области и посмотрите на ответ. Универсальный чат-ассистент ниже работает по тем же OpenAI-совместимым моделям, так что им удобно сравнивать «как отвечает облако» против ощущения от локального качества, чтобы заранее понять, какие задачи вообще стоит переносить на своё железо:
Чек-лист граблей
- Пробросили
11434в интернет без аутентификации → открытый генератор текста для всего света, жрёт ваш CPU; слушайте localhost, наружу — только через прокси с доступом. - Ставите «самую умную» fp16 без запаса памяти → модель вытесняет PHP-FPM и кладёт сервер; квант выбирайте по железу, не по амбиции.
- Забываете KV-кэш при расчёте RAM → вес 4.7 GB не значит «хватит 5 GB»: нужен запас на контекст и диалог.
- Считаете квант «технической мелочью» → q4_K_M против fp16 — это разница качества/памяти в разы; для бытовых задач q4_K_M — рабочий дефолт.
- Ищете «строго-русскую» модель по памяти и ставите несуществующий тег → команда падает; наличие тега сверяется на ollama.com в момент установки, надёжный дефолт для русского — Qwen2.5.
- Ожидаете облачного качества от локальной 7B → разочарование; на сложном облако пока впереди, для приватного же выбора — локаль.
- Требуете мгновенного ответа от локальной модели на CPU → при stream=false пользователь смотрит в пустой экран; для интерактива нужен стриминг.
- Ставили крупный
timeoutкак для облака → локальная генерация дольше, короткий таймаут обрывает ответ на середине; таймаут локального вызова — с запасом. - Дублируете секрет в
.envдля локального вызова → лишний ключ там, где аутентификации на localhost нет;.envнужен для облачных ключей. - Не ограничили модель на общем сервере → одна генерация съедает RAM/ЦП сайта;
MemoryMaxи лимиты юнита обязательны.
👤 Зарегистрируйтесь, чтобы добавить материал в закладки.
