telegram-cli-bot/AI_PROVIDER_ARCHITECTURE.md

234 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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*