====== 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 tiktoken # 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({})) {{gallery>:inteligencia_artificial}} ===== 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({}))