¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Memoria
El modo en que se gestiona la memoria en este apartado a través de langchain, está obsoleto Deprecated.
Se debe de hacer a través de LangGraph, pero como esto escapa al objetivo actual (aprender a manejar langchain), se hará de este modo.
Si a un modelo le hacemos varias consultas seguidas, al responder cada una, no recuerda qué respondió las anteriores, por lo que es complicado realizar con él una conversación coherente.
from langchain_ollama import ChatOllama chat = ChatOllama( model = "llama3.2", temperature = 0.0, verbose = False ) respuesta = chat.invoke("Hola, soy Alberto") print(respuesta.content) respuesta = chat.invoke("¿Sabes cómo me llamo?") print(respuesta.content)
Buffer de conversación
Cuando instanciamos la clase ConversationBufferMemory, en ésta se guarda todo el historial de conversación.
Si le pasamos esta información con una plantilla de prompt en cada iteración, le estaremos proporcionando al modelo una memoria a corto plazo a costa de una gran cantidad de tokens.
from langchain_ollama import ChatOllama from langchain.memory import ConversationBufferMemory from langchain.chains.llm import LLMChain from langchain.prompts import PromptTemplate chat = ChatOllama( model = "llama3.2", temperature = 0.0, verbose = False ) # Definimos el prompt con una plantilla, en el prompt especificaremos el historial # de la conversación (transcripción) que pasaremos en cada nueva llamada prompt = PromptTemplate( input_variables=["historial", "input"], template="{historial}\nUser: {input}\nAssistant:", ) # Creamos la memoria de la conversación memoria = ConversationBufferMemory(memory_key="historial", return_messages=True) # Cadena LLMChain con el modelo, el prompt y la memoria, hay que hacerlo así chat_chain = LLMChain( llm = chat, prompt=prompt, memory=memoria, verbose=False ) # Obtenemos las respuestas del modelo respuesta = chat_chain.invoke("Hola, soy Alberto") #print(respuesta) respuesta = chat_chain.invoke("¿Cuánto es 1+1?") #print(respuesta) respuesta = chat_chain.invoke("¿Cómo me llamo?") #print(respuesta) # Podemos añadir contexto a la memoria memoria.save_context( {"input":"Hola"}, {"output":"Qué pasa"} ) # Muestro la conversación completa print(memoria.buffer_as_str)
Ventana del Buffer de conversación
Podemos seleccionar el número de interacciones (pregunta-respuesta) que queremos que el modelo “recuerde” en el buffer instanciando la clase ConversationBufferWindowMemory.
from langchain.memory import ConversationBufferWindowMemory # Instanciamos la memoria con una ventana de contexto de 2 iteraciones: de las tres que hay, no recordará la primera memoria = ConversationBufferWindowMemory(k = 2) # En lugar de preguntar a un modelo, le introducimos las interacciones directamente en memoria memoria.save_context( {"input":"Hola"}, {"output":"Cómo lo llevas"} ) memoria.save_context( {"input":"Colgando, ligeramente a la izquierda"}, {"output":"Eso está bien"} ) memoria.save_context( {"input":"Qué hay de tu vida"}, {"output":"Sobreviviendo, cuando me dejan"} ) print(memoria.load_memory_variables({}))
Ventana de tokens del buffer de conversación
Del mismo modo que hicimos anteriormente, podemos limitar la cantidad de información que recuerda el modelo, pero limitando el número de tokens.
De esta manera se recordarán los últimos tokens en el número definido en la clase ConversationTokenBufferMemory
# CUARTO EJEMPLO: Definimos el número máximo de tokens a recordar # Se necesita instalar el módulo "tiktoken": pip install tiktokenpip # Tembién he tenido que instalar el módulo "transformers": pip install transformers from langchain.memory import ConversationTokenBufferMemory from langchain_ollama import ChatOllama chat = ChatOllama( model = "llama3.2", temperature = 0.0, verbose = False ) # Definimos la memoria, indicando el modelo y el número máximo de tokens a recordar memoria = ConversationTokenBufferMemory(llm=chat, max_token_limit=25) memoria.save_context ( {"input":"¿Qué es la IA?"}, {"output":"¡La IA mola!"} ) memoria.save_context ( {"input":"¿Tiene memoria?"}, {"output":"En eso estamos..."} ) memoria.save_context ( {"input":"¿Recordarás?"}, {"output":"Si no se me olvida"} ) print(memoria.load_memory_variables({}))
Resumen de conversación
Con el fin de “gastar” menos tokens evitando “arrastrar” toda la conversación de una interacción a otra con el modelo, la clase ConversationSummaryBufferMemory nos permite guardar en un buffer un resumen de la conversación, cuyo tamaño en tokens podemos especificar.
from langchain_ollama import ChatOllama from langchain.memory import ConversationSummaryBufferMemory from langchain.chains.llm import LLMChain from langchain.prompts import PromptTemplate # Definimos el chat del modelo chat = ChatOllama( model = "llama3.2", temperature = 0.0, verbose = False # Podemos añadir como parámetro 'num_ctx' para cambiar el nº de tokens de contexto, por defecto 2048. El modelo Llama 3.2 de 3B (3 mil millones de parámetros), tiene una ventana total de 128k. ) # Texto con el que vamos a trabajar with open('articulo_eureka_pequeño.txt', 'r') as articulo: texto = articulo.read() # Definimos la memoria memoria = ConversationSummaryBufferMemory(llm=chat, max_token_limit=100) # Si no se especifica max_token_limit, éste es de 2000 # Añadimos contexto a la conversación, incluído el artículo a resumir memoria.save_context ( {"input":"Hola, cómo estás"}, {"output":"Bien, gracias"} ) memoria.save_context ( {"input":"Me gustan las cosas del espacio:"}, {"output":"También a mí"} ) memoria.save_context ( {"input":"Podrías darme el contenido del artículo del blog 'Eureka':"}, {"output":f"{texto}"} ) #print(memoria.load_memory_variables({})) #print("---") # Creamos el prompt sólo con la entrada prompt = PromptTemplate( input_variables=["input"], template="{input}" ) # Cadena (chain) de conversación conversacion = LLMChain( llm = chat, prompt = prompt, memory=memoria, verbose=True ) respuesta = conversacion.invoke("¿Qué problema producen las megaconstelaciones de satélites?") print(respuesta) #print("---") #print(memoria.load_memory_variables({}))
