Skip to content

API, совместимый с OpenAI: Стратегия реализации /v1/chat/completions и /v1/responses

Вы будете использовать этот API, совместимый с OpenAI, чтобы напрямую подключить существующий OpenAI SDK/клиент к локальному шлюзу Antigravity Tools, с упором на реализацию /v1/chat/completions и /v1/responses, и научитесь быстро устранять неполадки с помощью заголовков ответа.

Чему вы научитесь

  • Подключиться напрямую к локальному шлюзу Antigravity Tools с помощью OpenAI SDK (или curl)
  • Реализовать /v1/chat/completions (включая stream: true) и /v1/responses
  • Понимать список моделей /v1/models и заголовок ответа X-Mapped-Model
  • При возникновении 401/404/429 знать, с чего начать устранение неполадок

Текущие проблемы

Многие клиенты/SDK распознают только форму интерфейса OpenAI: фиксированный URL, фиксированные поля JSON, фиксированный формат потока SSE. Цель Antigravity Tools — не заставить вас изменить клиент, а позволить клиенту «думать, что он вызывает OpenAI», фактически преобразуя запрос во внутренний вызов вышестоящего уровня, а затем преобразуя результат обратно в формат OpenAI.

Когда использовать этот метод

  • У вас уже есть набор инструментов, поддерживающих только OpenAI (плагины IDE, скрипты, боты, SDK), и вы не хотите писать новую интеграцию для каждого
  • Вы хотите единообразно направлять запросы через base_url в шлюз (локальный или локальной сети), а затем позволить шлюзу заниматься планированием аккаунтов, повторами и мониторингом

🎒 Подготовка

Предварительные условия

  • Вы уже запустили прокси-сервис на странице «API Proxy» Antigravity Tools и записали порт (например, 8045)
  • Вы уже добавили хотя бы один доступный аккаунт, иначе прокси не получит токен вышестоящего уровня

Как принести аутентификацию?

Когда вы включаете proxy.auth_mode и настраиваете proxy.api_key, запрос должен содержать API Key.

Промежуточное ПО Antigravity Tools будет приоритетно читать Authorization, также совместимо с x-api-key, x-goog-api-key. (Реализация: src-tauri/src/proxy/middleware/auth.rs)

Что такое API, совместимый с OpenAI?

API, совместимый с OpenAI — это набор маршрутов HTTP и протоколов JSON/SSE, которые «выглядят как OpenAI». Клиент отправляет запрос в локальный шлюз в формате OpenAI, шлюз преобразует запрос во внутренний вызов вышестоящего уровня, а затем преобразует ответ вышестоящего уровня обратно в структуру ответа OpenAI, чтобы существующий OpenAI SDK мог использоваться практически без изменений.

Обзор совместимых конечных точек (связано с этим уроком)

Конечная точкаНазначениеДоказательство кода
POST /v1/chat/completionsChat Completions (включая поток)Регистрация маршрута в src-tauri/src/proxy/server.rs; src-tauri/src/proxy/handlers/openai.rs
POST /v1/completionsLegacy Completions (использует тот же обработчик)Регистрация маршрута в src-tauri/src/proxy/server.rs
POST /v1/responsesСовместимость с Responses/Codex CLI (использует тот же обработчик)Регистрация маршрута в src-tauri/src/proxy/server.rs (комментарий: совместимость с Codex CLI)
GET /v1/modelsВозвращает список моделей (включая пользовательское сопоставление + динамическую генерацию)src-tauri/src/proxy/handlers/openai.rs + src-tauri/src/proxy/common/model_mapping.rs

Пошаговое руководство

Шаг 1: Подтвердите, что сервис жив (/healthz + /v1/models)

Зачем Сначала исключите низкоуровневые проблемы типа «сервис не запущен/порт неправильный/заблокирован брандмауэром».

bash
 # 1) Проверка работоспособности
curl -s http://127.0.0.1:8045/healthz

 # 2) Получить список моделей
curl -s http://127.0.0.1:8045/v1/models

Что вы должны увидеть: /healthz возвращает примерно {"status":"ok"}; /v1/models возвращает {"object":"list","data":[...]}.

Шаг 2: Вызов /v1/chat/completions с помощью OpenAI Python SDK

Зачем Этот шаг доказывает, что вся цепочка «OpenAI SDK → локальный шлюз → вышестоящий уровень → преобразование ответа OpenAI» проходит успешно.

python
import openai

client = openai.OpenAI(
    api_key="sk-antigravity",
    base_url="http://127.0.0.1:8045/v1",
)

response = client.chat.completions.create(
    model="gemini-3-flash",
    messages=[{"role": "user", "content": "Привет, представься"}],
)

print(response.choices[0].message.content)

Что вы должны увидеть: Терминал печатает фрагмент ответа модели.

Шаг 3: Включите поток, подтвердите потоковый возврат SSE

Зачем Многие клиенты зависят от протокола SSE OpenAI (Content-Type: text/event-stream). Этот шаг подтверждает, что потоковая цепочка и формат события доступны.

bash
curl -N http://127.0.0.1:8045/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "stream": true,
    "messages": [
      {"role": "user", "content": "Объясни в трёх предложениях, что такое локальный прокси-шлюз"}
    ]
  }'

Что вы должны увидеть: Терминал постоянно выводит строки, начинающиеся с data: { ... }, и заканчивается data: [DONE].

Шаг 4: Используйте /v1/responses (стиль Codex/Responses) для реализации запроса

Зачем Некоторые инструменты используют /v1/responses или используют поля instructions, input в теле запроса. Этот проект нормализует такие запросы как messages и затем повторно использует тот же набор логики преобразования. (Обработчик: src-tauri/src/proxy/handlers/openai.rs)

bash
curl -s http://127.0.0.1:8045/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "instructions": "Вы строгий код-ревьюер.",
    "input": "Укажи наиболее вероятную ошибку в следующем коде:\n\nfunction add(a, b) { return a - b }"
  }'

Что вы должны увидеть: Тело ответа — это объект ответа в стиле OpenAI (этот проект преобразует ответ Gemini в choices[].message.content).

Шаг 5: Подтвердите, что маршрутизация моделей эффективна (смотрите заголовок ответа X-Mapped-Model)

Зачемmodel, который вы пишете в клиенте, не обязательно является «физической моделью», которая фактически вызывается. Шлюз сначала делает сопоставление моделей (включая пользовательское сопоставление/подстановочные знаки, см. Маршрутизация моделей: Пользовательское сопоставление, приоритет подстановочных знаков и предустановленные стратегии), а затем помещает окончательный результат в заголовок ответа для вашего удобства при устранении неполадок.

bash
curl -i http://127.0.0.1:8045/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "привет"}]
  }'

Что вы должны увидеть: В заголовке ответа содержится X-Mapped-Model: ... (например, сопоставлено с gemini-2.5-flash), и, возможно, также X-Account-Email: ....

Контрольные точки ✅

  • GET /healthz возвращает {"status":"ok"} (или эквивалентный JSON)
  • GET /v1/models возвращает object=list и data — это массив
  • Непотоковый запрос /v1/chat/completions может получить choices[0].message.content
  • При stream: true можно получить SSE и он заканчивается [DONE]
  • curl -i может увидеть заголовок ответа X-Mapped-Model

Частые ошибки

1) Неправильный Base URL导致 404 (наиболее часто)

  • В примере OpenAI SDK base_url должен заканчиваться на /v1 (см. пример Python в README проекта).
  • Некоторые клиенты «дублируют путь». Например, в README явно упоминается: Kilo Code в режиме OpenAI может составить путь типа /v1/chat/completions/responses, что вызовет 404.

2) 401: не вышестоящий уровень отказал, а вы не принесли key или режим неправильный

Когда «эффективный режим» стратегии аутентификации не off, промежуточное ПО будет проверять заголовки запроса: Authorization: Bearer <proxy.api_key>, также совместимо с x-api-key, x-goog-api-key. (Реализация: src-tauri/src/proxy/middleware/auth.rs)

Подсказка по режиму аутентификации

auth_mode = auto автоматически решает на основе allow_lan_access:

  • allow_lan_access = true → эффективный режим — all_except_health (кроме /healthz требуется аутентификация)
  • allow_lan_access = false → эффективный режим — off (локальный доступ не требует аутентификации)

3) 429/503/529: прокси будет повторять + ротацию аккаунтов, но также может «пул исчерпан»

Обработчик OpenAI поддерживает до 3 попыток (и ограничен размером пула аккаунтов), при некоторых ошибках будет ожидать/ротацию аккаунтов и повтор. (Реализация: src-tauri/src/proxy/handlers/openai.rs)

Итог урока

  • /v1/chat/completions — это наиболее универсальная точка входа, stream: true использует SSE
  • /v1/responses и /v1/completions используют тот же совместимый обработчик, ключ — сначала нормализовать запрос как messages
  • X-Mapped-Model помогает вам подтвердить результат сопоставления «имя модели клиента → финальная физическая модель»

Предпросмотр следующего урока

В следующем уроке мы продолжим смотреть API, совместимый с Anthropic: /v1/messages и ключевые контракты Claude Code (соответствующая глава: platforms-anthropic).


Приложение: Справочник по исходному коду

Нажмите, чтобы раскрыть расположение исходного кода

Обновлено: 2026-01-23

ФункцияПуть к файлуСтроки
Регистрация маршрута OpenAI (включая /v1/responses)src-tauri/src/proxy/server.rs120-194
Обработчик Chat Completions (включая обнаружение формата Responses)src-tauri/src/proxy/handlers/openai.rs70-462
Обработчик /v1/completions и /v1/responses (нормализация Codex/Responses + повтор/ротация)src-tauri/src/proxy/handlers/openai.rs464-1080
Возврат /v1/models (динамический список моделей)src-tauri/src/proxy/handlers/openai.rs1082-1102
Структура данных запроса OpenAI (messages/instructions/input/size/quality)src-tauri/src/proxy/mappers/openai/models.rs7-38
---------
---------
Сопоставление моделей и приоритет подстановочных знаков (точный > подстановочный > по умолчанию)src-tauri/src/proxy/common/model_mapping.rs180-228
---------

Ключевые константы:

  • MAX_RETRY_ATTEMPTS = 3: максимальное количество попыток протокола OpenAI (включая ротацию) (см. src-tauri/src/proxy/handlers/openai.rs)

Ключевые функции:

  • transform_openai_request(...): преобразует тело запроса OpenAI во внутренний запрос вышестоящего уровня (см. src-tauri/src/proxy/mappers/openai/request.rs)
  • transform_openai_response(...): преобразует ответ вышестоящего уровня в choices/usage OpenAI (см. src-tauri/src/proxy/mappers/openai/response.rs)