Что это решает
Отдавать в чужой API переписку с клиентами, исходники и внутренние регламенты можно не всегда: где-то запрещает договор, где-то отраслевое требование, где-то на объекте просто нет интернета. Ollama снимает три вопроса разом — данные остаются на машине, счётчик токенов не тикает, квоты и лимиты никто не режет. Порог входа при этом ниже, чем у сборки llama.cpp руками: скачивание модели и запуск умещаются в две команды. Плата — своё железо и потолок качества у моделей, которые на это железо влезают.
Как устроено
Демон и клиент
Ollama состоит из фонового сервиса и CLI. Сервис слушает локальный порт 11434 и отдаёт HTTP API, командная строка — тонкий клиент к тому же API. Любая интеграция ходит по HTTP, а не запускает процесс на каждый запрос.
Модели хранятся в формате GGUF, под капотом работает движок семейства llama.cpp. Скачиваются они слоями по манифесту, как образы контейнеров: одинаковые слои между тегами переиспользуются, повторная загрузка не тянет всё заново.
ollama pull <модель> # скачать
ollama run <модель> # интерактивный чат
ollama list # что скачано и сколько занимает
ollama ps # что сейчас в памяти и на чём считается
ollama show <модель> # параметры, шаблон чата, лицензия
Квантование и память
Веса ужимают до 8, 5 или 4 бит, и это видно прямо в имени тега (q4_K_M и родственники). Грубая оценка потребления: число параметров умножить на количество байт на вес — при 4 битах это половина байта — и добавить запас на KV-кэш, который растёт вместе с длиной контекста и числом одновременных запросов. Отсюда практическое следствие: модель влезает по весам, а на длинном диалоге уходит в своп и начинает выдавать по токену в секунду.
Modelfile
Свой пресет собирается из текстового файла:
FROM <базовая модель>
SYSTEM "Отвечай кратко, только по документам компании."
PARAMETER temperature 0.2
PARAMETER num_ctx 8192
Команда ollama create мой-ассистент -f Modelfile превращает это в обычный локальный тег, который дальше запускается как любая другая модель. Директива TEMPLATE задаёт шаблон чата — расстановку служебных токенов ролей. Она наследуется от базовой модели, и ломать её без нужды не стоит: сбитый шаблон приводит к тому, что модель начинает договаривать реплики за пользователя.
API
Три основных маршрута: /api/generate — одиночное продолжение текста, /api/chat — диалог сообщениями с ролями, /api/embeddings — векторы для поиска. Плюс OpenAI-совместимый слой на /v1: клиентские библиотеки переключаются на локальную модель сменой базового URL и фиктивного ключа. Самый дешёвый способ прикрутить локальный запуск к коду, который уже написан под облако.
curl http://localhost:11434/api/chat -d '{
"model": "<модель>",
"messages": [{"role": "user", "content": "Сформулируй суть в двух предложениях"}],
"stream": false,
"options": {"temperature": 0.2, "num_ctx": 8192}
}'
Параметры генерации передаются в объекте options прямо в запросе и перебивают то, что зашито в Modelfile. Это удобно: один сервис может ходить к одной и той же модели с разными настройками под разные задачи, без создания отдельных тегов. Модель для эмбеддингов при этом берётся отдельная — генеративная модель векторы тоже отдаст, но качество поиска на них будет заметно хуже, чем на специализированной.
Жизненный цикл в памяти
Первый запрос загружает веса — от секунд до десятков секунд. Дальше модель висит в памяти и отвечает быстро. Параметр keep_alive определяет, сколько её держать после последнего обращения; переменные окружения задают, сколько моделей разрешено держать загруженными и сколько запросов обрабатывать параллельно. Две крупные модели одновременно — это две порции памяти, а не полторы.
Отдельного внимания заслуживает num_ctx. Длина контекста задаётся при запуске и по умолчанию заметно меньше того, что обещает карточка модели. Хвост диалога или начало длинного документа обрезаются молча, без предупреждения, и со стороны это выглядит как «модель тупая».
GPU и CPU
На видеокарте считается кратно быстрее, но модель должна поместиться в VRAM целиком. Не поместилась — часть слоёв уезжает на процессор, и скорость падает до неприемлемой. На Apple Silicon память общая, поэтому на ноутбуке запускаются модели крупнее, чем ожидается. Команда ollama ps показывает, какая доля модели ушла на GPU — с этого начинается любая разборка «почему так медленно».
Полезные сценарии
- Ответы по внутренним документам: эмбеддинги и генерация целиком на своей машине, ни один абзац договора не уезжает наружу.
- Массовая разметка и классификация архива, где важна не гениальность ответа, а отсутствие счёта за миллион запросов.
- Черновое автодополнение и объяснение кода в редакторе через локальный эндпоинт, без задержек сети.
- Демонстрации и полевые задачи там, где интернета нет или он платный и медленный.
- Прототип пайплайна перед выбором облачной модели: логика отлаживается локально, наружу переключается сменой базового URL.
Ограничения
- На сложных рассуждениях, длинном контексте и редких языках локальные модели уступают топовым облачным. «Почти так же» получается на простых и хорошо очерченных задачах.
- Скорость упирается в пропускную способность памяти. Один пользователь работает комфортно, десяток одновременных выстраивается в очередь.
- Контекст по умолчанию урезан. Без явного
num_ctxмодель теряет начало документа и выглядит хуже, чем она есть. - Квантование ниже четырёх бит заметно портит аккуратность в цифрах, форматах и следовании инструкции.
- Аутентификации в API нет вообще. Порт, выставленный на публичный интерфейс, отдаёт модель всем желающим за ваш счёт по электричеству. Наружу — только через обратный прокси с авторизацией или через приватную сеть.
- Лицензии моделей разные, и коммерческое применение проверяется по карточке модели, а не по факту успешного скачивания.
- Вызов инструментов и строгий структурированный вывод поддерживают не все модели, и качество там сильно скачет.
- Обновление тега меняет поведение. Для продакшена тег фиксируется, а обновление проходит через прогон своего набора задач.
Как проверить результат
ollama psво время запроса: видно, какая часть модели считается на GPU. Если там процессор, дальнейшие замеры скорости бессмысленны.ollama run <модель> --verbose: в конце ответа выводятся тайминги и скорость в токенах в секунду. Это первое число для сравнения моделей и квантований между собой.- Проверка контекста руками: положить в начало длинного текста метку («кодовое слово — гранит») и в конце спросить, какое там было кодовое слово. Не вспомнил — упёрлись в
num_ctx. - Прямой запрос curl к
/api/chatмимо CLI: так проверяется то, что увидит приложение, включая шаблон чата и системное сообщение. - Свой набор из 20–30 реальных задач с ожидаемыми ответами, прогнанный по двум-трём кандидатам одним и тем же промптом. Публичные рейтинги про конкретную задачу ничего не говорят.
- Наблюдение за памятью и свопом во время прогона: уход в своп виден как секунды на токен и лечится меньшей моделью или меньшим контекстом.
ss -tlnp | grep 11434— убедиться, что сервис слушает 127.0.0.1, а не 0.0.0.0.
Правило: локальная модель считается пригодной только после прогона собственного набора задач при явно заданном num_ctx и подтверждённой загрузке на GPU.
