Files
microdao-daarion/docs/integration/VISION_PARSER_TTS_PLAN.md

417 lines
14 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.
# 🚀 План інтеграції: Vision, Parser, TTS та Grafana
**Дата**: 2025-11-18
**Статус**: 📋 В плануванні
---
## ✅ Поточний стан
### Що вже працює:
- ✅ Голосові повідомлення (STT через Whisper)
- ✅ Фото detection (metadata → NATS)
- ✅ PDF detection (metadata → NATS)
- ✅ Prometheus metrics (Router + Gateway)
- ✅ 3 боти (DAARWIZZ, Helion, GREENFOOD)
- ✅ Helion 502 фікс (timeout 120s)
### Що не інтегровано:
- ⚠️ Vision Encoder (сервіс готовий, але не викликається)
- ⚠️ Parser Service для PDF (сервіс готовий, але не викликається)
- ⚠️ TTS для голосових відповідей
- ⚠️ Grafana дашборди (Grafana працює, дашборди порожні)
---
## 📋 План імплементації
### 1. **Vision Encoder Integration** 🖼️ (Пріоритет: 🔴 ВИСОКИЙ)
**Мета**: Бот може описувати що на фото.
**Кроки**:
#### 1.1. Оновити `router_handler.py`
Додати обробку `metadata.photo`:
```python
# В методі _handle_telegram_event():
if event.metadata and "photo" in event.metadata:
photo_info = event.metadata["photo"]
# Викликати Vision Encoder
vision_result = await self._analyze_photo(
photo_url=photo_info["file_url"],
caption=event.text or ""
)
# Додати результат Vision до контексту для LLM
enhanced_text = f"{event.text or ''}\n\n[VISION]: {vision_result}"
event.text = enhanced_text
```
#### 1.2. Додати метод `_analyze_photo()`
```python
async def _analyze_photo(self, photo_url: str, caption: str) -> str:
"""Викликати Vision Encoder Service"""
try:
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(
"http://dagi-vision-encoder:9500/analyze", # TODO: перевірити endpoint
json={
"image_url": photo_url,
"prompt": caption or "Опиши що на цьому зображенні"
}
)
response.raise_for_status()
result = response.json()
return result.get("description", "")
except Exception as e:
logger.error(f"❌ Vision Encoder error: {e}")
return "[Не вдалося проаналізувати зображення]"
```
#### 1.3. Перевірити Vision Encoder сервіс
```bash
# Перевірити чи працює
docker ps | grep vision-encoder
# Перевірити API
curl -X POST http://localhost:9500/analyze \
-H "Content-Type: application/json" \
-d '{"image_url": "https://example.com/image.jpg", "prompt": "Describe this image"}'
```
**Файли для зміни**:
- `/opt/telegram-infrastructure/telegram-gateway/app/router_handler.py`
**Очікуваний результат**:
```
Ти → 🖼️ [Фото кота] + "Хто це?"
Бот → На зображенні зображений рудий кіт, який сидить на підвіконні і дивиться у вікно...
```
---
### 2. **Parser Service Integration** 📄 (Пріоритет: 🔴 ВИСОКИЙ)
**Мета**: Бот може читати PDF і відповідати на питання.
**Кроки**:
#### 2.1. Оновити `router_handler.py`
Додати обробку `metadata.document`:
```python
# В методі _handle_telegram_event():
if event.metadata and "document" in event.metadata:
doc_info = event.metadata["document"]
# Викликати Parser Service
parsed_content = await self._parse_document(
doc_url=doc_info["file_url"],
file_name=doc_info["file_name"]
)
# Якщо є питання - відповісти на основі parsed_content
if event.text and event.text != f"[DOCUMENT] {doc_info['file_name']}":
# Додати parsed content до контексту
enhanced_text = f"Користувач запитує про документ '{doc_info['file_name']}':\n{event.text}\n\n[DOCUMENT_CONTENT]:\n{parsed_content[:2000]}"
event.text = enhanced_text
else:
# Просто парсинг без питання
await telegram_listener.send_message(
agent_id=event.agent_id,
chat_id=event.chat_id,
text=f"✅ Документ '{doc_info['file_name']}' оброблено.\n\nЗадай питання про нього!"
)
return
```
#### 2.2. Додати метод `_parse_document()`
```python
async def _parse_document(self, doc_url: str, file_name: str) -> str:
"""Викликати Parser Service для PDF"""
try:
async with httpx.AsyncClient(timeout=90.0) as client:
# Виклик DAGI Router з mode: "doc_parse"
response = await client.post(
f"{self._router_url}/route",
json={
"mode": "doc_parse",
"agent": "parser",
"payload": {
"context": {
"doc_url": doc_url,
"file_name": file_name,
"output_mode": "markdown" # або "chunks" для RAG
}
}
}
)
response.raise_for_status()
result = response.json()
# Витягнути parsed content
if "data" in result and "markdown" in result["data"]:
return result["data"]["markdown"]
return result.get("text", "")
except Exception as e:
logger.error(f"❌ Parser Service error: {e}")
return "[Не вдалося прочитати документ]"
```
#### 2.3. Інтеграція з RAG (опційно)
Для збереження документів у RAG:
```python
# Після парсингу викликати RAG ingest
await client.post(
f"{self._router_url}/route",
json={
"mode": "doc_parse",
"agent": "parser",
"payload": {
"context": {
"doc_url": doc_url,
"file_name": file_name,
"output_mode": "chunks",
"ingest": True,
"dao_id": event.agent_id,
"user_id": event.user_id
}
}
}
)
```
**Файли для зміни**:
- `/opt/telegram-infrastructure/telegram-gateway/app/router_handler.py`
**Очікуваний результат**:
```
Ти → 📄 whitepaper.pdf
Бот → ✅ Документ 'whitepaper.pdf' оброблено. Задай питання про нього!
Ти → "Про що цей документ?"
Бот → Це whitepaper проєкту MicroDAO, який описує...
```
---
### 3. **TTS Integration** 🔊 (Пріоритет: 🟡 СЕРЕДНІЙ)
**Мета**: Бот може відповідати голосом.
**Кроки**:
#### 3.1. Додати опцію для голосових відповідей
Користувач може вибрати режим відповіді (текст або голос).
**Варіант 1**: Команда `/voice` перемикає режим
```python
# Зберігати в Memory Service:
user_preferences = {
"reply_mode": "voice" # або "text"
}
```
**Варіант 2**: Реагувати голосом на голосові
```python
# Якщо користувач надіслав voice → відповісти voice
if message.voice or message.audio:
reply_mode = "voice"
else:
reply_mode = "text"
```
#### 3.2. Оновити `router_handler.py`
```python
async def _send_response(self, event, answer: str, reply_mode: str = "text"):
if reply_mode == "voice":
# Синтезувати голос через TTS
audio_bytes = await self._text_to_speech(answer)
# Відправити voice message через Telegram
await telegram_listener.send_voice(
agent_id=event.agent_id,
chat_id=event.chat_id,
audio_bytes=audio_bytes
)
else:
# Звичайний текст
await telegram_listener.send_message(
agent_id=event.agent_id,
chat_id=event.chat_id,
text=answer
)
```
#### 3.3. Додати метод `_text_to_speech()`
```python
async def _text_to_speech(self, text: str) -> bytes:
"""Викликати TTS Service"""
try:
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(
"http://dagi-tts:9001/tts", # TODO: перевірити endpoint
json={
"text": text,
"voice": "ukrainian_female" # або "english_male"
}
)
response.raise_for_status()
return response.content # Audio bytes (OGG/MP3)
except Exception as e:
logger.error(f"❌ TTS error: {e}")
return b"" # Fallback to text
```
#### 3.4. Додати `send_voice()` в `telegram_listener.py`
```python
async def send_voice(self, agent_id: str, chat_id: int, audio_bytes: bytes):
"""Відправити голосове повідомлення"""
bot_token = bots_registry.get_token_by_agent(agent_id)
bot = self._bots.get(bot_token)
if not bot or not audio_bytes:
# Fallback to text
return
from io import BytesIO
audio_file = BytesIO(audio_bytes)
audio_file.name = "voice.ogg"
await bot.send_voice(
chat_id=chat_id,
voice=audio_file
)
```
**Файли для зміни**:
- `/opt/telegram-infrastructure/telegram-gateway/app/router_handler.py`
- `/opt/telegram-infrastructure/telegram-gateway/app/telegram_listener.py`
**Очікуваний результат**:
```
Ти → 🎤 [Голосове] "Привіт"
Бот → 🔊 [Голосове] "Привіт! Як справи?"
```
---
### 4. **Grafana Dashboards** 📊 (Пріоритет: 🟢 НИЗЬКИЙ)
**Мета**: Візуалізація метрик (запити, помилки, latency).
**Кроки**:
#### 4.1. Створити дашборд "DAARION Services Overview"
**Панелі**:
1. **Total Requests** (counter)
- `rate(http_requests_total[5m])`
2. **Request Duration** (histogram)
- `histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))`
3. **Error Rate** (%)
- `rate(http_requests_total{status_code=~"5.."}[5m]) / rate(http_requests_total[5m])`
4. **Active Bots** (gauge)
- Custom metric: `telegram_gateway_active_bots`
5. **STT Requests** (counter)
- `rate(http_requests_total{job="dagi-stt"}[5m])`
6. **Router Latency** (graph)
- `http_request_duration_seconds{job="dagi-router"}`
#### 4.2. Створити файл дашборду
`/opt/microdao-daarion/monitoring/grafana/dashboards/daarion_overview.json`
```json
{
"dashboard": {
"title": "DAARION Services Overview",
"panels": [
{
"title": "Total Requests/sec",
"targets": [
{
"expr": "rate(http_requests_total[5m])"
}
]
},
// ... інші панелі
]
}
}
```
#### 4.3. Імпортувати в Grafana
```bash
# Через UI: http://144.76.224.179:3000
# Login: admin / admin
# Dashboards → Import → Upload JSON
```
**Файли для створення**:
- `/opt/microdao-daarion/monitoring/grafana/dashboards/daarion_overview.json`
- `/opt/microdao-daarion/monitoring/grafana/dashboards/telegram_bots.json`
**Очікуваний результат**:
- Красиві графіки в Grafana
- Real-time моніторинг всіх сервісів
---
## 🗓️ Порядок імплементації
### Phase 1 (Сьогодні): Vision + Parser
1. ✅ Vision Encoder integration (~30 хв)
2. ✅ Parser Service integration (~30 хв)
3. ✅ Тестування фото + PDF
### Phase 2 (Завтра/Пізніше): TTS
1. ✅ TTS integration (~45 хв)
2.`send_voice()` в telegram_listener
3. ✅ Тестування голосових відповідей
### Phase 3 (Опційно): Grafana
1. ✅ Створення дашбордів (~1 год)
2. ✅ Налаштування alerts
3. ✅ Документація
---
## 📝 Зміни в файлах (Summary)
### Для Vision + Parser:
- `telegram-gateway/app/router_handler.py`: +100 рядків
- `_analyze_photo()`
- `_parse_document()`
- Обробка `metadata.photo` та `metadata.document`
### Для TTS:
- `telegram-gateway/app/router_handler.py`: +50 рядків
- `_text_to_speech()`
- `_send_response()` з підтримкою voice
- `telegram-gateway/app/telegram_listener.py`: +20 рядків
- `send_voice()`
### Для Grafana:
- `monitoring/grafana/dashboards/*.json`: 2 нові файли
---
## 🚀 Готовий почати?
**Рекомендую порядок**:
1. **Vision Encoder** (найпростіше, одразу побачиш результат)
2. **Parser Service** (корисно для документів)
3. **TTS** (якщо треба голосові відповіді)
4. **Grafana** (коли все працює)
**Який пункт імплементуємо першим?** 🖼️📄🔊📊
---
*Створено: 2025-11-18*
*Автор: Assistant (via Cursor)*