Руководство
Создание прокси OpenAI API на Python: сначала напишите свой, затем подключите его ко всем моделям
Рабочий прокси на FastAPI с аутентификацией, ограничением частоты запросов и потоковой передачей; а также о том, как OpenAI-совместимый API HiAPI позволяет одному и тому же прокси обслуживать DeepSeek, Claude, GPT и другие модели.
TL;DR
- Прокси OpenAI API — это небольшой сервер между вашим приложением и API модели. Он хранит настоящие ключи и добавляет возможности, которых сам API не предоставляет: ключи для каждого клиента, ограничение частоты запросов, логирование и ротацию ключей. Ниже — рабочий вариант на FastAPI примерно на 50 строк.
- Текстовый API HiAPI совместим с OpenAI:
POST /v1/chat/completionsиPOST /v1/responsesнаходятся по адресуhttps://api.hiapi.ai/v1. Укажите официальномуopenaiSDK или вашему прокси этот base URL, и одним ключом можно вызывать текстовые модели DeepSeek, Claude, GPT, Kimi, GLM и Grok. - Изображения и видео — другое дело: они генерируются от секунд до минут, поэтому работают через асинхронный
POST /v1/tasksв HiAPI. Не передавайте такие запросы через синхронный прокси.
Шаг 1: минимальный сквозной прокси
Прокси проверяет внутренний ключ, присланный клиентом, заменяет его на настоящий ключ вышестоящего API и передаёт ответ обратно потоком.
pip install fastapi uvicorn httpx
# proxy.py
import os
import httpx
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse
from starlette.background import BackgroundTask
UPSTREAM = os.environ.get("UPSTREAM_BASE", "https://api.openai.com/v1")
UPSTREAM_KEY = os.environ["UPSTREAM_KEY"]
INTERNAL_KEYS = set(os.environ["INTERNAL_KEYS"].split(",")) # comma-separated
app = FastAPI()
client = httpx.AsyncClient(timeout=120.0)
def auth(request: Request) -> str:
header = request.headers.get("authorization", "")
key = header.removeprefix("Bearer ").strip()
if key not in INTERNAL_KEYS:
raise HTTPException(401, "invalid internal key")
return key
@app.post("/v1/{path:path}")
async def forward(path: str, request: Request):
tenant = auth(request)
body = await request.body()
upstream_req = client.build_request(
"POST", f"{UPSTREAM}/{path}", content=body,
headers={"Authorization": f"Bearer {UPSTREAM_KEY}",
"Content-Type": request.headers.get("content-type", "application/json")},
)
upstream = await client.send(upstream_req, stream=True)
# Stream back so long answers and SSE don't time out; close the upstream stream when done
return StreamingResponse(upstream.aiter_raw(), status_code=upstream.status_code,
media_type=upstream.headers.get("content-type"),
background=BackgroundTask(upstream.aclose))
Запустите его:
UPSTREAM_KEY=your-upstream-key INTERNAL_KEYS=tenant-a,tenant-b \
uvicorn proxy:app --host 0.0.0.0 --port 8000
Клиент работает с OpenAI SDK как обычно, указав адрес прокси в качестве base URL:
from openai import OpenAI
client = OpenAI(api_key="tenant-a", base_url="http://localhost:8000/v1")
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
print(resp.choices[0].message.content)
Диалог, потоковая передача и эмбеддинги идут через один и тот же обработчик, поскольку прокси никогда не разбирает содержимое тела запроса.
Шаг 2: добавьте возможности, которых нет в вышестоящем API
Ограничение частоты запросов по клиентам. Без него один активный клиент может исчерпать всю вашу квоту.
import time
from collections import defaultdict
_window: dict[str, list[float]] = defaultdict(list)
LIMIT = 60 # requests per 60 s
def check_rate_limit(tenant: str):
now = time.time()
_window[tenant] = [t for t in _window[tenant] if now - t < 60]
if len(_window[tenant]) >= LIMIT:
raise HTTPException(429, "rate limit exceeded")
_window[tenant].append(now)
Вызывайте её сразу после auth(). Если у вас несколько серверных процессов, перенесите счётчики в Redis (INCR плюс EXPIRE).
Логирование. Записывайте клиента, путь, код статуса, задержку и количество token. Никогда не записывайте заголовок Authorization.
Ротация ключей. Загружайте UPSTREAM_KEY из сервиса управления секретами и периодически обновляйте. Когда ключ вышестоящего API меняется на нижнем уровне, клиенты продолжают использовать свои клиентские ключи.
Правила стоимости. Разбирайте тело запроса и отклоняйте запросы, нарушающие политику, например использование дорогой модели на бесплатном тарифе или max_tokens, превышающий ваш лимит.
Шаг 3: разместите несколько поставщиков моделей за одним прокси
Подключить прокси к одному поставщику легко. Добавление Anthropic, DeepSeek или Moonshot означает разные заголовки аутентификации, структуры запросов и форматы ошибок, и тонкий прокси превращается в слой трансляции.
Текстовый API HiAPI использует структуру запросов OpenAI для всех своих текстовых моделей, поэтому прокси выше работает без изменений. Задайте две переменные окружения:
UPSTREAM_BASE=https://api.hiapi.ai/v1 UPSTREAM_KEY=your-hiapi-key INTERNAL_KEYS=tenant-a,tenant-b \
uvicorn proxy:app --host 0.0.0.0 --port 8000
Или пропустите прокси и используйте SDK напрямую:
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["HIAPI_KEY"], base_url="https://api.hiapi.ai/v1")
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Explain sparse attention in two sentences."}],
max_tokens=400,
)
print(resp.choices[0].message.content)
Мы запустили этот код с официальным пакетом openai для Python (3.35.1): один обычный вызов и один с stream=True; оба вызова завершились без ошибок, и SDK корректно разобрал ответы. В этом тесте был один подвох: при max_tokens=20 ответ оказался пустым, потому что deepseek-v4-flash потратил все 20 token на рассуждения (usage.completion_tokens_details.reasoning_tokens равно 22). Оставляйте рассуждающим моделям запас в несколько сотен token.
Некоторые текстовые модели в HiAPI:
| ID модели | Маршрут | Вход / выход, USD за 1 млн token |
|---|---|---|
deepseek-v4-flash |
Chat Completions | $0.14 / $0.28 |
deepseek-v4.1-flash |
Chat Completions и Responses | $0.44 / $1.32 |
gpt-5.6-luna |
Только Responses | $0.05 / $0.30 |
grok-4.6 |
Chat Completions | $0.84 / $2.52 |
deepseek-v4-pro |
Chat Completions и Responses | $1.50 / $4.50 |
claude-opus-5-5 |
Chat Completions | $2.02 / $10.08 |
kimi-k3 |
Chat Completions | $2.32 / $11.60 |
claude-sonnet-4-6 |
Chat Completions | $3.00 / $15.00 |
Актуальные цены HiAPI на 20 октября 2026 года. GET https://api.hiapi.ai/v1/models перечисляет все модели, доступные для вашего ключа.
Такие GPT-модели, как gpt-5.6-luna, доступны только через Responses API (client.responses.create), поэтому прокси, пересылающий /v1/{path}, покрывает оба варианта.
Неизвестный ID модели возвращает HTTP 400 в стиле ошибок OpenAI с request_id для обращения в поддержку:
{"error": {"code": "model_not_found", "type": "hiapi_error",
"message": "The requested model does not exist or is not available. Check the exact model ID with GET /v1/models and try again. ...",
"request_id": "..."}}
Шаг 4: изображения и видео не стоит помещать в синхронный прокси
Синхронный прокси держит соединение открытым, пока не вернётся ответ. Для текста это нормально. Изображения занимают десятки секунд, видео — минуты, а это дольше, чем готовы ждать большинство балансировщиков нагрузки и браузеров.
HiAPI запускает модели изображений и видео на асинхронном эндпоинте: отправьте задачу, получите task id, затем опрашивайте статус или принимайте callback.
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "z-image",
"input": {"prompt": "a glass data center at golden hour, isometric", "aspect_ratio": "16:9"},
"callback": {"url": "https://your-app.example.com/hiapi/callback", "when": "final"}
}'
# => {"code":200,"message":"success","data":{"taskId":"tk-hiapi-..."}}
Ваш прокси по-прежнему может пересылать вызов создания задачи, который возвращается немедленно. Результат затем приходит через ваш callback URL или GET /v1/tasks/{taskId}. Ссылки на результаты истекают примерно через 7 дней, поэтому сохраняйте файлы.
Контрольный список для продакшена
- Убирайте ключи из логов. Никогда не записывайте
Authorization— ни входящий, ни исходящий. - Используйте callback для медиазадач. Опрос тысяч задач расходует запросы впустую. Сделайте обработчик callback идемпотентным и используйте
taskIdв качестве ключа, так как доставка может повторяться. - Сохраняйте task id перед опросом. Если процесс упадёт, возобновите опрос, а не отправляйте задачу заново и не платите дважды.
- Оставляйте место для reasoning token. Задавайте
max_tokensзначительно выше ожидаемой длины ответа. - Проверяйте, что доступно вашему ключу.
GET /v1/modelsвозвращает список для этого ключа.
Частые вопросы
Можно ли использовать OpenAI Python SDK с HiAPI?
Да, для текстовых моделей. Укажите base_url="https://api.hiapi.ai/v1" и используйте свой ключ HiAPI. Изображения и видео используют /v1/tasks, этот эндпоинт не покрывается OpenAI SDK; вызывайте его через requests или httpx.
Нужен ли мне собственный прокси?
Только по тем же причинам, что и с любым поставщиком: ключи для каждого клиента, ограничение частоты запросов и журналы аудита. Внутри прокси больше не нужна трансляция под каждого поставщика.
Работает ли потоковая передача?
Да. stream=True возвращает события, отправляемые сервером и заканчивающиеся на data: [DONE], а прокси выше пересылает их потоком без буферизации.
Как заменить ключ HiAPI без прерывания обслуживания?
Создайте новый ключ в консоли, разверните его в прокси или хранилище ключей, затем отзовите старый. Во время переключения работают оба ключа.
Подробнее: документация Chat Completions, документация Responses и HiAPI как альтернатива прокси OpenAI API.
Похожие статьи
Все статьи →-
Руководство
Как вызвать hailuo-2.3-fast/image-to-video через HiAPI API: практика с curl и Python
Первый рабочий запрос к быстрому и недорогому уровню генерации видео по изображению — от ID модели до загрузки MP4
-
Руководство
Как вызывать hailuo-2.3/text-to-video через API HiAPI: curl, Python и рабочие примеры запросов
-
Руководство
Использование Kandinsky 6.0 Pro для преобразования текста в видео на HiAPI: руководство по curl и Python
Практическая демонстрация с упором на запросы: построение вызова от промпта до видеоклипа, отправка запроса, опрос статуса завершения и скачивание результата