Contenido del curso

Introducción a LangChain

Chats y memoria con LangChain

Memoria conversacional con ConversationalRetrievalChain

Resumen

Construir un chatbot que recuerde lo que conversaste cambia por completo la experiencia de usuario. Aquí aprenderás cómo agregar memoria a un chatbot con LangChain usando ConversationalRetrievalChain, partiendo de un proyecto que ya consulta la documentación de Hugging Face y transformándolo en un asistente conversacional con historial.

Por qué tu chatbot necesita memoria conversacional

Un chatbot sin memoria responde cada pregunta como si fuera la primera. Eso rompe la experiencia cuando el usuario quiere profundizar o pedir aclaraciones.

Al agregar un historial, el modelo recibe tres fuentes de información en cada turno: la pregunta nueva, los fragmentos recuperados de la base vectorial y la conversación previa. Con eso entiende referencias como "¿cómo los podría cargar y usar?" sin necesidad de repetir contexto.

¿Qué es ConversationalRetrievalChain? Es una cadena de LangChain que combina recuperación desde una base vectorial con historial de conversación. A diferencia de RetrievalQA, mantiene contexto entre preguntas para responder de forma coherente.

Cómo configurar el modo memory chat en run conversation

Dentro del archivo conversation-ai.py, la función run_conversation ya manejaba un modo QA. Para sumar memoria, agregas una rama nueva cuando el tipo de chat sea memory_chat [01:05].

El flujo queda así:

  • Detectar si chat_type es memory_chat e imprimir el mensaje informativo en consola.
  • Inicializar chat_history como una lista vacía antes del ciclo de conversación.
  • Llamar a process_memory_query en lugar de process_qa_query, pasando el query, el retriever, el modelo de lenguaje y el historial.

Esa lista vacía es la clave: va a ir creciendo con cada interacción y se inyecta a la cadena en cada turno.

Qué cambia entre process QA query y process memory query

La función process_memory_query parte de la misma estructura que process_qa_query, pero con tres diferencias importantes [03:15]:

  1. Recibe un parámetro adicional: chat_history.
  2. Importa y usa ConversationalRetrievalChain en lugar de RetrievalQA.
  3. La cadena se construye desde el modelo de lenguaje, no desde el tipo de cadena.

La instancia se crea con ConversationalRetrievalChain.from_llm, recibiendo el modelo de chat de OpenAI, el retriever y verbose=True para ver qué está ocurriendo internamente. El historial no se pasa al construir la cadena, se inyecta cuando la invocas.

Cómo se alimenta el historial del chat en cada turno

Al invocar la cadena, le pasas un diccionario con dos claves: question con el query del usuario y chat_history con la lista de mensajes previos. El resultado contiene la respuesta en result["answer"].

Después de cada respuesta, agregas la tupla pregunta y respuesta al historial con chat_history.append((query, result["answer"])) [05:42]. Así, en el siguiente turno, el modelo ya cuenta con todo el contexto previo.

Para depurar, conviene imprimir el historial antes de cada respuesta. En la primera pregunta verás que la historia está vacía. En la segunda, ya aparece la pregunta inicial junto con la respuesta del modelo, y así sucesivamente.

¿Para qué sirve verbose=True en LangChain? Activa la salida detallada de la cadena, mostrando el prompt completo que recibe el modelo, los fragmentos recuperados y los pasos intermedios. Es la forma más directa de debuguear qué está pasando.

Qué pasa cuando el prompt se satura con memoria buffer

Lo que estás haciendo manualmente con la lista equivale a un ConversationBufferMemory: guardas todo, sin filtrar. El problema aparece alrededor de la pregunta número ocho o nueve, cuando el prompt se llena tanto que el modelo colapsa [08:30].

Aquí entra un reto interesante: usar una cadena de sumarización para resumir las interacciones más antiguas. Una estrategia razonable es mantener las últimas dos preguntas intactas y resumir las anteriores en un bloque corto. Así controlas el tamaño del prompt sin perder contexto relevante.

Cómo correr el proyecto con Poetry, Black e isort

Antes de ejecutar, vale la pena dejar el código limpio:

  • black para formatear conversation-ai.py con un estilo consistente.
  • isort para ordenar las importaciones.
  • poetry run python hashira para correr el script principal del proyecto.

Al iniciar verás que carga el Chroma existente (la misma base vectorial), reutiliza el retriever y el modelo de chat de OpenAI, y confirma el modo memoria activado.

Al preguntar "¿qué modelos transformer me recomiendas para generación de texto?", responde con opciones como GPT-2. Si luego preguntas "¿cómo los podría cargar y usar?", entiende la referencia y explica métodos como from_pretrained, save_pretrained y push_to_hub, numerando los pasos.

Qué sigue después de tener tu chatbot con memoria

El proyecto base ya funciona, pero hay caminos para llevarlo más lejos:

  • Agregar un front-end con Streamlit o Gradio.
  • Ponerlo en producción para que varias personas lo usen al mismo tiempo.
  • Usar los callbacks de LangChain para monitoreo y trazabilidad.
  • Implementar la sumarización progresiva del historial para evitar el colapso del prompt.

¿Cuál de estos pasos vas a probar primero? Cuéntame en los comentarios qué tipo de memoria te interesa implementar en tu propio proyecto.