API Ollama: curl, Python и подключение к удалённой модели

Собственный API Ollama находится под /api, совместимые endpoints — под /v1. Выберите адрес, который ожидает ваш клиент. Нативный запрос чата отправляется на /api/chat; клиенту, который сам добавляет /chat/completions, нужен base URL с окончанием /v1.

Примеры предполагают, что Ollama уже запущена. На сервере используется порт 11434. На вашем компьютере — порт 11435 через SSH-туннель из инструкции.

Проверьте сервер и имя модели

На своём компьютере с открытым туннелем:

curl --fail-with-body http://127.0.0.1:11435/api/version
curl --fail-with-body http://127.0.0.1:11435/api/tags

Используйте полное имя из ответа. Название семейства, Hugging Face repository ID и тег Ollama — разные идентификаторы.

Нативный запрос чата

curl --fail-with-body http://127.0.0.1:11435/api/chat \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen2.5:7b-instruct-q4_K_M","messages":[{"role":"system","content":"Answer briefly."},{"role":"user","content":"What does a database index do?"}],"stream":false,"options":{"num_ctx":4096,"num_predict":128,"temperature":0}}'

Для русского ответа замените пользовательский текст, например на «Как работает индекс базы данных?». Не меняйте промпт между сравниваемыми замерами.

stream: false возвращает один JSON-ответ. При включённом streaming нативный API выдаёт JSON-объекты, разделённые переводом строки. Это другой формат потока, чем SSE у совместимого endpoint. Финальный нативный ответ содержит счётчики для измерения скорости.

Историю нужно передавать в массиве messages. Если каждый раз отправлять только последнее сообщение пользователя, сервер не восстановит предыдущий разговор автоматически.

Python без дополнительных пакетов

import json
import urllib.request

payload = {
    "model": "qwen2.5:7b-instruct-q4_K_M",
    "messages": [{"role": "user", "content": "Explain a database index briefly."}],
    "stream": False,
    "options": {"num_ctx": 4096, "num_predict": 128},
}
request = urllib.request.Request(
    "http://127.0.0.1:11435/api/chat",
    data=json.dumps(payload).encode("utf-8"),
    headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request, timeout=300) as response:
    result = json.load(response)
print(result["message"]["content"])

Это минимальная проверка подключения. В приложении для пользователей дополнительно обрабатывайте тайм-ауты, неуспешные HTTP-ответы и ограничения входа/выхода. Увеличение тайм-аута не поможет модели, которая не помещается в память.

OpenAI-совместимый запрос

curl --fail-with-body http://127.0.0.1:11435/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"qwen2.5:7b-instruct-q4_K_M","messages":[{"role":"user","content":"What does a database index do?"}],"max_tokens":128,"stream":false}'

Настройки совместимого клиента:

Поле Значение
Base URL http://127.0.0.1:11435/v1
Модель qwen2.5:7b-instruct-q4_K_M
API key, если поле обязательно Например, ollama; локальный сервер его игнорирует

Такой ключ не аутентифицирует запросы. В этой схеме доступ обеспечивается SSH-туннелем и локальным listener. Проверьте конкретные возможности, которые нужны приложению: инструменты, структурированный вывод или streaming. Общая совместимость API не гарантирует поддержку каждой функции.

Измерьте запрос

Сохраните measure-ollama.py и выполните:

python3 measure-ollama.py --url http://127.0.0.1:11435 --runs 3 > measurements.jsonl

Первая строка — прогрев с возможной загрузкой модели. Следующие содержат полное время последовательного запроса, загрузку и скорость декодирования. Полное время включает сеть, скорость генерации считается по серверным счётчикам. Это не измерение времени до первого токена или параллельной нагрузки. Файл содержит сгенерированные ответы: проверьте их перед передачей другим людям.

Для русскоязычного измерения можно добавить --prompt "Объясни индекс базы данных в трёх предложениях.". Остальные параметры сравниваемых запусков оставьте одинаковыми.

При ошибках используйте диагностику подключения и модели.

Источники: API чата, streaming, совместимые endpoints.

Все инструкции по запуску своей LLM.

Готовы запустить?

Запустить GPU-сервер