Saltar al contenido
OpenCohost Kira
Guía técnica verificada

Arquitectura verificada, implementación actual y límites en desarrollo.

Esta sección se actualizó contra la memoria del proyecto en Engram y la copia actual de la web. Separa comportamiento ya implementado, mensajes corregidos y trabajo futuro, porque una documentación para desarrolladores sirve solo si no promete de más.

Resumen de auditoría

Los puntos verdes ya estaban alineados con la memoria del proyecto. Los puntos ámbar se corrigieron en este pase. Los puntos azules son límites de desarrollo activo y no deben tratarse como garantías de release.

Verificado

OpenCohost es el chasis de orquestación

Correcto: el valor del producto está en coordinar Ollama, TTS, contexto de LiveAudio, Agenda Mode, reacción al chat, perfiles, presencia de avatar/música y resiliencia; no es solo un wrapper.

Corregido

La historia de voz no es solo Qwen-TTS

Actualizado: la implementación verificada incluye síntesis local con Piper, síntesis ligera opcional con Edge-TTS cuando la privacidad lo permite, y trabajo activo de voz personalizada/Qwen. La documentación ya no promete un stack garantizado solo con Qwen.

Verificado

Local-first no significa cómputo gratis

Correcto: el modo local evita billing cloud/API por defecto, pero el desarrollador igual debe presupuestar GPU/VRAM, RAM, electricidad, elección de modelo, carga del juego y tiempo de setup.

Verificado

LiveAudio sigue siendo un puente separado

Correcto: escucha de voz, Silero VAD, transcripción Whisper, subtítulos, transcripciones y contexto limpio pertenecen al puente LiveAudio, no a un micrófono siempre activo en OpenCohost.

Corregido

Ruta de instalador real y documentada

El sitio ahora enlaza el instalador alpha para Windows generado por CI en GitHub Releases y lo etiqueta como alpha; el copy de "no hay instalador" se retiró cuando el flujo de release se volvió real.

Raíz de composición

app_shell.py cablea el hilo motor, health monitor, cliente OBS, SmartAggregator, Stream Admin, topic inbox bridge, controles de TTS y paneles de UI mediante protocolos tipados. Debe orquestar; la lógica va en módulos testeables.

Observer UIState

Contenedor de estado thread-safe y agnóstico al framework, con propiedades tipadas. Los observers despachan en un hilo daemon; los callbacks de UI deben volver al main loop de Tk antes de tocar widgets.

Cola de prioridad + acumulación

El hilo motor prioriza entradas en tiempo real como PTT, chat y agenda, mientras compacta overflow en consultas acotadas para no enterrar a los modelos locales bajo ruido crudo del stream.

Cambio de tiers LLM

Los slots manuales Quality / Balanced / Fast mapean a tags de modelos Ollama. El cambio preserva conversación/perfil y hace rollback al último modelo bueno conocido ante fallos.

Ruta de voz con privacidad explícita

La ruta de TTS soporta síntesis local con Piper, presets persistidos de velocidad y un switch tts_local_only que bloquea Edge-TTS antes de que el texto pueda salir de la máquina.

Entrada de temas con aprobación humana

El topic inbox permite que agentes propongan ideas, pero approve sigue siendo solo humano. Validación de namespace al leer, timeouts cortos de SQLite y rollback protegen la UI bajo carga.

Avatar state bridge

Un puente pub/sub permite que módulos core señalen estados del avatar sin acoplarse a UI ni OBS. OBSClient puede suscribirse y actualizar fuentes de imagen cuando cambia el estado.

Escalera de degradación

La recuperación de agenda y el cambio de modelo priorizan degradación segura: reintentos, descarte de prefetch obsoleto, estados de pausa explícitos y rollback en vez de deadlocks silenciosos en vivo.

Notas verificadas de implementación reciente

Switch TTS local-only

tts_local_only.json persiste la preferencia en config. Cuando está ON, el motor enruta la síntesis ligera a Piper y server_qwen.py devuelve HTTP 400 antes de cualquier llamada a Edge-TTS.

Presets de velocidad Piper

La UI expone Rápida, Media, Calma y Lenta con valores length_scale. El motor persiste cambios en tts_speed.json y reconstruye la configuración de síntesis Piper bajo lock.

Fix de doble cierre de agenda

El controlador ya no hace prefetch de un segundo kira-agenda-stop cuando un tema está CLOSING, y las acciones prefetched obsoletas se descartan en vez de reproducirse después.

Topic inbox

Los agentes pueden proponer candidatos con namespace ti_. El polling de UI es fail-open, la aprobación es solo humana y los fallos al encolar hacen rollback de filas aprobadas.

Gotchas para contribuidores

Nunca uses metadata externa como proxy del estado interno
Un bug real de agenda vino de chequear current_speech_source.startsWith("kira-agenda") para inferir estado del controlador. El controlador puede emitir acciones con source="chat"; confiá en el estado del controlador, no en etiquetas pegadas a un evento.
Los widgets Tk son single-threaded
Cualquier mutación de widget debe ocurrir en el main loop. El hilo de dispatch de UIState es separado, así que los callbacks deben usar schedule_ui_update() / after_idle antes de tocar widgets Tk.
Reasoning token budget
Modelos como qwen3 y gemma pueden gastar parte del token budget en razonamiento interno. Un cap duro de num_predict puede devolver respuestas vacías o truncadas; el motor remueve ese cap para esas familias.
Los storage paths se resuelven al importar
STORAGE_PATHS se resuelve cuando se importa config/storage.py. apply_storage_environment() corre antes de inicializar librerías; cambiar storage.yaml en runtime no mueve rutas ya resueltas.
Los gates de privacidad van antes que los fallbacks cómodos
El switch local-only debe evaluarse antes del fallback ligero/offline de Edge-TTS. Reordenar esas ramas puede enviar texto a Microsoft aunque el usuario haya pedido síntesis solo local.
La configuración persistida puede contaminar tests
Cualquier test de comandos del motor que escriba preferencias como tts_local_only o tts_speed debe parchear save/load a una ruta temporal; si no, puede mutar la configuración real del usuario.
Validá namespaces de topics al leer, no solo al rutear
Filas hostiles o legacy pueden existir ya en SQLite. El topic inbox aísla IDs ajenos al leer para que el render y el dismiss de la UI coincidan sobre qué le pertenece.
app_shell.py tiene presupuesto duro de líneas
El guard de integración mantiene app_shell.py por debajo de 3100 líneas. El comportamiento nuevo de UI casi siempre debe vivir en un módulo pequeño inyectado, dejando app_shell solo para cableado.

Puntos de extensión

OpenCohost todavía no tiene un sistema formal de plugins, pero los desarrolladores pueden extender estas superficies de forma deliberada:

  • Perfiles (perfiles.json): texto del system prompt y flag use_system. Los defaults viven en config/default_profiles.json.
  • Slots de tiers LLM (llm_tiers.json): quality, balanced y fast validados contra modelos Ollama instalados al iniciar.
  • Archivos de privacidad y velocidad TTS: tts_local_only.json y tts_speed.json persisten política de voz y choices de length_scale de Piper.
  • YAMLs de configuración: storage.yaml, smart_aggregator.yaml, avatar.yaml y stream_admin.yaml configuran rutas, shaping de chat, OBS/avatar, OAuth y moderación.
  • Catálogo de modelos (config/settings.py): MODELS_CATALOG necesita display, desc, size_gb y family antes de aparecer de forma segura en la UI.
  • Sistema de protocolos (ui/protocols.py): MotorEventCallback, SmartAggregatorCallbacks y StreamAdminCallbacks definen contratos tipados de callback.
  • Topic inbox (opencohost/core/topic_inbox.py + ui/topic_inbox_bridge.py): permite propuestas de agentes sin saltarse aprobación humana.
  • Crash reporting (ui/crash_reporting.py): excepthook de Python, excepthook de threading, hook de callbacks Tk y faulthandler cubren distintas clases de falla.
Desafíos resueltos

Problemas difíciles de stream que ya tuvimos que resolver

Kira se fue formando con problemas reales de directo: chats ruidosos, voz con retraso, límites de hardware local, sesiones largas y la necesidad de ser útil sin quitarle el control al host.

Varias cargas de IA en una PC de streamer

Desafío

Correr un co-host local no es apretar un botón y magia. El stream puede necesitar LLM local, voz personalizada y escucha/transcripción mientras OBS, el juego y los overlays también están activos.

Ejemplo en vivo

Juego + OBS + voz de Kira + escucha de LiveAudio en la misma máquina.

Resultado

OpenCohost coordina las piezas y deja visible el tradeoff: calidad, velocidad, VRAM y carga del stream siguen bajo control del host.

Agenda Mode con contexto del directo

Desafío

Un co-host necesita ritmo. Si Kira solo lee un guion fijo, se siente muerta. Si reacciona a todo, se vuelve ruido. El desafío fue mantenerla enfocada sin apagar lo que pasa en el chat.

Ejemplo en vivo

Kira puede continuar un tema planeado, notar que el ambiente cambió y ajustar el ángulo sin robarle el control al streamer.

Resultado

Agenda Mode se pensó alrededor de un loop de eventos: el host marca dirección, Kira sostiene el flujo y el contexto del chat puede moldear la conversación sin tomar el mando.

Recuperación cuando el co-host se quedaba callado

Desafío

En versiones anteriores, ciertas combinaciones de co-host y chat en vivo podían dejar a Kira en silencio. Para un asistente de stream eso es grave: el momento muere, el host no recibe ayuda y la audiencia no ve nada.

Ejemplo en vivo

Un directo con chat activo y agenda corriendo no debería hacer que Kira se pause para siempre.

Resultado

Corregimos el flujo del producto para que co-host, reacción al chat y control del streamer convivan sin bloquearse.

Contexto de chat sin saturar el modelo

Desafío

Inyectar chat crudo a un LLM local es matar la experiencia. Un stream mezcla spam, bromas, mensajes repetidos, olas de reacción, frases cortas y picos repentinos de actividad.

Ejemplo en vivo

En vez de repetir el chat palabra por palabra, Kira entiende la presión del ambiente y responde como co-host.

Resultado

OpenCohost transforma el chat en contexto útil para que Kira reaccione al stream sin espejar la sala ni saturarse cuando el chat se pone caótico.

Push-to-talk para control real por voz

Desafío

Al conectar LiveAudio por WebSocket, Kira podía reaccionar a demasiado. Sin audífonos, incluso podía escucharse a sí misma por el micrófono y responder en bucle. Además, la transcripción de voz puede llegar con un pequeño retraso.

Ejemplo en vivo

Mantenés una tecla, hablás natural — incluso una idea larga — soltás y Kira recibe el contexto completo.

Resultado

PTT vuelve la escucha intencional: recoge voz mientras está activo, envía el contexto al soltar y acepta un pequeño margen de transcripción tardía para que la interacción se sienta más real.

Robustez bajo presión de directo

Desafío

Los directos no son demos limpias. Puede haber cortes, componentes ocupados, ventanas abiertas durante horas o entradas inesperadas. Una herramienta para streamers tiene que doblarse antes de romperse.

Ejemplo en vivo

Si una parte se retrasa o no está disponible, el show entero no debería caerse por eso.

Resultado

OpenCohost fue reforzado para degradar mejor ante problemas: Kira debería seguir siendo útil incluso cuando el entorno del stream se pone desordenado.

Memoria ordenada para sesiones largas

Desafío

Un stream puede durar horas. Si cada mensaje, broma, transcripción y respuesta vale lo mismo para siempre, el modelo local se ahoga y Kira pierde foco.

Ejemplo en vivo

Kira debería recordar la dirección útil del show, no arrastrar cada línea vieja del chat para siempre.

Resultado

OpenCohost mantiene continuidad con contexto compacto en vez de memoria infinita, ayudando a que Kira siga coherente en sesiones largas.

Presencia de Avatar y OBS

Desafío

Kira necesitaba sentirse presente en pantalla, no escondida en una caja de texto. La audiencia debería entender cuándo escucha, piensa o habla sin que el host lo explique todo el tiempo.

Ejemplo en vivo

Un viewer puede mirar el stream y entender rápido la presencia actual de Kira.

Resultado

Conectamos presencia visual con comportamiento amigable para OBS para que Kira se sienta parte del show, no una herramienta de fondo.

Una UI para streamers, no para técnicos

Desafío

La primera UI era demasiado densa. Mostraba demasiados controles juntos y se sentía más como una cabina técnica que como un producto de stream. Eso hace que la gente dude, aunque las funciones sean útiles.

Ejemplo en vivo

Un host debería encontrar voz, stream, co-host, música y avatar sin leer un manual antes.

Resultado

Remodelamos la interfaz con tabs más claras, secciones más tranquilas, explicaciones y una disposición más centrada en Kira para usuarios no técnicos.

Música que acompaña a Kira

Desafío

La música de fondo puede hacer que el stream se sienta vivo, pero también puede pelearse con el co-host. Si pisa a Kira, la audiencia tiene que esforzarse más para entender el momento.

Ejemplo en vivo

Kira habla, el stream sigue claro y la música acompaña el ambiente en vez de competir.

Resultado

OpenCohost ahora maneja mejor el flujo musical para que el show se sienta más suave cuando Kira entra en la conversación.

LiveAudio como puente de escucha separado

Desafío

La escucha por voz es suficientemente importante como para vivir en una pieza conectada propia. LiveAudio detecta cuándo alguien realmente habla, transcribe la voz localmente y pasa contexto limpio a OpenCohost.

Ejemplo en vivo

La voz puede convertirse en subtítulos, transcripciones y contexto útil sin hacer que OpenCohost escuche permanentemente por defecto.

Resultado

LiveAudio usa Silero VAD y OpenAI Whisper open-source como puente separado para contexto de voz, subtítulos y transcripciones.