7.0 KiB
llm-router-failover-proxy
Goal
LLM-роутер / failover-прокси для pi (кодинг-агент на Windows-воркстейшне vitya). Группирует все deepseek-v4-flash модели из разных роутеров в один алиас (deepseek-flash), отдельно deepseek-v4-pro (deepseek-pro). Приоритет: free-модели первыми, затем по приоритету провайдеров, официальный DeepSeek API (платный) — последним fallback'ом. При ошибке апстрима (429/5xx/таймаут/сеть) — автоматический переход к следующему.
Заказчик: vitya (через snolla-сессию). Решение, куда деплоить — за админом (см. «Деплой»).
Контекст
Потребитель один — pi на машине vitya (~/.pi/). Сейчас модели прописаны вручную в ~/.pi/agent/models.json (4 провайдера, ключи в ~/.pi/agent/auth.json):
| Провайдер | baseUrl | deepseek-v4-flash | deepseek-v4-pro |
|---|---|---|---|
| teamorouter | https://api.teamorouter.com/v1 | deepseek-v4-flash-free (free) |
deepseek-v4-pro-free (free) |
| orcarouter | https://api.orcarouter.ai/v1 | deepseek/deepseek-v4-flash-free (free) |
deepseek/deepseek-v4-pro-free (free) |
| anymodel | https://anymodel.org/v1 | am/deepseek-v4-flash (free) |
am/deepseek-v4-pro (free) |
| routerai | https://routerai.ru/api/v1 | — | — |
| deepseek (официальный) | https://api.deepseek.com | deepseek-chat (платный) |
deepseek-reasoner (платный) |
- Ключи всех апстримов уже лежат в
~/.pi/agent/auth.json(формат:{ "<provider>": { "type": "api_key", "key": "..." } }). Конфиг прокси может ссылаться на них или держать свои копии — на усмотрение админа (ключи не публиковать, gitignore). - Все free-модели — это deepseek-v4-flash/pro у разных посредников. Официальный DeepSeek API платный — последний в цепочке (fallback, когда все free лежат).
- Ранее обсуждено (рекомендация, НЕ приказ): деплой локально на Windows как winsw-сервис (паттерн agents-task-runner уже обкатан), Node-прокси без docker/WSL2. Решение за админом.
Требования
- OpenAI-совместимый эндпоинт (
/v1/chat/completions, openai-completions API). pi подключается одной записью в~/.pi/agent/models.json(провайдер + алиасы). - Алиасы моделей:
deepseek-flash→ пул flash-апстримов,deepseek-pro→ пул pro-апстримов. - Приоритет выбора: free-апстримы (teamorouter → orcarouter → anymodel, порядок конфига) → платный официальный DeepSeek → (остальные провайдеры, если появятся).
- Failover: на 429 / 5xx / таймаут / сетевую ошибку — retry к следующему апстриму в порядке приоритета. Желательно: cooldown для упавших апстримов (не долбить мёртвый), опционально circuit-breaker.
- Прозрачный passthrough: SSE-стриминг, tool-calls (pi использует активно, много раундов), thinking-блоки deepseek (reasoning) — всё должно доезжать без искажений. Модель в ответе — какую реально использовал.
- Логика по умолчанию: если все free живы — платный апстрим не вызывается (экономия).
- Конфиг — файл (YAML/JSON): алиас → упорядоченный список апстримов (baseUrl, key-ref, model-id, free/paid флаг, таймауты).
- Учёт: лог, какой апстрим обслужил запрос + usage. Cost-трекинг не обязателен (модели free), но знать, что сработал платный fallback — обязательно.
- Тесты: TDD (см. ниже).
Acceptance
- pi подключается к прокси одной записью в
~/.pi/agent/models.json;/model(илиpi --list-models) показываетdeepseek-flash/deepseek-pro. - Стриминг работает: ответ идёт потоком (не цельным blob).
- Tool-calls работают: несколько последовательных инструмент-раундов (типа как pi вызывает tools).
- Failover доказан тестом: верхний апстрим недоступен → запрос обслуживает следующий; при живых free — платный НЕ вызывается.
- Thinking/reasoning-контент deepseek не ломается (хотя бы smoke: ответ не пустой, без мусора).
- Инструкция для pi-интеграции (что писать в models.json) + как запускать/останавливать прокси (сервис/скрипт).
- Деплой выполнен (локально или VDS — решение админа) и живой smoke пройден.
Деплой (решение за админом)
Рекомендация заказчика: локально на Windows (Node-процесс, winsw-сервис — паттерн agents-task-runner; ключи не уходят на сервер; потребитель один — pi на этой машине; docker/WSL2 на Windows — боль). Если админ видит причину иначе (VDS, доступ с других устройств, Portainer-стек) — обосновать и сделать. Ключи апстримов на VDS — только если деплой туда, тогда по правилам админа (pass / env, не в git).
Обязательные скилы — вызвать до начала работы
- invoke
tdd-criteria— до написания кода - invoke
using-tasks— управление статусом задачи - invoke
project-discipline— коммиты/пуши - invoke
using-wikiпосле закрытия — заингесть.wiki/concepts/llm-router-failover-proxy.md(архитектура, решения, runbook)
TDD: да — failover/приоритет/стриминг это чистые юнит-кейсы; тест-харнесс обязателен (мок-апстримы). Разрешения: интерны: да | автопуш: да Weight: needs-claude Notify: victor/snolla