LangChain Ollama или облачная модель: один код, две модели

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

4 мин · · сравнение · разработка

LangChain Ollama и облачные модели в LangChain это два способа получить один и тот же объект «чат-модель»: ChatOllama запускает модель на вашем компьютере, ChatOpenAI с другим base_url обращается к облачной. Остальной код (промпты, цепочки, агенты) от выбора не зависит. Ниже сравним оба варианта по документации LangChain и Ollama и соберём код, где локальная и облачная модель переключаются одной настройкой. Версии пакетов сверяйте с документацией: они меняются.

ChatOllama: локальная модель

Интеграция живёт в пакете langchain-ollama. По документации LangChain порядок такой: установить Ollama и запустить локальный сервер, скачать модель командой ollama pull, затем создать объект.

bash
pip install -qU langchain-ollama
ollama pull gpt-oss:20b
bash
from langchain_ollama import ChatOllama

llm = ChatOllama(model="gpt-oss:20b", temperature=0)

ai_msg = llm.invoke([
    ("system", "Ты переводчик с английского на русский. Переводи фразу пользователя."),
    ("human", "I love programming."),
])
print(ai_msg.content)

Название модели в ChatOllama(model=...) должно совпадать с тегом, который вы скачали через ollama pull (список скачанных моделей показывает ollama list). Среди возможностей ChatOllama документация отмечает вызов инструментов, структурированный вывод, ввод изображений (для мультимодальных моделей), потоковую передачу по токенам и учёт токенов.

ChatOpenAI с base_url шлюза: облачная модель

Для облака берём ChatOpenAI из langchain-openai и указываем адрес шлюза. Для клиентов на OpenAI-формате у Zukko база заканчивается на /v1:

bash
pip install -qU langchain-openai
export ZUKKO_API_KEY="fetch_ваш_ключ"
bash
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="deepseek-v4.1-flash",
    base_url="https://api.zukko.pro/v1",
    api_key=os.environ["ZUKKO_API_KEY"],
)

ai_msg = llm.invoke([
    ("system", "Ты переводчик с английского на русский. Переводи фразу пользователя."),
    ("human", "I love programming."),
])
print(ai_msg.content)

Обратите внимание: вызов invoke, формат сообщений и объект ответа те же, что у ChatOllama. Это общий интерфейс чат-моделей LangChain. Подключение подробнее описано в статье LangChain: как указать наш base_url, а клиентские примеры на Python собраны в справочнике.

Один код, две модели: переключение одной настройкой

Есть два способа сделать код независимым от места запуска модели.

Способ 1: фабрика на двух классах

bash
import os
from langchain_ollama import ChatOllama
from langchain_openai import ChatOpenAI


def make_llm(backend: str | None = None):
    backend = backend or os.getenv("LLM_BACKEND", "cloud")
    if backend == "local":
        return ChatOllama(model=os.getenv("LOCAL_MODEL", "gpt-oss:20b"), temperature=0)
    return ChatOpenAI(
        model=os.getenv("CLOUD_MODEL", "deepseek-v4.1-flash"),
        base_url="https://api.zukko.pro/v1",
        api_key=os.environ["ZUKKO_API_KEY"],
    )


llm = make_llm()

Запуск LLM_BACKEND=local python app.py берёт Ollama, без переменной используется облако. Обе ветки возвращают чат-модель с одинаковыми методами invoke, stream, bind_tools и with_structured_output.

Способ 2: один класс и OpenAI-совместимый адрес Ollama

Ollama умеет отдавать OpenAI-совместимый API по адресу http://localhost:11434/v1 (раздел OpenAI compatibility в документации Ollama). Тогда нужен только ChatOpenAI, а переключаются три переменные:

bash
import os
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model=os.environ["LLM_MODEL"],
    base_url=os.environ["LLM_BASE_URL"],
    api_key=os.environ["LLM_API_KEY"],
)

Профиль для облака:

bash
export LLM_BASE_URL="https://api.zukko.pro/v1"
export LLM_API_KEY="fetch_ваш_ключ"
export LLM_MODEL="deepseek-v4.1-flash"

Профиль для локального Ollama:

bash
export LLM_BASE_URL="http://localhost:11434/v1"
export LLM_API_KEY="ollama"
export LLM_MODEL="gpt-oss:20b"

Для локального адреса ключ нужен лишь потому, что клиент требует непустое значение, а Ollama его не проверяет (если ваша конфигурация иначе, смотрите документацию Ollama). Этот способ хорош тем, что один класс и одни параметры. Его цена в том, что вы работаете только с тем, что отдаёт совместимый слой Ollama. Нативные параметры Ollama, например размер окна контекста num_ctx, удобнее задавать через ChatOllama.

Сравнение трёх вариантов

ChatOllamaChatOpenAI + Ollama /v1ChatOpenAI + шлюз
Где работает модельВаша машинаВаша машинаОблако
Пакетlangchain-ollamalangchain-openailangchain-openai
Нативные параметры OllamaДаТолько то, что отдаёт совместимый слойНе применимо
Выбор моделейТо, что вы скачали и потянет железоТо жеЛюбая модель каталога, список в GET /v1/models
Приватность данныхДанные остаются локальноЛокальноЗапросы уходят на шлюз и провайдеру модели
ОплатаЖелезо и электричествоТо жеЗа токены, баланс в долларах

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

Сколько стоит облачный вариант

Цены на 18 октября 2026 (за 1M токенов). Пусть за месяц отправляется 1M входных и 0.2M выходных токенов. Формула: вход × цена входа + выход × цена выхода.

МодельВход / выходРасчётМесяц
deepseek-v4.1-flash0.013 / 0.0381 × 0.013 + 0.2 × 0.038$0.0206
glm-5.3-flash0.04 / 0.041 × 0.04 + 0.2 × 0.04$0.048
gpt-6.1-sol0.27 / 1.321 × 0.27 + 0.2 × 1.32$0.534
claude-sonnet-5-50.4 / 21 × 0.4 + 0.2 × 2$0.80

Для Claude через OpenAI-формат весь вход идёт по цене входа. Скидка за кэш у Claude возможна только в Anthropic-формате. У локальной модели нет платы за токены, но есть расходы на оборудование и электричество; их стоит посчитать отдельно и сравнить со строкой выше для вашего объёма. Качество моделей разное, поэтому сначала прогоните свои 20–30 примеров на обоих вариантах.

Запасной вариант: локальная модель + облачный fallback

Если локальный сервер не отвечает, можно переключиться на облако автоматически. В LangChain у любого объекта-«раннабла» есть метод with_fallbacks:

bash
primary = ChatOllama(model="gpt-oss:20b", temperature=0)
backup = ChatOpenAI(
    model="deepseek-v4.1-flash",
    base_url="https://api.zukko.pro/v1",
    api_key=os.environ["ZUKKO_API_KEY"],
)
llm = primary.with_fallbacks([backup])

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

Частые вопросы

Нужен ли Ollama, чтобы вызывать облачные модели?

Нет: для облачных моделей с Zukko достаточно ChatOpenAI с base_url. Ollama нужен, только когда модель запускается локально.

Совпадут ли ответы локальной и облачной модели?

Нет, это разные модели. Код совпадёт, а качество и стиль ответов нужно проверять на ваших примерах.

Какой base_url указывать для шлюза?

https://api.zukko.pro/v1 для OpenAI-совместимых клиентов, к которым относится ChatOpenAI.

Как узнать, какие модели доступны в облаке?

Запросите GET https://api.zukko.pro/v1/models или откройте страницу «Модели» в кабинете.

Чтобы протестировать облачный вариант, создайте ключ в кабинете.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.