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

14 KiB
Raw Blame History

🚀 План інтеграції: 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

  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)