API Ollama для Python и проверка совместимости

API Ollama для Python и проверка совместимости

Отсутствие внешнего ключа не означает, что существующий API-клиент сразу станет локальным. Ты убрал строку с секретом, поднял модель на своей машине - и ждёшь, что старый Python-код продолжит работать как раньше. Часто не продолжает. Дело не в том, что локальный сервер «хуже». У него просто другой контракт эксплуатации: другие эндпоинты, другое поведение по умолчанию, другая форма ответа и другой тип исключения.

Разведём два понятия, которые сливаются в голове при первом переезде. Локальность - это где выполняется модель и куда уходят данные. Совместимость - это совпадает ли поведение сервера с тем, чего ждёт твой клиент. Первое ты меняешь одной командой. Второе не меняется само; его нужно проверить.

Проверять будем тремя режимами вызова на одном Python-клиенте. Результат этой проверки - не «работает или нет», а список: какие сценарии совпадают с ожиданием и какие требуют явной адаптации. И сразу граница: такая матрица честна ровно для той пары «версия сервера - версия клиента», на которой ты её прогнал. Она не доказывает совместимость всех клиентов и всех версий.

Почему «убрал ключ» и «стало совместимо» - разные события

Путаница начинается уже в словах: api ollama и ollama api, api key ollama и ollama api key в чужих заметках пишут вперемешку, будто разница только в порядке слов. Вопрос за всеми вариантами один - можно ли ткнуть старый клиент в локальный сервер и не переписывать код. А под разнобоем в словах лежит разнобой в ожиданиях: предположение, что локальный endpoint автоматически заменяет облачный API.

Он не заменяет. По документации Ollama (docs.ollama.com, обращение 18 июля 2026) родной ollama api - это два разных REST-эндпоинта для генерации текста. /api/chat работает с историей сообщений и ролями system/user/assistant/tool и держит состояние диалога. Эндпоинт ollama api generate (/api/generate) - stateless: он принимает одну строку prompt плюс опциональные system, raw, suffix. Формы тела у них разные, и клиент, который умеет только одну, вторую просто не поймёт.

Отдельная ловушка - поведение по умолчанию. И /api/chat, и /api/generate по документации Ollama выставляют stream в true по умолчанию. У OpenAI API умолчание обратное - stream=false. Клиент, написанный под привычки OpenAI, получит поток NDJSON-чанков вместо одного JSON, пока ты явно не передашь stream=false. Это не ошибка сервера; это разница контрактов, которую твой парсер не ждёт.

Отсюда же вырастает приём отладки, который экономит вечер: держи под рукой второй, заведомо OpenAI-совместимый endpoint и бей в него тем же клиентом. Прошло там, упало здесь - значит, дело в контракте локального сервера, а не в твоём коде. Внешним плечом такой пары может быть provod.ai (совместимый API-контур для агентов, IDE и SDK), куда тот же SDK направляется сменой base_url и ключа. Локальный контур Ollama он не подменяет; он нужен как вторая точка отсчёта.

Три режима, которые надо прогнать

Чтобы не гадать, зафиксируем ровно три режима вызова и то, что каждый обещает по документации.

Первый - родной generate. Ты шлёшь одну строку, ждёшь одно завершение. Полезно для промптов без истории: суммаризация, классификация, генерация по шаблону. Второй - родной chat. Ты шлёшь список сообщений с ролями, сервер держит структуру диалога. Третий - OpenAI-совместимый слой. Ollama отдельно публикует поверхность по адресу отличную от родных /api/*, чтобы клиент на OpenAI-SDK мог просто указать base_url на локальный инстанс. По документации Ollama в этом слое ollama api key` требуется, но игнорируется - любая непустая строка проходит.

Здесь важно не спутать поверхности. ollama local api живёт на родных /api/, а слой совместимости - на /v1/, и это разные контракты с разным набором возможностей. Базовый ollama api url для обоих один - ` различаются только пути. Официальные ollama api docs на docs.ollama.com описывают их отдельными страницами.

API Ollama для Python и проверка совместимости

Как это выглядит в Python-коде

Названия и здесь двоятся: ollama api python, ollama python api - пакет за ними один, официальный ollama (pip install ollama, репозиторий ollama-python). По документации на GitHub он оборачивает именно родной REST API, а не OpenAI-совместимый слой, через классы Client и AsyncClient с методами chat(), generate(), embed(), list(), show(), pull() и другими, и по умолчанию ходит на ` Вот минимальный прогон двух родных режимов.

import ollama client = ollama.Client(host="http://localhost:11434") # режим generate: одиночный prompt, stateless gen = client.generate( model="llama3.2", prompt="ping", stream=False, # иначе по умолчанию придёт поток ) # режим chat: список сообщений, роли chat = client.chat( model="llama3.2", messages=[{"role": "user", "content": "ping"}], stream=False, )

Третий режим идёт через OpenAI-SDK, направленный на локальный слой. Тут же удобно поставить рядом внешний совместимый маршрут - тем же SDK, сменой base_url и ключа, - чтобы сравнить форму ответа.

from openai import OpenAI # OpenAI-совместимый слой Ollama local = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") resp = local.chat.completions.create( model="llama3.2", messages=[{"role": "user", "content": "ping"}], ) # внешний совместимый маршрут для сравнения external = OpenAI(base_url="https://api.provod.ai/v1", api_key="...")

Обрати внимание, что во втором случае меняются ровно две строки - адрес и ключ. Внешний маршрут обязан вести себя как OpenAI, потому что на него нацелены чужие SDK: provod.ai принимает клиенты OpenAI и Anthropic той же сменой base_url и ключа, поэтому и годится эталоном - один и тот же код гоняешь против локальной модели и против облачной и смотришь, где расходятся формы ответа. Локальный контур ты держишь у себя ради данных; внешний маршрут берёшь там, где нужна модель, которой у тебя локально нет. Задачи разные.

Матрица «режим - клиент - ожидание - наблюдение»

Теперь главный инструмент. Вместо «попробовать и посмотреть» - таблица, где для каждого режима заранее закреплено ожидание из документации, а колонку наблюдения ты заполняешь на своём прогоне. Сценарий считается переносимым только тогда, когда наблюдение совпало с закреплённым ожиданием. Если ожидание не определено - строку нельзя оценивать, её надо доопределить до запуска.

Ожидания ниже взяты из документации Ollama; наблюдения - твоя первая колонка ответственности, потому что готовых прогонов для конкретно твоей пары версий не существует. Именно поэтому рядом с каждой строкой фиксируй ollama --version и вывод pip show ollama. Проект выпускает частые точечные релизы: последний тег на момент сверки документации для этой статьи - v0.32.1 от 16 июля 2026 (страница релизов Ollama на GitHub). Через версию поля могут отличаться.

  • Режим: /api/generate • Что шлёшь: строка prompt • Ожидание по документации Ollama: stream=true по умолчанию; в ответе total_duration, eval_count и другие родные поля • Наблюдение (заполняешь сам): ?
  • Режим: /api/chat • Что шлёшь: список messages • Ожидание по документации Ollama: stream=true по умолчанию; поле thinking/think со значениями high/medium/low/max • Наблюдение (заполняешь сам): ?
  • Режим: /v1/chat/completions • Что шлёшь: форма OpenAI • Ожидание по документации Ollama: api_key игнорируется; форма ответа OpenAI-подобная, но без части возможностей • Наблюдение (заполняешь сам): ?
  • Режим: обработка ошибок • Что шлёшь: некорректный запрос • Ожидание по документации Ollama: ollama.ResponseError с error и status_code, а не исключения OpenAI SDK • Наблюдение (заполняешь сам): ?

Родной конверт ответа - отдельный источник расхождений. По документации Ollama он несёт поля, которых нет в схеме OpenAI: тайминги наносекундной точности (total_duration, load_duration, prompt_eval_duration, eval_duration), счётчики токенов (prompt_eval_count, eval_count) и отдельное поле reasoning-effort. Код, который лезет в ответ по ключам OpenAI, эти поля не найдёт и упадёт или молча вернёт пустоту.

API Ollama для Python и проверка совместимости

Где именно ломается совместимость

Похожий интерфейс generate/chat не гарантирует одинаковое поведение клиента - и это главный сюрприз переезда. Слой ollama openai api выглядит как OpenAI, отвечает почти как OpenAI, и именно поэтому вводит в заблуждение: паритет неполный. Синтаксическая похожесть не доказывает поведенческую совместимость.

По документации Ollama слой совместимости на /v1/ имеет прямо задокументированные ограничения. Он не поддерживает stateful-разговоры через /v1/responses, для зрения принимает только base64-картинки (не URL изображений), а prompt у /v1/completions - только строка, без массива. Эндпоинт /v1/images/generations помечен как экспериментальный и может измениться или исчезнуть в будущих версиях. То есть сам слой совместимости - движущаяся цель, и закладываться на него как на замороженный контракт рано.

Ещё одна тихая мина - имена моделей. Чтобы обратиться к модели под привычным именем вроде gpt-3.5-turbo через слой совместимости, придётся вручную сделать псевдоним локальной модели командой ollama cp: Ollama не подменяет имена OpenAI на локальные автоматически. Клиент, который зашивает имя модели строкой, на этом месте получит ошибку «модель не найдена», хотя модель у тебя есть.

API Ollama для Python и проверка совместимости

Что решать по итогам матрицы

Правило, которого я здесь держусь, простое: адаптируй клиент только после обнаруженного конкретного различия, а не превентивно. Предположить полную совместимость дешевле на старте, но дороже на проде, когда парсер молча теряет поле. Прогнать три режима до адаптации - принятая цена: несколько минут на клиент против отладки в бою.

Из матрицы вырастает короткий список решений. Если наблюдение по строке совпало с ожиданием - сценарий переносится как есть, трогать нечего. Если разошлось - фиксируешь минимальную адаптацию ровно под это различие: явный stream=False, чтение родных ключей ответа, перехват ollama.ResponseError вместо исключений OpenAI SDK, псевдоним модели через ollama cp. Локальный запуск даёт контроль над данными и стоимостью, но переносит на тебя ответственность за совместимость - это и есть та плата, которую видно только на прогоне.

  • Что показал прогон: Наблюдение совпало с ожиданием • Решение: Перенести сценарий без изменений
  • Что показал прогон: Пришёл поток вместо JSON • Решение: Передавать stream=False явно
  • Что показал прогон: Поля ответа не читаются • Решение: Читать родные ключи конверта Ollama
  • Что показал прогон: Исключение другого типа • Решение: Ловить ollama.ResponseError
  • Что показал прогон: Модель «не найдена» по OpenAI-имени • Решение: Сделать псевдоним через ollama cp
  • Что показал прогон: Ожидание не определено • Решение: Не оценивать строку, доопределить и перепрогнать
API Ollama для Python и проверка совместимости

Чего эта проверка не решает

Матрица честна для одной пары версий и одного клиента. Не экстраполируй результат одного клиента на все клиенты и все релизы: наличие поля вроде think или поведение format=/tools= в Python-пакете от версии к версии меняется. Поэтому колонка версий - не формальность.

Она не решает и вопрос доступа к моделям, которых у тебя нет локально. Локальный контур - про данные и контроль; внешний совместимый маршрут - про каталог. provod.ai здесь не подменяет локальный Ollama: он не даёт ни изоляции контура, ни контроля над весами. Его роль в этом сюжете узкая - вторая точка отсчёта, на которой тот же Python-клиент проверяется против облачных моделей.

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

FAQ

Локальный запуск отменяет облачный, или это разные режимы? Разные. Quickstart Ollama прямо различает ollama run для локального выполнения и ollama run :cloud (с ollama signin) для облачной модели в том же CLI. Один endpoint не подменяет другой прозрачно.

Какой ollama api url ставить в клиент? По умолчанию Родные вызовы идут на /api/*, OpenAI-совместимые - на /v1/`. Пути разные, хост один.

Нужен ли ключ для локального сервера? Для родного API - нет. В OpenAI-совместимом слое ключ передаётся, но по документации игнорируется, так что подойдёт любая непустая строка.

Можно ли просто переставить base_url со старого OpenAI-клиента и не думать? Можно попробовать, но именно из-за этого допущения ломается первый запуск: умолчание стрима, форма ответа, имена моделей и тип исключения отличаются. Проверь три режима по матрице.

API Ollama для Python и проверка совместимости

Когда матрица заполнена и нужна вторая точка отсчёта - или просто модель, которой на твоей машине нет, - подключи provod.ai тем же клиентом, сменой base_url и ключа: Claude, GPT, Gemini, DeepSeek и Qwen открываются через один совместимый API, с оплатой рублями и без иностранной карты. Локальный контур Ollama это не отменяет - у него своя работа, и данные остаются на твоей машине.

Источники

  • Документация Ollama, /api/chat и /api/generate (docs.ollama.com), обращение 18 июля 2026.
  • Документация Ollama, OpenAI-совместимость (docs.ollama.com/api/openai-compatibility), обращение 18 июля 2026.
  • Ollama, блог об OpenAI-совместимости (ollama.com/blog/openai-compatibility), обращение 18 июля 2026.
  • Официальный Python-клиент, репозиторий ollama-python (github.com/ollama/ollama-python), обращение 18 июля 2026.
  • Страница релизов Ollama, тег v0.32.1 от 16 июля 2026 (github.com/ollama/ollama/releases).
  • Quickstart Ollama, локальный и облачный режимы (docs.ollama.com/quickstart), обращение 18 июля 2026.

provod.ai — мировой AI-каталог с оплатой из России

Подключайте нужные модели без зарубежной банковской карты и обходных платёжных схем: доступ работает через российскую платформу, а баланс пополняется в рублях.

В одном каталоге — актуальные модели для текста и медиа: GPT от OpenAI, Claude от Anthropic, Gemini от Google, Grok от xAI, DeepSeek, Qwen, GLM, Kimi и MiniMax; для изображений — Nano Banana 2 Pro и GPT Image; для видео — последние версии Seedance, Kling, Veo и Google Omni. Также доступны модели для reasoning, поиска, документов, эмбеддингов, музыки и аудио.

Российский способ оплаты не удорожает саму модель: цена соответствует официальному тарифу 1:1, без собственной наценки provod.ai.

Начните работать без платёжных барьеров: форма регистрации · цены на модели · защита данных по 152-ФЗ · главная provod.ai