Перейти к основному содержимому

Как добавить провайдера или протокол

Этот документ описывает практический чек-лист для расширения gpt2giga новым вышестоящим провайдером или новым публичным протоколом. Перед изменением набора API сначала нужно решить, что именно добавляется:

  • новый публичный протокол: клиенты отправляют полезные нагрузки, совместимые с Gemini, а вышестоящий сервис остаётся GigaChat;
  • новый вышестоящий провайдер: нормализованные запросы исполняются не только через GigaChat;
  • оба слоя сразу.

Термины:

  • адаптер протокола переводит внешний сетевой формат в нормализованные модели и обратно;
  • адаптер провайдера исполняет нормализованный запрос в конкретном вышестоящем сервисе;
  • роутер подключает HTTP-поверхность и занимается авторизацией, контекстом запроса, потоковой передачей и типом содержимого ответа;
  • наблюдаемость, журналы трафика и метрики получают безопасные нормализованные поля или поля контекста запроса.

1. Зафиксировать область

Для нового протокола:

  • определить маршруты, заголовки, ожидания по авторизации и политику псевдонима /v1;
  • описать минимальные поддерживаемые операции: chat/messages, embeddings, эндпоинт типа responses, count tokens, models;
  • решить, какие необязательные поля принимаются и игнорируются для совместимости с SDK.

Для нового вышестоящего провайдера:

  • определить настройки авторизации и обращение с секретами;
  • описать синхронные/без потоковой передачи и потоковые вызовы SDK;
  • определить разрешение модели, метку параллелизма по моделям и семантику таймаута/повторов;
  • решить, какие специфичные для провайдера поля можно хранить в provider_metadata.

2. Добавить конфигурацию

Обновите:

  • gpt2giga/models/config.py: настройки, валидаторы, значения по умолчанию.
  • .env.example: новые переменные окружения и безопасные значения по умолчанию.
  • docs/configuration.md: описание для пользователя.
  • tests/test_config/test_config.py: значения по умолчанию, разбор окружения, некорректные значения.

Секреты должны оставаться в окружении/менеджере секретов. Не добавляйте секреты провайдера в примеры CLI, журналы трафика, метки метрик или отладочный вывод.

3. Добавить адаптер протокола

Файлы для нового публичного протокола обычно живут в gpt2giga/protocols/<protocol>/.

Минимальный набор:

  • adapter.py с реализацией ProtocolAdapter из gpt2giga/core/interfaces.py;
  • преобразователь запроса в NormalizedChatRequest или другую нормализованную модель;
  • преобразователь ответа из NormalizedResponse в публичную форму ответа;
  • преобразователь потока из NormalizedStreamEvent в публичный формат SSE/событий;
  • санитайзер/классификатор параметров, если SDK присылает много необязательных полей.

Правила сопоставления:

  • канонические поля кладите в нормализованные поля;
  • неизвестные или принятые, но не исполняемые публичные поля кладите в raw_extensions, если их нужно сохранить;
  • специфичный для провайдера проброс кладите в provider_metadata;
  • не смешивайте заголовки авторизации/транспорта с полезной нагрузкой модели;
  • схемы инструментов и вызовы инструментов приводите к NormalizedTool и NormalizedToolCall;
  • использование токенов приводите к input_tokens, output_tokens, total_tokens;
  • причины завершения приводите к общему набору вроде stop, length, tool_calls, если это возможно.

Для уже подключённого протокола Gemini это сделано отдельным преобразователем Gemini-в-нормализованное, а не новой веткой внутри адаптера OpenAI. Специфичные для Gemini настройки безопасности, кандидаты, части контента, объявления инструментов и события потока должны быть либо подняты в канонические поля, либо явно сохранены в расширениях. Для будущих протоколов сохраняйте тот же принцип изоляции сетевого формата от адаптера OpenAI.

4. Добавить адаптер провайдера

Файлы для нового вышестоящего провайдера живут в gpt2giga/providers/<provider>/.

Обычно нужны:

  • adapter.py: реализация для вызовов без потоковой передачи и потоковых;
  • auth.py: помощники для учётных данных/access-токена;
  • client.py: фабрика SDK/клиента;
  • streaming.py: фрагменты вышестоящего сервиса в NormalizedStreamEvent;
  • types.py: локальные Protocol/типы, если типы SDK неудобны для тестов.

Адаптер провайдера должен:

  • принимать NormalizedChatRequest;
  • вызывать вышестоящий сервис в первую очередь асинхронно;
  • обновлять фактическую модель в RequestContext через update_request_context;
  • использовать ModelConcurrencyLimiter с ограниченной меткой провайдера;
  • возвращать NormalizedResponse для вызовов без потоковой передачи;
  • возвращать NormalizedStreamEvent для потоковых;
  • нормализовать ошибки провайдера в NormalizedError;
  • сохранять только безопасные метаданные провайдера;
  • не писать необработанные учётные данные, API-ключи, cookie и заголовки авторизации.

Если вышестоящий провайдер умеет нативно принимать нормализованную полезную нагрузку, не нужно реконструировать форму OpenAI. Для GigaChat текущий адаптер пока переиспользует OpenAI-подобную полезную нагрузку и прежний RequestTransformer; это переходная деталь, а не требование для новых провайдеров.

5. Подключить маршруты

Обновите нужные слои:

  • gpt2giga/routers/<protocol>/: конкретные HTTP-обработчики.
  • gpt2giga/api/<protocol>/routes.py: агрегация маршрутов.
  • gpt2giga/app/factory.py: подключение, зависимости авторизации, debug/admin-флаги.
  • gpt2giga/openapi_specs/: дополнения OpenAPI для новых эндпоинтов.
  • gpt2giga/app_state.py и настройка жизненного цикла, если нужен новый клиент.

Обработчик маршрута должен:

  • читать тело через общие помощники;
  • создавать или использовать контекст запроса;
  • применять политику авторизации прокси/admin;
  • вызывать адаптер протокола и адаптер провайдера;
  • оборачивать итератор потокового тела так, чтобы метрики, журналы трафика и наблюдаемость видели финальный жизненный цикл;
  • сохранять склейку диалогов только там, где семантика совпадает.

6. Добавить наблюдаемость

Новый провайдер/протокол должен быть виден в Phoenix/OpenTelemetry, метриках и журналах трафика без включения захвата промптов.

Обновите наблюдаемость LLM:

  • используйте build_llm_chat_completion_attributes() для чат-подобных сценариев, если запрос/ответ уже нормализованы;
  • добавьте отдельный помощник в gpt2giga/sinks/observability/<protocol>.py, если публичный протокол имеет особый формат вывода/событий;
  • задайте имя спана, если нужен новый корневой спан, например Gemini-Content;
  • выставляйте gpt2giga.api_format в ограниченное значение: chat_completions, responses, messages, generate_content, embeddings или новый явный формат;
  • сопоставляйте вехи потока с событиями спана через NormalizedStreamEvent, где возможно;
  • сохраняйте видимость инструментов: количество/имена по умолчанию, аргументы/схема только при GPT2GIGA_OBSERVABILITY_CAPTURE_CONTENT=True и GPT2GIGA_OBSERVABILITY_CAPTURE_TOOL_ARGS=True;
  • не добавляйте промпты, ответы, аргументы инструментов или необработанную полезную нагрузку провайдера в атрибуты без включения и маскирования.

Обновите наблюдаемость жизненного цикла запроса:

  • RequestContext.protocol, route, запрошенная/фактическая модель и провайдер должны заполняться до отправки;
  • LLM-маршруты должны выставлять context.llm_observability_emitted=True, чтобы не дублировать успешный спан жизненного цикла;
  • ошибки должны попадать в error_type, error_message, статус OpenTelemetry и нормализованные поля ошибок.

Обновите метрики:

  • метки провайдера/протокола должны быть ограниченными;
  • не добавляйте идентификатор запроса, идентификатор трейса, идентификатор пользователя, хеш API-ключа или необработанные варианты модели с высокой кардинальностью;
  • проверьте число запросов, задержку, задержку вышестоящего сервиса, ошибки вышестоящего сервиса, суммарные токены, отключения потока и отброшенные события очереди.

Обновите журналы трафика:

  • захват содержимого запросов/ответов остаётся включаемым;
  • новые поля полезной нагрузки должны проходить маскирование;
  • если схема хранилища требует новые индексируемые поля, добавьте миграцию и обновление шаблона OpenSearch;
  • фильтры admin-логов должны использовать ограниченные поля.

7. Добавить отладочную трансляцию

Для нового протокола/провайдера расширьте защищённый debug API:

  • SUPPORTED_TRANSLATE_FORMATS в gpt2giga/api/admin/routes.py;
  • эндпоинт <protocol>-to-normalized, если нужен короткий путь;
  • обработку универсальной пары /_debug/translate;
  • фикстуры в tests/fixtures/debug_translate/;
  • тесты на неподдерживаемые пары и безопасные ошибки.

Отладочная трансляция не должна требовать реальных учётных данных вышестоящего сервиса, кроме направлений, где нужно реально подготовить полезную нагрузку SDK провайдера. Необработанные секреты не должны попадать в ответ.

8. Добавить тесты

Минимальный набор:

  • модульные тесты адаптера: запрос, ответ, инструменты, мультимодальный контент, ошибки;
  • тесты преобразователя потока: события start/delta/tool/usage/end/error;
  • тесты роутера: без потоковой передачи, потоковые, авторизация, некорректные параметры, откат;
  • тесты наблюдаемости: спаны, атрибуты, флаги захвата, маскирование, события инструментов;
  • тесты метрик/журналов трафика, если меняются метки или отправляемые поля;
  • тесты OpenAPI;
  • эталонные фикстуры (golden) для публичного формата ответа/SSE;
  • smoke-тесты совместимости SDK, если есть доступный пакет клиента.

Для протокола Gemini отдельно проверьте сопоставление кандидатов, причины завершения, поля, связанные с безопасностью, объявления инструментов/вызовы функций, мультимодальные части и порядок событий потока.

9. Обновить документацию

Обновите:

  • docs/api-compatibility.md: статус маршрутов и ограничения.
  • docs/client-parameter-compatibility.md: принятые/поддерживаемые/игнорируемые поля.
  • docs/configuration.md: переменные окружения и режимы.
  • docs/operations.md: метрики, журналы трафика, наблюдаемость, debug-эндпоинты.
  • docs/deployment.md: изменения compose/окружения, если появились внешние сервисы.
  • docs/architecture/normalized-messages.md: если изменился нормализованный контракт или статус выполнения.
  • таблицу документации в README, если появился новый документ для пользователя.

Документация должна явно разделять «реализовано сейчас» и «подготовлено для следующего шага». Это особенно важно для частично подготовленных семейств API, например Files/Batches, чтобы не обещать публичный маршрут, пока он не подключён и не покрыт тестами.

10. Проверить качество

Перед PR:

uv run ruff check .
uv run ruff format --check .
uv run pytest tests/ --cov=. --cov-report=term --cov-fail-under=80

Если менялись зависимости, обновите uv.lock. Если менялись контракты deploy/окружения, проверьте .env.example, compose-файлы и документацию вместе.