# AI Provider Architecture v0.7.1 ## Обзор Начиная с версии 0.7.1 бот использует **универсальный интерфейс** для всех AI-провайдеров. Это позволяет любому AI-провайдеру работать с инструментами (SSH, DDGS, RSS, Cron) одинаковым образом. ## Архитектура ``` ┌─────────────────────────────────────────────────────────┐ │ Bot (bot.py) │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ AIProviderManager │ │ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │ │ │ QwenCode │ │ GigaChat │ ... │ │ │ │ │ Provider │ │ Provider │ │ │ │ │ └──────┬──────┘ └────────┬─────────┘ │ │ │ │ │ │ │ │ │ │ └──────────┬───────┘ │ │ │ │ │ │ │ │ │ ┌──────────▼──────────┐ │ │ │ │ │ BaseAIProvider │ │ │ │ │ │ (Protocol) │ │ │ │ │ └──────────┬──────────┘ │ │ │ └────────────────────┼────────────────────────────┘ │ │ │ │ │ ┌─────────────┴──────────────┐ │ │ │ Tools Registry │ │ │ │ ┌──────┐ ┌─────┐ ┌────┐ │ │ │ │ │ SSH │ │DDGS │ │RSS │ │ │ │ │ └──────┘ └─────┘ └────┘ │ │ │ └────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` ## Ключевые компоненты ### 1. BaseAIProvider (`bot/base_ai_provider.py`) **Базовый протокол** для всех AI-провайдеров: ```python class BaseAIProvider(ABC): @property def provider_name(self) -> str: ... @property def supports_tools(self) -> bool: ... @property def supports_streaming(self) -> bool: ... async def chat(...) -> ProviderResponse: ... async def process_with_tools(...) -> ProviderResponse: ... ``` **Ключевая особенность:** Метод `process_with_tools` реализует универсальный цикл: 1. Отправить запрос провайдеру 2. Распарсить вызовы инструментов 3. Выполнить инструменты 4. Отправить результаты обратно 5. Повторить пока не будет финального ответа ### 2. QwenCodeProvider (`bot/providers/qwen_provider.py`) Адаптер для Qwen Code CLI: - **Нативная поддержка инструментов** через stream-json - **Потоковый вывод** (on_chunk callback) - Парсинг tool calls из JSON ответа ### 3. GigaChatProvider (`bot/providers/gigachat_provider.py`) Адаптер для GigaChat API: - **Эмуляция инструментов** через текстовые блоки - Парсинг `` ```tool {...} ``` `` из текста - Автоматическое формирование tool prompt ### 4. AIProviderManager (`bot/ai_provider_manager.py`) Управление провайдерами: - Переключение между провайдерами - Единый реестр инструментов для всех - Маршрутизация запросов ## Как это работает ### Сценарий 1: Qwen Code ```python # Пользователь: "проверь нагрузку на сервере" 1. AIProviderManager получает запрос 2. Вызывает QwenCodeProvider.process_with_tools() 3. Qwen возвращает: { "content": "Проверяю нагрузку...", "tool_calls": [{"name": "ssh_tool", "args": {"command": "uptime"}}] } 4. AIProviderManager выполняет ssh_tool.execute() 5. Результат возвращается Qwen для финального ответа ``` ### Сценарий 2: GigaChat ```python # Пользователь: "найди новости про Python" 1. AIProviderManager получает запрос 2. Вызывает GigaChatProvider.process_with_tools() 3. GigaChat возвращает текст: "Ищу новости... ```tool {"name": "ddgs_tool", "arguments": {"query": "Python news 2026"}} ```" 4. GigaChatProvider._parse_tool_calls() извлекает вызов 5. AIProviderManager выполняет ddgs_tool.execute() 6. Результат возвращается GigaChat для продолжения ``` ## Добавление нового провайдера Чтобы добавить новый AI-провайдер (например, OpenAI): ```python # bot/providers/openai_provider.py from bot.base_ai_provider import BaseAIProvider, ProviderResponse, AIMessage, ToolCall class OpenAIProvider(BaseAIProvider): @property def provider_name(self) -> str: return "OpenAI" @property def supports_tools(self) -> bool: return True # Или False если не поддерживает @property def supports_streaming(self) -> bool: return True async def chat(...) -> ProviderResponse: # Реализация через OpenAI API ... ``` Затем зарегистрировать в `AIProviderManager._init_providers()`: ```python from bot.providers.openai_provider import OpenAIProvider self._providers[AIProvider.OPENAI.value] = OpenAIAI(api_key=...) ``` ## Преимущества архитектуры | Преимущество | Описание | |-------------|----------| | **Единый интерфейс** | Все провайдеры работают одинаково | | **Инструменты для всех** | Любой провайдер может использовать SSH, DDGS, RSS, Cron | | **Легкое расширение** | Новый провайдер = один класс | | **Совместимость** | Старый код продолжает работать | | **Гибкость** | Можно переключаться на лету | ## Настройка ### Для Qwen Code ```bash # Требуется установленный qwen-code CLI npm install -g @anthropic-ai/qwen-code ``` ### Для GigaChat Добавьте в `.env`: ```env GIGACHAT_CLIENT_ID=ваш-client-id-uuid GIGACHAT_CLIENT_SECRET=ваш-client-secret GIGACHAT_SCOPE=GIGACHAT_API_PERS ``` ## Переключение провайдера ```telegram /ai qwen # Переключиться на Qwen Code /ai gigachat # Переключиться на GigaChat /ai # Показать текущего провайдера ``` ## Статус провайдеров | Провайдер | Инструменты | Стриминг | Статус | |-----------|-------------|----------|--------| | Qwen Code | ✅ Нативно | ✅ | ✅ Готов | | GigaChat | ✅ Эмуляция | ❌ | ✅ Готов | | OpenAI | ✅ Нативно | ✅ | 🔜 Скоро | | YandexGPT | ✅ Эмуляция | ❌ | 🔜 Скоро | ## Миграция с v0.5.x Старый код: ```python # Прямой вызов qwen_manager result = await qwen_manager.run_task(...) ``` Новый код: ```python # Через AIProviderManager result = await ai_provider_manager.execute_request( provider_id="qwen", user_id=user_id, prompt="запрос" ) ``` ## Будущие улучшения - [ ] Поддержка OpenAI Provider - [ ] YandexGPT Provider - [ ] Автоматический выбор провайдера по типу задачи - [ ] Балансировка нагрузки между провайдерами - [ ] Кэширование ответов - [ ] Fallback при ошибке провайдера --- *Версия: 0.7.1* *Дата: 2026-02-26*