234 lines
9.2 KiB
Markdown
234 lines
9.2 KiB
Markdown
# 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*
|