Quiero tener una IA offline que hable conmigo creo que george hotz hizo un stream de esto: can tinygrad whisper? Se trataba de eso el stream ? Como puedo conseguir esto. Quiero tener una IA offline que corra qwen, kimi o GLM y que hable conmigo que transcriba mi voz y que me conteste

Sí, existe ese stream. Se llama exactamente “can tinygrad whisper?” (3 de junio de 2023), y ahí George Hotz efectivamente logra correr Whisper (el modelo de speech-to-text) dentro de tinygrad, su propio framework de deep learning. Ojo: buena parte del stream en realidad es un rant sobre los drivers de AMD (mirá los capítulos del video), y tinygrad es un framework experimental/educativo pensado para entender cómo funciona un framework de deep learning por dentro, no una herramienta pensada para armar fácilmente un asistente de voz casero. O sea, es un proyecto genial para aprender, pero no es el camino práctico para lo que vos querés.

Para lo que buscás (hablarle a una IA local que transcriba tu voz, piense con un LLM, y te conteste hablado) el stack que usa la comunidad hoy es otro, y está bastante maduro:

1. Voz → texto (STT): whisper.cpp o faster-whisper (implementaciones optimizadas de Whisper, corren en CPU o GPU, 100% offline).

2. El cerebro (LLM): Ollama o llama.cpp corriendo un modelo cuantizado en formato GGUF.

  • Qwen (Qwen3, en tamaños 4B/8B/14B/32B) anda muy bien local y tiene buen soporte en Ollama.
  • GLM (GLM-4, de Zhipu) también tiene versiones chicas que corren en PC de consumo.
  • Kimi K2 es otra historia: es un modelo gigante de ~1 billón de parámetros (MoE), y hasta la versión cuantizada más chica pesa arriba de 200GB. Prácticamente imposible correrlo en una compu doméstica normal, salvo que tengas un servidor con muchísima RAM/VRAM. Para uso local yo lo descartaría.

3. Texto → voz (TTS): Piper (archivado en GitHub pero sigue funcionando) o alternativas más nuevas como Kokoro-82M o Coqui XTTS.

4. El “pegamento”: un script en Python que conecte micrófono → whisper.cpp → Ollama → TTS → parlante. O si no querés programar nada, Open WebUI ya trae entrada/salida de voz integrada con Ollama. Si además querés que esté “siempre escuchando” con palabra de activación (tipo “Hey Jarvis”), se le suma OpenWakeWord o Porcupine.

Para darte una recomendación concreta de qué tamaño de modelo y qué stack conviene armar, necesito saber con qué hardware contás:

Con GPU NVIDIA dedicada tenés el mejor punto de partida — todo el stack corre acelerado por CUDA. Lo único que cambia según tu tarjeta es el tamaño de modelo que podés mover cómodo:

VRAM LLM recomendado (Qwen3 / GLM-4, GGUF vía Ollama)
6-8 GB qwen3:4b o qwen3:8b (q4)
10-12 GB qwen3:14b (q4)
16 GB qwen3:14b (q8) o qwen3:32b (q4)
24 GB+ qwen3:32b, glm-4-32b

Whisper (STT) y el TTS pesan poco (unos cientos de MB a 1-2GB de VRAM), así que no compiten mucho con el LLM.

Te armo un script inicial que conecta todo: graba tu voz, la transcribe con faster-whisper (CUDA), la manda a Ollama, y te contesta hablando. Después lo podés ajustar (cambiar de TTS a Piper/Kokoro para mejor voz, agregar wake word, etc).Pasos para dejarlo andando:

1. Instalá Ollamahttps://ollama.com/download (tiene instalador para Windows/Linux con soporte CUDA automático).

2. Bajá un modelo:

ollama pull qwen3:8b

(ajustá el tamaño según la tabla de arriba — para GPU NVIDIA con 8-12GB de VRAM, qwen3:8b o qwen3:14b van bien).

3. Instalá las dependencias de Python:

pip install faster-whisper sounddevice numpy requests pyttsx3

4. Corré el script (voice_assistant.py, arriba). Presionás Enter, hablás, y te contesta por voz.

Cosas a saber:

  • pyttsx3 es la voz “genérica” del sistema (offline, cero configuración, pero suena robótica). Cuando funcione el flujo básico, te conviene cambiarlo por Piper o Kokoro-TTS para una voz mucho más natural — son un poco más de instalación pero vale la pena.
  • Si DEVICE = "cuda" te tira error, es que faster-whisper no encuentra CUDA/cuDNN instalado — probá DEVICE = "cpu" primero para confirmar que el resto del flujo funciona, y después arreglás la parte de GPU.
  • Ahora mismo graba duración fija (5s) al presionar Enter. Es “push-to-talk” simple. Si querés que quede siempre escuchando con palabra de activación tipo “Hey Qwen”, el siguiente paso natural es sumar OpenWakeWord.
  • Kimi te lo saco de la ecuación para uso local por lo que hablamos (demasiado grande). Si en algún momento querés esa capacidad y no te importa que no sea 100% offline, la alternativa es pegarle a su API en vez de correrlo local — pero ya no sería offline.
"""
Asistente de voz 100% offline
--------------------------------
Voz -> texto (faster-whisper, CUDA) -> LLM (Ollama) -> texto -> voz (pyttsx3)

Requisitos (instalar UNA VEZ en tu PC, no en este sandbox):
    pip install faster-whisper sounddevice numpy requests pyttsx3

Además necesitás:
  1) Ollama instalado y corriendo (https://ollama.com)
     ollama pull qwen3:8b        <- o el tamaño que elijas según tu VRAM
  2) Una GPU NVIDIA con drivers CUDA (para acelerar faster-whisper).
     Si no tenés CUDA configurado, cambiá DEVICE = "cpu" abajo (más lento).

Cómo se usa:
  - Corré el script.
  - Presioná ENTER, hablá durante RECORD_SECONDS, y esperá la respuesta.
  - Ctrl+C para salir.

Esto es un punto de partida funcional, no un producto terminado. Ideas para
mejorar después: detección de silencio en vez de duración fija, wake word
(OpenWakeWord/Porcupine), reemplazar pyttsx3 por Piper o Kokoro-TTS (voces
mucho más naturales), y mantener historial de conversación.
"""

import sounddevice as sd
import numpy as np
import requests
import pyttsx3
from faster_whisper import WhisperModel

# ---------------------- CONFIGURACIÓN ----------------------
OLLAMA_URL = "http://localhost:11434/api/chat"
OLLAMA_MODEL = "qwen3:8b"          # cambiá esto por el modelo que hayas bajado
WHISPER_MODEL_SIZE = "small"       # tiny/base/small/medium/large-v3
DEVICE = "cuda"                    # "cuda" si tenés GPU NVIDIA lista, si no "cpu"
COMPUTE_TYPE = "float16"           # "float16" en GPU, "int8" si usás CPU
LANGUAGE = "es"                    # idioma de tu voz
SAMPLE_RATE = 16000
RECORD_SECONDS = 5                 # cuánto graba después de presionar ENTER
SYSTEM_PROMPT = "Sos un asistente de voz conciso y directo. Respondé en pocas frases."
# -------------------------------------------------------------

print("Cargando modelo de transcripción (Whisper)...")
stt_model = WhisperModel(WHISPER_MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE)

print("Cargando motor de voz (TTS)...")
tts_engine = pyttsx3.init()
tts_engine.setProperty("rate", 175)

conversation_history = [{"role": "system", "content": SYSTEM_PROMPT}]


def grabar_audio(segundos: int, sample_rate: int) -> np.ndarray:
    print(f"Grabando {segundos}s... hablá ahora.")
    audio = sd.rec(int(segundos * sample_rate), samplerate=sample_rate, channels=1, dtype="float32")
    sd.wait()
    return audio.flatten()


def transcribir(audio: np.ndarray) -> str:
    segments, _ = stt_model.transcribe(audio, language=LANGUAGE)
    texto = " ".join(segment.text.strip() for segment in segments)
    return texto.strip()


def preguntar_al_llm(texto_usuario: str) -> str:
    conversation_history.append({"role": "user", "content": texto_usuario})
    payload = {
        "model": OLLAMA_MODEL,
        "messages": conversation_history,
        "stream": False,
    }
    respuesta = requests.post(OLLAMA_URL, json=payload, timeout=120)
    respuesta.raise_for_status()
    data = respuesta.json()
    contenido = data["message"]["content"]
    conversation_history.append({"role": "assistant", "content": contenido})
    return contenido


def hablar(texto: str) -> None:
    tts_engine.say(texto)
    tts_engine.runAndWait()


def main() -> None:
    print("\nAsistente de voz offline listo. Presioná ENTER para hablar (Ctrl+C para salir).\n")
    while True:
        input("-> ENTER para grabar: ")
        audio = grabar_audio(RECORD_SECONDS, SAMPLE_RATE)

        print("Transcribiendo...")
        texto_usuario = transcribir(audio)
        if not texto_usuario:
            print("(No se detectó voz, probá de nuevo)")
            continue
        print(f"Vos dijiste: {texto_usuario}")

        print("Pensando...")
        respuesta = preguntar_al_llm(texto_usuario)
        print(f"Asistente: {respuesta}")

        hablar(respuesta)


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\nChau!")

Sí, ahora te entendí bien — y quiero ser honesto: esto es un proyecto serio, de varias semanas, no un script de una tarde. Pero es totalmente posible y hay piezas open source que ya hacen gran parte del trabajo. Te explico el mapa completo.

Lo que en realidad son dos piezas:

  1. El cerebro conversacional en tiempo real — el que escucha, piensa y habla con fluidez natural, con barge-in (que puedas interrumpirlo y que reaccione, como una persona real).
  2. El puente telefónico — lo que hace que ese cerebro pueda estar del otro lado de una llamada real (recibiéndola o marcándola).

Lo interesante es que ambas piezas las resuelve el mismo proyecto: se llama Agent Voice Response (AVR) — es open source, corre sobre Asterisk (la central telefónica open source de siempre), y está diseñado justo para esto: barge-in nativo, respuestas sub-segundo, y motores intercambiables de ASR/LLM/TTS. Podés cablearlo 100% local con Ollama (Qwen3 o GLM-4) + Vosk o Silero (STT) + Kokoro o Coqui TTS. Nada de esto toca la nube.

Un límite real que tenés que aceptar: el “cerebro” (transcripción + razonamiento + voz) puede ser 100% offline. Pero para que la IA hable con otra persona real por teléfono, en algún punto ese audio tiene que salir a la red telefónica — igual que cualquier llamada tuya. Eso significa que necesitás sí o sí una de estas tres cosas: una troncal SIP de algún proveedor VoIP, un adaptador a tu línea fija (ATA), o un módem GSM con una SIM. No hay forma de evitar tocar la red telefónica — lo que sí es 100% tuyo y offline es que ningún dato pase por un servicio de IA en la nube (nada de Twilio+OpenAI, por ejemplo).

Sobre Moshi (el modelo de Kyutai que es realmente full-duplex, ~200ms de latencia, indistinguible en fluidez): es una maravilla técnica, pero hoy solo funciona en inglés. Si querés hablar en español, no te sirve para este proyecto — mejor ni lo consideres por ahora.

Plan de ataque que te propongo, en dos fases:

  • Fase 1 — validar el cerebro: instalar AVR con Ollama (Qwen3) + STT/TTS en español, y probarlo con un softphone SIP común (Zoiper, Linphone) llamándote a vos mismo dentro de tu red. Acá ya tenés “hablame de forma natural y fluida” funcionando, sin meterte todavía con líneas telefónicas reales.
  • Fase 2 — conectar a la red real: una vez que la conversación fluye bien, le sumás a Asterisk una troncal SIP (o un ATA a tu línea fija) para que pueda efectivamente marcar o atender llamadas de gente de verdad.

¿Querés que te arme la guía de instalación paso a paso de AVR + Ollama (Fase 1), o preferís que primero exploremos qué proveedor SIP/opción de línea te conviene para la Fase 2?