Docker / publish (push) Canceled after 0s
Release / crates-io (push) Canceled after 0s
Release / release (macos-14, aarch64-apple-darwin) (push) Canceled after 0s
Release / release (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Canceled after 0s
Release / release (windows-latest, x86_64-pc-windows-msvc) (push) Canceled after 0s
router.allaigate.com now resolves and serves a valid certificate, so the hosted routing API no longer has to be reached by bare IP with certificate verification switched off. Make https://router.allaigate.com the default [router].url with verify_tls = true. Existing configs still pointing at 138.226.222.209 (with or without a scheme or a trailing slash) are moved to the hostname on load and have verification restored, then saved: it is the same machine, and this is the difference between a verified connection and a blind one. A self-hosted router URL is left untouched. README, docs/ROUTER.md (both languages), config/gateway.example.toml and bench/accuracy.py follow. Verified live: the migration rewrites a legacy config on startup, admin health reports the hostname reachable over verified TLS (389 ms), and real requests route through it - "math"/medium 0.416 and "translation"/low 0.268 with route_source=router.
296 lines
20 KiB
Markdown
296 lines
20 KiB
Markdown
# Cortiq Gateway
|
||
|
||
[English](README.md) · **Русский**
|
||
|
||
[](https://crates.io/crates/cortiq-gateway)
|
||
[](https://github.com/infosave2007/cortiq-gateway/pkgs/container/cortiq-gateway)
|
||
[](LICENSE)
|
||

|
||

|
||
|
||
**Универсальный LLM-шлюз с интеллектуальной маршрутизацией.**
|
||
Один OpenAI-совместимый endpoint → автоматический выбор модели из вашего пула
|
||
(локальные дешёвые + хостовые дорогие) на основе типа задачи и сложности, которые
|
||
определяет [allaigate / cortiq-router](https://api.allaigate.com).
|
||
|
||
> Меняете в своём агенте/SDK только `base_url` — и получаете «умный» роутинг между
|
||
> моделями. Никакой логики выбора модели на стороне клиента.
|
||
|
||
```
|
||
┌─────────────┐ OpenAI / Anthropic / MCP ┌──────────────────┐
|
||
│ Агент / │ ─────────────────────────────▶│ Cortiq Gateway │
|
||
│ разработчик │ (стандартный протокол) │ (этот проект) │
|
||
└─────────────┘ ◀─────────────────────────────└──────────────────┘
|
||
ответ + метаданные │ │
|
||
│ /v1/route│ вызов LLM
|
||
▼ ▼
|
||
┌──────────────┐ ┌─────────────────────┐
|
||
│ cortiq-router│ │ Пул моделей │
|
||
│ (тип задачи, │ │ • local llama.cpp │
|
||
│ сложность) │ │ • ollama / vLLM │
|
||
└──────────────┘ │ • OpenAI / Claude │
|
||
└─────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## ✨ Ключевое
|
||
|
||
- **Запуск без конфигурации.** `cortiq-gateway` без флагов: конфиг создаётся сам, занятый порт меняется на свободный, браузер открывается на мастере, который скачивает готовую локальную модель и заводит её в роутинг — без TOML, без токена, без отдельно запущенного сервера модели.
|
||
- **Быстрый.** Rust/Tokio: overhead шлюза с **субмиллисекундным p99** — ~10× к throughput Portkey и ~47× к LiteLLM в сопоставимом бенчмарке ([детали](BENCHMARKS.md)).
|
||
- **Drop-in OpenAI API + стриминг.** Направьте любой OpenAI-клиент на шлюз и шлите `model: "cortiq-auto"`; `stream: true` поддержан (SSE).
|
||
- **Интеллектуальный роутинг.** `complexity.tier` → упорядоченный пул моделей (`low → локально`, `high → облако`), с fallback и мягкой деградацией, если роутер недоступен. Плюс **правила по задачам** (`[routing.tasks]`): переводы — в локальную модель, код — сильнейшему кодеру; цепочка по сложности остаётся резервом ([доки](docs/ROUTING.ru.md)).
|
||
- **Генерация картинок и видео.** Песочница запускает локальные text-to-image (Lumina) и text-to-video (MiniMax-H3) `.cmf` модели через `cortiq imagine`/`animate`: живой прогресс с ETA, галерея генераций, экспорт в PNG, проигрывание AVI прямо в браузере — без ffmpeg вообще.
|
||
- **Встроенная многоязычная панель управления.** Модели, роутинг, протоколы, ключи и секреты — из веб-интерфейса, **без ручного TOML и без рестарта** (горячая перезагрузка). **7 языков** (en, ru, de, fr, es, zh, tr), тёмная/светлая тема.
|
||
- **Живая аналитика.** Статистика по запросам (токены, стоимость, латентность, доля успеха, failover), графики, разбивка по моделям/полосам/задачам и Prometheus `GET /metrics`.
|
||
- **Playground.** Прогон промпта через живой пайплайн с разбором решения роутинга.
|
||
- **Один самодостаточный бинарь.** SPA встроена в Rust-бинарь — ничего лишнего разворачивать не нужно.
|
||
- **Секреты не покидают шлюз.** Агенты держат только виртуальный ключ шлюза; ключи провайдеров живут в шлюзе и наружу не уходят.
|
||
|
||
---
|
||
|
||
## 📦 Установка
|
||
|
||
```bash
|
||
# Docker (GitHub Container Registry)
|
||
docker run -p 9000:9000 -e CORTIQ_ADMIN_TOKEN=secret \
|
||
-v "$PWD/config:/app/config" ghcr.io/infosave2007/cortiq-gateway:latest
|
||
# → панель на http://localhost:9000/admin
|
||
|
||
# с crates.io
|
||
cargo install cortiq-gateway
|
||
cortiq-gateway # без флагов, без конфига, без токена — см. Быстрый старт
|
||
|
||
# или сборка из исходников
|
||
git clone https://github.com/infosave2007/cortiq-gateway
|
||
cd cortiq-gateway
|
||
cargo build --release # ./target/release/cortiq-gateway
|
||
```
|
||
|
||
Образ идёт с дефолтным конфигом и работает из коробки; смонтируйте `/app/config`
|
||
(с `gateway.toml`), чтобы использовать свой. Теги: `:latest`, `:X.Y.Z`, `:edge`
|
||
(linux/amd64 + arm64).
|
||
|
||
**Docker Compose** — шлюз + локальная модель Ollama одной командой:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
docker compose exec ollama ollama pull qwen2.5:0.5b # один раз скачать модель
|
||
# → OpenAI API на http://localhost:9000/v1 · панель на /admin (токен: change-me)
|
||
```
|
||
|
||
См. [`docker-compose.yml`](docker-compose.yml). Для умного роутинга задайте
|
||
`CORTIQ_ROUTER_KEY` и добавьте `[router]` (см. [docs/ROUTER.ru.md](docs/ROUTER.ru.md)).
|
||
|
||
Развёртывание для команды/офиса (сервис systemd/launchd/Windows, TLS-прокси, API-ключи с лимитами и месячными бюджетами, бэкапы): [docs/DEPLOY.ru.md](docs/DEPLOY.ru.md).
|
||
|
||
---
|
||
|
||
## 🖥️ Панель управления
|
||
|
||

|
||
|
||
В шлюз встроена веб-панель на **`/admin`**:
|
||
|
||
| | |
|
||
|---|---|
|
||
|  |  |
|
||
| **Models** — добавление/правка/probe моделей, ключи провайдеров | **Routing** — визуальный редактор полос (упорядоченный) |
|
||
|  |  |
|
||
| **Playground** — тест живого пайплайна с решением роутинга | **Dashboard** — трафик, стоимость, латентность |
|
||
|
||
Панель **по умолчанию открыта** — токен не нужен. Чтобы закрыть её, задайте любое из
|
||
`--admin-token <ТОКЕН>`, `[admin].token` или `[admin].token_env`:
|
||
|
||
```bash
|
||
cortiq-gateway --admin-token <ВАШ_ТОКЕН>
|
||
# откройте http://localhost:9000/admin?token=<ВАШ_ТОКЕН>
|
||
```
|
||
|
||
Когда токен задан, все эндпоинты `/admin/api/*` требуют его как Bearer. Значения секретов
|
||
API наружу не отдаёт (только статус наличия: `store` / `env` / `missing`).
|
||
|
||
---
|
||
|
||
## 🚀 Быстрый старт
|
||
|
||
```bash
|
||
cortiq-gateway
|
||
```
|
||
|
||
Это вся команда. При первом запуске шлюз:
|
||
|
||
1. **создаёт конфиг** — `config/gateway.toml`, если запущен из репозитория, иначе
|
||
`~/.cortiq-gateway/gateway.toml` (переопределяется через `$CORTIQ_GATEWAY_HOME` или `--config`);
|
||
2. **подбирает свободный порт**, если 9000 занят, и записывает выбор в конфиг;
|
||
3. **открывает браузер** на мастере настройки `/admin#/onboarding`.
|
||
|
||
Мастер доводит от нуля до работающей локальной модели:
|
||
|
||
| Шаг | Что происходит |
|
||
|---|---|
|
||
| **Язык** | 7 языков; потом меняется в шапке |
|
||
| **Готовые модели** | `.cmf` модели [`infosave`](https://huggingface.co/infosave), список читается с HuggingFace вживую — выбираете квантизацию и видите реальный прогресс загрузки |
|
||
| **Любая модель с HF** | поиск по HuggingFace и автоконвертация в `.cmf` |
|
||
| **Завершить** | каждая скачанная модель подключается как локальная, поднимается её `cortiq serve`, `routing.default` указывает на неё — и вы попадаете в Песочницу |
|
||
|
||
Никаких правок TOML, отдельного шага «зарегистрировать» и вручную запущенного сервера модели.
|
||
Мастер не нужен? Добавляйте модели из панели (**Модели**, **Импорт модели**) или пишите конфиг
|
||
руками — оба пути работают, изменения применяются на лету без перезапуска.
|
||
|
||
```bash
|
||
# явный конфиг / порт / без браузера — всё опционально
|
||
cortiq-gateway --config config/gateway.toml --no-browser --no-port-search
|
||
```
|
||
|
||
Для умного роутинга по пулу направьте `[router]` на хостовый allaigate или локальный
|
||
`cortiq-router` (см. [docs/ROUTER.ru.md](docs/ROUTER.ru.md)). Без роутера шлюз мягко
|
||
деградирует до модели по умолчанию, поэтому чисто локальная установка работает сразу.
|
||
|
||
Теперь любой OpenAI-клиент работает через шлюз:
|
||
|
||
```python
|
||
from openai import OpenAI
|
||
client = OpenAI(base_url="http://localhost:9000/v1", api_key="sk-gw-...")
|
||
|
||
resp = client.chat.completions.create(
|
||
model="cortiq-auto", # ← магическая модель = «выбери сам»
|
||
messages=[{"role": "user", "content": "Solve x^2 - 5x + 6 = 0"}],
|
||
)
|
||
print(resp.choices[0].message.content)
|
||
# заголовки ответа покажут выбор шлюза:
|
||
# X-Cortiq-Task-Label: math
|
||
# X-Cortiq-Complexity-Tier: low
|
||
# X-Cortiq-Selected-Model: local-qwen
|
||
```
|
||
|
||
`model: "cortiq-auto"` включает роутинг. Любое **реальное** имя модели из конфига
|
||
(`"gpt-4o-mini"`, `"local-qwen"`) — это passthrough напрямую, без роутинга.
|
||
|
||
> **Используете хостовый allaigate-роутер?** Он стоит по умолчанию: `url =
|
||
> "https://router.allaigate.com"`, `verify_tls = true`. Задайте `taxonomy_id =
|
||
> "data-assistant"` и ключ `cortiq_…` в `CORTIQ_ROUTER_KEY`. На сложных запросах роутер эскалирует к oracle (~10 с), поэтому
|
||
> ставьте `timeout_ms = 12000+` — иначе шлюз мягко деградирует на default-модель.
|
||
|
||
---
|
||
|
||
## 🧭 Роутер (allaigate)
|
||
|
||
Роутинг `cortiq-auto` обеспечивает **семантический роутер** — классификатор, который
|
||
читает промпт и возвращает тип задачи + сложность. Используйте хостовый
|
||
**[allaigate](https://api.allaigate.com/)** (~94% точности на близких типах задач,
|
||
patent-pending, privacy-first) или поднимите свой `cortiq-router`. Pinned-моделям роутер не нужен.
|
||
|
||
> 🎉 **Акция:** возьмите **Starter-ключ за $1** по промокоду **`LAUNCH1`** на
|
||
> **[api.allaigate.com](https://api.allaigate.com/)** (число активаций ограничено).
|
||
|
||
Настройка, тарифы, контракт API и как проверить точность: **[docs/ROUTER.ru.md](docs/ROUTER.ru.md)**.
|
||
|
||
---
|
||
|
||
## Поток запроса
|
||
|
||
1. Клиент → `POST /v1/chat/completions` (или Anthropic/MCP) с `model: "cortiq-auto"`.
|
||
2. Шлюз извлекает **текст для маршрутизации** (стратегия настраивается, см. [docs/ROUTING.ru.md](docs/ROUTING.ru.md)).
|
||
3. Шлюз → `cortiq-router /v1/route` → получает `task_label` + `complexity.tier`.
|
||
4. Шлюз выбирает модель из пула по таблице роутинга (с порядком fallback).
|
||
5. Шлюз → провайдер выбранной модели (транслируя протокол при необходимости), возвращает ответ.
|
||
6. Шлюз отдаёт метаданные роутинга в заголовках/`usage`, считает стоимость и статистику.
|
||
|
||
Подробно — [docs/ARCHITECTURE.ru.md](docs/ARCHITECTURE.ru.md).
|
||
|
||
---
|
||
|
||
## Поддерживаемые протоколы (входящие)
|
||
|
||
| Протокол | Endpoint | Статус |
|
||
|---|---|---|
|
||
| OpenAI Chat Completions | `POST /v1/chat/completions` | ✅ реализовано (+ стриминг) |
|
||
| OpenAI Embeddings | `POST /v1/embeddings` | ✅ реализовано |
|
||
| Anthropic Messages | `POST /v1/messages` | ✅ реализовано (+ стриминг) |
|
||
| MCP (Model Context Protocol) | `POST /mcp` (JSON-RPC) | ✅ реализовано |
|
||
| OpenAI Completions (legacy) | `POST /v1/completions` | ✅ реализовано (+ стриминг) |
|
||
| OpenAI Models | `GET /v1/models` | ✅ реализовано |
|
||
| Native passthrough | `POST /route` | ✅ реализовано |
|
||
|
||
## Поддерживаемые провайдеры (исходящие)
|
||
|
||
| Провайдер | Покрывает |
|
||
|---|---|
|
||
| `openai` (OpenAI-совместимый) | OpenAI, OpenRouter, Together, Groq, **vLLM, llama.cpp server, LM Studio, Ollama (`/v1`)** |
|
||
| `anthropic` | Claude Messages API (+ стриминг) |
|
||
| `ollama` | нативный Ollama API |
|
||
| `http` | произвольный HTTP-эндпоинт (свой адаптер) |
|
||
|
||
---
|
||
|
||
## Конфигурация
|
||
|
||
Полный пример — [config/gateway.example.toml](config/gateway.example.toml).
|
||
Модель роутинга и cost-aware выбор — [docs/ROUTING.ru.md](docs/ROUTING.ru.md).
|
||
Всё из конфига также правится из панели управления в рантайме.
|
||
|
||
---
|
||
|
||
## ⚡ Производительность и точность
|
||
|
||
**Латентность** — overhead шлюза при проксировании одного мгновенного бэкенда, `ab -k -r -c 20 -n 5000`:
|
||
|
||
| Шлюз | req/s | p50 | p99 |
|
||
|---|--:|--:|--:|
|
||
| **Cortiq Gateway** (Rust) | **~57 300** | 0 ms | **1 ms** |
|
||
| Portkey (Node) | ~5 800 | 3 ms | 9 ms |
|
||
| LiteLLM (Python, 4 воркера) | ~1 200 | 9 ms | 59 ms |
|
||
|
||
**Точность** — определение типа задачи на естественных промптах (7 типов). У LiteLLM/Portkey
|
||
семантического роутера нет; keyword-эвристика — это DIY-замена:
|
||
|
||
| Классификатор | Точность |
|
||
|---|--:|
|
||
| **семантический роутер allaigate** | **100%** (37/37) |
|
||
| keyword-эвристика (без классификатора) | 32% (12/37) |
|
||
|
||
Методология, оговорки и воспроизводимый harness — **[BENCHMARKS.md](BENCHMARKS.md)**
|
||
(`bash bench/run.sh`, `python3 bench/accuracy.py`). Числа зависят от железа; важны разрывы.
|
||
|
||
## Сборка и тесты
|
||
|
||
```bash
|
||
cargo build --release # один самодостаточный бинарь (SPA встроена)
|
||
cargo test # round-trip конфига, валидация роутинга
|
||
```
|
||
|
||
## ✅ Проверено
|
||
|
||
| Область | Как проверено | Статус |
|
||
|---|---|---|
|
||
| Round-trip загрузки/записи конфига, валидация роутинга | `cargo test` (юнит) | ✅ |
|
||
| Сборка · формат · линт | CI: `cargo build` / `fmt --check` / `clippy -D warnings` на Linux · macOS · Windows | ✅ |
|
||
| OpenAI Chat + SSE-стриминг | интеграционно (mock-бэкенд) | ✅ |
|
||
| Anthropic Messages — in/out, стриминг + не-стриминг | интеграционно (mock) | ✅ |
|
||
| Embeddings (`POST /v1/embeddings`) | интеграционно (mock) | ✅ |
|
||
| Семантический кэш — hit / miss / экономия | интеграционно (mock) | ✅ |
|
||
| MCP — `initialize` / `tools/list` / `tools/call` | интеграционно (mock) | ✅ |
|
||
| Models · Completions · нативный `POST /route` | интеграционно (mock) | ✅ |
|
||
| Роутинг — auto / pinned / failover / деградация | интеграционно (mock **и** живой allaigate-роутер) | ✅ |
|
||
| Горячая перезагрузка конфига (без рестарта) | интеграционно | ✅ |
|
||
| Бенчмарк latency vs LiteLLM / Portkey | `bench/run.sh` (Apache Bench) — см. [BENCHMARKS.md](BENCHMARKS.md) | ✅ |
|
||
| Точность определения типа задачи | `bench/accuracy.py` — живой роутер 100% vs keyword-эвристика 32% | ✅ |
|
||
|
||
---
|
||
|
||
## Статус
|
||
|
||
Реализовано: OpenAI Chat Completions **со стримингом (SSE)**, провайдер и вход
|
||
**Anthropic** `/v1/messages` (стриминг), **embeddings**, **семантический кэш**,
|
||
**MCP**-сервер, роутинг с fallback и мягкой деградацией, учёт стоимости/токенов,
|
||
**встроенная многоязычная панель управления с горячей перезагрузкой конфига**,
|
||
статистика и Prometheus `GET /metrics`. В планах: per-account таблицы роутинга,
|
||
feedback-loop в роутер. Дорожная карта —
|
||
[docs/ARCHITECTURE.ru.md](docs/ARCHITECTURE.ru.md). Контрибьюции приветствуются —
|
||
см. [CONTRIBUTING.ru.md](CONTRIBUTING.ru.md).
|
||
|
||
## Лицензия
|
||
|
||
Apache-2.0 — см. [LICENSE](LICENSE).
|