Construir un chatbot que recuerde quién eres y qué dijiste antes no es magia: es memoria conversacional, y LangChain ofrece herramientas concretas para implementarla con modelos como GPT-3.5 Turbo. Aquí se desglosa paso a paso cómo pasar de un modelo sin contexto a un asistente que mantiene historial por usuario y responde en tiempo real.
¿Por qué un modelo de lenguaje no recuerda por defecto?
Cuando invocamos un modelo como GPT-3.5 Turbo con un solo human message —por ejemplo, "Hi, my name is Bob"— el modelo responde amablemente [01:25]. Sin embargo, si en una segunda llamada independiente le preguntamos cuál es nuestro nombre, se disculpa y dice que no tiene acceso a información personal [02:05]. Esto ocurre porque cada invocación es sin estado: el modelo no conserva datos entre peticiones.
Este comportamiento demuestra que, para sostener una conversación coherente, necesitamos inyectar explícitamente el historial de mensajes.
¿Cómo simular memoria con una lista de mensajes?
Una solución inicial es enviar al modelo una lista completa de la interacción previa. LangChain permite importar tres tipos de objetos clave:
- HumanMessage: representa lo que dice el usuario.
- AIMessage: representa la respuesta del asistente.
- Una segunda HumanMessage con la pregunta de seguimiento.
Al pasar esta lista al método invoke [02:30], el modelo ya puede responder correctamente: "Tu nombre es Bob". Estamos construyendo un historial manual que le da contexto al modelo antes de cada respuesta.
¿Qué herramientas de LangChain automatizan el historial?
Mandar listas a mano se vuelve impráctico rápidamente. LangChain resuelve esto con módulos específicos del paquete langchain_core [03:25]:
- BaseChatMessageHistory: clase base para construir la función que genera y almacena el historial.
- InMemoryChatMessageHistory: implementación que guarda los mensajes en memoria RAM.
- RunnableWithMessageHistory: envuelve al modelo para que automáticamente acceda al historial antes de cada invocación.
¿Cómo funciona el session ID?
El concepto de session ID es fundamental [03:55]. Cada conversación se identifica con un identificador único —puede ser un string como "abc1" o "abc3"—. La función get_session_history recibe este session ID y busca en un diccionario (store) si ya existe historial para esa sesión. Si no existe, crea una nueva instancia de InMemoryChatMessageHistory y la almacena.
python
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = InMemoryChatMessageHistory()
return store[session_id]
Esta función se conecta con el modelo a través de RunnableWithMessageHistory, que recibe el modelo y la referencia a get_session_history [04:50].
¿Cómo se gestiona la memoria con múltiples usuarios?
Una vez configurado, cada invocación requiere un diccionario de configuración con el session ID correspondiente [05:15]. Al enviar "Hola, soy Bob" bajo el session ID "abc1" y luego preguntar el nombre, el modelo responde correctamente porque todo queda almacenado en store.
Para verificar la persistencia, basta con inspeccionar store [06:40]. Ahí aparecen:
- El session ID asociado.
- La secuencia de human messages y respuestas del modelo.
- Cada nueva interacción (como "How are you?") se añade al final del historial.
¿Qué pasa al crear un nuevo session ID?
Al crear "abc3" y preguntar directamente "¿Cuál es mi nombre?", el modelo indica que no puede saberlo [07:35]. Es una sesión vacía, sin historial previo. Pero al decirle "Mi nombre es Carly" y repetir la pregunta, responde correctamente: "Tu nombre es Carly" [08:10].
Lo más importante: al revisar store, ambas sesiones coexisten. La conversación de Bob bajo "abc1" permanece intacta mientras Carly opera bajo "abc3" [08:30]. Así se logra:
- Aislamiento por usuario: cada session ID tiene su propio historial.
- Persistencia en memoria: la información no se pierde entre llamadas mientras la aplicación esté activa.
- Escalabilidad conceptual: aunque aquí se usa un diccionario en RAM, el patrón se extiende a bases de datos reales.
El streaming de respuestas complementa esta arquitectura al mostrar los tokens a medida que el modelo los genera, creando una experiencia más fluida y rápida para el usuario final.
¿En qué proyecto aplicarías un asistente con memoria conversacional? Comparte tu idea en los comentarios.