Un robot de escritorio que te escucha, te entiende y te responde en menos de un segundo.
Quick Start Β· Arquitectura Β· Performance Β· Roadmap Β· Contribuir
La mayorΓa de los asistentes de voz DIY son lentos. Entre que terminΓ‘s de hablar y escuchΓ‘s la primera palabra del robot pasan 2 a 4 segundos. Arriba de 1.5 s se siente robot-lento. Arriba de 3 s el usuario abandona.
Michibot tiene un solo objetivo: que la primera palabra del robot sea audible en menos de 900 ms en turnos complejos, y en menos de 200 ms en respuestas conocidas. A esa velocidad la conversaciΓ³n deja de sentirse como hablarle a una mΓ‘quina.
No es magia β es la suma de decisiones de arquitectura que la mayorΓa de los proyectos DIY no toman: streaming end-to-end desde el primer dΓa, wake word on-device, un router de 3 tiers que evita llamar al LLM en el 70 % de los turnos, proveedores cloud especializados por etapa, y pre-warming de todas las conexiones.
Michibot es la fusiΓ³n de ElectronBot (cuerpo + servos + display) y EchoEar (audio ESP32-S3), con un backend en Python que lo hace conversacional.
Medido en condiciones reales β desktop LATAM contra PoPs US-East, red domΓ©stica:
| Tier | QuΓ© hace | p50 first-audio | Costo / turno | % de turnos |
|---|---|---|---|---|
| T1 Β· Canned | Respuesta WAV pre-sintetizada desde disco | ~15 ms | $0.000000 | ~40 % |
| T2 Β· Template | Datos locales β Cartesia streaming | ~235 ms | ~$0.0019 | ~30 % |
| T3 Β· LLM full | STT β Groq Llama 70B β Cartesia, con speculative TTS | ~586 ms | ~$0.0065 | ~30 % |
Costo promedio ponderado: ~$0.0027 por turno. Con 600 turnos/mes el costo
variable es ~$1.60 β margen suficiente para una subscripciΓ³n de $9.99/mes.
π¬ El T2 bajΓ³ de 935 ms β 235 ms (β700 ms) al hacer la conexiΓ³n WebSocket a Cartesia persistente. Ver
adapters/tts_cartesia.py.
- π― Intent Router 3-tier β el 70 % de los turnos se responden sin llamar al LLM
- β‘ Streaming end-to-end desde el primer dΓa (speculative TTS por frase)
- π Barge-in nativo β interrumpΓs al robot hablando encima, se calla al toque
- π Adapter pattern puro β swapeΓ‘s proveedores editando un YAML, cero
if provider == - βοΈ Dual-mode cloud / local β misma interfaz, Deepgram/Groq/Cartesia o whisper.cpp/Ollama/Piper
- π₯ Pre-warming de WebSockets β la primera respuesta no paga el handshake
- π Cost tracker + mΓ©tricas JSONL β p50/p95 y costo por tier con un script
- π± Wake word "Hola Michi" β entrenable, on-device vΓa microWakeWord en Week 2
- π€ Un solo chip β ESP32-S3 maneja audio + WiFi + servos + display (Week 2-3)
βββββββββββββββββββββ DEVICE (ESP32-S3 β Week 2-3) ββββββββββββββββββββ
β β
β mic I2S βββΆ ESP-SR AFE βββΆ microWakeWord("Hola Michi") β
β β β
β βΌ β
β ACK filler <50 ms β
β β β
β βΌ β
β WebSocket client β
β speaker I2S βββ audio playback βββ WebSocket client β
β display GC9A01 βββ face animation βββ event handler β
β servos (portados del STM32 original) β
ββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WebSocket binario (PCM 16 kHz) + JSON control
βΌ
βββββββββββββββββββββ BACKEND (FastAPI Β· async) ββββββββββββββββββββββββ
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β VoiceSessionOrchestrator β β
β β STT stream βββΆ Intent Router βββΆ response stream β β
β β β β β β β
β β βΌ βΌ βΌ β β
β β βββββββββββββββββββββββββββββββ β β
β β β T1 Canned ~15 ms β ~40 % β β
β β β T2 Template ~235 ms β ~30 % β β
β β β T3 LLM full ~586 ms β ~30 % β β
β β βββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² β² β² β
β β β β β
β Deepgram Groq 70B Cartesia β
β Nova-3 500 tok/s Sonic β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Cada turno pasa primero por un Intent Router que clasifica en 3 tiers:
| Tier | CuΓ‘ndo dispara | QuΓ© ejecuta | Costo |
|---|---|---|---|
| T1 | Match regex contra ~18 frases canned (saludos, cortesΓas, afirmaciones) | Lee un WAV del disco y lo stremea al cliente | $0 |
| T2 | Match contra handlers de template (ej: "ΒΏquΓ© hora es?") | Genera texto con datos locales, manda a TTS streaming | Solo TTS |
| T3 | Fallback: cualquier cosa que no matchee T1/T2 | Pipeline completo STT β Groq Llama 70B β Cartesia con speculative TTS | Los 3 |
El ~70 % de los turnos de una conversaciΓ³n real caen en T1/T2. Por eso la latencia percibida promedio es muchΓsimo mΓ‘s baja que el peor caso.
- Python 3.11+
- uv β gestor de dependencias rΓ‘pido
- MicrΓ³fono y parlantes funcionando
- 3 API keys (las 3 tienen free tier):
git clone https://github.com/<tu-user>/michibot.git
cd michibot
uv sync
cp env.example.txt .env
# EditΓ‘ .env y pegΓ‘ las 3 API keys# Terminal 1 β backend
uv run uvicorn electronbot_es.server.app:app --host 127.0.0.1 --port 8000
# Terminal 2 β cliente mock con wake word
uv run python -m electronbot_es.mock.mock_esp32 --wake-word
# DecΓ "hey jarvis" (placeholder β el real "Hola Michi" llega en Week 2)uv run python scripts/metrics.py --last 20Ejemplo de salida
=== Michibot metrics β 20 turns ===
tier n % first_audio p50 p95 tts_first p50 p95 avg_cost total
---------------------------------------------------------------------------------
T1 8 40% 15 ms 30 ms 15 ms 30 ms $0.000000 $0.0000
T2 6 30% 235 ms 280 ms 235 ms 280 ms $0.001878 $0.0113
T3 6 30% 586 ms 820 ms 586 ms 820 ms $0.006514 $0.0391
---------------------------------------------------------------------------------
total cost: $0.0504 avg/turn: $0.002520
T3 tokens avg: in=225 out=41
T1+T2 match rate: 70% (target >60%)
michibot/
βββ src/electronbot_es/
β βββ core/
β β βββ orchestrator.py # VoiceSessionOrchestrator + speculative TTS
β β βββ cost.py # EstimaciΓ³n de costo por turno
β β βββ obs.py # Logger JSONL de mΓ©tricas
β β βββ messages.py # Schemas pydantic del protocolo WebSocket
β β βββ protocols.py # STT / LLM / TTS como Protocol
β β βββ persona.py # System prompt LATAM del LLM
β β βββ config.py
β βββ router/
β β βββ intent_router.py # DecisiΓ³n T1 / T2 / T3
β β βββ canned_responses.yaml
β β βββ templates/ # Handlers T2 (hora, clima, etc.)
β βββ adapters/
β β βββ stt_deepgram.py Β· stt_whisper.py
β β βββ llm_groq.py Β· llm_claude.py Β· llm_ollama.py
β β βββ tts_cartesia.py Β· tts_piper.py
β βββ server/
β β βββ app.py # FastAPI + /ws/voice
β βββ mock/
β βββ mock_esp32.py # Cliente de desarrollo (mic + speaker + WS)
β βββ wake_word.py # openWakeWord wrapper
βββ docs/
β βββ protocol.md # Contrato WebSocket v1 (inmutable)
β βββ roadmap.md # Weeks 2-12+
β βββ hardware.md # Decisiones de hardware
β βββ cloud-providers.md # Setup Deepgram / Groq / Cartesia
β βββ llm-benchmark.md # Benchmark espaΓ±ol LATAM
βββ assets/canned/ # WAVs pre-sintetizados (T1)
βββ scripts/ # generate_canned, metrics, benchmarks, ...
βββ tests/ # pytest Β· 40+ tests
|
Backend
|
Cloud providers
|
Local / dev
|
|
Device (Week 2+)
|
Mobile (Week 7+)
|
Tooling
|
| Semana | Objetivo | Estado |
|---|---|---|
| W1 | Backend + mock + router + observabilidad | β |
| W2 | Firmware ESP32-S3 + wake word real "Hola Michi" | π |
| W3 | Servos + display GC9A01 + personalidad fΓsica | β³ |
| W4 | IntegraciΓ³n end-to-end + aceptaciΓ³n MVP | β³ |
| W5-6 | Multi-tenant (Supabase + auth + billing) | β³ |
| W7-8 | App mΓ³vil React Native + Expo | β³ |
| W9 | Deploy producciΓ³n + stores + beta cerrada | β³ |
| W10-12 | IteraciΓ³n + launch pΓΊblico | β³ |
Detalles semana por semana en docs/roadmap.md.
docs/protocol.mdΒ· Contrato WebSocket (inmutable)docs/hardware.mdΒ· Por quΓ© ESP32-S3 ΓΊnico y por quΓ© no LLM on-devicedocs/cloud-providers.mdΒ· Setup de las 3 API keysdocs/roadmap.mdΒ· Plan semana por semana hasta launchdocs/llm-benchmark.mdΒ· Comparativa de LLMs en espaΓ±ol LATAM
Michibot es un proyecto en desarrollo activo β Week 1 reciΓ©n cerrΓ³. Si querΓ©s aportar:
- Issues β reportΓ‘ bugs, pedΓ features, comentΓ‘ ideas
- Benchmarks β si tenΓ©s una GPU decente y querΓ©s correr el modo local, mandΓ‘ tus nΓΊmeros
- Canned responses LATAM β falta ampliar el catΓ‘logo T1 con mΓ‘s variantes regionales (Argentina, MΓ©xico, Colombia, Chile, PerΓΊβ¦)
- Voces TTS β experimentar con Cartesia Voice Cloning para acentos regionales (la voz actual es neutro LATAM)
MIT. Hecho con cariΓ±o en LATAM.
Si Michibot te parece interesante, tirale una β β ayuda un montΓ³n.