🚀 План інтеграції: 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:
# В методі _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()¶
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 сервіс¶
# Перевірити чи працює
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:
# В методі _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()¶
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:
# Після парсингу викликати 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 перемикає режим
# Зберігати в Memory Service:
user_preferences = {
"reply_mode": "voice" # або "text"
}
Варіант 2: Реагувати голосом на голосові
# Якщо користувач надіслав voice → відповісти voice
if message.voice or message.audio:
reply_mode = "voice"
else:
reply_mode = "text"
3.2. Оновити router_handler.py¶
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()¶
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¶
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
{
"dashboard": {
"title": "DAARION Services Overview",
"panels": [
{
"title": "Total Requests/sec",
"targets": [
{
"expr": "rate(http_requests_total[5m])"
}
]
},
// ... інші панелі
]
}
}
4.3. Імпортувати в Grafana¶
# Через 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¶
- ✅ Vision Encoder integration (~30 хв)
- ✅ Parser Service integration (~30 хв)
- ✅ Тестування фото + PDF
Phase 2 (Завтра/Пізніше): TTS¶
- ✅ TTS integration (~45 хв)
- ✅
send_voice()в telegram_listener - ✅ Тестування голосових відповідей
Phase 3 (Опційно): Grafana¶
- ✅ Створення дашбордів (~1 год)
- ✅ Налаштування alerts
- ✅ Документація
📝 Зміни в файлах (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()з підтримкою voicetelegram-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)