GPT-OSS API: локальное подключение из Python через Ollama

В этой статье

Для обращения к локальному GPT-OSS API из Python отправьте POST на адрес:

http://localhost:11434/v1/chat/completions

В запросе нужны модель gpt-oss:20b, массив messages и stream: false. В ответе придёт готовый JSON, из которого программа прочитает choices[0].message.content. Это OpenAI-совместимый интерфейс Ollama: он использует схему Chat Completions, а запрос выполняет локальная модель. Документация Ollama об OpenAI-совместимости

Локальный сервер Ollama по умолчанию не требует авторизации. Заголовок Authorization и ключ OpenAI здесь не нужны. Документация об аутентификации Ollama

Если для ручного разбора этого кода вы также пользуетесь личным ChatGPT, Amber Market — сервис оплаты зарубежных сервисов — помогает оформить из России месячный ChatGPT Plus на своём аккаунте через менеджера. Заказ можно оплатить через СБП. Для оформления нужен аккаунт Free без действующей подписки; продление доступно после её окончания. Перед оплатой проверьте актуальные условия и итоговую стоимость. Сам локальный GPT-OSS не требует Plus и не расходует баланс OpenAI API. У облачных продуктов свои расчёты: ChatGPT Plus и API оплачиваются отдельно, подписка не пополняет API-баланс.

Подготовьте модель и проверьте адрес

Пример рассчитан на установленный Ollama, Python 3 и подходящий для модели компьютер. Python и Ollama работают на одной машине, без разделения через Docker или WSL. По умолчанию Ollama слушает 127.0.0.1:11434; в программе ниже используется соответствующий локальный адрес localhost:11434. FAQ Ollama

При работающем Ollama скачайте модель и проверьте её имя:

ollama pull gpt-oss:20b
ollama list

В списке должен быть точный тег gpt-oss:20b, без суффикса -cloud. Если модель уже загружена, достаточно ollama list. Уже запущенный сервис повторно запускать не нужно.

В руководстве OpenAI для GPT-OSS 20B рекомендуется от 16 ГБ видеопамяти или общей памяти. Программа обойдётся стандартной библиотекой Python, но саму модель всё равно нужно разместить в памяти. Требования к компьютеру сверяйте с официальным руководством по локальному запуску.

Полный файл gpt_oss_api.py

Сохраните этот код в gpt_oss_api.py. Он отправляет JSON, отдельно сообщает об HTTP-ошибках и проблемах соединения, затем извлекает текст ответа.

import json
import urllib.error
import urllib.request

URL = "http://localhost:11434/v1/chat/completions"
MODEL = "gpt-oss:20b"

payload = {
    "model": MODEL,
    "messages": [
        {
            "role": "user",
            "content": (
                "Письма: Мария — счёт; Олег — встреча; "
                "Мария — договор. Верни только темы писем от Марии "
                "через запятую, без вступления."
            ),
        }
    ],
    "stream": False,
}

request = urllib.request.Request(
    URL,
    data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
    headers={"Content-Type": "application/json"},
    method="POST",
)

try:
    with urllib.request.urlopen(request, timeout=120) as response:
        result = json.load(response)
except urllib.error.HTTPError as error:
    details = error.read().decode("utf-8", errors="replace")
    print(f"HTTP {error.code}: {details}")
    raise SystemExit(1)
except urllib.error.URLError as error:
    print(f"Ошибка соединения с Ollama: {error.reason}")
    raise SystemExit(1)
except TimeoutError:
    print("Истёк тайм-аут ожидания данных от Ollama.")
    raise SystemExit(1)
except json.JSONDecodeError as error:
    print(f"Ollama вернул некорректный JSON: {error}")
    raise SystemExit(1)

try:
    content = result["choices"][0]["message"]["content"]
except (KeyError, IndexError, TypeError):
    print(f"В ответе нет ожидаемого поля content: {result}")
    raise SystemExit(1)

if not isinstance(content, str) or not content.strip():
    print(f"Поле content не содержит текста: {result}")
    raise SystemExit(1)

print(content)

ensure_ascii=False оставляет русские символы в JSON, а encode("utf-8") превращает его в байты тела запроса. Content-Type: application/json сообщает серверу формат тела. При stream: false программа ждёт готовый JSON и читает его через json.load.

Значение timeout=120 задаёт 120 секунд ожидания для блокирующих сетевых операций. Это выбранный лимит программы, а не обещание скорости модели или строгий предел времени всего запуска. Первый запрос может ждать загрузки весов в память.

Здесь везде используется /v1/chat/completions. Нативный маршрут Ollama /api/chat — отдельный интерфейс: подставлять его в этот код нельзя, в частности, путь к тексту ответа будет другим. Облачный OpenAI Responses API и Ollama Cloud также не участвуют в запросе.

Если позже замените urllib на Python SDK openai, для этого локального сервера задайте base_url="http://localhost:11434/v1". SDK требует поле api_key, поэтому ему можно передать формальную строку "ollama": локальный сервер её игнорирует. В текущем примере нет ни SDK, ни этого поля.

Получите текст и проверьте две темы

Запустите файл:

python gpt_oss_api.py

После успешного ответа программа печатает choices[0].message.content. Для приведённых входных данных эталон — счёт, договор: две темы писем Марии в исходном порядке, без вступления. Это ожидаемый результат задания, а не записанный вывод запуска модели.

Сравните с ним полученный текст вручную. Ответ HTTP 200 и наличие content подтверждают, что запрос прошёл и текст получен; они не подтверждают правильность фильтра. В ответе не должно оказаться встречи Олега, лишней темы или переставленных местами писем.

Модельный ответ остаётся строкой данных. Для этой задачи его нужно напечатать, а не передавать в exec или другой интерпретатор.

Если запрос не проходит

Connection refused означает, что по указанному адресу не удалось подключиться к локальному процессу. Проверьте URL в файле, откройте приложение Ollama, если оно не запущено, и убедитесь, что Python выполняется на том же компьютере. Если Ollama уже работает, проверьте его локальный адрес. Облачный ключ эту ошибку не исправит.

HTTP-ошибка означает, что сервер ответил отказом. Код печатает и статус, и тело ответа. Если сообщение указывает на неизвестную модель, сверяйте тег с ollama list; для этого примера нужна именно gpt-oss:20b. При её отсутствии выполните ollama pull gpt-oss:20b и повторите запрос.

При долгом ожидании или тайм-ауте проверьте загрузку модели и доступную память. Увеличение timeout даст больше времени на ответ, но не ускорит вычисления. Покупка ChatGPT Plus на работу локального Ollama не повлияет.

Для этого сценария оставьте сервер на локальном адресе: открывать его в интернет, менять bind, порты или прокси не требуется. Если задача сменится на запрос к облачной модели OpenAI, используйте отдельный пример подключения к OpenAI API.

Источники

Есть следующая задача?Ещё по теме «Работа с API» →