Memoria de IA: historial de conversación y tokens
Puntos clave a recordar: Dar memoria a una IA conversacional se basa en tres mecanismos: una ventana deslizante con prioridades (system prompt + últimos intercambios siempre incluidos), un presupuesto de tokens controlado para gestionar los costos (una conversación de 10 intercambios cuesta 5 veces más), y un sistema de fallback entre modelos LLM para garantizar la disponibilidad. Esta es la diferencia entre una herramienta y un verdadero asistente.
La primera versión de la IA en TAMSIV era amnésica. "Añade pan a mi lista de la compra" funcionaba perfectamente. Pero continuar con "Ponla para mañana" fallaba estrepitosamente — la IA no sabía de qué tarea se hablaba. Cada intercambio comenzaba de cero.
Este problema es fundamental en cualquier aplicación de IA conversacional. Los LLM no tienen ninguna memoria nativa. En cada solicitud, es necesario reenviar todo el contexto. Y eso lo cambia todo — en términos de UX, costo y arquitectura.
Así es como le di memoria a la IA de TAMSIV.
¿Por qué los LLM no tienen memoria?
Es contraintuitivo cuando usas ChatGPT o Claude, pero estos modelos no tienen ninguna persistencia entre solicitudes. Cada llamada a la API es independiente. La "memoria" que percibes en una conversación de ChatGPT es la aplicación que reenvía el historial completo en cada mensaje.
Concretamente, cuando envías tu quinto mensaje en una conversación, la API recibe:
- El system prompt (las instrucciones de comportamiento)
- El mensaje 1 + la respuesta 1
- El mensaje 2 + la respuesta 2
- El mensaje 3 + la respuesta 3
- El mensaje 4 + la respuesta 4
- Tu mensaje 5
Con cada intercambio adicional, el payload crece. Y con él, dos problemas: la ventana de contexto (límite técnico del modelo) y el costo en tokens (cada token se factura).
Esto es lo que la documentación de OpenAI llama gestión del estado de la conversación.
¿Cómo funciona la ventana deslizante de TAMSIV?
La solución clásica es la ventana deslizante: solo se conservan los N últimos intercambios. Pero una ventana deslizante bruta es demasiado simplista para una aplicación como TAMSIV, donde la IA debe comprender referencias a acciones pasadas.
He implementado una ventana deslizante con prioridades:
- Prioridad máxima: el system prompt (siempre incluido, nunca truncado)
- Prioridad alta: los 2 últimos intercambios (el contexto inmediato)
- Prioridad alta: las function calls y sus resultados (las acciones realizadas — creación de tarea, modificación de nota, etc.)
- Prioridad media: los intercambios anteriores (3 a N-2)
- Prioridad baja: los intercambios antiguos, resumidos o eliminados según el presupuesto de tokens
¿Por qué las function calls son prioritarias? Porque en TAMSIV, cuando el usuario dice "Modifica la prioridad de la tarea que acabamos de crear", la IA debe saber qué tarea se creó. Esta información está en el function_result de un intercambio anterior. Sin ella, la IA no puede resolver el pronombre "la".
¿Cómo gestionar el presupuesto de tokens sin disparar los costos?
Este es el quid de la cuestión. Una conversación de 10 intercambios puede costar 5 veces más que un intercambio aislado, porque el payload acumulativo se reenvía cada vez.
Ejemplo concreto con un modelo a 0.001$ / 1000 tokens:
- Intercambio 1: ~500 tokens (system prompt + mensaje) = 0.0005$
- Intercambio 5: ~2500 tokens (historial 1-4 + mensaje 5) = 0.0025$
- Intercambio 10: ~5000 tokens (historial 1-9 + mensaje 10) = 0.005$
- Total conversación 10 intercambios: ~25 000 tokens acumulados = 0.025$
Para una aplicación con miles de usuarios, estos céntimos se suman rápidamente. He implementado tres salvaguardas:
- Límite de 20 intercambios por conversación: más allá de eso, se recomienda iniciar una nueva conversación. Esto evita las conversaciones monstruosas de 100 intercambios.
- Contador de tokens estimado: antes de cada llamada, el backend estima el número de tokens del payload completo. Si excede el presupuesto, los intercambios más antiguos se truncan.
- Elección del modelo según la complejidad: un mensaje simple ("Añade pan") utiliza un modelo ligero. Una solicitud compleja ("Reorganiza mis tareas de la semana por prioridad") utiliza un modelo más potente.
¿Cómo funciona el fallback entre modelos LLM?
En producción, la fiabilidad no es negociable. Si el modelo principal (configurado a través de OPENROUTER_MODEL) devuelve un error 429 (límite de tasa) o 503 (servicio no disponible), el usuario no debe notar nada.
El backend de TAMSIV implementa un fallback automático:
- Llamada al modelo principal a través de OpenRouter
- Si hay error 429/503 → reintento con
OPENROUTER_FALLBACK_MODEL - El
AlertServiceenvía un correo electrónico al administrador para informar del fallback - El usuario recibe su respuesta normalmente — sin degradación perceptible
En producción, TAMSIV realiza 2 o 3 fallbacks por semana. Es mínimo, pero sucede. Sin este mecanismo, el usuario vería un mensaje de error genérico — y probablemente abandonaría la aplicación.
La elección de OpenRouter como proxy LLM (en lugar de llamar directamente a la API de OpenAI o Anthropic) es estratégica: permite cambiar de modelo sin modificar el código. Si sale un nuevo modelo, basta con cambiar una variable de entorno. El pipeline vocal completo permanece idéntico.
¿Qué impacto tiene la memoria en la experiencia del usuario?
La diferencia es espectacular. Antes del historial de conversación, cada intercambio era independiente. Después, la IA se convierte en un verdadero asistente:
- "Modifica la prioridad de la tarea que acabamos de crear" → la IA sabe qué tarea y la modifica
- "Finalmente, ponlo para el viernes" → la IA comprende que "eso" se refiere al último evento creado
- "Añade también una nota sobre esto" → la IA retoma el tema de la conversación para crear la nota
- "No, dije mañana, no pasado mañana" → la IA corrige comprendiendo la referencia temporal
Esta es la diferencia entre un formulario vocal (repetir todo cada vez) y un asistente que escucha y recuerda. Esto es lo que hace que el Dictáfono de TAMSIV sea utilizable a diario.
¿Cómo influye el system prompt en la calidad de las respuestas?
El system prompt es el documento más importante de la aplicación. Es el que define el comportamiento de la IA: tono, formato de respuesta, herramientas de función disponibles, restricciones.
El system prompt de TAMSIV incluye:
- La persona: "Eres el asistente de voz de TAMSIV, una aplicación de gestión de tareas y notas."
- Las function tools: las 7 funciones que la IA puede llamar (
create_task,update_task,create_memo,update_memo,create_calendar_event,ask_clarification,end_conversation) - Las restricciones: respuestas cortas (el usuario escucha a través de TTS), sin markdown, sin listas largas
- El contexto del usuario: el idioma preferido, la zona horaria, el plan (Free/Pro/Team)
Un system prompt bien diseñado reduce drásticamente las alucinaciones y las respuestas fuera de tema. Es una inversión que se refleja en cada conversación.
¿Cómo gestionar las conversaciones multimodales (voz + texto)?
En TAMSIV, el usuario habla pero la IA responde con voz (a través de OpenAI TTS) Y con texto (mostrado en pantalla). El historial almacena ambas formas:
- Lado del usuario: el texto transcrito por el STT (no el audio bruto — demasiado pesado en tokens)
- Lado de la IA: el texto de la respuesta (enviado al TTS y mostrado)
El pipeline completo es: Audio → STT → Texto → LLM (con historial) → Texto → TTS → Audio. El historial solo vive en la capa de texto, lo que simplifica enormemente la arquitectura.
¿Qué alternativas a la ventana deslizante existen?
La ventana deslizante no es el único enfoque. Existen otras estrategias:
- Summarization: resumir los intercambios antiguos en un párrafo condensado. Ventaja: máxima compresión. Inconveniente: pérdida de detalles y una llamada LLM adicional para el resumen.
- RAG (Retrieval Augmented Generation): almacenar el historial en una base vectorial y recuperar solo los intercambios relevantes por similitud semántica. Potente pero pesado de implementar.
- Memoria explícita: almacenar "hechos" extraídos de las conversaciones (preferencias del usuario, tareas recurrentes) en una base estructurada. Esto es lo que hace ChatGPT con su función "Memory".
Para TAMSIV, la ventana deslizante con prioridades es el mejor compromiso: simple de implementar, eficiente en tokens y suficiente para conversaciones de 5 a 15 intercambios. Si las conversaciones fueran mucho más largas, consideraría el RAG.
¿Cómo implementar un historial de conversación en tu propio proyecto?
Si estás construyendo una aplicación con un LLM, aquí tienes los pasos:
- Almacena el historial en el servidor: nunca confíes en el cliente para mantener el estado de la conversación. El backend es la fuente de la verdad.
- Implementa una ventana deslizante: comienza de forma sencilla (mantener los N últimos intercambios), luego añade prioridades si es necesario.
- Presupuesta los tokens: cuenta los tokens antes de cada llamada. Trunca inteligentemente si se excede el presupuesto.
- Añade un fallback: como mínimo, un modelo de respaldo en caso de error del modelo principal.
- Mide los costos: registra cada llamada con el número de tokens utilizados. Esto permite optimizar el sistema a largo plazo.
El panel de administración de TAMSIV muestra las métricas de conversación en tiempo real: número promedio de intercambios, costo promedio por conversación, tasa de fallback. Estos datos son esenciales para optimizar los costos en producción.
Preguntas Frecuentes
¿Cuántos intercambios realiza un usuario promedio por conversación?
En TAMSIV, el promedio es de 3 a 5 intercambios. El usuario típico dice "Añade una tarea para mañana: llamar al dentista", confirma la vista previa y continúa con una modificación ("Ponla en prioridad alta"). Las conversaciones largas (más de 10 intercambios) representan menos del 10% del volumen.
¿El costo del historial de conversación es significativo?
Sí, es el principal gasto del pipeline de IA. Cada intercambio adicional aumenta el costo acumulado. Para TAMSIV, el costo promedio por conversación es de aproximadamente 0.01 a 0.03 EUR con el modelo principal. El modelo de fallback suele ser más barato, lo que compensa parcialmente los sobrecostos.
¿Es necesario almacenar el historial en la base de datos?
Para TAMSIV, el historial vive en memoria (lado del backend) durante la sesión WebSocket. No se persiste en la base de datos — cuando la conexión se cierra, el historial se pierde. Es una elección deliberada: las conversaciones son cortas y transitorias. Si necesitas retomar conversaciones más tarde, será necesario persistir en la base de datos.
¿OpenRouter vs llamar directamente a las APIs de los proveedores de LLM?
OpenRouter actúa como un proxy que unifica el acceso a decenas de modelos (OpenAI, Anthropic, Google, etc.) a través de una única API. La ventaja: cambiar de modelo sin modificar el código. El inconveniente: una capa adicional (latencia marginal). Para una aplicación como TAMSIV que necesita flexibilidad y fallback, es una elección obvia.
¿La memoria de conversación funciona con el modo Realtime?
TAMSIV tiene tres modos WebSocket. En modo LiveWebSocket (el modo predeterminado), el historial se gestiona manualmente como se describe en este artículo. En modo Realtime (OpenAI Realtime API), el historial se gestiona de forma nativa por la API — es un protocolo bidireccional con estado. El modo legacy funciona en batch sin persistencia.