Перейти к содержанию

Chat completions

Шлюз реализует тот же HTTP-слой, что и публичный API OpenAI Chat Completions: метод POST /v1/chat/completions, JSON-тело и ответ со списком choices. Это позволяет подключиться через официальный OpenAI SDK для Python (и аналоги в других языках), указав базовый URL вашего окружения.

Единственное жёсткое отличие: поле model

Строковое значение model всегда должно быть GUID агента в вашей инфраструктуре (Agent Engine ID), например "a1b2c3d4-e5f6-7890-abcd-ef1234567890". Имя тарифной модели в стиле gpt-4.1-mini здесь не применимо: шлюз сопоставляет запрос именно этому агенту.

Все отличия интеграции сводятся к базовому URL, ключу и корректному GUID в model.

Быстрый старт: OpenAI SDK (Python)

Установите пакет распространением из PyPI «openai»:

pip install openai

Соберите base_url как BASE_GATE без хвостового слэша плюс сегмент /v1 — именно его ожидает клиент при формировании пути /chat/completions.

import os
from openai import OpenAI

BASE_GATE = os.environ["BASE_GATE"].rstrip("/")
TOKEN = os.environ["TOKEN"]
AGENT_ID = os.environ["AGENT_ID"]

client = OpenAI(api_key=TOKEN, base_url=f"{BASE_GATE}/v1")

completion = client.chat.completions.create(
    model=AGENT_ID,
    messages=[{"role": "user", "content": "Кратко расскажи, для чего этот сервис."}],
    temperature=0.7,
)
print(completion.choices[0].message.content)
import os
from openai import OpenAI

BASE_GATE = os.environ["BASE_GATE"].rstrip("/")
TOKEN = os.environ["TOKEN"]
AGENT_ID = os.environ["AGENT_ID"]

client = OpenAI(api_key=TOKEN, base_url=f"{BASE_GATE}/v1")

stream = client.chat.completions.create(
    model=AGENT_ID,
    messages=[{"role": "user", "content": "Привет"}],
    stream=True,
)
for chunk in stream:
    piece = chunk.choices[0].delta.content or ""
    if piece:
        print(piece, end="", flush=True)

Основные поля тела запроса

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

Поле Обязательно Комментарий
model да Строковый GUID агента
messages да История сообщений с ролями system, user, assistant и т.д.
stream нет true включает Server-Sent Events (text/event-stream)
temperature, top_p, max_tokens, stop, штрафы частотности, n, seed, … нет Проброс при необходимости; поддержка каждого поля зависит от цепочки агента

Успешный ответ без стриминга

Ответ имеет тип application/json. В составе данных обычно присутствуют поля наподобие id, created, имя модели, массив choices (message.role, message.content, причины завершения) и объект usage с подсчётом токенов.

Формат близок к документации OpenAI; полагайтесь при приёмке на фактический JSON вашей сборки для полей второго порядка.

Потоковая генерация

При stream: true транспорт — SSE. Формат порций может повторять OpenAI-совместимый поток через SDK; при ручном HTTP-клиенте читайте событие построчно и строки вида data: …, завершая по маркеру [DONE] у конвейера, который его испускает.

Ошибки в формате OpenAI

При корректной авторизации, но ошибке обработки пути /v1/chat/…, приложение может вернуть объект:

{
  "error": {
    "message": "Пояснение для человека",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }
}

Типичные случаи по семантике сервера:

HTTP Комментарий
400 Логические или синтаксические ошибки запроса; иногда вклад валидации модели состояния
403 Отключённый агент (agent_disabled и родственный код там, где они различаются)
404 Агент не найден для переданного model
500 Внутренний отказ узла генерации или шлюза

Ошибки до успешной аутентификации см. текст 403 в Аутентификация и ключи.

Отдельно: раннее отклонение невалидного GUID в model может прийти с не зашитыми тем же объектом телом простого текстового ошибки или иным не-OpenAI сообщением при отладке смотрится Content-Type ответа.

Низкоуровневые вызовы (HTTP)

Ниже — те же сценарии без SDK: универсальный клиент httpx (удобнее для SSE) или requests, а также curl для воспроизведения минимальных запросов.

Окружение: BASE_GATE — без завершающего /; TOKEN — секрет без префикса Bearer; AGENT_ID — GUID агента.

Без потока

import os
import httpx

BASE_GATE = os.environ["BASE_GATE"].rstrip("/")
TOKEN = os.environ["TOKEN"]
AGENT_ID = os.environ["AGENT_ID"]

payload = {
    "model": AGENT_ID,
    "messages": [{"role": "user", "content": "Кратко опиши назначение API-шлюза."}],
    "temperature": 0.7,
}

url = f"{BASE_GATE}/v1/chat/completions"

resp = httpx.post(
    url,
    headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
    json=payload,
    timeout=120.0,
)
resp.raise_for_status()
data = resp.json()
print(data["choices"][0]["message"]["content"])
export BASE_GATE="https://api.theta-cloud.ru"
export TOKEN='<ваш ключ>'
export AGENT_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

curl -sS -X POST "${BASE_GATE}/v1/chat/completions" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"model\":\"${AGENT_ID}\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет\"}]}"

С потоком (SSE руками)

import json
import os

import httpx

BASE_GATE = os.environ["BASE_GATE"].rstrip("/")
TOKEN = os.environ["TOKEN"]
AGENT_ID = os.environ["AGENT_ID"]

url = f"{BASE_GATE}/v1/chat/completions"
payload = {"model": AGENT_ID, "messages": [{"role": "user", "content": "Привет"}], "stream": True}

with httpx.Client(timeout=120.0) as client:
    with client.stream(
        "POST",
        url,
        headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"},
        json=payload,
    ) as resp:
        resp.raise_for_status()
        for line in resp.iter_lines():
            line = line.strip()
            if not line.startswith("data:"):
                continue
            blob = line[5:].strip()
            if blob == "[DONE]":
                break
            try:
                print(json.loads(blob))
            except json.JSONDecodeError:
                continue

Ручной разбор SSE

Такой парсер годится для экспериментов; в продакшене чаще удобнее OpenAI SDK выше или готовый HTTP-клиент с политикой повторов.

export BASE_GATE="https://api.theta-cloud.ru"
export TOKEN='<ваш ключ>'
export AGENT_ID='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

curl -N -sS -X POST "${BASE_GATE}/v1/chat/completions" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{\"model\":\"${AGENT_ID}\",\"messages\":[{\"role\":\"user\",\"content\":\"Привет\"}],\"stream\":true}"