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/completions | Chat Completions (включая поток) | Регистрация маршрута в src-tauri/src/proxy/server.rs; src-tauri/src/proxy/handlers/openai.rs |
POST /v1/completions | Legacy 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)
Зачем Сначала исключите низкоуровневые проблемы типа «сервис не запущен/порт неправильный/заблокирован брандмауэром».
# 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» проходит успешно.
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). Этот шаг подтверждает, что потоковая цепочка и формат события доступны.
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)
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, который вы пишете в клиенте, не обязательно является «физической моделью», которая фактически вызывается. Шлюз сначала делает сопоставление моделей (включая пользовательское сопоставление/подстановочные знаки, см. Маршрутизация моделей: Пользовательское сопоставление, приоритет подстановочных знаков и предустановленные стратегии), а затем помещает окончательный результат в заголовок ответа для вашего удобства при устранении неполадок.
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используют тот же совместимый обработчик, ключ — сначала нормализовать запрос какmessagesX-Mapped-Modelпомогает вам подтвердить результат сопоставления «имя модели клиента → финальная физическая модель»
Предпросмотр следующего урока
В следующем уроке мы продолжим смотреть API, совместимый с Anthropic: /v1/messages и ключевые контракты Claude Code (соответствующая глава:
platforms-anthropic).
Приложение: Справочник по исходному коду
Нажмите, чтобы раскрыть расположение исходного кода
Обновлено: 2026-01-23
| Функция | Путь к файлу | Строки |
|---|---|---|
| Регистрация маршрута OpenAI (включая /v1/responses) | src-tauri/src/proxy/server.rs | 120-194 |
| Обработчик Chat Completions (включая обнаружение формата Responses) | src-tauri/src/proxy/handlers/openai.rs | 70-462 |
| Обработчик /v1/completions и /v1/responses (нормализация Codex/Responses + повтор/ротация) | src-tauri/src/proxy/handlers/openai.rs | 464-1080 |
| Возврат /v1/models (динамический список моделей) | src-tauri/src/proxy/handlers/openai.rs | 1082-1102 |
| Структура данных запроса OpenAI (messages/instructions/input/size/quality) | src-tauri/src/proxy/mappers/openai/models.rs | 7-38 |
| --- | --- | --- |
| --- | --- | --- |
| Сопоставление моделей и приоритет подстановочных знаков (точный > подстановочный > по умолчанию) | src-tauri/src/proxy/common/model_mapping.rs | 180-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/usageOpenAI (см.src-tauri/src/proxy/mappers/openai/response.rs)