Menu iconMenu icon
OpenAI API Biblia Volumen 1

Capítulo 7: Memoria y Conversaciones de Varios Turnos

7.1 Memoria a Corto vs Largo Plazo

El Capítulo 7 explora los aspectos críticos de la gestión del historial de conversaciones y el contexto en aplicaciones de IA, centrándose particularmente en cómo los sistemas de memoria impactan la efectividad de las interacciones de múltiples turnos. A medida que los asistentes de IA se vuelven cada vez más sofisticados, entender cómo implementar y gestionar adecuadamente la memoria conversacional se vuelve esencial para los desarrolladores que construyen aplicaciones robustas de IA.

Este capítulo te guiará a través de varios enfoques para manejar el historial de conversaciones, desde la gestión básica del contexto hasta técnicas avanzadas para mantener interacciones a largo plazo con el usuario. Exploraremos las diferencias entre los sistemas de memoria a corto y largo plazo, discutiremos implementaciones prácticas de gestión de hilos, y examinaremos estrategias para manejar las limitaciones de contexto.

Profundicemos en los cinco temas críticos que exploraremos en este capítulo:

  • Memoria a Corto vs Largo Plazo: Este concepto fundamental explora cómo los sistemas de IA manejan las conversaciones inmediatas versus el almacenamiento de información para uso futuro. Examinaremos cómo la memoria a corto plazo gestiona el contexto y las respuestas actuales, mientras que la memoria a largo plazo mantiene las preferencias del usuario, las interacciones pasadas y los comportamientos aprendidos a través de múltiples sesiones. Comprender estas diferencias es crucial para construir sistemas efectivos de IA conversacional.
  • Gestión de Hilos y Ventanas de Contexto: Profundizaremos en los aspectos técnicos de la gestión de hilos de conversación, incluyendo cómo organizar y mantener múltiples flujos de conversación simultáneamente. Aprenderás sobre las limitaciones de tokens en diferentes modelos de IA, cómo optimizar las ventanas de contexto para un mejor rendimiento, y técnicas para gestionar conversaciones complejas y ramificadas de manera efectiva.
  • Almacenamiento y Recuperación de Interacciones Pasadas: Esta sección cubre la implementación práctica de sistemas de almacenamiento de conversaciones. Exploraremos varias soluciones de bases de datos, estrategias de caché y mecanismos de recuperación que permiten a los sistemas de IA acceder y utilizar conversaciones históricas. Aprenderás sobre diferentes enfoques para almacenar datos de conversación, desde almacenamiento simple basado en texto hasta sofisticadas bases de datos vectoriales.
  • Soluciones para Límites de Contexto: Abordaremos uno de los desafíos más comunes en las conversaciones de IA: lidiar con las limitaciones de contexto. Descubrirás estrategias innovadoras para gestionar conversaciones largas, incluyendo técnicas como resumen de conversaciones, poda selectiva de contexto y gestión dinámica de contexto. También exploraremos cómo mantener la coherencia de la conversación cuando se trabaja con ventanas de contexto limitadas.
  • Actualizaciones sobre la Función de Memoria de ChatGPT: Los últimos desarrollos en las capacidades de memoria de ChatGPT están transformando cómo abordamos la gestión de conversaciones. Examinaremos las nuevas características, sus aplicaciones prácticas y cómo los desarrolladores pueden aprovechar estas capacidades en sus aplicaciones. Esta sección también cubrirá las mejores prácticas para integrar las funciones de memoria de ChatGPT con sistemas existentes y posibles desarrollos futuros en esta área.

Al final de este capítulo, tendrás una comprensión integral de cómo implementar sistemas de memoria efectivos en tus aplicaciones de IA, permitiendo conversaciones más naturales y conscientes del contexto.

La memoria conversacional es un pilar fundamental en la construcción de aplicaciones de IA efectivas que pueden participar en diálogos naturales y fluidos. Este sistema de memoria permite a la IA mantener conversaciones coherentes mediante la comprensión y referencia a intercambios previos, de manera similar a cómo los humanos recuerdan y construyen sobre partes anteriores de una conversación. Sin esta capacidad, cada respuesta estaría desconectada y contextualmente ciega, llevando a interacciones frustrantes y poco naturales.

El sistema de memoria en la IA conversacional cumple múltiples funciones cruciales. Ayuda a mantener la continuidad del tema, permite la resolución adecuada de referencias (entendiendo pronombres como "eso" o "ellos"), y permite que la IA construya sobre información previamente establecida. Esto crea una interacción más atractiva e inteligente que se siente natural para los usuarios.

La memoria en la IA conversacional puede entenderse a través de dos perspectivas distintas pero complementarias: memoria a corto plazo y memoria a largo plazo. Estos dos tipos de sistemas de memoria trabajan juntos para crear una comprensión integral tanto del contexto inmediato como de las interacciones históricas.

7.1.1 Memoria a Corto Plazo

La memoria a corto plazo es un componente crucial que permite a los modelos de IA mantener el contexto durante las conversaciones en curso. Piensa en ella como un espacio de trabajo temporal donde la IA mantiene un registro de la discusión actual. Cuando interactúas con la API, envías una secuencia de mensajes que incluyen instrucciones del sistema (que establecen el comportamiento de la IA), entradas del usuario (tus preguntas o declaraciones) y respuestas del asistente (las respuestas previas de la IA).

El modelo procesa toda esta información dentro de su ventana de contexto - un espacio significativo que puede manejar hasta 128,000 tokens en modelos avanzados, aproximadamente equivalente al texto de un libro pequeño. Esta extensa ventana de contexto permite a la IA elaborar respuestas que no solo son relevantes para tu pregunta inmediata sino también consistentes con todo el flujo de la conversación.

Características Clave de la Memoria a Corto Plazo:

Ventana de Contexto

La ventana de contexto sirve como la memoria de trabajo de la IA, funcionando como un búfer temporal que procesa y retiene el historial completo de mensajes proporcionado en tu llamada a la API. Esta ventana es esencial para mantener conversaciones coherentes y permitir que la IA entienda y haga referencia a intercambios previos. Aquí hay un desglose detallado:

  1. Tamaño y Capacidad:
  • GPT-3.5: Puede manejar hasta 4,096 tokens
  • GPT-4: Soporta hasta 8,192 tokens
  • Modelos avanzados: Pueden procesar hasta 128,000 tokens
  1. Gestión de Tokens:
    Cuando las conversaciones exceden estos límites, el sistema emplea un enfoque de "ventana deslizante", eliminando automáticamente mensajes más antiguos para acomodar los nuevos. Este proceso es similar a cómo los humanos naturalmente olvidan detalles específicos de conversaciones anteriores mientras retienen los temas y conceptos principales.

Por ejemplo:

Usuario: "¿Qué tiempo hace?"

Asistente: "Está soleado y hace 75°F."

Usuario: "¿Debería llevar una chaqueta?"

Asistente: "Dada la temperatura cálida que mencioné (75°F), probablemente no necesitarás una chaqueta."

Aquí te mostramos cómo podemos implementar una conversación básica sobre el clima que demuestra la memoria a corto plazo:

import openai
import os
from dotenv import load_dotenv

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

# Initialize conversation history
conversation = [
    {"role": "system", "content": "You are a helpful weather assistant."}
]

def get_response(message):
    # Add user message to conversation history
    conversation.append({"role": "user", "content": message})
    
    # Get response from API
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation,
        temperature=0.7
    )
    
    # Extract and store assistant's response
    assistant_response = response.choices[0].message['content']
    conversation.append({"role": "assistant", "content": assistant_response})
    
    return assistant_response

# Example conversation
print("User: What's the weather like?")
print("Assistant:", get_response("What's the weather like?"))

print("\nUser: Should I bring a jacket?")
print("Assistant:", get_response("Should I bring a jacket?"))

Analicemos cómo este código demuestra la memoria a corto plazo:

  • La lista de conversación mantiene todo el historial del chat
  • Cada nuevo mensaje (tanto del usuario como del asistente) se agrega a este historial
  • Al realizar nuevas llamadas a la API, se envía el contexto completo de la conversación
  • Esto permite que el asistente haga referencia a información previa (como la temperatura) en respuestas subsiguientes

Cuando ejecutes este código, el asistente mantendrá el contexto durante toda la conversación, tal como en nuestro ejemplo donde recordó la temperatura al responder sobre la chaqueta.

En esta interacción, la ventana de contexto mantiene la información de temperatura del primer intercambio, permitiendo que el asistente haga una recomendación relevante en su segunda respuesta. Sin embargo, si esta conversación continuara por cientos de mensajes, los detalles más antiguos eventualmente se recortarían para dar espacio a nueva información.

Gestión de Memoria Específica de Sesión:

La memoria a corto plazo opera dentro de los límites de una única sesión de conversación, similar a cómo funciona la memoria a corto plazo humana durante una discusión específica. Esto significa que la IA mantiene el contexto y recuerda detalles solo dentro del hilo de conversación actual. Analicemos esto con algunos ejemplos:

Durante una sesión:
Usuario: "Mi nombre es Sarah."
Asistente: "¡Encantado de conocerte, Sarah!"
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para ti, Sarah?"

En este caso, el asistente recuerda el nombre del usuario durante toda la conversación. Sin embargo, cuando inicias una nueva sesión:

Nueva sesión:
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para tu ubicación?"

Observa cómo el asistente ya no recuerda el nombre del usuario de la sesión anterior. Esto se debe a que cada nueva sesión comienza con una pizarra limpia. Sin embargo, hay varias formas de mantener la continuidad entre sesiones:

  1. Inyección Explícita de Contexto: Puedes incluir manualmente información importante de sesiones anteriores en tu mensaje inicial o del sistema.
  2. Integración de Base de Datos: Almacenar información clave del usuario y preferencias en una base de datos y recuperarlas al inicio de cada sesión.
  3. Resumen de Sesión: Crear un breve resumen de interacciones previas para incluir en nuevas sesiones cuando sea relevante.

Por ejemplo, para mantener el contexto entre sesiones, podrías comenzar una nueva sesión con:
Sistema: "Esta usuaria es Sarah, quien previamente mostró interés en actualizaciones del tiempo y habla español."

Aquí está el ejemplo de código:

import openai
from datetime import datetime
import sqlite3

class UserSessionManager:
    def __init__(self):
        # Initialize database connection
        self.conn = sqlite3.connect('user_sessions.db')
        self.create_tables()
        
    def create_tables(self):
        cursor = self.conn.cursor()
        # Create tables for user info and session history
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                user_id TEXT PRIMARY KEY,
                name TEXT,
                preferences TEXT
            )
        ''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS sessions (
                session_id TEXT PRIMARY KEY,
                user_id TEXT,
                timestamp DATETIME,
                context TEXT
            )
        ''')
        self.conn.commit()

    def start_new_session(self, user_id):
        # Retrieve user information from database
        cursor = self.conn.cursor()
        cursor.execute('SELECT name, preferences FROM users WHERE user_id = ?', (user_id,))
        user_data = cursor.execute.fetchone()
        
        if user_data:
            name, preferences = user_data
            # Create system message with user context
            system_message = f"This user is {name}. {preferences}"
        else:
            system_message = "You are a helpful assistant."
            
        return [{"role": "system", "content": system_message}]

    def save_user_info(self, user_id, name, preferences):
        cursor = self.conn.cursor()
        cursor.execute('''
            INSERT OR REPLACE INTO users (user_id, name, preferences) 
            VALUES (?, ?, ?)
        ''', (user_id, name, preferences))
        self.conn.commit()

# Example usage
def demonstrate_session_memory():
    session_manager = UserSessionManager()
    
    # First session - Save user information
    session_manager.save_user_info(
        "user123",
        "Sarah",
        "previously expressed interest in weather updates and speaks Spanish"
    )
    
    # Start a new session with context
    conversation = session_manager.start_new_session("user123")
    
    # Make API call with context
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation + [
            {"role": "user", "content": "What's the weather like?"}
        ]
    )
    
    return response

# Run demonstration
if __name__ == "__main__":
    response = demonstrate_session_memory()
    print("Assistant's response with context:", response.choices[0].message['content'])

Desglose del Código:

  • La clase UserSessionManager maneja todas las operaciones relacionadas con la sesión:
    • Inicializa la conexión a la base de datos SQLite para almacenamiento persistente
    • Crea tablas para almacenar información del usuario e historial de sesiones
    • Proporciona métodos para gestionar datos de usuario y sesiones
  • Componentes Principales:
    • create_tables(): Configura el esquema de la base de datos para almacenar datos de usuario e historial de sesiones
    • save_user_info(): Almacena o actualiza la información del usuario en la base de datos
    • start_new_session(): Recupera el contexto del usuario y crea una nueva sesión de conversación
  • La demostración muestra cómo:
    • Guardar información del usuario (nombre, preferencias) en la base de datos
    • Iniciar una nueva sesión que incluye el contexto del usuario
    • Realizar llamadas a la API con el contexto mantenido

Esta implementación permite que el asistente mantenga el contexto del usuario a través de diferentes sesiones, abordando las limitaciones de memoria discutidas en el ejemplo anterior. Cuando Sarah inicia una nueva sesión, el asistente ya conocerá su nombre y preferencias, lo que lleva a interacciones más personalizadas.

Este enfoque te permite transferir selectivamente información importante mientras mantienes la eficiencia de la gestión de memoria específica de sesión.

Actualizaciones Dinámicas y Refinamiento Continuo del Contexto:

La conversación evoluciona naturalmente a medida que se agregan nuevos mensajes al contexto, creando un diálogo fluido y adaptativo. Esta naturaleza dinámica permite que la IA refine continuamente su comprensión y respuestas basándose en la información más reciente, similar a cómo los humanos procesan e incorporan nuevos detalles durante una conversación. El modelo puede:

  • Hacer referencia a puntos anteriores en la conversación con precisión
  • Mantener consistencia a través de múltiples intercambios
  • Construir sobre conceptos previamente establecidos
  • Ajustar sus respuestas basándose en el nuevo contexto

Por ejemplo, considera este flujo de conversación:

Usuario: "Estoy planeando un viaje a Japón."

Asistente: "¡Qué emocionante! ¿Cuándo planeas visitar?"

Usuario: "En abril del próximo año."

Asistente: "¡Abril es perfecto para la temporada de flores de cerezo en Japón! ¿Te gustaría algunas recomendaciones específicas basadas en esta fecha?"

Usuario: "Sí, pero me preocupan las multitudes."

Asistente: "Entiendo tu preocupación sobre las multitudes durante la temporada de flores de cerezo, puedo sugerirte algunos lugares menos turísticos y horarios óptimos para visitar..."

En este intercambio, la IA demuestra actualización dinámica del contexto al:

  • Recordar el plan inicial de viaje
  • Incorporar el momento específico (abril)
  • Conectarlo con información relevante (temporada de flores de cerezo)
  • Adaptar las recomendaciones basándose en la preocupación expresada sobre las multitudes

Aquí hay un ejemplo de código que demuestra este tipo de conversación contextual:

import openai
from datetime import datetime

class TravelAssistant:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a helpful travel assistant specializing in Japan travel advice."}
        ]
        self.user_preferences = {
            "destination": None,
            "travel_date": None,
            "concerns": []
        }

    def update_preferences(self, message):
        # Simple preference extraction logic
        if "Japan" in message:
            self.user_preferences["destination"] = "Japan"
        if "April" in message:
            self.user_preferences["travel_date"] = "April"
        if "crowds" in message.lower():
            self.user_preferences["concerns"].append("crowds")

    def get_contextual_response(self, user_message):
        # Update user preferences based on message
        self.update_preferences(user_message)
        
        # Add user message to conversation history
        self.conversation_history.append({"role": "user", "content": user_message})
        
        # Generate system note with current context
        context_note = self._generate_context_note()
        if context_note:
            self.conversation_history.append({"role": "system", "content": context_note})

        # Get response from API
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=self.conversation_history,
            temperature=0.7
        )

        assistant_response = response.choices[0].message["content"]
        self.conversation_history.append({"role": "assistant", "content": assistant_response})
        return assistant_response

    def _generate_context_note(self):
        context = []
        if self.user_preferences["destination"]:
            context.append(f"User is planning a trip to {self.user_preferences['destination']}")
        if self.user_preferences["travel_date"]:
            context.append(f"Planning to travel in {self.user_preferences['travel_date']}")
        if self.user_preferences["concerns"]:
            context.append(f"Expressed concerns about: {', '.join(self.user_preferences['concerns'])}")
        
        return "; ".join(context) if context else None

# Example usage
def demonstrate_travel_assistant():
    assistant = TravelAssistant()
    
    # Simulate the conversation
    conversation = [
        "I'm planning a trip to Japan.",
        "In April next year.",
        "Yes, but I'm worried about the crowds."
    ]
    
    print("Starting conversation simulation...")
    for message in conversation:
        print(f"\nUser: {message}")
        response = assistant.get_contextual_response(message)
        print(f"Assistant: {response}")
        print(f"Current Context: {assistant._generate_context_note()}")

if __name__ == "__main__":
    demonstrate_travel_assistant()

Desglose del Código:

  • La clase TravelAssistant mantiene dos componentes principales:
    • conversation_history: Almacena el hilo completo de la conversación
    • user_preferences: Rastrea el contexto importante sobre los planes de viaje del usuario
  • Métodos Principales:
    • update_preferences(): Extrae y almacena información relevante de los mensajes del usuario
    • get_contextual_response(): Gestiona el flujo de la conversación y las interacciones con la API
    • _generate_context_note(): Crea resúmenes de contexto a partir de las preferencias almacenadas
  • El código demuestra:
    • Construcción progresiva del contexto conforme se desarrolla la conversación
    • Mantenimiento de las preferencias del usuario a través de múltiples intercambios
    • Inyección dinámica de contexto en la conversación
    • Manejo estructurado del flujo de conversación

Esta implementación muestra cómo mantener el contexto a través de una conversación de múltiples turnos mientras se realiza un seguimiento de las preferencias y preocupaciones específicas del usuario, similar al flujo de conversación demostrado en el ejemplo anterior.

Esta gestión dinámica del contexto asegura que cada respuesta no solo sea relevante a la pregunta inmediata sino que también esté informada por todo el historial de la conversación, creando un diálogo más natural y coherente.

Un Ejemplo Integral: Implementación de Memoria a Corto Plazo en Conversaciones de Múltiples Turnos

A continuación se muestra un ejemplo usando Python para simular una conversación con memoria a corto plazo, que demuestra cómo mantener el contexto durante un diálogo en curso. El historial de conversación se implementa como una lista de mensajes, donde cada mensaje contiene tanto el rol (sistema, usuario o asistente) como el contenido de ese mensaje.

Esta lista se actualiza continuamente y se pasa a cada llamada API subsiguiente, permitiendo que la IA haga referencia y construya sobre intercambios previos. Este enfoque es particularmente útil para mantener conversaciones coherentes donde el contexto de mensajes anteriores influye en las respuestas posteriores. La implementación permite que el asistente recuerde y haga referencia a preguntas, respuestas y detalles importantes previos a lo largo de la conversación:

import openai
import os
from dotenv import load_dotenv
from datetime import datetime
import json

# Load environment variables and configure OpenAI
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

class ConversationManager:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a friendly assistant that helps with technical queries."}
        ]
        self.session_metadata = {
            "start_time": datetime.now(),
            "query_count": 0,
            "topics": set()
        }
    
    def save_conversation(self, filename="conversation_history.json"):
        """Save the current conversation to a JSON file"""
        data = {
            "history": self.conversation_history,
            "metadata": {
                **self.session_metadata,
                "topics": list(self.session_metadata["topics"]),
                "start_time": self.session_metadata["start_time"].isoformat()
            }
        }
        with open(filename, 'w') as f:
            json.dump(data, f, indent=2)
    
    def load_conversation(self, filename="conversation_history.json"):
        """Load a previous conversation from a JSON file"""
        try:
            with open(filename, 'r') as f:
                data = json.load(f)
                self.conversation_history = data["history"]
                self.session_metadata = data["metadata"]
                self.session_metadata["topics"] = set(self.session_metadata["topics"])
                self.session_metadata["start_time"] = datetime.fromisoformat(
                    self.session_metadata["start_time"]
                )
            return True
        except FileNotFoundError:
            return False

    def ask_question(self, question, topic=None):
        """Ask a question and maintain conversation context"""
        # Update metadata
        self.session_metadata["query_count"] += 1
        if topic:
            self.session_metadata["topics"].add(topic)

        # Append the user's question
        self.conversation_history.append({"role": "user", "content": question})

        try:
            # Make the API call with current conversation history
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=self.conversation_history,
                max_tokens=150,
                temperature=0.7,
                presence_penalty=0.6  # Encourage more diverse responses
            )

            # Extract and store the assistant's reply
            answer = response["choices"][0]["message"]["content"]
            self.conversation_history.append({"role": "assistant", "content": answer})
            
            return answer

        except Exception as e:
            error_msg = f"Error during API call: {str(e)}"
            print(error_msg)
            return error_msg

    def get_conversation_summary(self):
        """Return a summary of the conversation session"""
        return {
            "Duration": datetime.now() - self.session_metadata["start_time"],
            "Total Questions": self.session_metadata["query_count"],
            "Topics Covered": list(self.session_metadata["topics"]),
            "Message Count": len(self.conversation_history)
        }

def demonstrate_conversation():
    # Initialize the conversation manager
    manager = ConversationManager()
    
    # Example multi-turn conversation
    questions = [
        ("What is a variable in Python?", "python_basics"),
        ("Can you give an example of declaring one?", "python_basics"),
        ("How do I use variables in a function?", "python_functions")
    ]
    
    # Run through the conversation
    for question, topic in questions:
        print(f"\nUser: {question}")
        response = manager.ask_question(question, topic)
        print(f"Assistant: {response}")
    
    # Save the conversation
    manager.save_conversation()
    
    # Print conversation summary
    print("\nConversation Summary:")
    for key, value in manager.get_conversation_summary().items():
        print(f"{key}: {value}")

if __name__ == "__main__":
    demonstrate_conversation()

Desglose y Explicación del Código:

  1. Estructura de Clase e Inicialización
    • La clase ConversationManager proporciona una forma estructurada de manejar conversaciones
    • Mantiene tanto el historial de conversación como los metadatos de sesión
    • Utiliza un mensaje del sistema para establecer el rol del asistente
  2. Funciones de Almacenamiento Persistente
    • save_conversation(): Exporta el historial de conversación y metadatos a JSON
    • load_conversation(): Restaura conversaciones previas desde archivos guardados
    • Maneja automáticamente la serialización/deserialización de fechas y horas
  3. Manejo Mejorado de Preguntas
    • Rastrea temas de conversación y contador de consultas
    • Incluye manejo de errores para llamadas a la API
    • Utiliza presence_penalty para fomentar respuestas diversas
  4. Metadatos y Análisis
    • Rastrea la duración de la sesión
    • Mantiene un conjunto de temas de conversación
    • Proporciona resúmenes detallados de la conversación
  5. Mejoras Clave Sobre la Versión Básica
    • Agregado manejo de errores y registro apropiado
    • Implementada persistencia de conversación
    • Incluidos análisis y metadatos de sesión
    • Mejorada modularidad y organización del código

Este ejemplo proporciona una base robusta para construir aplicaciones conversacionales, con características de persistencia, manejo de errores y análisis que serían valiosas en un entorno de producción.

En este ejemplo, el historial de conversación (memoria a corto plazo) se actualiza continuamente con cada interacción, permitiendo que el asistente haga referencia a mensajes anteriores según sea necesario.

7.1.2 Memoria a Largo Plazo

Mientras que la memoria a corto plazo es inherente en cada llamada a la API, la memoria a largo plazo en la IA conversacional representa un enfoque más sofisticado para mantener el contexto a través de múltiples interacciones. A diferencia de la memoria a corto plazo, que solo retiene información durante una única conversación, la memoria a largo plazo crea un registro persistente de las interacciones del usuario que puede abarcar días, semanas o incluso meses. Esto se logra típicamente almacenando historiales de conversación en bases de datos o sistemas de archivos, que luego pueden ser accedidos de manera inteligente cuando sea necesario.

El proceso funciona primero capturando y almacenando datos relevantes de la conversación, incluyendo preferencias del usuario, detalles importantes y puntos clave de discusión. Cuando un usuario regresa para una nueva sesión, el sistema puede recuperar esta información almacenada e inyectar selectivamente el contexto más relevante en futuros mensajes. Esto crea una experiencia más personalizada y continua, ya que la IA puede hacer referencia a interacciones pasadas y construir sobre el conocimiento previamente establecido.

Por ejemplo, si un usuario discutió sus preferencias dietéticas en una sesión anterior, el sistema puede recordar esta información semanas después al proporcionar recomendaciones de recetas, creando una interacción más natural y contextualmente consciente. Esta capacidad de mantener y utilizar el contexto histórico es esencial para construir sistemas conversacionales verdaderamente inteligentes que puedan proporcionar continuidad y personalización a través de múltiples interacciones.

Características Clave de la Memoria a Largo Plazo:

Persistencia Entre Sesiones:

La memoria a largo plazo implica crear un registro permanente del historial de conversación en bases de datos o sistemas de almacenamiento, formando una base de conocimiento integral para cada interacción del usuario. Este enfoque sofisticado permite que los sistemas de IA mantengan un contexto detallado incluso cuando los usuarios regresan después de períodos prolongados - desde días hasta meses o incluso años.

El sistema logra esto a través de varios mecanismos clave:

  1. Almacenamiento de Conversación: Cada interacción significativa se almacena en bases de datos estructuradas, incluyendo preferencias del usuario, solicitudes específicas y decisiones importantes.
  2. Recuperación de Contexto: Cuando un usuario regresa, el sistema puede acceder y utilizar inteligentemente sus datos históricos para proporcionar respuestas personalizadas.
  3. Reconocimiento de Patrones: Con el tiempo, el sistema aprende los patrones y preferencias del usuario, creando una comprensión más matizada de las necesidades individuales.

Por ejemplo:

  • Un usuario menciona que es alérgico a los frutos secos en enero. Seis meses después, cuando solicita recomendaciones de recetas, el sistema automáticamente filtra las recetas que contienen frutos secos.
  • Durante una conversación de soporte técnico en marzo, un usuario indica que está usando Windows 11. En diciembre, cuando busca ayuda con un nuevo problema, el sistema ya conoce su sistema operativo.
  • Una aplicación de aprendizaje de idiomas recuerda que un usuario tiene dificultades con las conjugaciones en tiempo pasado, incorporando automáticamente más ejercicios de práctica en esta área a través de múltiples sesiones.

Aquí está el código de implementación:

from datetime import datetime
import openai

class LongTermMemorySystem:
    def __init__(self, api_key):
        self.api_key = api_key
        openai.api_key = api_key
        self.preferences = {}
    
    def store_preference(self, user_id, pref_type, pref_value):
        if user_id not in self.preferences:
            self.preferences[user_id] = []
        self.preferences[user_id].append({
            'type': pref_type,
            'value': pref_value,
            'timestamp': datetime.now()
        })

    def get_user_preferences(self, user_id, pref_type=None):
        if user_id not in self.preferences:
            return []
        
        if pref_type:
            relevant_prefs = [p for p in self.preferences[user_id] 
                            if p['type'] == pref_type]
            return [(p['value'],) for p in sorted(relevant_prefs, 
                    key=lambda x: x['timestamp'], reverse=True)]
        
        return [(p['type'], p['value']) for p in self.preferences[user_id]]

    async def get_ai_response(self, prompt, context):
        try:
            response = await openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "You are an AI assistant with access to user preferences."},
                    {"role": "user", "content": f"Context: {context}\nPrompt: {prompt}"}
                ]
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"

# Example usage
async def demonstrate_long_term_memory():
    memory_system = LongTermMemorySystem("your-api-key-here")
    
    # Scenario 1: Food Allergies
    user_id = "user123"
    memory_system.store_preference(user_id, "food_allergy", "nuts")
    
    async def get_recipe_recommendations(user_id):
        allergies = memory_system.get_user_preferences(user_id, "food_allergy")
        context = f"User has allergies: {allergies if allergies else 'None'}"
        prompt = "Recommend safe recipes for this user."
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 2: Technical Support
    memory_system.store_preference(user_id, "operating_system", "Windows 11")
    
    async def provide_tech_support(user_id, issue):
        os = memory_system.get_user_preferences(user_id, "operating_system")
        context = f"User's OS: {os[0][0] if os else 'Unknown'}"
        prompt = f"Help with issue: {issue}"
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 3: Language Learning
    memory_system.store_preference(user_id, "grammar_challenge", "past_tense")
    
    async def generate_language_exercises(user_id):
        challenges = memory_system.get_user_preferences(user_id, "grammar_challenge")
        context = f"User struggles with: {challenges[0][0] if challenges else 'No specific areas'}"
        prompt = "Generate appropriate language exercises."
        return await memory_system.get_ai_response(prompt, context)

    # Demonstrate the system
    print("Recipe Recommendations:", await get_recipe_recommendations(user_id))
    print("Tech Support:", await provide_tech_support(user_id, "printer not working"))
    print("Language Exercises:", await generate_language_exercises(user_id))

if __name__ == "__main__":
    import asyncio
    asyncio.run(demonstrate_long_term_memory())

Este código implementa un sistema de memoria a largo plazo para conversaciones de IA que almacena y gestiona las preferencias del usuario.

Aquí se desglosan sus componentes principales:

  1. Clase LongTermMemorySystem
  • Se inicializa con una clave API para la integración con OpenAI
  • Mantiene un diccionario de preferencias de usuario
  1. Métodos Principales
  • store_preference: Almacena preferencias de usuario con marcas de tiempo
  • get_user_preferences: Recupera preferencias almacenadas, opcionalmente filtradas por tipo
  • get_ai_response: Genera respuestas de IA usando la API de OpenAI con contexto del usuario
  1. Escenarios de Demostración
  • Alergias Alimentarias: Almacena y utiliza información sobre alergias para recomendaciones de recetas
  • Soporte Técnico: Mantiene información del sistema operativo para soporte técnico contextual
  • Aprendizaje de Idiomas: Registra desafíos gramaticales para personalizar ejercicios

El sistema demuestra cómo mantener preferencias persistentes del usuario a través de múltiples sesiones, permitiendo interacciones personalizadas y conscientes del contexto. Utiliza programación asíncrona (async/await) para interacciones eficientes con la API e incluye manejo de errores para una operación robusta.

Esta persistencia asegura que la IA desarrolle una comprensión cada vez más sofisticada de cada usuario con el tiempo, conduciendo a interacciones más personalizadas, relevantes y conscientes del contexto. El sistema esencialmente desarrolla una "memoria" de las preferencias, desafíos e historial de cada usuario, similar a como un humano recordaría detalles importantes sobre amigos o colegas.

Recuperación Selectiva:

En lugar de cargar todo el historial de conversación para cada interacción, los sistemas de memoria a largo plazo utilizan métodos sofisticados de recuperación para acceder eficientemente a la información relevante. Estos sistemas emplean varias técnicas avanzadas:

  • Búsqueda Vectorial
    • Convierte texto en representaciones matemáticas (vectores)
    • Encuentra rápidamente conversaciones con significado semántico similar
    • Ejemplo: Cuando un usuario pregunta sobre "frameworks de aprendizaje automático", el sistema puede encontrar discusiones previas sobre TensorFlow o PyTorch, incluso si no se usaron exactamente esos términos
  • Puntuación de Importancia
    • Clasifica segmentos de conversación basados en relevancia y significancia
    • Considera factores como actualidad, participación del usuario y alineación temática
    • Ejemplo: Una discusión detallada reciente sobre programación tendría mayor prioridad que una mención breve antigua al responder preguntas de código
  • Relevancia Temporal
    • Pondera la información basada en sensibilidad temporal
    • Prioriza conversaciones recientes mientras mantiene acceso a contexto histórico importante
    • Ejemplo: Al discutir preferencias actuales, las conversaciones recientes sobre gustos/disgustos tienen prioridad sobre las más antiguas que podrían estar desactualizadas

Aquí hay un ejemplo de implementación de estos conceptos:

from datetime import datetime
import openai
from typing import List, Dict, Optional

class AdvancedMemoryRetrieval:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.conversations = []
        
    def add_conversation(self, text: str, timestamp: Optional[datetime] = None, engagement_score: float = 0):
        if timestamp is None:
            timestamp = datetime.now()
        
        # Convert text to vector representation using OpenAI
        try:
            response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=text
            )
            vector = response['data'][0]['embedding']
        except Exception as e:
            print(f"Error creating embedding: {e}")
            vector = None
        
        self.conversations.append({
            'text': text,
            'vector': vector,
            'timestamp': timestamp,
            'engagement': engagement_score
        })
    
    def vector_search(self, query: str, top_k: int = 3) -> List[Dict]:
        try:
            query_response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=query
            )
            query_vector = query_response['data'][0]['embedding']
            
            similarities = []
            for conv in self.conversations:
                if conv['vector'] is not None:
                    # Calculate cosine similarity
                    similarity = self._calculate_similarity(query_vector, conv['vector'])
                    similarities.append((conv, similarity))
            
            return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]
        except Exception as e:
            print(f"Error in vector search: {e}")
            return []
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def calculate_importance_score(self, conversation: Dict, query_time: datetime) -> float:
        time_diff = (query_time - conversation['timestamp']).total_seconds()
        recency_score = 1 / (1 + np.log1p(time_diff))
        return 0.7 * recency_score + 0.3 * conversation['engagement']
    
    def retrieve_relevant_context(self, query: str, top_k: int = 3) -> List[Dict]:
        # Get semantically similar conversations
        similar_convs = self.vector_search(query, top_k=top_k*2)
        
        if not similar_convs:
            return []
        
        # Calculate importance scores
        now = datetime.now()
        scored_convs = []
        for conv, similarity in similar_convs:
            importance = self.calculate_importance_score(conv, now)
            final_score = 0.6 * similarity + 0.4 * importance
            scored_convs.append((conv, final_score))
        
        # Get top results
        top_results = sorted(scored_convs, key=lambda x: x[1], reverse=True)[:top_k]
        
        # Use GPT-4o to enhance context understanding
        try:
            contexts = [result[0]['text'] for result in top_results]
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Analyze these conversation snippets and their relevance to the query."},
                    {"role": "user", "content": f"Query: {query}\nContexts: {contexts}"}
                ]
            )
            # Add GPT-4o analysis to results
            for result in top_results:
                result[0]['analysis'] = response.choices[0].message.content
        except Exception as e:
            print(f"Error in GPT analysis: {e}")
        
        return top_results

# Example usage
def demonstrate_retrieval():
    retriever = AdvancedMemoryRetrieval("your-openai-api-key-here")
    
    # Add some sample conversations
    retriever.add_conversation(
        "TensorFlow is great for deep learning projects",
        timestamp=datetime(2025, 1, 1),
        engagement_score=0.8
    )
    retriever.add_conversation(
        "PyTorch provides dynamic computational graphs",
        timestamp=datetime(2025, 3, 1),
        engagement_score=0.9
    )
    
    # Retrieve relevant context
    query = "What are good machine learning frameworks?"
    results = retriever.retrieve_relevant_context(query)
    
    for conv, score in results:
        print(f"Score: {score:.2f}")
        print(f"Text: {conv['text']}")
        if 'analysis' in conv:
            print(f"Analysis: {conv['analysis']}\n")

if __name__ == "__main__":
    demonstrate_retrieval()

Este código implementa un sistema avanzado de recuperación de memoria conversacional.

Aquí se desglosan sus componentes principales:

  1. Estructura de Clase Principal
  • La clase AdvancedMemoryRetrieval gestiona el almacenamiento y recuperación de conversaciones
  • Utiliza la API de OpenAI para crear embeddings de texto y analizar conversaciones
  1. Características Principales
  • Almacenamiento de Conversaciones:
    • Almacena texto, embeddings vectoriales, marcas temporales y puntuaciones de participación
    • Crea representaciones vectoriales de conversaciones usando el modelo de embedding de OpenAI
  • Búsqueda Vectorial:
    • Implementa búsqueda semántica usando similitud del coseno
    • Devuelve las k conversaciones más similares basadas en comparaciones vectoriales
  • Puntuación de Importancia:
    • Combina métricas de actualidad (basadas en tiempo) y participación
    • Utiliza una fórmula ponderada: 70% actualidad + 30% participación
  • Recuperación de Contexto:
    • Combina similitud vectorial (60%) con puntuaciones de importancia (40%)
    • Utiliza GPT-4o para analizar y mejorar la comprensión de los contextos recuperados
  1. Implementación de Ejemplo
  • El código de demostración muestra cómo:
    • Inicializar el sistema con conversaciones de ejemplo sobre frameworks de aprendizaje automático
    • Recuperar contexto relevante basado en una consulta
    • Mostrar resultados con puntuaciones y análisis

Esta implementación muestra técnicas modernas para gestionar el historial de conversaciones, combinando búsqueda semántica, relevancia temporal y métricas de participación para proporcionar respuestas contextualmente apropiadas.

Este enfoque selectivo asegura que las respuestas sean focalizadas y relevantes mientras mantiene la eficiencia computacional. Por ejemplo, en un escenario de soporte técnico, cuando un usuario pregunta sobre la resolución de problemas de una función específica del software, el sistema recuperaría solo las conversaciones previas sobre esa función y mensajes de error relacionados, en lugar de cargar todo su historial de soporte.

Al implementar estos métodos de recuperación, el sistema puede mantener la conciencia contextual de una conversación humana mientras opera dentro de límites computacionales prácticos.

Gestión Personalizada:

Construir una memoria a largo plazo efectiva requiere un diseño de sistema cuidadoso y la consideración de múltiples factores. Exploremos los componentes clave:

1. Arquitectura de Almacenamiento

Las estructuras de almacenamiento eficientes son cruciales para gestionar el historial de conversaciones. Esto puede incluir:

  • Bases de datos distribuidas para escalabilidad
    • Uso de MongoDB para datos de conversación no estructurados
    • Implementación de Redis para interacciones recientes de acceso rápido

2. Mecanismos de Recuperación

Los algoritmos de recuperación inteligente aseguran un acceso rápido a la información relevante:

  • Búsqueda semántica usando embeddings
    • Ejemplo: Convertir "¿Cómo restablezco mi contraseña?" en un vector para encontrar consultas similares anteriores
  • Clasificación contextual
    • Ejemplo: Priorizar conversaciones recientes de soporte técnico cuando el usuario reporta un error

3. Compresión de Datos y Resumen

Métodos para mantener la eficiencia mientras se preserva el significado:

  • Resumen automático de conversaciones
    • Ejemplo: Condensar un hilo de 30 mensajes sobre requisitos de proyecto en puntos clave
  • Técnicas de compresión inteligente
    • Ejemplo: Almacenar patrones comunes como plantillas en lugar de conversaciones completas

4. Gestión de Limitaciones del Sistema

Equilibrar capacidades con recursos:

  • Cuotas de almacenamiento por usuario/conversación
    • Ejemplo: Limitar el almacenamiento a 6 meses de historial de conversación por defecto
  • Asignación de poder de procesamiento
    • Ejemplo: Usar procesamiento por lotes para análisis histórico durante horas valle

5. Privacidad y Seguridad

Consideraciones críticas para el manejo de datos:

  • Cifrado de conversaciones almacenadas
    • Ejemplo: Usar cifrado AES-256 para todos los datos de conversación
  • Gestión del consentimiento del usuario
    • Ejemplo: Permitir que los usuarios opten por no participar en el almacenamiento a largo plazo

6. Ciclo de Vida de la Información

Gestionar datos durante su vida útil:

  • Reglas de archivo automatizado
    • Ejemplo: Mover conversaciones de más de 1 año a almacenamiento frío
  • Políticas de degradación de datos
    • Ejemplo: Eliminar automáticamente información personal después de períodos específicos
  • Evaluación regular de relevancia
    • Ejemplo: Usar métricas de participación para determinar qué información retener

Aquí hay una implementación de código:

import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import openai

class ConversationManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.storage = {}
        self.user_preferences = {}
        
    def summarize_conversation(self, messages: List[Dict]) -> str:
        """Summarize a conversation thread using GPT-4o."""
        try:
            conversation_text = "\n".join([f"{msg['role']}: {msg['content']}" for msg in messages])
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Please summarize this conversation in 3 key points."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            # Fallback to simple summarization if API call fails
            summary = []
            for msg in messages[-3:]:  # Take last 3 messages
                if len(msg['content']) > 100:
                    summary.append(f"Key point: {msg['content'][:100]}...")
                else:
                    summary.append(msg['content'])
            return "\n".join(summary)
    
    def store_conversation(self, user_id: str, conversation: List[Dict]) -> bool:
        """Store conversation with quota and privacy checks."""
        # Check storage quota
        if len(self.storage.get(user_id, [])) >= 1000:  # Example quota
            self._archive_old_conversations(user_id)
            
        # Check user consent
        if not self.user_preferences.get(user_id, {}).get('storage_consent', True):
            return False
            
        # Generate embedding for semantic search
        conversation_text = " ".join(msg['content'] for msg in conversation)
        try:
            embedding = openai.Embedding.create(
                input=conversation_text,
                model="text-embedding-ada-002"
            )
            embedding_vector = embedding['data'][0]['embedding']
        except Exception:
            embedding_vector = None
            
        # Store conversation with summary and embedding
        summary = self.summarize_conversation(conversation)
        if user_id not in self.storage:
            self.storage[user_id] = []
        self.storage[user_id].append({
            'timestamp': datetime.now(),
            'summary': summary,
            'conversation': conversation,
            'embedding': embedding_vector
        })
        return True
    
    def _archive_old_conversations(self, user_id: str) -> None:
        """Archive conversations older than 6 months."""
        cutoff_date = datetime.now() - timedelta(days=180)
        current = self.storage.get(user_id, [])
        self.storage[user_id] = [
            conv for conv in current 
            if conv['timestamp'] > cutoff_date
        ]
    
    def get_relevant_context(self, user_id: str, query: str) -> Optional[str]:
        """Retrieve relevant context using semantic search."""
        if user_id not in self.storage:
            return None
            
        try:
            # Get query embedding
            query_embedding = openai.Embedding.create(
                input=query,
                model="text-embedding-ada-002"
            )
            query_vector = query_embedding['data'][0]['embedding']
            
            # Find most relevant conversations
            relevant_contexts = []
            for conv in self.storage[user_id]:
                if conv['embedding']:
                    relevance_score = self._calculate_similarity(
                        query_vector,
                        conv['embedding']
                    )
                    if relevance_score > 0.7:  # Threshold
                        relevant_contexts.append(conv['summary'])
                        
            return relevant_contexts[0] if relevant_contexts else None
        except Exception:
            # Fallback to simple word matching if embedding fails
            return self._simple_context_search(user_id, query)
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def _simple_context_search(self, user_id: str, query: str) -> Optional[str]:
        """Simple relevance calculation using word overlap."""
        query_words = set(query.lower().split())
        best_score = 0
        best_summary = None
        
        for conv in self.storage[user_id]:
            summary_words = set(conv['summary'].lower().split())
            score = len(query_words & summary_words) / len(query_words)
            if score > best_score:
                best_score = score
                best_summary = conv['summary']
                
        return best_summary if best_score > 0.3 else None

# Example usage
def demonstrate_conversation_management():
    manager = ConversationManager("your-openai-api-key-here")
    
    # Store a conversation
    user_id = "user123"
    conversation = [
        {"role": "user", "content": "How do I implement encryption?"},
        {"role": "assistant", "content": "Here's a detailed guide..."},
        {"role": "user", "content": "Thanks, that helps!"}
    ]
    
    # Set user preferences
    manager.user_preferences[user_id] = {'storage_consent': True}
    
    # Store the conversation
    stored = manager.store_conversation(user_id, conversation)
    print(f"Conversation stored: {stored}")
    
    # Later, retrieve relevant context
    context = manager.get_relevant_context(user_id, "encryption implementation")
    print(f"Retrieved context: {context}")

if __name__ == "__main__":
    demonstrate_conversation_management()

Este código implementa una clase ConversationManager para gestionar conversaciones de IA con memoria y recuperación de contexto.

Aquí están los componentes principales:

Funcionalidad Central:

  • Almacenamiento de Conversaciones:
    • Almacena conversaciones con marcas de tiempo, resúmenes y embeddings
    • Implementa cuotas de almacenamiento y verificaciones de consentimiento del usuario
    • Archiva conversaciones con más de 6 meses de antigüedad
  • Resumen de Conversaciones:
    • Utiliza GPT-4o para crear resúmenes concisos de conversaciones
    • Incluye mecanismo de respaldo cuando fallan las llamadas a la API
    • Almacena resúmenes para una recuperación eficiente
  • Búsqueda Semántica:
    • Genera embeddings usando el modelo de embedding de OpenAI
    • Implementa similitud del coseno para encontrar conversaciones relevantes
    • Incluye respaldo a coincidencia simple de palabras cuando fallan los embeddings

Características Principales:

  • Controles de Privacidad:
    • Verifica el consentimiento del usuario antes de almacenar conversaciones
    • Gestiona preferencias de usuario y consentimiento de almacenamiento
  • Gestión de Memoria:
    • Implementa cuotas de almacenamiento (1000 conversaciones por usuario)
    • Archiva conversaciones antiguas automáticamente
    • Utiliza búsqueda semántica para recuperar contexto relevante

Ejemplo de Uso:

  • El código demuestra:
    • Almacenamiento de una conversación sobre encriptación
    • Configuración de preferencias de usuario
    • Recuperación de contexto relevante basado en consultas

Esta implementación se centra en equilibrar el almacenamiento eficiente de conversaciones con la recuperación inteligente, mientras mantiene la privacidad del usuario y el rendimiento del sistema.

Este ejemplo demuestra la aplicación práctica de los conceptos discutidos anteriormente, incluyendo compresión de datos, limitaciones del sistema, controles de privacidad y gestión del ciclo de vida de la información. El código proporciona una base que puede extenderse con características más sofisticadas como resumen basado en aprendizaje automático o esquemas de encriptación avanzados.

Un Ejemplo Completo: Simulando Memoria a Largo Plazo

Exploremos un ejemplo práctico que demuestra cómo implementar la memoria de conversación en aplicaciones de IA. Este ejemplo muestra dos componentes clave: guardar el historial de conversación para referencia futura y recuperar el contexto relevante al comenzar una nueva sesión de conversación. Para mantener el ejemplo sencillo y enfocarnos en los conceptos principales, usaremos un enfoque simple de almacenamiento en memoria usando una variable, aunque en un entorno de producción típicamente usarías un sistema de base de datos o almacenamiento persistente.

Este ejemplo sirve para ilustrar varios conceptos importantes:

  • Cómo capturar y almacenar historial de conversación significativo
    • La mecánica de guardar información contextual para referencia futura
    • Métodos para recuperar y utilizar contexto previo de conversación
  • Cómo mantener la continuidad de conversación a través de múltiples sesiones
    • Técnicas para integrar contexto pasado en nuevas conversaciones
    • Estrategias para gestionar el estado de la conversación

# Comprehensive example of conversation memory management with OpenAI API

from typing import List, Dict, Optional
import json
from datetime import datetime
import openai
from dataclasses import dataclass
from enum import Enum

class MemoryType(Enum):
    SHORT_TERM = "short_term"
    LONG_TERM = "long_term"
    SEMANTIC = "semantic"

@dataclass
class Message:
    role: str  # system, user, or assistant
    content: str
    timestamp: datetime
    metadata: Dict = None

class ConversationMemoryManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.long_term_memory = []
        self.semantic_memory = {}  # Store embeddings for semantic search
        self.active_conversations = {}
        self.max_memory_size = 1000
        self.model = "gpt-4o"  # OpenAI model to use
        
    def save_conversation(self, conversation_id: str, messages: List[Message]) -> bool:
        """
        Save conversation with metadata and timestamps.
        Returns success status.
        """
        try:
            # Generate embeddings for semantic search
            conversation_text = " ".join(msg.content for msg in messages)
            embedding = self._get_embedding(conversation_text)
            
            conversation_data = {
                "id": conversation_id,
                "timestamp": datetime.now(),
                "messages": [self._message_to_dict(msg) for msg in messages],
                "summary": self._generate_summary(messages),
                "embedding": embedding
            }
            
            # Implement memory management
            if len(self.long_term_memory) >= self.max_memory_size:
                self._prune_old_conversations()
                
            self.long_term_memory.append(conversation_data)
            self._update_semantic_memory(conversation_data)
            return True
        except Exception as e:
            print(f"Error saving conversation: {e}")
            return False
    
    def retrieve_context(self, 
                        conversation_id: str, 
                        query: str = None,
                        memory_type: MemoryType = MemoryType.LONG_TERM) -> Optional[str]:
        """
        Retrieve context based on memory type and query.
        Uses OpenAI embeddings for semantic search.
        """
        if memory_type == MemoryType.SEMANTIC and query:
            return self._semantic_search(query)
        elif memory_type == MemoryType.LONG_TERM:
            return self._get_latest_context(conversation_id)
        return None

    def _get_embedding(self, text: str) -> List[float]:
        """
        Get embeddings using OpenAI's embedding model.
        """
        response = openai.Embedding.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response['data'][0]['embedding']

    def _semantic_search(self, query: str) -> Optional[str]:
        """
        Perform semantic search using OpenAI embeddings.
        """
        if not self.semantic_memory:
            return None
            
        query_embedding = self._get_embedding(query)
        
        # Calculate cosine similarity with stored embeddings
        best_match = None
        best_score = -1
        
        for conv_id, conv_data in self.semantic_memory.items():
            similarity = self._cosine_similarity(query_embedding, conv_data["embedding"])
            if similarity > best_score:
                best_score = similarity
                best_match = conv_data["summary"]
        
        return best_match if best_score > 0.7 else None

    def _cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """
        Calculate cosine similarity between two vectors.
        """
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

    def _get_latest_context(self, conversation_id: str) -> Optional[str]:
        """
        Retrieve the most recent relevant context.
        """
        relevant_convs = [
            conv for conv in self.long_term_memory 
            if conv["id"] == conversation_id
        ]
        
        if not relevant_convs:
            return None
            
        latest_conv = max(relevant_convs, key=lambda x: x["timestamp"])
        return latest_conv["summary"]

    def _generate_summary(self, messages: List[Message]) -> str:
        """
        Generate a summary using OpenAI's GPT-4o model.
        """
        try:
            conversation_text = "\n".join([f"{msg.role}: {msg.content}" for msg in messages])
            response = openai.ChatCompletion.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": "Please provide a brief summary of the following conversation."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            print(f"Error generating summary: {e}")
            # Fallback to simple summary
            key_messages = [msg for msg in messages if msg.role == "assistant"][-3:]
            return " ".join(msg.content[:100] + "..." for msg in key_messages)

    def _message_to_dict(self, message: Message) -> Dict:
        """
        Convert Message object to dictionary format compatible with OpenAI API.
        """
        return {
            "role": message.role,
            "content": message.content,
            "timestamp": message.timestamp.isoformat(),
            "metadata": message.metadata or {}
        }

    def _prune_old_conversations(self) -> None:
        """
        Remove oldest conversations when reaching memory limit.
        """
        self.long_term_memory.sort(key=lambda x: x["timestamp"])
        self.long_term_memory = self.long_term_memory[-self.max_memory_size:]

    def _update_semantic_memory(self, conversation_data: Dict) -> None:
        """
        Update semantic memory with conversation embeddings.
        """
        self.semantic_memory[conversation_data["id"]] = {
            "embedding": conversation_data["embedding"],
            "summary": conversation_data["summary"]
        }

# Example usage
def demonstrate_conversation_memory():
    # Initialize memory manager with OpenAI API key
    memory_manager = ConversationMemoryManager("your-api-key-here")
    
    # Create sample conversation
    conversation_id = "conv_123"
    messages = [
        Message(
            role="system",
            content="You are a helpful assistant that explains concepts clearly.",
            timestamp=datetime.now()
        ),
        Message(
            role="user",
            content="What is a class in object-oriented programming?",
            timestamp=datetime.now()
        ),
        Message(
            role="assistant",
            content="A class in OOP is a blueprint for creating objects, defining their properties and behaviors.",
            timestamp=datetime.now()
        )
    ]
    
    # Save conversation
    memory_manager.save_conversation(conversation_id, messages)
    
    # Retrieve context using different methods
    long_term_context = memory_manager.retrieve_context(
        conversation_id,
        memory_type=MemoryType.LONG_TERM
    )
    print("Long-term Context:", long_term_context)
    
    semantic_context = memory_manager.retrieve_context(
        conversation_id,
        query="How do classes work in programming?",
        memory_type=MemoryType.SEMANTIC
    )
    print("Semantic Context:", semantic_context)

if __name__ == "__main__":
    demonstrate_conversation_memory()

Este código de ejemplo implementa un sistema integral de gestión de memoria de conversación. Estos son los componentes principales:

1. Clases principales y estructuras de datos

  • El enum MemoryType define tres tipos de memoria: corto plazo, largo plazo y semántica
  • La dataclass Message almacena mensajes de conversación con rol, contenido, marca de tiempo y metadatos

2. Clase ConversationMemoryManager

  • Gestiona tres tipos de almacenamiento:
    • Memoria a largo plazo: Almacena conversaciones completas
    • Memoria semántica: Almacena embeddings para búsqueda semántica
    • Conversaciones activas: Maneja conversaciones en curso

3. Características principales

  • Guardado de conversaciones: Almacena conversaciones con metadatos, marcas de tiempo y embeddings
  • Recuperación de contexto: Admite tanto recuperación directa como búsqueda semántica
  • Gestión de memoria: Implementa poda al alcanzar el tamaño máximo de memoria (1000 conversaciones)
  • Resumen automático: Genera resúmenes de conversación usando el modelo GPT de OpenAI

4. Características avanzadas

  • Búsqueda semántica usando embeddings de OpenAI y similitud del coseno
  • Mecanismos de respaldo para la generación de resúmenes si la API de OpenAI falla
  • Poda eficiente de memoria para mantener el rendimiento del sistema

El código demuestra la implementación tanto de búsqueda semántica como de almacenamiento tradicional de conversaciones, haciéndolo adecuado para aplicaciones que requieren una gestión sofisticada de memoria de conversación.

Entender la interacción entre la memoria a corto y largo plazo es crucial para diseñar conversaciones efectivas de múltiples turnos en sistemas de IA. Analicemos estos dos tipos de memoria y sus roles:

La memoria a corto plazo opera dentro del contexto inmediato de una conversación. Se maneja automáticamente durante cada llamada a la API, manteniendo el flujo actual del diálogo y los intercambios recientes. Este tipo de memoria es esencial para comprender el contexto inmediato, las referencias y mantener la coherencia dentro de una única sesión de conversación.

La memoria a largo plazo, por otro lado, requiere una implementación más sofisticada. Involucra:

  • Almacenamiento persistente del historial de conversaciones en bases de datos o sistemas de almacenamiento externos
  • Mecanismos inteligentes de recuperación para seleccionar contexto histórico relevante
  • Decisiones estratégicas sobre qué información almacenar y recuperar
  • Métodos para gestionar limitaciones de almacenamiento y limpiar datos antiguos

Cuando combinas estos dos enfoques de memoria de manera efectiva, puedes crear aplicaciones de IA que demuestren:

  • Conciencia contextual a través de múltiples conversaciones
  • Flujo de conversación natural que se siente humano
  • Capacidad para hacer referencia y construir sobre interacciones pasadas
  • Comprensión consistente de las preferencias e historial del usuario

La clave del éxito radica en encontrar el equilibrio adecuado entre estos tipos de memoria e implementarlos de una manera que mejore la experiencia del usuario mientras se gestionan eficientemente los recursos del sistema.

7.1 Memoria a Corto vs Largo Plazo

El Capítulo 7 explora los aspectos críticos de la gestión del historial de conversaciones y el contexto en aplicaciones de IA, centrándose particularmente en cómo los sistemas de memoria impactan la efectividad de las interacciones de múltiples turnos. A medida que los asistentes de IA se vuelven cada vez más sofisticados, entender cómo implementar y gestionar adecuadamente la memoria conversacional se vuelve esencial para los desarrolladores que construyen aplicaciones robustas de IA.

Este capítulo te guiará a través de varios enfoques para manejar el historial de conversaciones, desde la gestión básica del contexto hasta técnicas avanzadas para mantener interacciones a largo plazo con el usuario. Exploraremos las diferencias entre los sistemas de memoria a corto y largo plazo, discutiremos implementaciones prácticas de gestión de hilos, y examinaremos estrategias para manejar las limitaciones de contexto.

Profundicemos en los cinco temas críticos que exploraremos en este capítulo:

  • Memoria a Corto vs Largo Plazo: Este concepto fundamental explora cómo los sistemas de IA manejan las conversaciones inmediatas versus el almacenamiento de información para uso futuro. Examinaremos cómo la memoria a corto plazo gestiona el contexto y las respuestas actuales, mientras que la memoria a largo plazo mantiene las preferencias del usuario, las interacciones pasadas y los comportamientos aprendidos a través de múltiples sesiones. Comprender estas diferencias es crucial para construir sistemas efectivos de IA conversacional.
  • Gestión de Hilos y Ventanas de Contexto: Profundizaremos en los aspectos técnicos de la gestión de hilos de conversación, incluyendo cómo organizar y mantener múltiples flujos de conversación simultáneamente. Aprenderás sobre las limitaciones de tokens en diferentes modelos de IA, cómo optimizar las ventanas de contexto para un mejor rendimiento, y técnicas para gestionar conversaciones complejas y ramificadas de manera efectiva.
  • Almacenamiento y Recuperación de Interacciones Pasadas: Esta sección cubre la implementación práctica de sistemas de almacenamiento de conversaciones. Exploraremos varias soluciones de bases de datos, estrategias de caché y mecanismos de recuperación que permiten a los sistemas de IA acceder y utilizar conversaciones históricas. Aprenderás sobre diferentes enfoques para almacenar datos de conversación, desde almacenamiento simple basado en texto hasta sofisticadas bases de datos vectoriales.
  • Soluciones para Límites de Contexto: Abordaremos uno de los desafíos más comunes en las conversaciones de IA: lidiar con las limitaciones de contexto. Descubrirás estrategias innovadoras para gestionar conversaciones largas, incluyendo técnicas como resumen de conversaciones, poda selectiva de contexto y gestión dinámica de contexto. También exploraremos cómo mantener la coherencia de la conversación cuando se trabaja con ventanas de contexto limitadas.
  • Actualizaciones sobre la Función de Memoria de ChatGPT: Los últimos desarrollos en las capacidades de memoria de ChatGPT están transformando cómo abordamos la gestión de conversaciones. Examinaremos las nuevas características, sus aplicaciones prácticas y cómo los desarrolladores pueden aprovechar estas capacidades en sus aplicaciones. Esta sección también cubrirá las mejores prácticas para integrar las funciones de memoria de ChatGPT con sistemas existentes y posibles desarrollos futuros en esta área.

Al final de este capítulo, tendrás una comprensión integral de cómo implementar sistemas de memoria efectivos en tus aplicaciones de IA, permitiendo conversaciones más naturales y conscientes del contexto.

La memoria conversacional es un pilar fundamental en la construcción de aplicaciones de IA efectivas que pueden participar en diálogos naturales y fluidos. Este sistema de memoria permite a la IA mantener conversaciones coherentes mediante la comprensión y referencia a intercambios previos, de manera similar a cómo los humanos recuerdan y construyen sobre partes anteriores de una conversación. Sin esta capacidad, cada respuesta estaría desconectada y contextualmente ciega, llevando a interacciones frustrantes y poco naturales.

El sistema de memoria en la IA conversacional cumple múltiples funciones cruciales. Ayuda a mantener la continuidad del tema, permite la resolución adecuada de referencias (entendiendo pronombres como "eso" o "ellos"), y permite que la IA construya sobre información previamente establecida. Esto crea una interacción más atractiva e inteligente que se siente natural para los usuarios.

La memoria en la IA conversacional puede entenderse a través de dos perspectivas distintas pero complementarias: memoria a corto plazo y memoria a largo plazo. Estos dos tipos de sistemas de memoria trabajan juntos para crear una comprensión integral tanto del contexto inmediato como de las interacciones históricas.

7.1.1 Memoria a Corto Plazo

La memoria a corto plazo es un componente crucial que permite a los modelos de IA mantener el contexto durante las conversaciones en curso. Piensa en ella como un espacio de trabajo temporal donde la IA mantiene un registro de la discusión actual. Cuando interactúas con la API, envías una secuencia de mensajes que incluyen instrucciones del sistema (que establecen el comportamiento de la IA), entradas del usuario (tus preguntas o declaraciones) y respuestas del asistente (las respuestas previas de la IA).

El modelo procesa toda esta información dentro de su ventana de contexto - un espacio significativo que puede manejar hasta 128,000 tokens en modelos avanzados, aproximadamente equivalente al texto de un libro pequeño. Esta extensa ventana de contexto permite a la IA elaborar respuestas que no solo son relevantes para tu pregunta inmediata sino también consistentes con todo el flujo de la conversación.

Características Clave de la Memoria a Corto Plazo:

Ventana de Contexto

La ventana de contexto sirve como la memoria de trabajo de la IA, funcionando como un búfer temporal que procesa y retiene el historial completo de mensajes proporcionado en tu llamada a la API. Esta ventana es esencial para mantener conversaciones coherentes y permitir que la IA entienda y haga referencia a intercambios previos. Aquí hay un desglose detallado:

  1. Tamaño y Capacidad:
  • GPT-3.5: Puede manejar hasta 4,096 tokens
  • GPT-4: Soporta hasta 8,192 tokens
  • Modelos avanzados: Pueden procesar hasta 128,000 tokens
  1. Gestión de Tokens:
    Cuando las conversaciones exceden estos límites, el sistema emplea un enfoque de "ventana deslizante", eliminando automáticamente mensajes más antiguos para acomodar los nuevos. Este proceso es similar a cómo los humanos naturalmente olvidan detalles específicos de conversaciones anteriores mientras retienen los temas y conceptos principales.

Por ejemplo:

Usuario: "¿Qué tiempo hace?"

Asistente: "Está soleado y hace 75°F."

Usuario: "¿Debería llevar una chaqueta?"

Asistente: "Dada la temperatura cálida que mencioné (75°F), probablemente no necesitarás una chaqueta."

Aquí te mostramos cómo podemos implementar una conversación básica sobre el clima que demuestra la memoria a corto plazo:

import openai
import os
from dotenv import load_dotenv

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

# Initialize conversation history
conversation = [
    {"role": "system", "content": "You are a helpful weather assistant."}
]

def get_response(message):
    # Add user message to conversation history
    conversation.append({"role": "user", "content": message})
    
    # Get response from API
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation,
        temperature=0.7
    )
    
    # Extract and store assistant's response
    assistant_response = response.choices[0].message['content']
    conversation.append({"role": "assistant", "content": assistant_response})
    
    return assistant_response

# Example conversation
print("User: What's the weather like?")
print("Assistant:", get_response("What's the weather like?"))

print("\nUser: Should I bring a jacket?")
print("Assistant:", get_response("Should I bring a jacket?"))

Analicemos cómo este código demuestra la memoria a corto plazo:

  • La lista de conversación mantiene todo el historial del chat
  • Cada nuevo mensaje (tanto del usuario como del asistente) se agrega a este historial
  • Al realizar nuevas llamadas a la API, se envía el contexto completo de la conversación
  • Esto permite que el asistente haga referencia a información previa (como la temperatura) en respuestas subsiguientes

Cuando ejecutes este código, el asistente mantendrá el contexto durante toda la conversación, tal como en nuestro ejemplo donde recordó la temperatura al responder sobre la chaqueta.

En esta interacción, la ventana de contexto mantiene la información de temperatura del primer intercambio, permitiendo que el asistente haga una recomendación relevante en su segunda respuesta. Sin embargo, si esta conversación continuara por cientos de mensajes, los detalles más antiguos eventualmente se recortarían para dar espacio a nueva información.

Gestión de Memoria Específica de Sesión:

La memoria a corto plazo opera dentro de los límites de una única sesión de conversación, similar a cómo funciona la memoria a corto plazo humana durante una discusión específica. Esto significa que la IA mantiene el contexto y recuerda detalles solo dentro del hilo de conversación actual. Analicemos esto con algunos ejemplos:

Durante una sesión:
Usuario: "Mi nombre es Sarah."
Asistente: "¡Encantado de conocerte, Sarah!"
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para ti, Sarah?"

En este caso, el asistente recuerda el nombre del usuario durante toda la conversación. Sin embargo, cuando inicias una nueva sesión:

Nueva sesión:
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para tu ubicación?"

Observa cómo el asistente ya no recuerda el nombre del usuario de la sesión anterior. Esto se debe a que cada nueva sesión comienza con una pizarra limpia. Sin embargo, hay varias formas de mantener la continuidad entre sesiones:

  1. Inyección Explícita de Contexto: Puedes incluir manualmente información importante de sesiones anteriores en tu mensaje inicial o del sistema.
  2. Integración de Base de Datos: Almacenar información clave del usuario y preferencias en una base de datos y recuperarlas al inicio de cada sesión.
  3. Resumen de Sesión: Crear un breve resumen de interacciones previas para incluir en nuevas sesiones cuando sea relevante.

Por ejemplo, para mantener el contexto entre sesiones, podrías comenzar una nueva sesión con:
Sistema: "Esta usuaria es Sarah, quien previamente mostró interés en actualizaciones del tiempo y habla español."

Aquí está el ejemplo de código:

import openai
from datetime import datetime
import sqlite3

class UserSessionManager:
    def __init__(self):
        # Initialize database connection
        self.conn = sqlite3.connect('user_sessions.db')
        self.create_tables()
        
    def create_tables(self):
        cursor = self.conn.cursor()
        # Create tables for user info and session history
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                user_id TEXT PRIMARY KEY,
                name TEXT,
                preferences TEXT
            )
        ''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS sessions (
                session_id TEXT PRIMARY KEY,
                user_id TEXT,
                timestamp DATETIME,
                context TEXT
            )
        ''')
        self.conn.commit()

    def start_new_session(self, user_id):
        # Retrieve user information from database
        cursor = self.conn.cursor()
        cursor.execute('SELECT name, preferences FROM users WHERE user_id = ?', (user_id,))
        user_data = cursor.execute.fetchone()
        
        if user_data:
            name, preferences = user_data
            # Create system message with user context
            system_message = f"This user is {name}. {preferences}"
        else:
            system_message = "You are a helpful assistant."
            
        return [{"role": "system", "content": system_message}]

    def save_user_info(self, user_id, name, preferences):
        cursor = self.conn.cursor()
        cursor.execute('''
            INSERT OR REPLACE INTO users (user_id, name, preferences) 
            VALUES (?, ?, ?)
        ''', (user_id, name, preferences))
        self.conn.commit()

# Example usage
def demonstrate_session_memory():
    session_manager = UserSessionManager()
    
    # First session - Save user information
    session_manager.save_user_info(
        "user123",
        "Sarah",
        "previously expressed interest in weather updates and speaks Spanish"
    )
    
    # Start a new session with context
    conversation = session_manager.start_new_session("user123")
    
    # Make API call with context
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation + [
            {"role": "user", "content": "What's the weather like?"}
        ]
    )
    
    return response

# Run demonstration
if __name__ == "__main__":
    response = demonstrate_session_memory()
    print("Assistant's response with context:", response.choices[0].message['content'])

Desglose del Código:

  • La clase UserSessionManager maneja todas las operaciones relacionadas con la sesión:
    • Inicializa la conexión a la base de datos SQLite para almacenamiento persistente
    • Crea tablas para almacenar información del usuario e historial de sesiones
    • Proporciona métodos para gestionar datos de usuario y sesiones
  • Componentes Principales:
    • create_tables(): Configura el esquema de la base de datos para almacenar datos de usuario e historial de sesiones
    • save_user_info(): Almacena o actualiza la información del usuario en la base de datos
    • start_new_session(): Recupera el contexto del usuario y crea una nueva sesión de conversación
  • La demostración muestra cómo:
    • Guardar información del usuario (nombre, preferencias) en la base de datos
    • Iniciar una nueva sesión que incluye el contexto del usuario
    • Realizar llamadas a la API con el contexto mantenido

Esta implementación permite que el asistente mantenga el contexto del usuario a través de diferentes sesiones, abordando las limitaciones de memoria discutidas en el ejemplo anterior. Cuando Sarah inicia una nueva sesión, el asistente ya conocerá su nombre y preferencias, lo que lleva a interacciones más personalizadas.

Este enfoque te permite transferir selectivamente información importante mientras mantienes la eficiencia de la gestión de memoria específica de sesión.

Actualizaciones Dinámicas y Refinamiento Continuo del Contexto:

La conversación evoluciona naturalmente a medida que se agregan nuevos mensajes al contexto, creando un diálogo fluido y adaptativo. Esta naturaleza dinámica permite que la IA refine continuamente su comprensión y respuestas basándose en la información más reciente, similar a cómo los humanos procesan e incorporan nuevos detalles durante una conversación. El modelo puede:

  • Hacer referencia a puntos anteriores en la conversación con precisión
  • Mantener consistencia a través de múltiples intercambios
  • Construir sobre conceptos previamente establecidos
  • Ajustar sus respuestas basándose en el nuevo contexto

Por ejemplo, considera este flujo de conversación:

Usuario: "Estoy planeando un viaje a Japón."

Asistente: "¡Qué emocionante! ¿Cuándo planeas visitar?"

Usuario: "En abril del próximo año."

Asistente: "¡Abril es perfecto para la temporada de flores de cerezo en Japón! ¿Te gustaría algunas recomendaciones específicas basadas en esta fecha?"

Usuario: "Sí, pero me preocupan las multitudes."

Asistente: "Entiendo tu preocupación sobre las multitudes durante la temporada de flores de cerezo, puedo sugerirte algunos lugares menos turísticos y horarios óptimos para visitar..."

En este intercambio, la IA demuestra actualización dinámica del contexto al:

  • Recordar el plan inicial de viaje
  • Incorporar el momento específico (abril)
  • Conectarlo con información relevante (temporada de flores de cerezo)
  • Adaptar las recomendaciones basándose en la preocupación expresada sobre las multitudes

Aquí hay un ejemplo de código que demuestra este tipo de conversación contextual:

import openai
from datetime import datetime

class TravelAssistant:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a helpful travel assistant specializing in Japan travel advice."}
        ]
        self.user_preferences = {
            "destination": None,
            "travel_date": None,
            "concerns": []
        }

    def update_preferences(self, message):
        # Simple preference extraction logic
        if "Japan" in message:
            self.user_preferences["destination"] = "Japan"
        if "April" in message:
            self.user_preferences["travel_date"] = "April"
        if "crowds" in message.lower():
            self.user_preferences["concerns"].append("crowds")

    def get_contextual_response(self, user_message):
        # Update user preferences based on message
        self.update_preferences(user_message)
        
        # Add user message to conversation history
        self.conversation_history.append({"role": "user", "content": user_message})
        
        # Generate system note with current context
        context_note = self._generate_context_note()
        if context_note:
            self.conversation_history.append({"role": "system", "content": context_note})

        # Get response from API
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=self.conversation_history,
            temperature=0.7
        )

        assistant_response = response.choices[0].message["content"]
        self.conversation_history.append({"role": "assistant", "content": assistant_response})
        return assistant_response

    def _generate_context_note(self):
        context = []
        if self.user_preferences["destination"]:
            context.append(f"User is planning a trip to {self.user_preferences['destination']}")
        if self.user_preferences["travel_date"]:
            context.append(f"Planning to travel in {self.user_preferences['travel_date']}")
        if self.user_preferences["concerns"]:
            context.append(f"Expressed concerns about: {', '.join(self.user_preferences['concerns'])}")
        
        return "; ".join(context) if context else None

# Example usage
def demonstrate_travel_assistant():
    assistant = TravelAssistant()
    
    # Simulate the conversation
    conversation = [
        "I'm planning a trip to Japan.",
        "In April next year.",
        "Yes, but I'm worried about the crowds."
    ]
    
    print("Starting conversation simulation...")
    for message in conversation:
        print(f"\nUser: {message}")
        response = assistant.get_contextual_response(message)
        print(f"Assistant: {response}")
        print(f"Current Context: {assistant._generate_context_note()}")

if __name__ == "__main__":
    demonstrate_travel_assistant()

Desglose del Código:

  • La clase TravelAssistant mantiene dos componentes principales:
    • conversation_history: Almacena el hilo completo de la conversación
    • user_preferences: Rastrea el contexto importante sobre los planes de viaje del usuario
  • Métodos Principales:
    • update_preferences(): Extrae y almacena información relevante de los mensajes del usuario
    • get_contextual_response(): Gestiona el flujo de la conversación y las interacciones con la API
    • _generate_context_note(): Crea resúmenes de contexto a partir de las preferencias almacenadas
  • El código demuestra:
    • Construcción progresiva del contexto conforme se desarrolla la conversación
    • Mantenimiento de las preferencias del usuario a través de múltiples intercambios
    • Inyección dinámica de contexto en la conversación
    • Manejo estructurado del flujo de conversación

Esta implementación muestra cómo mantener el contexto a través de una conversación de múltiples turnos mientras se realiza un seguimiento de las preferencias y preocupaciones específicas del usuario, similar al flujo de conversación demostrado en el ejemplo anterior.

Esta gestión dinámica del contexto asegura que cada respuesta no solo sea relevante a la pregunta inmediata sino que también esté informada por todo el historial de la conversación, creando un diálogo más natural y coherente.

Un Ejemplo Integral: Implementación de Memoria a Corto Plazo en Conversaciones de Múltiples Turnos

A continuación se muestra un ejemplo usando Python para simular una conversación con memoria a corto plazo, que demuestra cómo mantener el contexto durante un diálogo en curso. El historial de conversación se implementa como una lista de mensajes, donde cada mensaje contiene tanto el rol (sistema, usuario o asistente) como el contenido de ese mensaje.

Esta lista se actualiza continuamente y se pasa a cada llamada API subsiguiente, permitiendo que la IA haga referencia y construya sobre intercambios previos. Este enfoque es particularmente útil para mantener conversaciones coherentes donde el contexto de mensajes anteriores influye en las respuestas posteriores. La implementación permite que el asistente recuerde y haga referencia a preguntas, respuestas y detalles importantes previos a lo largo de la conversación:

import openai
import os
from dotenv import load_dotenv
from datetime import datetime
import json

# Load environment variables and configure OpenAI
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

class ConversationManager:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a friendly assistant that helps with technical queries."}
        ]
        self.session_metadata = {
            "start_time": datetime.now(),
            "query_count": 0,
            "topics": set()
        }
    
    def save_conversation(self, filename="conversation_history.json"):
        """Save the current conversation to a JSON file"""
        data = {
            "history": self.conversation_history,
            "metadata": {
                **self.session_metadata,
                "topics": list(self.session_metadata["topics"]),
                "start_time": self.session_metadata["start_time"].isoformat()
            }
        }
        with open(filename, 'w') as f:
            json.dump(data, f, indent=2)
    
    def load_conversation(self, filename="conversation_history.json"):
        """Load a previous conversation from a JSON file"""
        try:
            with open(filename, 'r') as f:
                data = json.load(f)
                self.conversation_history = data["history"]
                self.session_metadata = data["metadata"]
                self.session_metadata["topics"] = set(self.session_metadata["topics"])
                self.session_metadata["start_time"] = datetime.fromisoformat(
                    self.session_metadata["start_time"]
                )
            return True
        except FileNotFoundError:
            return False

    def ask_question(self, question, topic=None):
        """Ask a question and maintain conversation context"""
        # Update metadata
        self.session_metadata["query_count"] += 1
        if topic:
            self.session_metadata["topics"].add(topic)

        # Append the user's question
        self.conversation_history.append({"role": "user", "content": question})

        try:
            # Make the API call with current conversation history
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=self.conversation_history,
                max_tokens=150,
                temperature=0.7,
                presence_penalty=0.6  # Encourage more diverse responses
            )

            # Extract and store the assistant's reply
            answer = response["choices"][0]["message"]["content"]
            self.conversation_history.append({"role": "assistant", "content": answer})
            
            return answer

        except Exception as e:
            error_msg = f"Error during API call: {str(e)}"
            print(error_msg)
            return error_msg

    def get_conversation_summary(self):
        """Return a summary of the conversation session"""
        return {
            "Duration": datetime.now() - self.session_metadata["start_time"],
            "Total Questions": self.session_metadata["query_count"],
            "Topics Covered": list(self.session_metadata["topics"]),
            "Message Count": len(self.conversation_history)
        }

def demonstrate_conversation():
    # Initialize the conversation manager
    manager = ConversationManager()
    
    # Example multi-turn conversation
    questions = [
        ("What is a variable in Python?", "python_basics"),
        ("Can you give an example of declaring one?", "python_basics"),
        ("How do I use variables in a function?", "python_functions")
    ]
    
    # Run through the conversation
    for question, topic in questions:
        print(f"\nUser: {question}")
        response = manager.ask_question(question, topic)
        print(f"Assistant: {response}")
    
    # Save the conversation
    manager.save_conversation()
    
    # Print conversation summary
    print("\nConversation Summary:")
    for key, value in manager.get_conversation_summary().items():
        print(f"{key}: {value}")

if __name__ == "__main__":
    demonstrate_conversation()

Desglose y Explicación del Código:

  1. Estructura de Clase e Inicialización
    • La clase ConversationManager proporciona una forma estructurada de manejar conversaciones
    • Mantiene tanto el historial de conversación como los metadatos de sesión
    • Utiliza un mensaje del sistema para establecer el rol del asistente
  2. Funciones de Almacenamiento Persistente
    • save_conversation(): Exporta el historial de conversación y metadatos a JSON
    • load_conversation(): Restaura conversaciones previas desde archivos guardados
    • Maneja automáticamente la serialización/deserialización de fechas y horas
  3. Manejo Mejorado de Preguntas
    • Rastrea temas de conversación y contador de consultas
    • Incluye manejo de errores para llamadas a la API
    • Utiliza presence_penalty para fomentar respuestas diversas
  4. Metadatos y Análisis
    • Rastrea la duración de la sesión
    • Mantiene un conjunto de temas de conversación
    • Proporciona resúmenes detallados de la conversación
  5. Mejoras Clave Sobre la Versión Básica
    • Agregado manejo de errores y registro apropiado
    • Implementada persistencia de conversación
    • Incluidos análisis y metadatos de sesión
    • Mejorada modularidad y organización del código

Este ejemplo proporciona una base robusta para construir aplicaciones conversacionales, con características de persistencia, manejo de errores y análisis que serían valiosas en un entorno de producción.

En este ejemplo, el historial de conversación (memoria a corto plazo) se actualiza continuamente con cada interacción, permitiendo que el asistente haga referencia a mensajes anteriores según sea necesario.

7.1.2 Memoria a Largo Plazo

Mientras que la memoria a corto plazo es inherente en cada llamada a la API, la memoria a largo plazo en la IA conversacional representa un enfoque más sofisticado para mantener el contexto a través de múltiples interacciones. A diferencia de la memoria a corto plazo, que solo retiene información durante una única conversación, la memoria a largo plazo crea un registro persistente de las interacciones del usuario que puede abarcar días, semanas o incluso meses. Esto se logra típicamente almacenando historiales de conversación en bases de datos o sistemas de archivos, que luego pueden ser accedidos de manera inteligente cuando sea necesario.

El proceso funciona primero capturando y almacenando datos relevantes de la conversación, incluyendo preferencias del usuario, detalles importantes y puntos clave de discusión. Cuando un usuario regresa para una nueva sesión, el sistema puede recuperar esta información almacenada e inyectar selectivamente el contexto más relevante en futuros mensajes. Esto crea una experiencia más personalizada y continua, ya que la IA puede hacer referencia a interacciones pasadas y construir sobre el conocimiento previamente establecido.

Por ejemplo, si un usuario discutió sus preferencias dietéticas en una sesión anterior, el sistema puede recordar esta información semanas después al proporcionar recomendaciones de recetas, creando una interacción más natural y contextualmente consciente. Esta capacidad de mantener y utilizar el contexto histórico es esencial para construir sistemas conversacionales verdaderamente inteligentes que puedan proporcionar continuidad y personalización a través de múltiples interacciones.

Características Clave de la Memoria a Largo Plazo:

Persistencia Entre Sesiones:

La memoria a largo plazo implica crear un registro permanente del historial de conversación en bases de datos o sistemas de almacenamiento, formando una base de conocimiento integral para cada interacción del usuario. Este enfoque sofisticado permite que los sistemas de IA mantengan un contexto detallado incluso cuando los usuarios regresan después de períodos prolongados - desde días hasta meses o incluso años.

El sistema logra esto a través de varios mecanismos clave:

  1. Almacenamiento de Conversación: Cada interacción significativa se almacena en bases de datos estructuradas, incluyendo preferencias del usuario, solicitudes específicas y decisiones importantes.
  2. Recuperación de Contexto: Cuando un usuario regresa, el sistema puede acceder y utilizar inteligentemente sus datos históricos para proporcionar respuestas personalizadas.
  3. Reconocimiento de Patrones: Con el tiempo, el sistema aprende los patrones y preferencias del usuario, creando una comprensión más matizada de las necesidades individuales.

Por ejemplo:

  • Un usuario menciona que es alérgico a los frutos secos en enero. Seis meses después, cuando solicita recomendaciones de recetas, el sistema automáticamente filtra las recetas que contienen frutos secos.
  • Durante una conversación de soporte técnico en marzo, un usuario indica que está usando Windows 11. En diciembre, cuando busca ayuda con un nuevo problema, el sistema ya conoce su sistema operativo.
  • Una aplicación de aprendizaje de idiomas recuerda que un usuario tiene dificultades con las conjugaciones en tiempo pasado, incorporando automáticamente más ejercicios de práctica en esta área a través de múltiples sesiones.

Aquí está el código de implementación:

from datetime import datetime
import openai

class LongTermMemorySystem:
    def __init__(self, api_key):
        self.api_key = api_key
        openai.api_key = api_key
        self.preferences = {}
    
    def store_preference(self, user_id, pref_type, pref_value):
        if user_id not in self.preferences:
            self.preferences[user_id] = []
        self.preferences[user_id].append({
            'type': pref_type,
            'value': pref_value,
            'timestamp': datetime.now()
        })

    def get_user_preferences(self, user_id, pref_type=None):
        if user_id not in self.preferences:
            return []
        
        if pref_type:
            relevant_prefs = [p for p in self.preferences[user_id] 
                            if p['type'] == pref_type]
            return [(p['value'],) for p in sorted(relevant_prefs, 
                    key=lambda x: x['timestamp'], reverse=True)]
        
        return [(p['type'], p['value']) for p in self.preferences[user_id]]

    async def get_ai_response(self, prompt, context):
        try:
            response = await openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "You are an AI assistant with access to user preferences."},
                    {"role": "user", "content": f"Context: {context}\nPrompt: {prompt}"}
                ]
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"

# Example usage
async def demonstrate_long_term_memory():
    memory_system = LongTermMemorySystem("your-api-key-here")
    
    # Scenario 1: Food Allergies
    user_id = "user123"
    memory_system.store_preference(user_id, "food_allergy", "nuts")
    
    async def get_recipe_recommendations(user_id):
        allergies = memory_system.get_user_preferences(user_id, "food_allergy")
        context = f"User has allergies: {allergies if allergies else 'None'}"
        prompt = "Recommend safe recipes for this user."
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 2: Technical Support
    memory_system.store_preference(user_id, "operating_system", "Windows 11")
    
    async def provide_tech_support(user_id, issue):
        os = memory_system.get_user_preferences(user_id, "operating_system")
        context = f"User's OS: {os[0][0] if os else 'Unknown'}"
        prompt = f"Help with issue: {issue}"
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 3: Language Learning
    memory_system.store_preference(user_id, "grammar_challenge", "past_tense")
    
    async def generate_language_exercises(user_id):
        challenges = memory_system.get_user_preferences(user_id, "grammar_challenge")
        context = f"User struggles with: {challenges[0][0] if challenges else 'No specific areas'}"
        prompt = "Generate appropriate language exercises."
        return await memory_system.get_ai_response(prompt, context)

    # Demonstrate the system
    print("Recipe Recommendations:", await get_recipe_recommendations(user_id))
    print("Tech Support:", await provide_tech_support(user_id, "printer not working"))
    print("Language Exercises:", await generate_language_exercises(user_id))

if __name__ == "__main__":
    import asyncio
    asyncio.run(demonstrate_long_term_memory())

Este código implementa un sistema de memoria a largo plazo para conversaciones de IA que almacena y gestiona las preferencias del usuario.

Aquí se desglosan sus componentes principales:

  1. Clase LongTermMemorySystem
  • Se inicializa con una clave API para la integración con OpenAI
  • Mantiene un diccionario de preferencias de usuario
  1. Métodos Principales
  • store_preference: Almacena preferencias de usuario con marcas de tiempo
  • get_user_preferences: Recupera preferencias almacenadas, opcionalmente filtradas por tipo
  • get_ai_response: Genera respuestas de IA usando la API de OpenAI con contexto del usuario
  1. Escenarios de Demostración
  • Alergias Alimentarias: Almacena y utiliza información sobre alergias para recomendaciones de recetas
  • Soporte Técnico: Mantiene información del sistema operativo para soporte técnico contextual
  • Aprendizaje de Idiomas: Registra desafíos gramaticales para personalizar ejercicios

El sistema demuestra cómo mantener preferencias persistentes del usuario a través de múltiples sesiones, permitiendo interacciones personalizadas y conscientes del contexto. Utiliza programación asíncrona (async/await) para interacciones eficientes con la API e incluye manejo de errores para una operación robusta.

Esta persistencia asegura que la IA desarrolle una comprensión cada vez más sofisticada de cada usuario con el tiempo, conduciendo a interacciones más personalizadas, relevantes y conscientes del contexto. El sistema esencialmente desarrolla una "memoria" de las preferencias, desafíos e historial de cada usuario, similar a como un humano recordaría detalles importantes sobre amigos o colegas.

Recuperación Selectiva:

En lugar de cargar todo el historial de conversación para cada interacción, los sistemas de memoria a largo plazo utilizan métodos sofisticados de recuperación para acceder eficientemente a la información relevante. Estos sistemas emplean varias técnicas avanzadas:

  • Búsqueda Vectorial
    • Convierte texto en representaciones matemáticas (vectores)
    • Encuentra rápidamente conversaciones con significado semántico similar
    • Ejemplo: Cuando un usuario pregunta sobre "frameworks de aprendizaje automático", el sistema puede encontrar discusiones previas sobre TensorFlow o PyTorch, incluso si no se usaron exactamente esos términos
  • Puntuación de Importancia
    • Clasifica segmentos de conversación basados en relevancia y significancia
    • Considera factores como actualidad, participación del usuario y alineación temática
    • Ejemplo: Una discusión detallada reciente sobre programación tendría mayor prioridad que una mención breve antigua al responder preguntas de código
  • Relevancia Temporal
    • Pondera la información basada en sensibilidad temporal
    • Prioriza conversaciones recientes mientras mantiene acceso a contexto histórico importante
    • Ejemplo: Al discutir preferencias actuales, las conversaciones recientes sobre gustos/disgustos tienen prioridad sobre las más antiguas que podrían estar desactualizadas

Aquí hay un ejemplo de implementación de estos conceptos:

from datetime import datetime
import openai
from typing import List, Dict, Optional

class AdvancedMemoryRetrieval:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.conversations = []
        
    def add_conversation(self, text: str, timestamp: Optional[datetime] = None, engagement_score: float = 0):
        if timestamp is None:
            timestamp = datetime.now()
        
        # Convert text to vector representation using OpenAI
        try:
            response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=text
            )
            vector = response['data'][0]['embedding']
        except Exception as e:
            print(f"Error creating embedding: {e}")
            vector = None
        
        self.conversations.append({
            'text': text,
            'vector': vector,
            'timestamp': timestamp,
            'engagement': engagement_score
        })
    
    def vector_search(self, query: str, top_k: int = 3) -> List[Dict]:
        try:
            query_response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=query
            )
            query_vector = query_response['data'][0]['embedding']
            
            similarities = []
            for conv in self.conversations:
                if conv['vector'] is not None:
                    # Calculate cosine similarity
                    similarity = self._calculate_similarity(query_vector, conv['vector'])
                    similarities.append((conv, similarity))
            
            return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]
        except Exception as e:
            print(f"Error in vector search: {e}")
            return []
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def calculate_importance_score(self, conversation: Dict, query_time: datetime) -> float:
        time_diff = (query_time - conversation['timestamp']).total_seconds()
        recency_score = 1 / (1 + np.log1p(time_diff))
        return 0.7 * recency_score + 0.3 * conversation['engagement']
    
    def retrieve_relevant_context(self, query: str, top_k: int = 3) -> List[Dict]:
        # Get semantically similar conversations
        similar_convs = self.vector_search(query, top_k=top_k*2)
        
        if not similar_convs:
            return []
        
        # Calculate importance scores
        now = datetime.now()
        scored_convs = []
        for conv, similarity in similar_convs:
            importance = self.calculate_importance_score(conv, now)
            final_score = 0.6 * similarity + 0.4 * importance
            scored_convs.append((conv, final_score))
        
        # Get top results
        top_results = sorted(scored_convs, key=lambda x: x[1], reverse=True)[:top_k]
        
        # Use GPT-4o to enhance context understanding
        try:
            contexts = [result[0]['text'] for result in top_results]
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Analyze these conversation snippets and their relevance to the query."},
                    {"role": "user", "content": f"Query: {query}\nContexts: {contexts}"}
                ]
            )
            # Add GPT-4o analysis to results
            for result in top_results:
                result[0]['analysis'] = response.choices[0].message.content
        except Exception as e:
            print(f"Error in GPT analysis: {e}")
        
        return top_results

# Example usage
def demonstrate_retrieval():
    retriever = AdvancedMemoryRetrieval("your-openai-api-key-here")
    
    # Add some sample conversations
    retriever.add_conversation(
        "TensorFlow is great for deep learning projects",
        timestamp=datetime(2025, 1, 1),
        engagement_score=0.8
    )
    retriever.add_conversation(
        "PyTorch provides dynamic computational graphs",
        timestamp=datetime(2025, 3, 1),
        engagement_score=0.9
    )
    
    # Retrieve relevant context
    query = "What are good machine learning frameworks?"
    results = retriever.retrieve_relevant_context(query)
    
    for conv, score in results:
        print(f"Score: {score:.2f}")
        print(f"Text: {conv['text']}")
        if 'analysis' in conv:
            print(f"Analysis: {conv['analysis']}\n")

if __name__ == "__main__":
    demonstrate_retrieval()

Este código implementa un sistema avanzado de recuperación de memoria conversacional.

Aquí se desglosan sus componentes principales:

  1. Estructura de Clase Principal
  • La clase AdvancedMemoryRetrieval gestiona el almacenamiento y recuperación de conversaciones
  • Utiliza la API de OpenAI para crear embeddings de texto y analizar conversaciones
  1. Características Principales
  • Almacenamiento de Conversaciones:
    • Almacena texto, embeddings vectoriales, marcas temporales y puntuaciones de participación
    • Crea representaciones vectoriales de conversaciones usando el modelo de embedding de OpenAI
  • Búsqueda Vectorial:
    • Implementa búsqueda semántica usando similitud del coseno
    • Devuelve las k conversaciones más similares basadas en comparaciones vectoriales
  • Puntuación de Importancia:
    • Combina métricas de actualidad (basadas en tiempo) y participación
    • Utiliza una fórmula ponderada: 70% actualidad + 30% participación
  • Recuperación de Contexto:
    • Combina similitud vectorial (60%) con puntuaciones de importancia (40%)
    • Utiliza GPT-4o para analizar y mejorar la comprensión de los contextos recuperados
  1. Implementación de Ejemplo
  • El código de demostración muestra cómo:
    • Inicializar el sistema con conversaciones de ejemplo sobre frameworks de aprendizaje automático
    • Recuperar contexto relevante basado en una consulta
    • Mostrar resultados con puntuaciones y análisis

Esta implementación muestra técnicas modernas para gestionar el historial de conversaciones, combinando búsqueda semántica, relevancia temporal y métricas de participación para proporcionar respuestas contextualmente apropiadas.

Este enfoque selectivo asegura que las respuestas sean focalizadas y relevantes mientras mantiene la eficiencia computacional. Por ejemplo, en un escenario de soporte técnico, cuando un usuario pregunta sobre la resolución de problemas de una función específica del software, el sistema recuperaría solo las conversaciones previas sobre esa función y mensajes de error relacionados, en lugar de cargar todo su historial de soporte.

Al implementar estos métodos de recuperación, el sistema puede mantener la conciencia contextual de una conversación humana mientras opera dentro de límites computacionales prácticos.

Gestión Personalizada:

Construir una memoria a largo plazo efectiva requiere un diseño de sistema cuidadoso y la consideración de múltiples factores. Exploremos los componentes clave:

1. Arquitectura de Almacenamiento

Las estructuras de almacenamiento eficientes son cruciales para gestionar el historial de conversaciones. Esto puede incluir:

  • Bases de datos distribuidas para escalabilidad
    • Uso de MongoDB para datos de conversación no estructurados
    • Implementación de Redis para interacciones recientes de acceso rápido

2. Mecanismos de Recuperación

Los algoritmos de recuperación inteligente aseguran un acceso rápido a la información relevante:

  • Búsqueda semántica usando embeddings
    • Ejemplo: Convertir "¿Cómo restablezco mi contraseña?" en un vector para encontrar consultas similares anteriores
  • Clasificación contextual
    • Ejemplo: Priorizar conversaciones recientes de soporte técnico cuando el usuario reporta un error

3. Compresión de Datos y Resumen

Métodos para mantener la eficiencia mientras se preserva el significado:

  • Resumen automático de conversaciones
    • Ejemplo: Condensar un hilo de 30 mensajes sobre requisitos de proyecto en puntos clave
  • Técnicas de compresión inteligente
    • Ejemplo: Almacenar patrones comunes como plantillas en lugar de conversaciones completas

4. Gestión de Limitaciones del Sistema

Equilibrar capacidades con recursos:

  • Cuotas de almacenamiento por usuario/conversación
    • Ejemplo: Limitar el almacenamiento a 6 meses de historial de conversación por defecto
  • Asignación de poder de procesamiento
    • Ejemplo: Usar procesamiento por lotes para análisis histórico durante horas valle

5. Privacidad y Seguridad

Consideraciones críticas para el manejo de datos:

  • Cifrado de conversaciones almacenadas
    • Ejemplo: Usar cifrado AES-256 para todos los datos de conversación
  • Gestión del consentimiento del usuario
    • Ejemplo: Permitir que los usuarios opten por no participar en el almacenamiento a largo plazo

6. Ciclo de Vida de la Información

Gestionar datos durante su vida útil:

  • Reglas de archivo automatizado
    • Ejemplo: Mover conversaciones de más de 1 año a almacenamiento frío
  • Políticas de degradación de datos
    • Ejemplo: Eliminar automáticamente información personal después de períodos específicos
  • Evaluación regular de relevancia
    • Ejemplo: Usar métricas de participación para determinar qué información retener

Aquí hay una implementación de código:

import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import openai

class ConversationManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.storage = {}
        self.user_preferences = {}
        
    def summarize_conversation(self, messages: List[Dict]) -> str:
        """Summarize a conversation thread using GPT-4o."""
        try:
            conversation_text = "\n".join([f"{msg['role']}: {msg['content']}" for msg in messages])
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Please summarize this conversation in 3 key points."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            # Fallback to simple summarization if API call fails
            summary = []
            for msg in messages[-3:]:  # Take last 3 messages
                if len(msg['content']) > 100:
                    summary.append(f"Key point: {msg['content'][:100]}...")
                else:
                    summary.append(msg['content'])
            return "\n".join(summary)
    
    def store_conversation(self, user_id: str, conversation: List[Dict]) -> bool:
        """Store conversation with quota and privacy checks."""
        # Check storage quota
        if len(self.storage.get(user_id, [])) >= 1000:  # Example quota
            self._archive_old_conversations(user_id)
            
        # Check user consent
        if not self.user_preferences.get(user_id, {}).get('storage_consent', True):
            return False
            
        # Generate embedding for semantic search
        conversation_text = " ".join(msg['content'] for msg in conversation)
        try:
            embedding = openai.Embedding.create(
                input=conversation_text,
                model="text-embedding-ada-002"
            )
            embedding_vector = embedding['data'][0]['embedding']
        except Exception:
            embedding_vector = None
            
        # Store conversation with summary and embedding
        summary = self.summarize_conversation(conversation)
        if user_id not in self.storage:
            self.storage[user_id] = []
        self.storage[user_id].append({
            'timestamp': datetime.now(),
            'summary': summary,
            'conversation': conversation,
            'embedding': embedding_vector
        })
        return True
    
    def _archive_old_conversations(self, user_id: str) -> None:
        """Archive conversations older than 6 months."""
        cutoff_date = datetime.now() - timedelta(days=180)
        current = self.storage.get(user_id, [])
        self.storage[user_id] = [
            conv for conv in current 
            if conv['timestamp'] > cutoff_date
        ]
    
    def get_relevant_context(self, user_id: str, query: str) -> Optional[str]:
        """Retrieve relevant context using semantic search."""
        if user_id not in self.storage:
            return None
            
        try:
            # Get query embedding
            query_embedding = openai.Embedding.create(
                input=query,
                model="text-embedding-ada-002"
            )
            query_vector = query_embedding['data'][0]['embedding']
            
            # Find most relevant conversations
            relevant_contexts = []
            for conv in self.storage[user_id]:
                if conv['embedding']:
                    relevance_score = self._calculate_similarity(
                        query_vector,
                        conv['embedding']
                    )
                    if relevance_score > 0.7:  # Threshold
                        relevant_contexts.append(conv['summary'])
                        
            return relevant_contexts[0] if relevant_contexts else None
        except Exception:
            # Fallback to simple word matching if embedding fails
            return self._simple_context_search(user_id, query)
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def _simple_context_search(self, user_id: str, query: str) -> Optional[str]:
        """Simple relevance calculation using word overlap."""
        query_words = set(query.lower().split())
        best_score = 0
        best_summary = None
        
        for conv in self.storage[user_id]:
            summary_words = set(conv['summary'].lower().split())
            score = len(query_words & summary_words) / len(query_words)
            if score > best_score:
                best_score = score
                best_summary = conv['summary']
                
        return best_summary if best_score > 0.3 else None

# Example usage
def demonstrate_conversation_management():
    manager = ConversationManager("your-openai-api-key-here")
    
    # Store a conversation
    user_id = "user123"
    conversation = [
        {"role": "user", "content": "How do I implement encryption?"},
        {"role": "assistant", "content": "Here's a detailed guide..."},
        {"role": "user", "content": "Thanks, that helps!"}
    ]
    
    # Set user preferences
    manager.user_preferences[user_id] = {'storage_consent': True}
    
    # Store the conversation
    stored = manager.store_conversation(user_id, conversation)
    print(f"Conversation stored: {stored}")
    
    # Later, retrieve relevant context
    context = manager.get_relevant_context(user_id, "encryption implementation")
    print(f"Retrieved context: {context}")

if __name__ == "__main__":
    demonstrate_conversation_management()

Este código implementa una clase ConversationManager para gestionar conversaciones de IA con memoria y recuperación de contexto.

Aquí están los componentes principales:

Funcionalidad Central:

  • Almacenamiento de Conversaciones:
    • Almacena conversaciones con marcas de tiempo, resúmenes y embeddings
    • Implementa cuotas de almacenamiento y verificaciones de consentimiento del usuario
    • Archiva conversaciones con más de 6 meses de antigüedad
  • Resumen de Conversaciones:
    • Utiliza GPT-4o para crear resúmenes concisos de conversaciones
    • Incluye mecanismo de respaldo cuando fallan las llamadas a la API
    • Almacena resúmenes para una recuperación eficiente
  • Búsqueda Semántica:
    • Genera embeddings usando el modelo de embedding de OpenAI
    • Implementa similitud del coseno para encontrar conversaciones relevantes
    • Incluye respaldo a coincidencia simple de palabras cuando fallan los embeddings

Características Principales:

  • Controles de Privacidad:
    • Verifica el consentimiento del usuario antes de almacenar conversaciones
    • Gestiona preferencias de usuario y consentimiento de almacenamiento
  • Gestión de Memoria:
    • Implementa cuotas de almacenamiento (1000 conversaciones por usuario)
    • Archiva conversaciones antiguas automáticamente
    • Utiliza búsqueda semántica para recuperar contexto relevante

Ejemplo de Uso:

  • El código demuestra:
    • Almacenamiento de una conversación sobre encriptación
    • Configuración de preferencias de usuario
    • Recuperación de contexto relevante basado en consultas

Esta implementación se centra en equilibrar el almacenamiento eficiente de conversaciones con la recuperación inteligente, mientras mantiene la privacidad del usuario y el rendimiento del sistema.

Este ejemplo demuestra la aplicación práctica de los conceptos discutidos anteriormente, incluyendo compresión de datos, limitaciones del sistema, controles de privacidad y gestión del ciclo de vida de la información. El código proporciona una base que puede extenderse con características más sofisticadas como resumen basado en aprendizaje automático o esquemas de encriptación avanzados.

Un Ejemplo Completo: Simulando Memoria a Largo Plazo

Exploremos un ejemplo práctico que demuestra cómo implementar la memoria de conversación en aplicaciones de IA. Este ejemplo muestra dos componentes clave: guardar el historial de conversación para referencia futura y recuperar el contexto relevante al comenzar una nueva sesión de conversación. Para mantener el ejemplo sencillo y enfocarnos en los conceptos principales, usaremos un enfoque simple de almacenamiento en memoria usando una variable, aunque en un entorno de producción típicamente usarías un sistema de base de datos o almacenamiento persistente.

Este ejemplo sirve para ilustrar varios conceptos importantes:

  • Cómo capturar y almacenar historial de conversación significativo
    • La mecánica de guardar información contextual para referencia futura
    • Métodos para recuperar y utilizar contexto previo de conversación
  • Cómo mantener la continuidad de conversación a través de múltiples sesiones
    • Técnicas para integrar contexto pasado en nuevas conversaciones
    • Estrategias para gestionar el estado de la conversación

# Comprehensive example of conversation memory management with OpenAI API

from typing import List, Dict, Optional
import json
from datetime import datetime
import openai
from dataclasses import dataclass
from enum import Enum

class MemoryType(Enum):
    SHORT_TERM = "short_term"
    LONG_TERM = "long_term"
    SEMANTIC = "semantic"

@dataclass
class Message:
    role: str  # system, user, or assistant
    content: str
    timestamp: datetime
    metadata: Dict = None

class ConversationMemoryManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.long_term_memory = []
        self.semantic_memory = {}  # Store embeddings for semantic search
        self.active_conversations = {}
        self.max_memory_size = 1000
        self.model = "gpt-4o"  # OpenAI model to use
        
    def save_conversation(self, conversation_id: str, messages: List[Message]) -> bool:
        """
        Save conversation with metadata and timestamps.
        Returns success status.
        """
        try:
            # Generate embeddings for semantic search
            conversation_text = " ".join(msg.content for msg in messages)
            embedding = self._get_embedding(conversation_text)
            
            conversation_data = {
                "id": conversation_id,
                "timestamp": datetime.now(),
                "messages": [self._message_to_dict(msg) for msg in messages],
                "summary": self._generate_summary(messages),
                "embedding": embedding
            }
            
            # Implement memory management
            if len(self.long_term_memory) >= self.max_memory_size:
                self._prune_old_conversations()
                
            self.long_term_memory.append(conversation_data)
            self._update_semantic_memory(conversation_data)
            return True
        except Exception as e:
            print(f"Error saving conversation: {e}")
            return False
    
    def retrieve_context(self, 
                        conversation_id: str, 
                        query: str = None,
                        memory_type: MemoryType = MemoryType.LONG_TERM) -> Optional[str]:
        """
        Retrieve context based on memory type and query.
        Uses OpenAI embeddings for semantic search.
        """
        if memory_type == MemoryType.SEMANTIC and query:
            return self._semantic_search(query)
        elif memory_type == MemoryType.LONG_TERM:
            return self._get_latest_context(conversation_id)
        return None

    def _get_embedding(self, text: str) -> List[float]:
        """
        Get embeddings using OpenAI's embedding model.
        """
        response = openai.Embedding.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response['data'][0]['embedding']

    def _semantic_search(self, query: str) -> Optional[str]:
        """
        Perform semantic search using OpenAI embeddings.
        """
        if not self.semantic_memory:
            return None
            
        query_embedding = self._get_embedding(query)
        
        # Calculate cosine similarity with stored embeddings
        best_match = None
        best_score = -1
        
        for conv_id, conv_data in self.semantic_memory.items():
            similarity = self._cosine_similarity(query_embedding, conv_data["embedding"])
            if similarity > best_score:
                best_score = similarity
                best_match = conv_data["summary"]
        
        return best_match if best_score > 0.7 else None

    def _cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """
        Calculate cosine similarity between two vectors.
        """
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

    def _get_latest_context(self, conversation_id: str) -> Optional[str]:
        """
        Retrieve the most recent relevant context.
        """
        relevant_convs = [
            conv for conv in self.long_term_memory 
            if conv["id"] == conversation_id
        ]
        
        if not relevant_convs:
            return None
            
        latest_conv = max(relevant_convs, key=lambda x: x["timestamp"])
        return latest_conv["summary"]

    def _generate_summary(self, messages: List[Message]) -> str:
        """
        Generate a summary using OpenAI's GPT-4o model.
        """
        try:
            conversation_text = "\n".join([f"{msg.role}: {msg.content}" for msg in messages])
            response = openai.ChatCompletion.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": "Please provide a brief summary of the following conversation."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            print(f"Error generating summary: {e}")
            # Fallback to simple summary
            key_messages = [msg for msg in messages if msg.role == "assistant"][-3:]
            return " ".join(msg.content[:100] + "..." for msg in key_messages)

    def _message_to_dict(self, message: Message) -> Dict:
        """
        Convert Message object to dictionary format compatible with OpenAI API.
        """
        return {
            "role": message.role,
            "content": message.content,
            "timestamp": message.timestamp.isoformat(),
            "metadata": message.metadata or {}
        }

    def _prune_old_conversations(self) -> None:
        """
        Remove oldest conversations when reaching memory limit.
        """
        self.long_term_memory.sort(key=lambda x: x["timestamp"])
        self.long_term_memory = self.long_term_memory[-self.max_memory_size:]

    def _update_semantic_memory(self, conversation_data: Dict) -> None:
        """
        Update semantic memory with conversation embeddings.
        """
        self.semantic_memory[conversation_data["id"]] = {
            "embedding": conversation_data["embedding"],
            "summary": conversation_data["summary"]
        }

# Example usage
def demonstrate_conversation_memory():
    # Initialize memory manager with OpenAI API key
    memory_manager = ConversationMemoryManager("your-api-key-here")
    
    # Create sample conversation
    conversation_id = "conv_123"
    messages = [
        Message(
            role="system",
            content="You are a helpful assistant that explains concepts clearly.",
            timestamp=datetime.now()
        ),
        Message(
            role="user",
            content="What is a class in object-oriented programming?",
            timestamp=datetime.now()
        ),
        Message(
            role="assistant",
            content="A class in OOP is a blueprint for creating objects, defining their properties and behaviors.",
            timestamp=datetime.now()
        )
    ]
    
    # Save conversation
    memory_manager.save_conversation(conversation_id, messages)
    
    # Retrieve context using different methods
    long_term_context = memory_manager.retrieve_context(
        conversation_id,
        memory_type=MemoryType.LONG_TERM
    )
    print("Long-term Context:", long_term_context)
    
    semantic_context = memory_manager.retrieve_context(
        conversation_id,
        query="How do classes work in programming?",
        memory_type=MemoryType.SEMANTIC
    )
    print("Semantic Context:", semantic_context)

if __name__ == "__main__":
    demonstrate_conversation_memory()

Este código de ejemplo implementa un sistema integral de gestión de memoria de conversación. Estos son los componentes principales:

1. Clases principales y estructuras de datos

  • El enum MemoryType define tres tipos de memoria: corto plazo, largo plazo y semántica
  • La dataclass Message almacena mensajes de conversación con rol, contenido, marca de tiempo y metadatos

2. Clase ConversationMemoryManager

  • Gestiona tres tipos de almacenamiento:
    • Memoria a largo plazo: Almacena conversaciones completas
    • Memoria semántica: Almacena embeddings para búsqueda semántica
    • Conversaciones activas: Maneja conversaciones en curso

3. Características principales

  • Guardado de conversaciones: Almacena conversaciones con metadatos, marcas de tiempo y embeddings
  • Recuperación de contexto: Admite tanto recuperación directa como búsqueda semántica
  • Gestión de memoria: Implementa poda al alcanzar el tamaño máximo de memoria (1000 conversaciones)
  • Resumen automático: Genera resúmenes de conversación usando el modelo GPT de OpenAI

4. Características avanzadas

  • Búsqueda semántica usando embeddings de OpenAI y similitud del coseno
  • Mecanismos de respaldo para la generación de resúmenes si la API de OpenAI falla
  • Poda eficiente de memoria para mantener el rendimiento del sistema

El código demuestra la implementación tanto de búsqueda semántica como de almacenamiento tradicional de conversaciones, haciéndolo adecuado para aplicaciones que requieren una gestión sofisticada de memoria de conversación.

Entender la interacción entre la memoria a corto y largo plazo es crucial para diseñar conversaciones efectivas de múltiples turnos en sistemas de IA. Analicemos estos dos tipos de memoria y sus roles:

La memoria a corto plazo opera dentro del contexto inmediato de una conversación. Se maneja automáticamente durante cada llamada a la API, manteniendo el flujo actual del diálogo y los intercambios recientes. Este tipo de memoria es esencial para comprender el contexto inmediato, las referencias y mantener la coherencia dentro de una única sesión de conversación.

La memoria a largo plazo, por otro lado, requiere una implementación más sofisticada. Involucra:

  • Almacenamiento persistente del historial de conversaciones en bases de datos o sistemas de almacenamiento externos
  • Mecanismos inteligentes de recuperación para seleccionar contexto histórico relevante
  • Decisiones estratégicas sobre qué información almacenar y recuperar
  • Métodos para gestionar limitaciones de almacenamiento y limpiar datos antiguos

Cuando combinas estos dos enfoques de memoria de manera efectiva, puedes crear aplicaciones de IA que demuestren:

  • Conciencia contextual a través de múltiples conversaciones
  • Flujo de conversación natural que se siente humano
  • Capacidad para hacer referencia y construir sobre interacciones pasadas
  • Comprensión consistente de las preferencias e historial del usuario

La clave del éxito radica en encontrar el equilibrio adecuado entre estos tipos de memoria e implementarlos de una manera que mejore la experiencia del usuario mientras se gestionan eficientemente los recursos del sistema.

7.1 Memoria a Corto vs Largo Plazo

El Capítulo 7 explora los aspectos críticos de la gestión del historial de conversaciones y el contexto en aplicaciones de IA, centrándose particularmente en cómo los sistemas de memoria impactan la efectividad de las interacciones de múltiples turnos. A medida que los asistentes de IA se vuelven cada vez más sofisticados, entender cómo implementar y gestionar adecuadamente la memoria conversacional se vuelve esencial para los desarrolladores que construyen aplicaciones robustas de IA.

Este capítulo te guiará a través de varios enfoques para manejar el historial de conversaciones, desde la gestión básica del contexto hasta técnicas avanzadas para mantener interacciones a largo plazo con el usuario. Exploraremos las diferencias entre los sistemas de memoria a corto y largo plazo, discutiremos implementaciones prácticas de gestión de hilos, y examinaremos estrategias para manejar las limitaciones de contexto.

Profundicemos en los cinco temas críticos que exploraremos en este capítulo:

  • Memoria a Corto vs Largo Plazo: Este concepto fundamental explora cómo los sistemas de IA manejan las conversaciones inmediatas versus el almacenamiento de información para uso futuro. Examinaremos cómo la memoria a corto plazo gestiona el contexto y las respuestas actuales, mientras que la memoria a largo plazo mantiene las preferencias del usuario, las interacciones pasadas y los comportamientos aprendidos a través de múltiples sesiones. Comprender estas diferencias es crucial para construir sistemas efectivos de IA conversacional.
  • Gestión de Hilos y Ventanas de Contexto: Profundizaremos en los aspectos técnicos de la gestión de hilos de conversación, incluyendo cómo organizar y mantener múltiples flujos de conversación simultáneamente. Aprenderás sobre las limitaciones de tokens en diferentes modelos de IA, cómo optimizar las ventanas de contexto para un mejor rendimiento, y técnicas para gestionar conversaciones complejas y ramificadas de manera efectiva.
  • Almacenamiento y Recuperación de Interacciones Pasadas: Esta sección cubre la implementación práctica de sistemas de almacenamiento de conversaciones. Exploraremos varias soluciones de bases de datos, estrategias de caché y mecanismos de recuperación que permiten a los sistemas de IA acceder y utilizar conversaciones históricas. Aprenderás sobre diferentes enfoques para almacenar datos de conversación, desde almacenamiento simple basado en texto hasta sofisticadas bases de datos vectoriales.
  • Soluciones para Límites de Contexto: Abordaremos uno de los desafíos más comunes en las conversaciones de IA: lidiar con las limitaciones de contexto. Descubrirás estrategias innovadoras para gestionar conversaciones largas, incluyendo técnicas como resumen de conversaciones, poda selectiva de contexto y gestión dinámica de contexto. También exploraremos cómo mantener la coherencia de la conversación cuando se trabaja con ventanas de contexto limitadas.
  • Actualizaciones sobre la Función de Memoria de ChatGPT: Los últimos desarrollos en las capacidades de memoria de ChatGPT están transformando cómo abordamos la gestión de conversaciones. Examinaremos las nuevas características, sus aplicaciones prácticas y cómo los desarrolladores pueden aprovechar estas capacidades en sus aplicaciones. Esta sección también cubrirá las mejores prácticas para integrar las funciones de memoria de ChatGPT con sistemas existentes y posibles desarrollos futuros en esta área.

Al final de este capítulo, tendrás una comprensión integral de cómo implementar sistemas de memoria efectivos en tus aplicaciones de IA, permitiendo conversaciones más naturales y conscientes del contexto.

La memoria conversacional es un pilar fundamental en la construcción de aplicaciones de IA efectivas que pueden participar en diálogos naturales y fluidos. Este sistema de memoria permite a la IA mantener conversaciones coherentes mediante la comprensión y referencia a intercambios previos, de manera similar a cómo los humanos recuerdan y construyen sobre partes anteriores de una conversación. Sin esta capacidad, cada respuesta estaría desconectada y contextualmente ciega, llevando a interacciones frustrantes y poco naturales.

El sistema de memoria en la IA conversacional cumple múltiples funciones cruciales. Ayuda a mantener la continuidad del tema, permite la resolución adecuada de referencias (entendiendo pronombres como "eso" o "ellos"), y permite que la IA construya sobre información previamente establecida. Esto crea una interacción más atractiva e inteligente que se siente natural para los usuarios.

La memoria en la IA conversacional puede entenderse a través de dos perspectivas distintas pero complementarias: memoria a corto plazo y memoria a largo plazo. Estos dos tipos de sistemas de memoria trabajan juntos para crear una comprensión integral tanto del contexto inmediato como de las interacciones históricas.

7.1.1 Memoria a Corto Plazo

La memoria a corto plazo es un componente crucial que permite a los modelos de IA mantener el contexto durante las conversaciones en curso. Piensa en ella como un espacio de trabajo temporal donde la IA mantiene un registro de la discusión actual. Cuando interactúas con la API, envías una secuencia de mensajes que incluyen instrucciones del sistema (que establecen el comportamiento de la IA), entradas del usuario (tus preguntas o declaraciones) y respuestas del asistente (las respuestas previas de la IA).

El modelo procesa toda esta información dentro de su ventana de contexto - un espacio significativo que puede manejar hasta 128,000 tokens en modelos avanzados, aproximadamente equivalente al texto de un libro pequeño. Esta extensa ventana de contexto permite a la IA elaborar respuestas que no solo son relevantes para tu pregunta inmediata sino también consistentes con todo el flujo de la conversación.

Características Clave de la Memoria a Corto Plazo:

Ventana de Contexto

La ventana de contexto sirve como la memoria de trabajo de la IA, funcionando como un búfer temporal que procesa y retiene el historial completo de mensajes proporcionado en tu llamada a la API. Esta ventana es esencial para mantener conversaciones coherentes y permitir que la IA entienda y haga referencia a intercambios previos. Aquí hay un desglose detallado:

  1. Tamaño y Capacidad:
  • GPT-3.5: Puede manejar hasta 4,096 tokens
  • GPT-4: Soporta hasta 8,192 tokens
  • Modelos avanzados: Pueden procesar hasta 128,000 tokens
  1. Gestión de Tokens:
    Cuando las conversaciones exceden estos límites, el sistema emplea un enfoque de "ventana deslizante", eliminando automáticamente mensajes más antiguos para acomodar los nuevos. Este proceso es similar a cómo los humanos naturalmente olvidan detalles específicos de conversaciones anteriores mientras retienen los temas y conceptos principales.

Por ejemplo:

Usuario: "¿Qué tiempo hace?"

Asistente: "Está soleado y hace 75°F."

Usuario: "¿Debería llevar una chaqueta?"

Asistente: "Dada la temperatura cálida que mencioné (75°F), probablemente no necesitarás una chaqueta."

Aquí te mostramos cómo podemos implementar una conversación básica sobre el clima que demuestra la memoria a corto plazo:

import openai
import os
from dotenv import load_dotenv

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

# Initialize conversation history
conversation = [
    {"role": "system", "content": "You are a helpful weather assistant."}
]

def get_response(message):
    # Add user message to conversation history
    conversation.append({"role": "user", "content": message})
    
    # Get response from API
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation,
        temperature=0.7
    )
    
    # Extract and store assistant's response
    assistant_response = response.choices[0].message['content']
    conversation.append({"role": "assistant", "content": assistant_response})
    
    return assistant_response

# Example conversation
print("User: What's the weather like?")
print("Assistant:", get_response("What's the weather like?"))

print("\nUser: Should I bring a jacket?")
print("Assistant:", get_response("Should I bring a jacket?"))

Analicemos cómo este código demuestra la memoria a corto plazo:

  • La lista de conversación mantiene todo el historial del chat
  • Cada nuevo mensaje (tanto del usuario como del asistente) se agrega a este historial
  • Al realizar nuevas llamadas a la API, se envía el contexto completo de la conversación
  • Esto permite que el asistente haga referencia a información previa (como la temperatura) en respuestas subsiguientes

Cuando ejecutes este código, el asistente mantendrá el contexto durante toda la conversación, tal como en nuestro ejemplo donde recordó la temperatura al responder sobre la chaqueta.

En esta interacción, la ventana de contexto mantiene la información de temperatura del primer intercambio, permitiendo que el asistente haga una recomendación relevante en su segunda respuesta. Sin embargo, si esta conversación continuara por cientos de mensajes, los detalles más antiguos eventualmente se recortarían para dar espacio a nueva información.

Gestión de Memoria Específica de Sesión:

La memoria a corto plazo opera dentro de los límites de una única sesión de conversación, similar a cómo funciona la memoria a corto plazo humana durante una discusión específica. Esto significa que la IA mantiene el contexto y recuerda detalles solo dentro del hilo de conversación actual. Analicemos esto con algunos ejemplos:

Durante una sesión:
Usuario: "Mi nombre es Sarah."
Asistente: "¡Encantado de conocerte, Sarah!"
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para ti, Sarah?"

En este caso, el asistente recuerda el nombre del usuario durante toda la conversación. Sin embargo, cuando inicias una nueva sesión:

Nueva sesión:
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para tu ubicación?"

Observa cómo el asistente ya no recuerda el nombre del usuario de la sesión anterior. Esto se debe a que cada nueva sesión comienza con una pizarra limpia. Sin embargo, hay varias formas de mantener la continuidad entre sesiones:

  1. Inyección Explícita de Contexto: Puedes incluir manualmente información importante de sesiones anteriores en tu mensaje inicial o del sistema.
  2. Integración de Base de Datos: Almacenar información clave del usuario y preferencias en una base de datos y recuperarlas al inicio de cada sesión.
  3. Resumen de Sesión: Crear un breve resumen de interacciones previas para incluir en nuevas sesiones cuando sea relevante.

Por ejemplo, para mantener el contexto entre sesiones, podrías comenzar una nueva sesión con:
Sistema: "Esta usuaria es Sarah, quien previamente mostró interés en actualizaciones del tiempo y habla español."

Aquí está el ejemplo de código:

import openai
from datetime import datetime
import sqlite3

class UserSessionManager:
    def __init__(self):
        # Initialize database connection
        self.conn = sqlite3.connect('user_sessions.db')
        self.create_tables()
        
    def create_tables(self):
        cursor = self.conn.cursor()
        # Create tables for user info and session history
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                user_id TEXT PRIMARY KEY,
                name TEXT,
                preferences TEXT
            )
        ''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS sessions (
                session_id TEXT PRIMARY KEY,
                user_id TEXT,
                timestamp DATETIME,
                context TEXT
            )
        ''')
        self.conn.commit()

    def start_new_session(self, user_id):
        # Retrieve user information from database
        cursor = self.conn.cursor()
        cursor.execute('SELECT name, preferences FROM users WHERE user_id = ?', (user_id,))
        user_data = cursor.execute.fetchone()
        
        if user_data:
            name, preferences = user_data
            # Create system message with user context
            system_message = f"This user is {name}. {preferences}"
        else:
            system_message = "You are a helpful assistant."
            
        return [{"role": "system", "content": system_message}]

    def save_user_info(self, user_id, name, preferences):
        cursor = self.conn.cursor()
        cursor.execute('''
            INSERT OR REPLACE INTO users (user_id, name, preferences) 
            VALUES (?, ?, ?)
        ''', (user_id, name, preferences))
        self.conn.commit()

# Example usage
def demonstrate_session_memory():
    session_manager = UserSessionManager()
    
    # First session - Save user information
    session_manager.save_user_info(
        "user123",
        "Sarah",
        "previously expressed interest in weather updates and speaks Spanish"
    )
    
    # Start a new session with context
    conversation = session_manager.start_new_session("user123")
    
    # Make API call with context
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation + [
            {"role": "user", "content": "What's the weather like?"}
        ]
    )
    
    return response

# Run demonstration
if __name__ == "__main__":
    response = demonstrate_session_memory()
    print("Assistant's response with context:", response.choices[0].message['content'])

Desglose del Código:

  • La clase UserSessionManager maneja todas las operaciones relacionadas con la sesión:
    • Inicializa la conexión a la base de datos SQLite para almacenamiento persistente
    • Crea tablas para almacenar información del usuario e historial de sesiones
    • Proporciona métodos para gestionar datos de usuario y sesiones
  • Componentes Principales:
    • create_tables(): Configura el esquema de la base de datos para almacenar datos de usuario e historial de sesiones
    • save_user_info(): Almacena o actualiza la información del usuario en la base de datos
    • start_new_session(): Recupera el contexto del usuario y crea una nueva sesión de conversación
  • La demostración muestra cómo:
    • Guardar información del usuario (nombre, preferencias) en la base de datos
    • Iniciar una nueva sesión que incluye el contexto del usuario
    • Realizar llamadas a la API con el contexto mantenido

Esta implementación permite que el asistente mantenga el contexto del usuario a través de diferentes sesiones, abordando las limitaciones de memoria discutidas en el ejemplo anterior. Cuando Sarah inicia una nueva sesión, el asistente ya conocerá su nombre y preferencias, lo que lleva a interacciones más personalizadas.

Este enfoque te permite transferir selectivamente información importante mientras mantienes la eficiencia de la gestión de memoria específica de sesión.

Actualizaciones Dinámicas y Refinamiento Continuo del Contexto:

La conversación evoluciona naturalmente a medida que se agregan nuevos mensajes al contexto, creando un diálogo fluido y adaptativo. Esta naturaleza dinámica permite que la IA refine continuamente su comprensión y respuestas basándose en la información más reciente, similar a cómo los humanos procesan e incorporan nuevos detalles durante una conversación. El modelo puede:

  • Hacer referencia a puntos anteriores en la conversación con precisión
  • Mantener consistencia a través de múltiples intercambios
  • Construir sobre conceptos previamente establecidos
  • Ajustar sus respuestas basándose en el nuevo contexto

Por ejemplo, considera este flujo de conversación:

Usuario: "Estoy planeando un viaje a Japón."

Asistente: "¡Qué emocionante! ¿Cuándo planeas visitar?"

Usuario: "En abril del próximo año."

Asistente: "¡Abril es perfecto para la temporada de flores de cerezo en Japón! ¿Te gustaría algunas recomendaciones específicas basadas en esta fecha?"

Usuario: "Sí, pero me preocupan las multitudes."

Asistente: "Entiendo tu preocupación sobre las multitudes durante la temporada de flores de cerezo, puedo sugerirte algunos lugares menos turísticos y horarios óptimos para visitar..."

En este intercambio, la IA demuestra actualización dinámica del contexto al:

  • Recordar el plan inicial de viaje
  • Incorporar el momento específico (abril)
  • Conectarlo con información relevante (temporada de flores de cerezo)
  • Adaptar las recomendaciones basándose en la preocupación expresada sobre las multitudes

Aquí hay un ejemplo de código que demuestra este tipo de conversación contextual:

import openai
from datetime import datetime

class TravelAssistant:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a helpful travel assistant specializing in Japan travel advice."}
        ]
        self.user_preferences = {
            "destination": None,
            "travel_date": None,
            "concerns": []
        }

    def update_preferences(self, message):
        # Simple preference extraction logic
        if "Japan" in message:
            self.user_preferences["destination"] = "Japan"
        if "April" in message:
            self.user_preferences["travel_date"] = "April"
        if "crowds" in message.lower():
            self.user_preferences["concerns"].append("crowds")

    def get_contextual_response(self, user_message):
        # Update user preferences based on message
        self.update_preferences(user_message)
        
        # Add user message to conversation history
        self.conversation_history.append({"role": "user", "content": user_message})
        
        # Generate system note with current context
        context_note = self._generate_context_note()
        if context_note:
            self.conversation_history.append({"role": "system", "content": context_note})

        # Get response from API
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=self.conversation_history,
            temperature=0.7
        )

        assistant_response = response.choices[0].message["content"]
        self.conversation_history.append({"role": "assistant", "content": assistant_response})
        return assistant_response

    def _generate_context_note(self):
        context = []
        if self.user_preferences["destination"]:
            context.append(f"User is planning a trip to {self.user_preferences['destination']}")
        if self.user_preferences["travel_date"]:
            context.append(f"Planning to travel in {self.user_preferences['travel_date']}")
        if self.user_preferences["concerns"]:
            context.append(f"Expressed concerns about: {', '.join(self.user_preferences['concerns'])}")
        
        return "; ".join(context) if context else None

# Example usage
def demonstrate_travel_assistant():
    assistant = TravelAssistant()
    
    # Simulate the conversation
    conversation = [
        "I'm planning a trip to Japan.",
        "In April next year.",
        "Yes, but I'm worried about the crowds."
    ]
    
    print("Starting conversation simulation...")
    for message in conversation:
        print(f"\nUser: {message}")
        response = assistant.get_contextual_response(message)
        print(f"Assistant: {response}")
        print(f"Current Context: {assistant._generate_context_note()}")

if __name__ == "__main__":
    demonstrate_travel_assistant()

Desglose del Código:

  • La clase TravelAssistant mantiene dos componentes principales:
    • conversation_history: Almacena el hilo completo de la conversación
    • user_preferences: Rastrea el contexto importante sobre los planes de viaje del usuario
  • Métodos Principales:
    • update_preferences(): Extrae y almacena información relevante de los mensajes del usuario
    • get_contextual_response(): Gestiona el flujo de la conversación y las interacciones con la API
    • _generate_context_note(): Crea resúmenes de contexto a partir de las preferencias almacenadas
  • El código demuestra:
    • Construcción progresiva del contexto conforme se desarrolla la conversación
    • Mantenimiento de las preferencias del usuario a través de múltiples intercambios
    • Inyección dinámica de contexto en la conversación
    • Manejo estructurado del flujo de conversación

Esta implementación muestra cómo mantener el contexto a través de una conversación de múltiples turnos mientras se realiza un seguimiento de las preferencias y preocupaciones específicas del usuario, similar al flujo de conversación demostrado en el ejemplo anterior.

Esta gestión dinámica del contexto asegura que cada respuesta no solo sea relevante a la pregunta inmediata sino que también esté informada por todo el historial de la conversación, creando un diálogo más natural y coherente.

Un Ejemplo Integral: Implementación de Memoria a Corto Plazo en Conversaciones de Múltiples Turnos

A continuación se muestra un ejemplo usando Python para simular una conversación con memoria a corto plazo, que demuestra cómo mantener el contexto durante un diálogo en curso. El historial de conversación se implementa como una lista de mensajes, donde cada mensaje contiene tanto el rol (sistema, usuario o asistente) como el contenido de ese mensaje.

Esta lista se actualiza continuamente y se pasa a cada llamada API subsiguiente, permitiendo que la IA haga referencia y construya sobre intercambios previos. Este enfoque es particularmente útil para mantener conversaciones coherentes donde el contexto de mensajes anteriores influye en las respuestas posteriores. La implementación permite que el asistente recuerde y haga referencia a preguntas, respuestas y detalles importantes previos a lo largo de la conversación:

import openai
import os
from dotenv import load_dotenv
from datetime import datetime
import json

# Load environment variables and configure OpenAI
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

class ConversationManager:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a friendly assistant that helps with technical queries."}
        ]
        self.session_metadata = {
            "start_time": datetime.now(),
            "query_count": 0,
            "topics": set()
        }
    
    def save_conversation(self, filename="conversation_history.json"):
        """Save the current conversation to a JSON file"""
        data = {
            "history": self.conversation_history,
            "metadata": {
                **self.session_metadata,
                "topics": list(self.session_metadata["topics"]),
                "start_time": self.session_metadata["start_time"].isoformat()
            }
        }
        with open(filename, 'w') as f:
            json.dump(data, f, indent=2)
    
    def load_conversation(self, filename="conversation_history.json"):
        """Load a previous conversation from a JSON file"""
        try:
            with open(filename, 'r') as f:
                data = json.load(f)
                self.conversation_history = data["history"]
                self.session_metadata = data["metadata"]
                self.session_metadata["topics"] = set(self.session_metadata["topics"])
                self.session_metadata["start_time"] = datetime.fromisoformat(
                    self.session_metadata["start_time"]
                )
            return True
        except FileNotFoundError:
            return False

    def ask_question(self, question, topic=None):
        """Ask a question and maintain conversation context"""
        # Update metadata
        self.session_metadata["query_count"] += 1
        if topic:
            self.session_metadata["topics"].add(topic)

        # Append the user's question
        self.conversation_history.append({"role": "user", "content": question})

        try:
            # Make the API call with current conversation history
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=self.conversation_history,
                max_tokens=150,
                temperature=0.7,
                presence_penalty=0.6  # Encourage more diverse responses
            )

            # Extract and store the assistant's reply
            answer = response["choices"][0]["message"]["content"]
            self.conversation_history.append({"role": "assistant", "content": answer})
            
            return answer

        except Exception as e:
            error_msg = f"Error during API call: {str(e)}"
            print(error_msg)
            return error_msg

    def get_conversation_summary(self):
        """Return a summary of the conversation session"""
        return {
            "Duration": datetime.now() - self.session_metadata["start_time"],
            "Total Questions": self.session_metadata["query_count"],
            "Topics Covered": list(self.session_metadata["topics"]),
            "Message Count": len(self.conversation_history)
        }

def demonstrate_conversation():
    # Initialize the conversation manager
    manager = ConversationManager()
    
    # Example multi-turn conversation
    questions = [
        ("What is a variable in Python?", "python_basics"),
        ("Can you give an example of declaring one?", "python_basics"),
        ("How do I use variables in a function?", "python_functions")
    ]
    
    # Run through the conversation
    for question, topic in questions:
        print(f"\nUser: {question}")
        response = manager.ask_question(question, topic)
        print(f"Assistant: {response}")
    
    # Save the conversation
    manager.save_conversation()
    
    # Print conversation summary
    print("\nConversation Summary:")
    for key, value in manager.get_conversation_summary().items():
        print(f"{key}: {value}")

if __name__ == "__main__":
    demonstrate_conversation()

Desglose y Explicación del Código:

  1. Estructura de Clase e Inicialización
    • La clase ConversationManager proporciona una forma estructurada de manejar conversaciones
    • Mantiene tanto el historial de conversación como los metadatos de sesión
    • Utiliza un mensaje del sistema para establecer el rol del asistente
  2. Funciones de Almacenamiento Persistente
    • save_conversation(): Exporta el historial de conversación y metadatos a JSON
    • load_conversation(): Restaura conversaciones previas desde archivos guardados
    • Maneja automáticamente la serialización/deserialización de fechas y horas
  3. Manejo Mejorado de Preguntas
    • Rastrea temas de conversación y contador de consultas
    • Incluye manejo de errores para llamadas a la API
    • Utiliza presence_penalty para fomentar respuestas diversas
  4. Metadatos y Análisis
    • Rastrea la duración de la sesión
    • Mantiene un conjunto de temas de conversación
    • Proporciona resúmenes detallados de la conversación
  5. Mejoras Clave Sobre la Versión Básica
    • Agregado manejo de errores y registro apropiado
    • Implementada persistencia de conversación
    • Incluidos análisis y metadatos de sesión
    • Mejorada modularidad y organización del código

Este ejemplo proporciona una base robusta para construir aplicaciones conversacionales, con características de persistencia, manejo de errores y análisis que serían valiosas en un entorno de producción.

En este ejemplo, el historial de conversación (memoria a corto plazo) se actualiza continuamente con cada interacción, permitiendo que el asistente haga referencia a mensajes anteriores según sea necesario.

7.1.2 Memoria a Largo Plazo

Mientras que la memoria a corto plazo es inherente en cada llamada a la API, la memoria a largo plazo en la IA conversacional representa un enfoque más sofisticado para mantener el contexto a través de múltiples interacciones. A diferencia de la memoria a corto plazo, que solo retiene información durante una única conversación, la memoria a largo plazo crea un registro persistente de las interacciones del usuario que puede abarcar días, semanas o incluso meses. Esto se logra típicamente almacenando historiales de conversación en bases de datos o sistemas de archivos, que luego pueden ser accedidos de manera inteligente cuando sea necesario.

El proceso funciona primero capturando y almacenando datos relevantes de la conversación, incluyendo preferencias del usuario, detalles importantes y puntos clave de discusión. Cuando un usuario regresa para una nueva sesión, el sistema puede recuperar esta información almacenada e inyectar selectivamente el contexto más relevante en futuros mensajes. Esto crea una experiencia más personalizada y continua, ya que la IA puede hacer referencia a interacciones pasadas y construir sobre el conocimiento previamente establecido.

Por ejemplo, si un usuario discutió sus preferencias dietéticas en una sesión anterior, el sistema puede recordar esta información semanas después al proporcionar recomendaciones de recetas, creando una interacción más natural y contextualmente consciente. Esta capacidad de mantener y utilizar el contexto histórico es esencial para construir sistemas conversacionales verdaderamente inteligentes que puedan proporcionar continuidad y personalización a través de múltiples interacciones.

Características Clave de la Memoria a Largo Plazo:

Persistencia Entre Sesiones:

La memoria a largo plazo implica crear un registro permanente del historial de conversación en bases de datos o sistemas de almacenamiento, formando una base de conocimiento integral para cada interacción del usuario. Este enfoque sofisticado permite que los sistemas de IA mantengan un contexto detallado incluso cuando los usuarios regresan después de períodos prolongados - desde días hasta meses o incluso años.

El sistema logra esto a través de varios mecanismos clave:

  1. Almacenamiento de Conversación: Cada interacción significativa se almacena en bases de datos estructuradas, incluyendo preferencias del usuario, solicitudes específicas y decisiones importantes.
  2. Recuperación de Contexto: Cuando un usuario regresa, el sistema puede acceder y utilizar inteligentemente sus datos históricos para proporcionar respuestas personalizadas.
  3. Reconocimiento de Patrones: Con el tiempo, el sistema aprende los patrones y preferencias del usuario, creando una comprensión más matizada de las necesidades individuales.

Por ejemplo:

  • Un usuario menciona que es alérgico a los frutos secos en enero. Seis meses después, cuando solicita recomendaciones de recetas, el sistema automáticamente filtra las recetas que contienen frutos secos.
  • Durante una conversación de soporte técnico en marzo, un usuario indica que está usando Windows 11. En diciembre, cuando busca ayuda con un nuevo problema, el sistema ya conoce su sistema operativo.
  • Una aplicación de aprendizaje de idiomas recuerda que un usuario tiene dificultades con las conjugaciones en tiempo pasado, incorporando automáticamente más ejercicios de práctica en esta área a través de múltiples sesiones.

Aquí está el código de implementación:

from datetime import datetime
import openai

class LongTermMemorySystem:
    def __init__(self, api_key):
        self.api_key = api_key
        openai.api_key = api_key
        self.preferences = {}
    
    def store_preference(self, user_id, pref_type, pref_value):
        if user_id not in self.preferences:
            self.preferences[user_id] = []
        self.preferences[user_id].append({
            'type': pref_type,
            'value': pref_value,
            'timestamp': datetime.now()
        })

    def get_user_preferences(self, user_id, pref_type=None):
        if user_id not in self.preferences:
            return []
        
        if pref_type:
            relevant_prefs = [p for p in self.preferences[user_id] 
                            if p['type'] == pref_type]
            return [(p['value'],) for p in sorted(relevant_prefs, 
                    key=lambda x: x['timestamp'], reverse=True)]
        
        return [(p['type'], p['value']) for p in self.preferences[user_id]]

    async def get_ai_response(self, prompt, context):
        try:
            response = await openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "You are an AI assistant with access to user preferences."},
                    {"role": "user", "content": f"Context: {context}\nPrompt: {prompt}"}
                ]
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"

# Example usage
async def demonstrate_long_term_memory():
    memory_system = LongTermMemorySystem("your-api-key-here")
    
    # Scenario 1: Food Allergies
    user_id = "user123"
    memory_system.store_preference(user_id, "food_allergy", "nuts")
    
    async def get_recipe_recommendations(user_id):
        allergies = memory_system.get_user_preferences(user_id, "food_allergy")
        context = f"User has allergies: {allergies if allergies else 'None'}"
        prompt = "Recommend safe recipes for this user."
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 2: Technical Support
    memory_system.store_preference(user_id, "operating_system", "Windows 11")
    
    async def provide_tech_support(user_id, issue):
        os = memory_system.get_user_preferences(user_id, "operating_system")
        context = f"User's OS: {os[0][0] if os else 'Unknown'}"
        prompt = f"Help with issue: {issue}"
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 3: Language Learning
    memory_system.store_preference(user_id, "grammar_challenge", "past_tense")
    
    async def generate_language_exercises(user_id):
        challenges = memory_system.get_user_preferences(user_id, "grammar_challenge")
        context = f"User struggles with: {challenges[0][0] if challenges else 'No specific areas'}"
        prompt = "Generate appropriate language exercises."
        return await memory_system.get_ai_response(prompt, context)

    # Demonstrate the system
    print("Recipe Recommendations:", await get_recipe_recommendations(user_id))
    print("Tech Support:", await provide_tech_support(user_id, "printer not working"))
    print("Language Exercises:", await generate_language_exercises(user_id))

if __name__ == "__main__":
    import asyncio
    asyncio.run(demonstrate_long_term_memory())

Este código implementa un sistema de memoria a largo plazo para conversaciones de IA que almacena y gestiona las preferencias del usuario.

Aquí se desglosan sus componentes principales:

  1. Clase LongTermMemorySystem
  • Se inicializa con una clave API para la integración con OpenAI
  • Mantiene un diccionario de preferencias de usuario
  1. Métodos Principales
  • store_preference: Almacena preferencias de usuario con marcas de tiempo
  • get_user_preferences: Recupera preferencias almacenadas, opcionalmente filtradas por tipo
  • get_ai_response: Genera respuestas de IA usando la API de OpenAI con contexto del usuario
  1. Escenarios de Demostración
  • Alergias Alimentarias: Almacena y utiliza información sobre alergias para recomendaciones de recetas
  • Soporte Técnico: Mantiene información del sistema operativo para soporte técnico contextual
  • Aprendizaje de Idiomas: Registra desafíos gramaticales para personalizar ejercicios

El sistema demuestra cómo mantener preferencias persistentes del usuario a través de múltiples sesiones, permitiendo interacciones personalizadas y conscientes del contexto. Utiliza programación asíncrona (async/await) para interacciones eficientes con la API e incluye manejo de errores para una operación robusta.

Esta persistencia asegura que la IA desarrolle una comprensión cada vez más sofisticada de cada usuario con el tiempo, conduciendo a interacciones más personalizadas, relevantes y conscientes del contexto. El sistema esencialmente desarrolla una "memoria" de las preferencias, desafíos e historial de cada usuario, similar a como un humano recordaría detalles importantes sobre amigos o colegas.

Recuperación Selectiva:

En lugar de cargar todo el historial de conversación para cada interacción, los sistemas de memoria a largo plazo utilizan métodos sofisticados de recuperación para acceder eficientemente a la información relevante. Estos sistemas emplean varias técnicas avanzadas:

  • Búsqueda Vectorial
    • Convierte texto en representaciones matemáticas (vectores)
    • Encuentra rápidamente conversaciones con significado semántico similar
    • Ejemplo: Cuando un usuario pregunta sobre "frameworks de aprendizaje automático", el sistema puede encontrar discusiones previas sobre TensorFlow o PyTorch, incluso si no se usaron exactamente esos términos
  • Puntuación de Importancia
    • Clasifica segmentos de conversación basados en relevancia y significancia
    • Considera factores como actualidad, participación del usuario y alineación temática
    • Ejemplo: Una discusión detallada reciente sobre programación tendría mayor prioridad que una mención breve antigua al responder preguntas de código
  • Relevancia Temporal
    • Pondera la información basada en sensibilidad temporal
    • Prioriza conversaciones recientes mientras mantiene acceso a contexto histórico importante
    • Ejemplo: Al discutir preferencias actuales, las conversaciones recientes sobre gustos/disgustos tienen prioridad sobre las más antiguas que podrían estar desactualizadas

Aquí hay un ejemplo de implementación de estos conceptos:

from datetime import datetime
import openai
from typing import List, Dict, Optional

class AdvancedMemoryRetrieval:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.conversations = []
        
    def add_conversation(self, text: str, timestamp: Optional[datetime] = None, engagement_score: float = 0):
        if timestamp is None:
            timestamp = datetime.now()
        
        # Convert text to vector representation using OpenAI
        try:
            response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=text
            )
            vector = response['data'][0]['embedding']
        except Exception as e:
            print(f"Error creating embedding: {e}")
            vector = None
        
        self.conversations.append({
            'text': text,
            'vector': vector,
            'timestamp': timestamp,
            'engagement': engagement_score
        })
    
    def vector_search(self, query: str, top_k: int = 3) -> List[Dict]:
        try:
            query_response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=query
            )
            query_vector = query_response['data'][0]['embedding']
            
            similarities = []
            for conv in self.conversations:
                if conv['vector'] is not None:
                    # Calculate cosine similarity
                    similarity = self._calculate_similarity(query_vector, conv['vector'])
                    similarities.append((conv, similarity))
            
            return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]
        except Exception as e:
            print(f"Error in vector search: {e}")
            return []
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def calculate_importance_score(self, conversation: Dict, query_time: datetime) -> float:
        time_diff = (query_time - conversation['timestamp']).total_seconds()
        recency_score = 1 / (1 + np.log1p(time_diff))
        return 0.7 * recency_score + 0.3 * conversation['engagement']
    
    def retrieve_relevant_context(self, query: str, top_k: int = 3) -> List[Dict]:
        # Get semantically similar conversations
        similar_convs = self.vector_search(query, top_k=top_k*2)
        
        if not similar_convs:
            return []
        
        # Calculate importance scores
        now = datetime.now()
        scored_convs = []
        for conv, similarity in similar_convs:
            importance = self.calculate_importance_score(conv, now)
            final_score = 0.6 * similarity + 0.4 * importance
            scored_convs.append((conv, final_score))
        
        # Get top results
        top_results = sorted(scored_convs, key=lambda x: x[1], reverse=True)[:top_k]
        
        # Use GPT-4o to enhance context understanding
        try:
            contexts = [result[0]['text'] for result in top_results]
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Analyze these conversation snippets and their relevance to the query."},
                    {"role": "user", "content": f"Query: {query}\nContexts: {contexts}"}
                ]
            )
            # Add GPT-4o analysis to results
            for result in top_results:
                result[0]['analysis'] = response.choices[0].message.content
        except Exception as e:
            print(f"Error in GPT analysis: {e}")
        
        return top_results

# Example usage
def demonstrate_retrieval():
    retriever = AdvancedMemoryRetrieval("your-openai-api-key-here")
    
    # Add some sample conversations
    retriever.add_conversation(
        "TensorFlow is great for deep learning projects",
        timestamp=datetime(2025, 1, 1),
        engagement_score=0.8
    )
    retriever.add_conversation(
        "PyTorch provides dynamic computational graphs",
        timestamp=datetime(2025, 3, 1),
        engagement_score=0.9
    )
    
    # Retrieve relevant context
    query = "What are good machine learning frameworks?"
    results = retriever.retrieve_relevant_context(query)
    
    for conv, score in results:
        print(f"Score: {score:.2f}")
        print(f"Text: {conv['text']}")
        if 'analysis' in conv:
            print(f"Analysis: {conv['analysis']}\n")

if __name__ == "__main__":
    demonstrate_retrieval()

Este código implementa un sistema avanzado de recuperación de memoria conversacional.

Aquí se desglosan sus componentes principales:

  1. Estructura de Clase Principal
  • La clase AdvancedMemoryRetrieval gestiona el almacenamiento y recuperación de conversaciones
  • Utiliza la API de OpenAI para crear embeddings de texto y analizar conversaciones
  1. Características Principales
  • Almacenamiento de Conversaciones:
    • Almacena texto, embeddings vectoriales, marcas temporales y puntuaciones de participación
    • Crea representaciones vectoriales de conversaciones usando el modelo de embedding de OpenAI
  • Búsqueda Vectorial:
    • Implementa búsqueda semántica usando similitud del coseno
    • Devuelve las k conversaciones más similares basadas en comparaciones vectoriales
  • Puntuación de Importancia:
    • Combina métricas de actualidad (basadas en tiempo) y participación
    • Utiliza una fórmula ponderada: 70% actualidad + 30% participación
  • Recuperación de Contexto:
    • Combina similitud vectorial (60%) con puntuaciones de importancia (40%)
    • Utiliza GPT-4o para analizar y mejorar la comprensión de los contextos recuperados
  1. Implementación de Ejemplo
  • El código de demostración muestra cómo:
    • Inicializar el sistema con conversaciones de ejemplo sobre frameworks de aprendizaje automático
    • Recuperar contexto relevante basado en una consulta
    • Mostrar resultados con puntuaciones y análisis

Esta implementación muestra técnicas modernas para gestionar el historial de conversaciones, combinando búsqueda semántica, relevancia temporal y métricas de participación para proporcionar respuestas contextualmente apropiadas.

Este enfoque selectivo asegura que las respuestas sean focalizadas y relevantes mientras mantiene la eficiencia computacional. Por ejemplo, en un escenario de soporte técnico, cuando un usuario pregunta sobre la resolución de problemas de una función específica del software, el sistema recuperaría solo las conversaciones previas sobre esa función y mensajes de error relacionados, en lugar de cargar todo su historial de soporte.

Al implementar estos métodos de recuperación, el sistema puede mantener la conciencia contextual de una conversación humana mientras opera dentro de límites computacionales prácticos.

Gestión Personalizada:

Construir una memoria a largo plazo efectiva requiere un diseño de sistema cuidadoso y la consideración de múltiples factores. Exploremos los componentes clave:

1. Arquitectura de Almacenamiento

Las estructuras de almacenamiento eficientes son cruciales para gestionar el historial de conversaciones. Esto puede incluir:

  • Bases de datos distribuidas para escalabilidad
    • Uso de MongoDB para datos de conversación no estructurados
    • Implementación de Redis para interacciones recientes de acceso rápido

2. Mecanismos de Recuperación

Los algoritmos de recuperación inteligente aseguran un acceso rápido a la información relevante:

  • Búsqueda semántica usando embeddings
    • Ejemplo: Convertir "¿Cómo restablezco mi contraseña?" en un vector para encontrar consultas similares anteriores
  • Clasificación contextual
    • Ejemplo: Priorizar conversaciones recientes de soporte técnico cuando el usuario reporta un error

3. Compresión de Datos y Resumen

Métodos para mantener la eficiencia mientras se preserva el significado:

  • Resumen automático de conversaciones
    • Ejemplo: Condensar un hilo de 30 mensajes sobre requisitos de proyecto en puntos clave
  • Técnicas de compresión inteligente
    • Ejemplo: Almacenar patrones comunes como plantillas en lugar de conversaciones completas

4. Gestión de Limitaciones del Sistema

Equilibrar capacidades con recursos:

  • Cuotas de almacenamiento por usuario/conversación
    • Ejemplo: Limitar el almacenamiento a 6 meses de historial de conversación por defecto
  • Asignación de poder de procesamiento
    • Ejemplo: Usar procesamiento por lotes para análisis histórico durante horas valle

5. Privacidad y Seguridad

Consideraciones críticas para el manejo de datos:

  • Cifrado de conversaciones almacenadas
    • Ejemplo: Usar cifrado AES-256 para todos los datos de conversación
  • Gestión del consentimiento del usuario
    • Ejemplo: Permitir que los usuarios opten por no participar en el almacenamiento a largo plazo

6. Ciclo de Vida de la Información

Gestionar datos durante su vida útil:

  • Reglas de archivo automatizado
    • Ejemplo: Mover conversaciones de más de 1 año a almacenamiento frío
  • Políticas de degradación de datos
    • Ejemplo: Eliminar automáticamente información personal después de períodos específicos
  • Evaluación regular de relevancia
    • Ejemplo: Usar métricas de participación para determinar qué información retener

Aquí hay una implementación de código:

import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import openai

class ConversationManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.storage = {}
        self.user_preferences = {}
        
    def summarize_conversation(self, messages: List[Dict]) -> str:
        """Summarize a conversation thread using GPT-4o."""
        try:
            conversation_text = "\n".join([f"{msg['role']}: {msg['content']}" for msg in messages])
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Please summarize this conversation in 3 key points."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            # Fallback to simple summarization if API call fails
            summary = []
            for msg in messages[-3:]:  # Take last 3 messages
                if len(msg['content']) > 100:
                    summary.append(f"Key point: {msg['content'][:100]}...")
                else:
                    summary.append(msg['content'])
            return "\n".join(summary)
    
    def store_conversation(self, user_id: str, conversation: List[Dict]) -> bool:
        """Store conversation with quota and privacy checks."""
        # Check storage quota
        if len(self.storage.get(user_id, [])) >= 1000:  # Example quota
            self._archive_old_conversations(user_id)
            
        # Check user consent
        if not self.user_preferences.get(user_id, {}).get('storage_consent', True):
            return False
            
        # Generate embedding for semantic search
        conversation_text = " ".join(msg['content'] for msg in conversation)
        try:
            embedding = openai.Embedding.create(
                input=conversation_text,
                model="text-embedding-ada-002"
            )
            embedding_vector = embedding['data'][0]['embedding']
        except Exception:
            embedding_vector = None
            
        # Store conversation with summary and embedding
        summary = self.summarize_conversation(conversation)
        if user_id not in self.storage:
            self.storage[user_id] = []
        self.storage[user_id].append({
            'timestamp': datetime.now(),
            'summary': summary,
            'conversation': conversation,
            'embedding': embedding_vector
        })
        return True
    
    def _archive_old_conversations(self, user_id: str) -> None:
        """Archive conversations older than 6 months."""
        cutoff_date = datetime.now() - timedelta(days=180)
        current = self.storage.get(user_id, [])
        self.storage[user_id] = [
            conv for conv in current 
            if conv['timestamp'] > cutoff_date
        ]
    
    def get_relevant_context(self, user_id: str, query: str) -> Optional[str]:
        """Retrieve relevant context using semantic search."""
        if user_id not in self.storage:
            return None
            
        try:
            # Get query embedding
            query_embedding = openai.Embedding.create(
                input=query,
                model="text-embedding-ada-002"
            )
            query_vector = query_embedding['data'][0]['embedding']
            
            # Find most relevant conversations
            relevant_contexts = []
            for conv in self.storage[user_id]:
                if conv['embedding']:
                    relevance_score = self._calculate_similarity(
                        query_vector,
                        conv['embedding']
                    )
                    if relevance_score > 0.7:  # Threshold
                        relevant_contexts.append(conv['summary'])
                        
            return relevant_contexts[0] if relevant_contexts else None
        except Exception:
            # Fallback to simple word matching if embedding fails
            return self._simple_context_search(user_id, query)
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def _simple_context_search(self, user_id: str, query: str) -> Optional[str]:
        """Simple relevance calculation using word overlap."""
        query_words = set(query.lower().split())
        best_score = 0
        best_summary = None
        
        for conv in self.storage[user_id]:
            summary_words = set(conv['summary'].lower().split())
            score = len(query_words & summary_words) / len(query_words)
            if score > best_score:
                best_score = score
                best_summary = conv['summary']
                
        return best_summary if best_score > 0.3 else None

# Example usage
def demonstrate_conversation_management():
    manager = ConversationManager("your-openai-api-key-here")
    
    # Store a conversation
    user_id = "user123"
    conversation = [
        {"role": "user", "content": "How do I implement encryption?"},
        {"role": "assistant", "content": "Here's a detailed guide..."},
        {"role": "user", "content": "Thanks, that helps!"}
    ]
    
    # Set user preferences
    manager.user_preferences[user_id] = {'storage_consent': True}
    
    # Store the conversation
    stored = manager.store_conversation(user_id, conversation)
    print(f"Conversation stored: {stored}")
    
    # Later, retrieve relevant context
    context = manager.get_relevant_context(user_id, "encryption implementation")
    print(f"Retrieved context: {context}")

if __name__ == "__main__":
    demonstrate_conversation_management()

Este código implementa una clase ConversationManager para gestionar conversaciones de IA con memoria y recuperación de contexto.

Aquí están los componentes principales:

Funcionalidad Central:

  • Almacenamiento de Conversaciones:
    • Almacena conversaciones con marcas de tiempo, resúmenes y embeddings
    • Implementa cuotas de almacenamiento y verificaciones de consentimiento del usuario
    • Archiva conversaciones con más de 6 meses de antigüedad
  • Resumen de Conversaciones:
    • Utiliza GPT-4o para crear resúmenes concisos de conversaciones
    • Incluye mecanismo de respaldo cuando fallan las llamadas a la API
    • Almacena resúmenes para una recuperación eficiente
  • Búsqueda Semántica:
    • Genera embeddings usando el modelo de embedding de OpenAI
    • Implementa similitud del coseno para encontrar conversaciones relevantes
    • Incluye respaldo a coincidencia simple de palabras cuando fallan los embeddings

Características Principales:

  • Controles de Privacidad:
    • Verifica el consentimiento del usuario antes de almacenar conversaciones
    • Gestiona preferencias de usuario y consentimiento de almacenamiento
  • Gestión de Memoria:
    • Implementa cuotas de almacenamiento (1000 conversaciones por usuario)
    • Archiva conversaciones antiguas automáticamente
    • Utiliza búsqueda semántica para recuperar contexto relevante

Ejemplo de Uso:

  • El código demuestra:
    • Almacenamiento de una conversación sobre encriptación
    • Configuración de preferencias de usuario
    • Recuperación de contexto relevante basado en consultas

Esta implementación se centra en equilibrar el almacenamiento eficiente de conversaciones con la recuperación inteligente, mientras mantiene la privacidad del usuario y el rendimiento del sistema.

Este ejemplo demuestra la aplicación práctica de los conceptos discutidos anteriormente, incluyendo compresión de datos, limitaciones del sistema, controles de privacidad y gestión del ciclo de vida de la información. El código proporciona una base que puede extenderse con características más sofisticadas como resumen basado en aprendizaje automático o esquemas de encriptación avanzados.

Un Ejemplo Completo: Simulando Memoria a Largo Plazo

Exploremos un ejemplo práctico que demuestra cómo implementar la memoria de conversación en aplicaciones de IA. Este ejemplo muestra dos componentes clave: guardar el historial de conversación para referencia futura y recuperar el contexto relevante al comenzar una nueva sesión de conversación. Para mantener el ejemplo sencillo y enfocarnos en los conceptos principales, usaremos un enfoque simple de almacenamiento en memoria usando una variable, aunque en un entorno de producción típicamente usarías un sistema de base de datos o almacenamiento persistente.

Este ejemplo sirve para ilustrar varios conceptos importantes:

  • Cómo capturar y almacenar historial de conversación significativo
    • La mecánica de guardar información contextual para referencia futura
    • Métodos para recuperar y utilizar contexto previo de conversación
  • Cómo mantener la continuidad de conversación a través de múltiples sesiones
    • Técnicas para integrar contexto pasado en nuevas conversaciones
    • Estrategias para gestionar el estado de la conversación

# Comprehensive example of conversation memory management with OpenAI API

from typing import List, Dict, Optional
import json
from datetime import datetime
import openai
from dataclasses import dataclass
from enum import Enum

class MemoryType(Enum):
    SHORT_TERM = "short_term"
    LONG_TERM = "long_term"
    SEMANTIC = "semantic"

@dataclass
class Message:
    role: str  # system, user, or assistant
    content: str
    timestamp: datetime
    metadata: Dict = None

class ConversationMemoryManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.long_term_memory = []
        self.semantic_memory = {}  # Store embeddings for semantic search
        self.active_conversations = {}
        self.max_memory_size = 1000
        self.model = "gpt-4o"  # OpenAI model to use
        
    def save_conversation(self, conversation_id: str, messages: List[Message]) -> bool:
        """
        Save conversation with metadata and timestamps.
        Returns success status.
        """
        try:
            # Generate embeddings for semantic search
            conversation_text = " ".join(msg.content for msg in messages)
            embedding = self._get_embedding(conversation_text)
            
            conversation_data = {
                "id": conversation_id,
                "timestamp": datetime.now(),
                "messages": [self._message_to_dict(msg) for msg in messages],
                "summary": self._generate_summary(messages),
                "embedding": embedding
            }
            
            # Implement memory management
            if len(self.long_term_memory) >= self.max_memory_size:
                self._prune_old_conversations()
                
            self.long_term_memory.append(conversation_data)
            self._update_semantic_memory(conversation_data)
            return True
        except Exception as e:
            print(f"Error saving conversation: {e}")
            return False
    
    def retrieve_context(self, 
                        conversation_id: str, 
                        query: str = None,
                        memory_type: MemoryType = MemoryType.LONG_TERM) -> Optional[str]:
        """
        Retrieve context based on memory type and query.
        Uses OpenAI embeddings for semantic search.
        """
        if memory_type == MemoryType.SEMANTIC and query:
            return self._semantic_search(query)
        elif memory_type == MemoryType.LONG_TERM:
            return self._get_latest_context(conversation_id)
        return None

    def _get_embedding(self, text: str) -> List[float]:
        """
        Get embeddings using OpenAI's embedding model.
        """
        response = openai.Embedding.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response['data'][0]['embedding']

    def _semantic_search(self, query: str) -> Optional[str]:
        """
        Perform semantic search using OpenAI embeddings.
        """
        if not self.semantic_memory:
            return None
            
        query_embedding = self._get_embedding(query)
        
        # Calculate cosine similarity with stored embeddings
        best_match = None
        best_score = -1
        
        for conv_id, conv_data in self.semantic_memory.items():
            similarity = self._cosine_similarity(query_embedding, conv_data["embedding"])
            if similarity > best_score:
                best_score = similarity
                best_match = conv_data["summary"]
        
        return best_match if best_score > 0.7 else None

    def _cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """
        Calculate cosine similarity between two vectors.
        """
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

    def _get_latest_context(self, conversation_id: str) -> Optional[str]:
        """
        Retrieve the most recent relevant context.
        """
        relevant_convs = [
            conv for conv in self.long_term_memory 
            if conv["id"] == conversation_id
        ]
        
        if not relevant_convs:
            return None
            
        latest_conv = max(relevant_convs, key=lambda x: x["timestamp"])
        return latest_conv["summary"]

    def _generate_summary(self, messages: List[Message]) -> str:
        """
        Generate a summary using OpenAI's GPT-4o model.
        """
        try:
            conversation_text = "\n".join([f"{msg.role}: {msg.content}" for msg in messages])
            response = openai.ChatCompletion.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": "Please provide a brief summary of the following conversation."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            print(f"Error generating summary: {e}")
            # Fallback to simple summary
            key_messages = [msg for msg in messages if msg.role == "assistant"][-3:]
            return " ".join(msg.content[:100] + "..." for msg in key_messages)

    def _message_to_dict(self, message: Message) -> Dict:
        """
        Convert Message object to dictionary format compatible with OpenAI API.
        """
        return {
            "role": message.role,
            "content": message.content,
            "timestamp": message.timestamp.isoformat(),
            "metadata": message.metadata or {}
        }

    def _prune_old_conversations(self) -> None:
        """
        Remove oldest conversations when reaching memory limit.
        """
        self.long_term_memory.sort(key=lambda x: x["timestamp"])
        self.long_term_memory = self.long_term_memory[-self.max_memory_size:]

    def _update_semantic_memory(self, conversation_data: Dict) -> None:
        """
        Update semantic memory with conversation embeddings.
        """
        self.semantic_memory[conversation_data["id"]] = {
            "embedding": conversation_data["embedding"],
            "summary": conversation_data["summary"]
        }

# Example usage
def demonstrate_conversation_memory():
    # Initialize memory manager with OpenAI API key
    memory_manager = ConversationMemoryManager("your-api-key-here")
    
    # Create sample conversation
    conversation_id = "conv_123"
    messages = [
        Message(
            role="system",
            content="You are a helpful assistant that explains concepts clearly.",
            timestamp=datetime.now()
        ),
        Message(
            role="user",
            content="What is a class in object-oriented programming?",
            timestamp=datetime.now()
        ),
        Message(
            role="assistant",
            content="A class in OOP is a blueprint for creating objects, defining their properties and behaviors.",
            timestamp=datetime.now()
        )
    ]
    
    # Save conversation
    memory_manager.save_conversation(conversation_id, messages)
    
    # Retrieve context using different methods
    long_term_context = memory_manager.retrieve_context(
        conversation_id,
        memory_type=MemoryType.LONG_TERM
    )
    print("Long-term Context:", long_term_context)
    
    semantic_context = memory_manager.retrieve_context(
        conversation_id,
        query="How do classes work in programming?",
        memory_type=MemoryType.SEMANTIC
    )
    print("Semantic Context:", semantic_context)

if __name__ == "__main__":
    demonstrate_conversation_memory()

Este código de ejemplo implementa un sistema integral de gestión de memoria de conversación. Estos son los componentes principales:

1. Clases principales y estructuras de datos

  • El enum MemoryType define tres tipos de memoria: corto plazo, largo plazo y semántica
  • La dataclass Message almacena mensajes de conversación con rol, contenido, marca de tiempo y metadatos

2. Clase ConversationMemoryManager

  • Gestiona tres tipos de almacenamiento:
    • Memoria a largo plazo: Almacena conversaciones completas
    • Memoria semántica: Almacena embeddings para búsqueda semántica
    • Conversaciones activas: Maneja conversaciones en curso

3. Características principales

  • Guardado de conversaciones: Almacena conversaciones con metadatos, marcas de tiempo y embeddings
  • Recuperación de contexto: Admite tanto recuperación directa como búsqueda semántica
  • Gestión de memoria: Implementa poda al alcanzar el tamaño máximo de memoria (1000 conversaciones)
  • Resumen automático: Genera resúmenes de conversación usando el modelo GPT de OpenAI

4. Características avanzadas

  • Búsqueda semántica usando embeddings de OpenAI y similitud del coseno
  • Mecanismos de respaldo para la generación de resúmenes si la API de OpenAI falla
  • Poda eficiente de memoria para mantener el rendimiento del sistema

El código demuestra la implementación tanto de búsqueda semántica como de almacenamiento tradicional de conversaciones, haciéndolo adecuado para aplicaciones que requieren una gestión sofisticada de memoria de conversación.

Entender la interacción entre la memoria a corto y largo plazo es crucial para diseñar conversaciones efectivas de múltiples turnos en sistemas de IA. Analicemos estos dos tipos de memoria y sus roles:

La memoria a corto plazo opera dentro del contexto inmediato de una conversación. Se maneja automáticamente durante cada llamada a la API, manteniendo el flujo actual del diálogo y los intercambios recientes. Este tipo de memoria es esencial para comprender el contexto inmediato, las referencias y mantener la coherencia dentro de una única sesión de conversación.

La memoria a largo plazo, por otro lado, requiere una implementación más sofisticada. Involucra:

  • Almacenamiento persistente del historial de conversaciones en bases de datos o sistemas de almacenamiento externos
  • Mecanismos inteligentes de recuperación para seleccionar contexto histórico relevante
  • Decisiones estratégicas sobre qué información almacenar y recuperar
  • Métodos para gestionar limitaciones de almacenamiento y limpiar datos antiguos

Cuando combinas estos dos enfoques de memoria de manera efectiva, puedes crear aplicaciones de IA que demuestren:

  • Conciencia contextual a través de múltiples conversaciones
  • Flujo de conversación natural que se siente humano
  • Capacidad para hacer referencia y construir sobre interacciones pasadas
  • Comprensión consistente de las preferencias e historial del usuario

La clave del éxito radica en encontrar el equilibrio adecuado entre estos tipos de memoria e implementarlos de una manera que mejore la experiencia del usuario mientras se gestionan eficientemente los recursos del sistema.

7.1 Memoria a Corto vs Largo Plazo

El Capítulo 7 explora los aspectos críticos de la gestión del historial de conversaciones y el contexto en aplicaciones de IA, centrándose particularmente en cómo los sistemas de memoria impactan la efectividad de las interacciones de múltiples turnos. A medida que los asistentes de IA se vuelven cada vez más sofisticados, entender cómo implementar y gestionar adecuadamente la memoria conversacional se vuelve esencial para los desarrolladores que construyen aplicaciones robustas de IA.

Este capítulo te guiará a través de varios enfoques para manejar el historial de conversaciones, desde la gestión básica del contexto hasta técnicas avanzadas para mantener interacciones a largo plazo con el usuario. Exploraremos las diferencias entre los sistemas de memoria a corto y largo plazo, discutiremos implementaciones prácticas de gestión de hilos, y examinaremos estrategias para manejar las limitaciones de contexto.

Profundicemos en los cinco temas críticos que exploraremos en este capítulo:

  • Memoria a Corto vs Largo Plazo: Este concepto fundamental explora cómo los sistemas de IA manejan las conversaciones inmediatas versus el almacenamiento de información para uso futuro. Examinaremos cómo la memoria a corto plazo gestiona el contexto y las respuestas actuales, mientras que la memoria a largo plazo mantiene las preferencias del usuario, las interacciones pasadas y los comportamientos aprendidos a través de múltiples sesiones. Comprender estas diferencias es crucial para construir sistemas efectivos de IA conversacional.
  • Gestión de Hilos y Ventanas de Contexto: Profundizaremos en los aspectos técnicos de la gestión de hilos de conversación, incluyendo cómo organizar y mantener múltiples flujos de conversación simultáneamente. Aprenderás sobre las limitaciones de tokens en diferentes modelos de IA, cómo optimizar las ventanas de contexto para un mejor rendimiento, y técnicas para gestionar conversaciones complejas y ramificadas de manera efectiva.
  • Almacenamiento y Recuperación de Interacciones Pasadas: Esta sección cubre la implementación práctica de sistemas de almacenamiento de conversaciones. Exploraremos varias soluciones de bases de datos, estrategias de caché y mecanismos de recuperación que permiten a los sistemas de IA acceder y utilizar conversaciones históricas. Aprenderás sobre diferentes enfoques para almacenar datos de conversación, desde almacenamiento simple basado en texto hasta sofisticadas bases de datos vectoriales.
  • Soluciones para Límites de Contexto: Abordaremos uno de los desafíos más comunes en las conversaciones de IA: lidiar con las limitaciones de contexto. Descubrirás estrategias innovadoras para gestionar conversaciones largas, incluyendo técnicas como resumen de conversaciones, poda selectiva de contexto y gestión dinámica de contexto. También exploraremos cómo mantener la coherencia de la conversación cuando se trabaja con ventanas de contexto limitadas.
  • Actualizaciones sobre la Función de Memoria de ChatGPT: Los últimos desarrollos en las capacidades de memoria de ChatGPT están transformando cómo abordamos la gestión de conversaciones. Examinaremos las nuevas características, sus aplicaciones prácticas y cómo los desarrolladores pueden aprovechar estas capacidades en sus aplicaciones. Esta sección también cubrirá las mejores prácticas para integrar las funciones de memoria de ChatGPT con sistemas existentes y posibles desarrollos futuros en esta área.

Al final de este capítulo, tendrás una comprensión integral de cómo implementar sistemas de memoria efectivos en tus aplicaciones de IA, permitiendo conversaciones más naturales y conscientes del contexto.

La memoria conversacional es un pilar fundamental en la construcción de aplicaciones de IA efectivas que pueden participar en diálogos naturales y fluidos. Este sistema de memoria permite a la IA mantener conversaciones coherentes mediante la comprensión y referencia a intercambios previos, de manera similar a cómo los humanos recuerdan y construyen sobre partes anteriores de una conversación. Sin esta capacidad, cada respuesta estaría desconectada y contextualmente ciega, llevando a interacciones frustrantes y poco naturales.

El sistema de memoria en la IA conversacional cumple múltiples funciones cruciales. Ayuda a mantener la continuidad del tema, permite la resolución adecuada de referencias (entendiendo pronombres como "eso" o "ellos"), y permite que la IA construya sobre información previamente establecida. Esto crea una interacción más atractiva e inteligente que se siente natural para los usuarios.

La memoria en la IA conversacional puede entenderse a través de dos perspectivas distintas pero complementarias: memoria a corto plazo y memoria a largo plazo. Estos dos tipos de sistemas de memoria trabajan juntos para crear una comprensión integral tanto del contexto inmediato como de las interacciones históricas.

7.1.1 Memoria a Corto Plazo

La memoria a corto plazo es un componente crucial que permite a los modelos de IA mantener el contexto durante las conversaciones en curso. Piensa en ella como un espacio de trabajo temporal donde la IA mantiene un registro de la discusión actual. Cuando interactúas con la API, envías una secuencia de mensajes que incluyen instrucciones del sistema (que establecen el comportamiento de la IA), entradas del usuario (tus preguntas o declaraciones) y respuestas del asistente (las respuestas previas de la IA).

El modelo procesa toda esta información dentro de su ventana de contexto - un espacio significativo que puede manejar hasta 128,000 tokens en modelos avanzados, aproximadamente equivalente al texto de un libro pequeño. Esta extensa ventana de contexto permite a la IA elaborar respuestas que no solo son relevantes para tu pregunta inmediata sino también consistentes con todo el flujo de la conversación.

Características Clave de la Memoria a Corto Plazo:

Ventana de Contexto

La ventana de contexto sirve como la memoria de trabajo de la IA, funcionando como un búfer temporal que procesa y retiene el historial completo de mensajes proporcionado en tu llamada a la API. Esta ventana es esencial para mantener conversaciones coherentes y permitir que la IA entienda y haga referencia a intercambios previos. Aquí hay un desglose detallado:

  1. Tamaño y Capacidad:
  • GPT-3.5: Puede manejar hasta 4,096 tokens
  • GPT-4: Soporta hasta 8,192 tokens
  • Modelos avanzados: Pueden procesar hasta 128,000 tokens
  1. Gestión de Tokens:
    Cuando las conversaciones exceden estos límites, el sistema emplea un enfoque de "ventana deslizante", eliminando automáticamente mensajes más antiguos para acomodar los nuevos. Este proceso es similar a cómo los humanos naturalmente olvidan detalles específicos de conversaciones anteriores mientras retienen los temas y conceptos principales.

Por ejemplo:

Usuario: "¿Qué tiempo hace?"

Asistente: "Está soleado y hace 75°F."

Usuario: "¿Debería llevar una chaqueta?"

Asistente: "Dada la temperatura cálida que mencioné (75°F), probablemente no necesitarás una chaqueta."

Aquí te mostramos cómo podemos implementar una conversación básica sobre el clima que demuestra la memoria a corto plazo:

import openai
import os
from dotenv import load_dotenv

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

# Initialize conversation history
conversation = [
    {"role": "system", "content": "You are a helpful weather assistant."}
]

def get_response(message):
    # Add user message to conversation history
    conversation.append({"role": "user", "content": message})
    
    # Get response from API
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation,
        temperature=0.7
    )
    
    # Extract and store assistant's response
    assistant_response = response.choices[0].message['content']
    conversation.append({"role": "assistant", "content": assistant_response})
    
    return assistant_response

# Example conversation
print("User: What's the weather like?")
print("Assistant:", get_response("What's the weather like?"))

print("\nUser: Should I bring a jacket?")
print("Assistant:", get_response("Should I bring a jacket?"))

Analicemos cómo este código demuestra la memoria a corto plazo:

  • La lista de conversación mantiene todo el historial del chat
  • Cada nuevo mensaje (tanto del usuario como del asistente) se agrega a este historial
  • Al realizar nuevas llamadas a la API, se envía el contexto completo de la conversación
  • Esto permite que el asistente haga referencia a información previa (como la temperatura) en respuestas subsiguientes

Cuando ejecutes este código, el asistente mantendrá el contexto durante toda la conversación, tal como en nuestro ejemplo donde recordó la temperatura al responder sobre la chaqueta.

En esta interacción, la ventana de contexto mantiene la información de temperatura del primer intercambio, permitiendo que el asistente haga una recomendación relevante en su segunda respuesta. Sin embargo, si esta conversación continuara por cientos de mensajes, los detalles más antiguos eventualmente se recortarían para dar espacio a nueva información.

Gestión de Memoria Específica de Sesión:

La memoria a corto plazo opera dentro de los límites de una única sesión de conversación, similar a cómo funciona la memoria a corto plazo humana durante una discusión específica. Esto significa que la IA mantiene el contexto y recuerda detalles solo dentro del hilo de conversación actual. Analicemos esto con algunos ejemplos:

Durante una sesión:
Usuario: "Mi nombre es Sarah."
Asistente: "¡Encantado de conocerte, Sarah!"
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para ti, Sarah?"

En este caso, el asistente recuerda el nombre del usuario durante toda la conversación. Sin embargo, cuando inicias una nueva sesión:

Nueva sesión:
Usuario: "¿Qué tiempo hace?"
Asistente: "¿Te gustaría que consultara el tiempo para tu ubicación?"

Observa cómo el asistente ya no recuerda el nombre del usuario de la sesión anterior. Esto se debe a que cada nueva sesión comienza con una pizarra limpia. Sin embargo, hay varias formas de mantener la continuidad entre sesiones:

  1. Inyección Explícita de Contexto: Puedes incluir manualmente información importante de sesiones anteriores en tu mensaje inicial o del sistema.
  2. Integración de Base de Datos: Almacenar información clave del usuario y preferencias en una base de datos y recuperarlas al inicio de cada sesión.
  3. Resumen de Sesión: Crear un breve resumen de interacciones previas para incluir en nuevas sesiones cuando sea relevante.

Por ejemplo, para mantener el contexto entre sesiones, podrías comenzar una nueva sesión con:
Sistema: "Esta usuaria es Sarah, quien previamente mostró interés en actualizaciones del tiempo y habla español."

Aquí está el ejemplo de código:

import openai
from datetime import datetime
import sqlite3

class UserSessionManager:
    def __init__(self):
        # Initialize database connection
        self.conn = sqlite3.connect('user_sessions.db')
        self.create_tables()
        
    def create_tables(self):
        cursor = self.conn.cursor()
        # Create tables for user info and session history
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                user_id TEXT PRIMARY KEY,
                name TEXT,
                preferences TEXT
            )
        ''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS sessions (
                session_id TEXT PRIMARY KEY,
                user_id TEXT,
                timestamp DATETIME,
                context TEXT
            )
        ''')
        self.conn.commit()

    def start_new_session(self, user_id):
        # Retrieve user information from database
        cursor = self.conn.cursor()
        cursor.execute('SELECT name, preferences FROM users WHERE user_id = ?', (user_id,))
        user_data = cursor.execute.fetchone()
        
        if user_data:
            name, preferences = user_data
            # Create system message with user context
            system_message = f"This user is {name}. {preferences}"
        else:
            system_message = "You are a helpful assistant."
            
        return [{"role": "system", "content": system_message}]

    def save_user_info(self, user_id, name, preferences):
        cursor = self.conn.cursor()
        cursor.execute('''
            INSERT OR REPLACE INTO users (user_id, name, preferences) 
            VALUES (?, ?, ?)
        ''', (user_id, name, preferences))
        self.conn.commit()

# Example usage
def demonstrate_session_memory():
    session_manager = UserSessionManager()
    
    # First session - Save user information
    session_manager.save_user_info(
        "user123",
        "Sarah",
        "previously expressed interest in weather updates and speaks Spanish"
    )
    
    # Start a new session with context
    conversation = session_manager.start_new_session("user123")
    
    # Make API call with context
    response = openai.ChatCompletion.create(
        model="gpt-4o",
        messages=conversation + [
            {"role": "user", "content": "What's the weather like?"}
        ]
    )
    
    return response

# Run demonstration
if __name__ == "__main__":
    response = demonstrate_session_memory()
    print("Assistant's response with context:", response.choices[0].message['content'])

Desglose del Código:

  • La clase UserSessionManager maneja todas las operaciones relacionadas con la sesión:
    • Inicializa la conexión a la base de datos SQLite para almacenamiento persistente
    • Crea tablas para almacenar información del usuario e historial de sesiones
    • Proporciona métodos para gestionar datos de usuario y sesiones
  • Componentes Principales:
    • create_tables(): Configura el esquema de la base de datos para almacenar datos de usuario e historial de sesiones
    • save_user_info(): Almacena o actualiza la información del usuario en la base de datos
    • start_new_session(): Recupera el contexto del usuario y crea una nueva sesión de conversación
  • La demostración muestra cómo:
    • Guardar información del usuario (nombre, preferencias) en la base de datos
    • Iniciar una nueva sesión que incluye el contexto del usuario
    • Realizar llamadas a la API con el contexto mantenido

Esta implementación permite que el asistente mantenga el contexto del usuario a través de diferentes sesiones, abordando las limitaciones de memoria discutidas en el ejemplo anterior. Cuando Sarah inicia una nueva sesión, el asistente ya conocerá su nombre y preferencias, lo que lleva a interacciones más personalizadas.

Este enfoque te permite transferir selectivamente información importante mientras mantienes la eficiencia de la gestión de memoria específica de sesión.

Actualizaciones Dinámicas y Refinamiento Continuo del Contexto:

La conversación evoluciona naturalmente a medida que se agregan nuevos mensajes al contexto, creando un diálogo fluido y adaptativo. Esta naturaleza dinámica permite que la IA refine continuamente su comprensión y respuestas basándose en la información más reciente, similar a cómo los humanos procesan e incorporan nuevos detalles durante una conversación. El modelo puede:

  • Hacer referencia a puntos anteriores en la conversación con precisión
  • Mantener consistencia a través de múltiples intercambios
  • Construir sobre conceptos previamente establecidos
  • Ajustar sus respuestas basándose en el nuevo contexto

Por ejemplo, considera este flujo de conversación:

Usuario: "Estoy planeando un viaje a Japón."

Asistente: "¡Qué emocionante! ¿Cuándo planeas visitar?"

Usuario: "En abril del próximo año."

Asistente: "¡Abril es perfecto para la temporada de flores de cerezo en Japón! ¿Te gustaría algunas recomendaciones específicas basadas en esta fecha?"

Usuario: "Sí, pero me preocupan las multitudes."

Asistente: "Entiendo tu preocupación sobre las multitudes durante la temporada de flores de cerezo, puedo sugerirte algunos lugares menos turísticos y horarios óptimos para visitar..."

En este intercambio, la IA demuestra actualización dinámica del contexto al:

  • Recordar el plan inicial de viaje
  • Incorporar el momento específico (abril)
  • Conectarlo con información relevante (temporada de flores de cerezo)
  • Adaptar las recomendaciones basándose en la preocupación expresada sobre las multitudes

Aquí hay un ejemplo de código que demuestra este tipo de conversación contextual:

import openai
from datetime import datetime

class TravelAssistant:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a helpful travel assistant specializing in Japan travel advice."}
        ]
        self.user_preferences = {
            "destination": None,
            "travel_date": None,
            "concerns": []
        }

    def update_preferences(self, message):
        # Simple preference extraction logic
        if "Japan" in message:
            self.user_preferences["destination"] = "Japan"
        if "April" in message:
            self.user_preferences["travel_date"] = "April"
        if "crowds" in message.lower():
            self.user_preferences["concerns"].append("crowds")

    def get_contextual_response(self, user_message):
        # Update user preferences based on message
        self.update_preferences(user_message)
        
        # Add user message to conversation history
        self.conversation_history.append({"role": "user", "content": user_message})
        
        # Generate system note with current context
        context_note = self._generate_context_note()
        if context_note:
            self.conversation_history.append({"role": "system", "content": context_note})

        # Get response from API
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=self.conversation_history,
            temperature=0.7
        )

        assistant_response = response.choices[0].message["content"]
        self.conversation_history.append({"role": "assistant", "content": assistant_response})
        return assistant_response

    def _generate_context_note(self):
        context = []
        if self.user_preferences["destination"]:
            context.append(f"User is planning a trip to {self.user_preferences['destination']}")
        if self.user_preferences["travel_date"]:
            context.append(f"Planning to travel in {self.user_preferences['travel_date']}")
        if self.user_preferences["concerns"]:
            context.append(f"Expressed concerns about: {', '.join(self.user_preferences['concerns'])}")
        
        return "; ".join(context) if context else None

# Example usage
def demonstrate_travel_assistant():
    assistant = TravelAssistant()
    
    # Simulate the conversation
    conversation = [
        "I'm planning a trip to Japan.",
        "In April next year.",
        "Yes, but I'm worried about the crowds."
    ]
    
    print("Starting conversation simulation...")
    for message in conversation:
        print(f"\nUser: {message}")
        response = assistant.get_contextual_response(message)
        print(f"Assistant: {response}")
        print(f"Current Context: {assistant._generate_context_note()}")

if __name__ == "__main__":
    demonstrate_travel_assistant()

Desglose del Código:

  • La clase TravelAssistant mantiene dos componentes principales:
    • conversation_history: Almacena el hilo completo de la conversación
    • user_preferences: Rastrea el contexto importante sobre los planes de viaje del usuario
  • Métodos Principales:
    • update_preferences(): Extrae y almacena información relevante de los mensajes del usuario
    • get_contextual_response(): Gestiona el flujo de la conversación y las interacciones con la API
    • _generate_context_note(): Crea resúmenes de contexto a partir de las preferencias almacenadas
  • El código demuestra:
    • Construcción progresiva del contexto conforme se desarrolla la conversación
    • Mantenimiento de las preferencias del usuario a través de múltiples intercambios
    • Inyección dinámica de contexto en la conversación
    • Manejo estructurado del flujo de conversación

Esta implementación muestra cómo mantener el contexto a través de una conversación de múltiples turnos mientras se realiza un seguimiento de las preferencias y preocupaciones específicas del usuario, similar al flujo de conversación demostrado en el ejemplo anterior.

Esta gestión dinámica del contexto asegura que cada respuesta no solo sea relevante a la pregunta inmediata sino que también esté informada por todo el historial de la conversación, creando un diálogo más natural y coherente.

Un Ejemplo Integral: Implementación de Memoria a Corto Plazo en Conversaciones de Múltiples Turnos

A continuación se muestra un ejemplo usando Python para simular una conversación con memoria a corto plazo, que demuestra cómo mantener el contexto durante un diálogo en curso. El historial de conversación se implementa como una lista de mensajes, donde cada mensaje contiene tanto el rol (sistema, usuario o asistente) como el contenido de ese mensaje.

Esta lista se actualiza continuamente y se pasa a cada llamada API subsiguiente, permitiendo que la IA haga referencia y construya sobre intercambios previos. Este enfoque es particularmente útil para mantener conversaciones coherentes donde el contexto de mensajes anteriores influye en las respuestas posteriores. La implementación permite que el asistente recuerde y haga referencia a preguntas, respuestas y detalles importantes previos a lo largo de la conversación:

import openai
import os
from dotenv import load_dotenv
from datetime import datetime
import json

# Load environment variables and configure OpenAI
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

class ConversationManager:
    def __init__(self):
        self.conversation_history = [
            {"role": "system", "content": "You are a friendly assistant that helps with technical queries."}
        ]
        self.session_metadata = {
            "start_time": datetime.now(),
            "query_count": 0,
            "topics": set()
        }
    
    def save_conversation(self, filename="conversation_history.json"):
        """Save the current conversation to a JSON file"""
        data = {
            "history": self.conversation_history,
            "metadata": {
                **self.session_metadata,
                "topics": list(self.session_metadata["topics"]),
                "start_time": self.session_metadata["start_time"].isoformat()
            }
        }
        with open(filename, 'w') as f:
            json.dump(data, f, indent=2)
    
    def load_conversation(self, filename="conversation_history.json"):
        """Load a previous conversation from a JSON file"""
        try:
            with open(filename, 'r') as f:
                data = json.load(f)
                self.conversation_history = data["history"]
                self.session_metadata = data["metadata"]
                self.session_metadata["topics"] = set(self.session_metadata["topics"])
                self.session_metadata["start_time"] = datetime.fromisoformat(
                    self.session_metadata["start_time"]
                )
            return True
        except FileNotFoundError:
            return False

    def ask_question(self, question, topic=None):
        """Ask a question and maintain conversation context"""
        # Update metadata
        self.session_metadata["query_count"] += 1
        if topic:
            self.session_metadata["topics"].add(topic)

        # Append the user's question
        self.conversation_history.append({"role": "user", "content": question})

        try:
            # Make the API call with current conversation history
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=self.conversation_history,
                max_tokens=150,
                temperature=0.7,
                presence_penalty=0.6  # Encourage more diverse responses
            )

            # Extract and store the assistant's reply
            answer = response["choices"][0]["message"]["content"]
            self.conversation_history.append({"role": "assistant", "content": answer})
            
            return answer

        except Exception as e:
            error_msg = f"Error during API call: {str(e)}"
            print(error_msg)
            return error_msg

    def get_conversation_summary(self):
        """Return a summary of the conversation session"""
        return {
            "Duration": datetime.now() - self.session_metadata["start_time"],
            "Total Questions": self.session_metadata["query_count"],
            "Topics Covered": list(self.session_metadata["topics"]),
            "Message Count": len(self.conversation_history)
        }

def demonstrate_conversation():
    # Initialize the conversation manager
    manager = ConversationManager()
    
    # Example multi-turn conversation
    questions = [
        ("What is a variable in Python?", "python_basics"),
        ("Can you give an example of declaring one?", "python_basics"),
        ("How do I use variables in a function?", "python_functions")
    ]
    
    # Run through the conversation
    for question, topic in questions:
        print(f"\nUser: {question}")
        response = manager.ask_question(question, topic)
        print(f"Assistant: {response}")
    
    # Save the conversation
    manager.save_conversation()
    
    # Print conversation summary
    print("\nConversation Summary:")
    for key, value in manager.get_conversation_summary().items():
        print(f"{key}: {value}")

if __name__ == "__main__":
    demonstrate_conversation()

Desglose y Explicación del Código:

  1. Estructura de Clase e Inicialización
    • La clase ConversationManager proporciona una forma estructurada de manejar conversaciones
    • Mantiene tanto el historial de conversación como los metadatos de sesión
    • Utiliza un mensaje del sistema para establecer el rol del asistente
  2. Funciones de Almacenamiento Persistente
    • save_conversation(): Exporta el historial de conversación y metadatos a JSON
    • load_conversation(): Restaura conversaciones previas desde archivos guardados
    • Maneja automáticamente la serialización/deserialización de fechas y horas
  3. Manejo Mejorado de Preguntas
    • Rastrea temas de conversación y contador de consultas
    • Incluye manejo de errores para llamadas a la API
    • Utiliza presence_penalty para fomentar respuestas diversas
  4. Metadatos y Análisis
    • Rastrea la duración de la sesión
    • Mantiene un conjunto de temas de conversación
    • Proporciona resúmenes detallados de la conversación
  5. Mejoras Clave Sobre la Versión Básica
    • Agregado manejo de errores y registro apropiado
    • Implementada persistencia de conversación
    • Incluidos análisis y metadatos de sesión
    • Mejorada modularidad y organización del código

Este ejemplo proporciona una base robusta para construir aplicaciones conversacionales, con características de persistencia, manejo de errores y análisis que serían valiosas en un entorno de producción.

En este ejemplo, el historial de conversación (memoria a corto plazo) se actualiza continuamente con cada interacción, permitiendo que el asistente haga referencia a mensajes anteriores según sea necesario.

7.1.2 Memoria a Largo Plazo

Mientras que la memoria a corto plazo es inherente en cada llamada a la API, la memoria a largo plazo en la IA conversacional representa un enfoque más sofisticado para mantener el contexto a través de múltiples interacciones. A diferencia de la memoria a corto plazo, que solo retiene información durante una única conversación, la memoria a largo plazo crea un registro persistente de las interacciones del usuario que puede abarcar días, semanas o incluso meses. Esto se logra típicamente almacenando historiales de conversación en bases de datos o sistemas de archivos, que luego pueden ser accedidos de manera inteligente cuando sea necesario.

El proceso funciona primero capturando y almacenando datos relevantes de la conversación, incluyendo preferencias del usuario, detalles importantes y puntos clave de discusión. Cuando un usuario regresa para una nueva sesión, el sistema puede recuperar esta información almacenada e inyectar selectivamente el contexto más relevante en futuros mensajes. Esto crea una experiencia más personalizada y continua, ya que la IA puede hacer referencia a interacciones pasadas y construir sobre el conocimiento previamente establecido.

Por ejemplo, si un usuario discutió sus preferencias dietéticas en una sesión anterior, el sistema puede recordar esta información semanas después al proporcionar recomendaciones de recetas, creando una interacción más natural y contextualmente consciente. Esta capacidad de mantener y utilizar el contexto histórico es esencial para construir sistemas conversacionales verdaderamente inteligentes que puedan proporcionar continuidad y personalización a través de múltiples interacciones.

Características Clave de la Memoria a Largo Plazo:

Persistencia Entre Sesiones:

La memoria a largo plazo implica crear un registro permanente del historial de conversación en bases de datos o sistemas de almacenamiento, formando una base de conocimiento integral para cada interacción del usuario. Este enfoque sofisticado permite que los sistemas de IA mantengan un contexto detallado incluso cuando los usuarios regresan después de períodos prolongados - desde días hasta meses o incluso años.

El sistema logra esto a través de varios mecanismos clave:

  1. Almacenamiento de Conversación: Cada interacción significativa se almacena en bases de datos estructuradas, incluyendo preferencias del usuario, solicitudes específicas y decisiones importantes.
  2. Recuperación de Contexto: Cuando un usuario regresa, el sistema puede acceder y utilizar inteligentemente sus datos históricos para proporcionar respuestas personalizadas.
  3. Reconocimiento de Patrones: Con el tiempo, el sistema aprende los patrones y preferencias del usuario, creando una comprensión más matizada de las necesidades individuales.

Por ejemplo:

  • Un usuario menciona que es alérgico a los frutos secos en enero. Seis meses después, cuando solicita recomendaciones de recetas, el sistema automáticamente filtra las recetas que contienen frutos secos.
  • Durante una conversación de soporte técnico en marzo, un usuario indica que está usando Windows 11. En diciembre, cuando busca ayuda con un nuevo problema, el sistema ya conoce su sistema operativo.
  • Una aplicación de aprendizaje de idiomas recuerda que un usuario tiene dificultades con las conjugaciones en tiempo pasado, incorporando automáticamente más ejercicios de práctica en esta área a través de múltiples sesiones.

Aquí está el código de implementación:

from datetime import datetime
import openai

class LongTermMemorySystem:
    def __init__(self, api_key):
        self.api_key = api_key
        openai.api_key = api_key
        self.preferences = {}
    
    def store_preference(self, user_id, pref_type, pref_value):
        if user_id not in self.preferences:
            self.preferences[user_id] = []
        self.preferences[user_id].append({
            'type': pref_type,
            'value': pref_value,
            'timestamp': datetime.now()
        })

    def get_user_preferences(self, user_id, pref_type=None):
        if user_id not in self.preferences:
            return []
        
        if pref_type:
            relevant_prefs = [p for p in self.preferences[user_id] 
                            if p['type'] == pref_type]
            return [(p['value'],) for p in sorted(relevant_prefs, 
                    key=lambda x: x['timestamp'], reverse=True)]
        
        return [(p['type'], p['value']) for p in self.preferences[user_id]]

    async def get_ai_response(self, prompt, context):
        try:
            response = await openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "You are an AI assistant with access to user preferences."},
                    {"role": "user", "content": f"Context: {context}\nPrompt: {prompt}"}
                ]
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"

# Example usage
async def demonstrate_long_term_memory():
    memory_system = LongTermMemorySystem("your-api-key-here")
    
    # Scenario 1: Food Allergies
    user_id = "user123"
    memory_system.store_preference(user_id, "food_allergy", "nuts")
    
    async def get_recipe_recommendations(user_id):
        allergies = memory_system.get_user_preferences(user_id, "food_allergy")
        context = f"User has allergies: {allergies if allergies else 'None'}"
        prompt = "Recommend safe recipes for this user."
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 2: Technical Support
    memory_system.store_preference(user_id, "operating_system", "Windows 11")
    
    async def provide_tech_support(user_id, issue):
        os = memory_system.get_user_preferences(user_id, "operating_system")
        context = f"User's OS: {os[0][0] if os else 'Unknown'}"
        prompt = f"Help with issue: {issue}"
        return await memory_system.get_ai_response(prompt, context)
    
    # Scenario 3: Language Learning
    memory_system.store_preference(user_id, "grammar_challenge", "past_tense")
    
    async def generate_language_exercises(user_id):
        challenges = memory_system.get_user_preferences(user_id, "grammar_challenge")
        context = f"User struggles with: {challenges[0][0] if challenges else 'No specific areas'}"
        prompt = "Generate appropriate language exercises."
        return await memory_system.get_ai_response(prompt, context)

    # Demonstrate the system
    print("Recipe Recommendations:", await get_recipe_recommendations(user_id))
    print("Tech Support:", await provide_tech_support(user_id, "printer not working"))
    print("Language Exercises:", await generate_language_exercises(user_id))

if __name__ == "__main__":
    import asyncio
    asyncio.run(demonstrate_long_term_memory())

Este código implementa un sistema de memoria a largo plazo para conversaciones de IA que almacena y gestiona las preferencias del usuario.

Aquí se desglosan sus componentes principales:

  1. Clase LongTermMemorySystem
  • Se inicializa con una clave API para la integración con OpenAI
  • Mantiene un diccionario de preferencias de usuario
  1. Métodos Principales
  • store_preference: Almacena preferencias de usuario con marcas de tiempo
  • get_user_preferences: Recupera preferencias almacenadas, opcionalmente filtradas por tipo
  • get_ai_response: Genera respuestas de IA usando la API de OpenAI con contexto del usuario
  1. Escenarios de Demostración
  • Alergias Alimentarias: Almacena y utiliza información sobre alergias para recomendaciones de recetas
  • Soporte Técnico: Mantiene información del sistema operativo para soporte técnico contextual
  • Aprendizaje de Idiomas: Registra desafíos gramaticales para personalizar ejercicios

El sistema demuestra cómo mantener preferencias persistentes del usuario a través de múltiples sesiones, permitiendo interacciones personalizadas y conscientes del contexto. Utiliza programación asíncrona (async/await) para interacciones eficientes con la API e incluye manejo de errores para una operación robusta.

Esta persistencia asegura que la IA desarrolle una comprensión cada vez más sofisticada de cada usuario con el tiempo, conduciendo a interacciones más personalizadas, relevantes y conscientes del contexto. El sistema esencialmente desarrolla una "memoria" de las preferencias, desafíos e historial de cada usuario, similar a como un humano recordaría detalles importantes sobre amigos o colegas.

Recuperación Selectiva:

En lugar de cargar todo el historial de conversación para cada interacción, los sistemas de memoria a largo plazo utilizan métodos sofisticados de recuperación para acceder eficientemente a la información relevante. Estos sistemas emplean varias técnicas avanzadas:

  • Búsqueda Vectorial
    • Convierte texto en representaciones matemáticas (vectores)
    • Encuentra rápidamente conversaciones con significado semántico similar
    • Ejemplo: Cuando un usuario pregunta sobre "frameworks de aprendizaje automático", el sistema puede encontrar discusiones previas sobre TensorFlow o PyTorch, incluso si no se usaron exactamente esos términos
  • Puntuación de Importancia
    • Clasifica segmentos de conversación basados en relevancia y significancia
    • Considera factores como actualidad, participación del usuario y alineación temática
    • Ejemplo: Una discusión detallada reciente sobre programación tendría mayor prioridad que una mención breve antigua al responder preguntas de código
  • Relevancia Temporal
    • Pondera la información basada en sensibilidad temporal
    • Prioriza conversaciones recientes mientras mantiene acceso a contexto histórico importante
    • Ejemplo: Al discutir preferencias actuales, las conversaciones recientes sobre gustos/disgustos tienen prioridad sobre las más antiguas que podrían estar desactualizadas

Aquí hay un ejemplo de implementación de estos conceptos:

from datetime import datetime
import openai
from typing import List, Dict, Optional

class AdvancedMemoryRetrieval:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.conversations = []
        
    def add_conversation(self, text: str, timestamp: Optional[datetime] = None, engagement_score: float = 0):
        if timestamp is None:
            timestamp = datetime.now()
        
        # Convert text to vector representation using OpenAI
        try:
            response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=text
            )
            vector = response['data'][0]['embedding']
        except Exception as e:
            print(f"Error creating embedding: {e}")
            vector = None
        
        self.conversations.append({
            'text': text,
            'vector': vector,
            'timestamp': timestamp,
            'engagement': engagement_score
        })
    
    def vector_search(self, query: str, top_k: int = 3) -> List[Dict]:
        try:
            query_response = openai.Embedding.create(
                model="text-embedding-ada-002",
                input=query
            )
            query_vector = query_response['data'][0]['embedding']
            
            similarities = []
            for conv in self.conversations:
                if conv['vector'] is not None:
                    # Calculate cosine similarity
                    similarity = self._calculate_similarity(query_vector, conv['vector'])
                    similarities.append((conv, similarity))
            
            return sorted(similarities, key=lambda x: x[1], reverse=True)[:top_k]
        except Exception as e:
            print(f"Error in vector search: {e}")
            return []
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def calculate_importance_score(self, conversation: Dict, query_time: datetime) -> float:
        time_diff = (query_time - conversation['timestamp']).total_seconds()
        recency_score = 1 / (1 + np.log1p(time_diff))
        return 0.7 * recency_score + 0.3 * conversation['engagement']
    
    def retrieve_relevant_context(self, query: str, top_k: int = 3) -> List[Dict]:
        # Get semantically similar conversations
        similar_convs = self.vector_search(query, top_k=top_k*2)
        
        if not similar_convs:
            return []
        
        # Calculate importance scores
        now = datetime.now()
        scored_convs = []
        for conv, similarity in similar_convs:
            importance = self.calculate_importance_score(conv, now)
            final_score = 0.6 * similarity + 0.4 * importance
            scored_convs.append((conv, final_score))
        
        # Get top results
        top_results = sorted(scored_convs, key=lambda x: x[1], reverse=True)[:top_k]
        
        # Use GPT-4o to enhance context understanding
        try:
            contexts = [result[0]['text'] for result in top_results]
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Analyze these conversation snippets and their relevance to the query."},
                    {"role": "user", "content": f"Query: {query}\nContexts: {contexts}"}
                ]
            )
            # Add GPT-4o analysis to results
            for result in top_results:
                result[0]['analysis'] = response.choices[0].message.content
        except Exception as e:
            print(f"Error in GPT analysis: {e}")
        
        return top_results

# Example usage
def demonstrate_retrieval():
    retriever = AdvancedMemoryRetrieval("your-openai-api-key-here")
    
    # Add some sample conversations
    retriever.add_conversation(
        "TensorFlow is great for deep learning projects",
        timestamp=datetime(2025, 1, 1),
        engagement_score=0.8
    )
    retriever.add_conversation(
        "PyTorch provides dynamic computational graphs",
        timestamp=datetime(2025, 3, 1),
        engagement_score=0.9
    )
    
    # Retrieve relevant context
    query = "What are good machine learning frameworks?"
    results = retriever.retrieve_relevant_context(query)
    
    for conv, score in results:
        print(f"Score: {score:.2f}")
        print(f"Text: {conv['text']}")
        if 'analysis' in conv:
            print(f"Analysis: {conv['analysis']}\n")

if __name__ == "__main__":
    demonstrate_retrieval()

Este código implementa un sistema avanzado de recuperación de memoria conversacional.

Aquí se desglosan sus componentes principales:

  1. Estructura de Clase Principal
  • La clase AdvancedMemoryRetrieval gestiona el almacenamiento y recuperación de conversaciones
  • Utiliza la API de OpenAI para crear embeddings de texto y analizar conversaciones
  1. Características Principales
  • Almacenamiento de Conversaciones:
    • Almacena texto, embeddings vectoriales, marcas temporales y puntuaciones de participación
    • Crea representaciones vectoriales de conversaciones usando el modelo de embedding de OpenAI
  • Búsqueda Vectorial:
    • Implementa búsqueda semántica usando similitud del coseno
    • Devuelve las k conversaciones más similares basadas en comparaciones vectoriales
  • Puntuación de Importancia:
    • Combina métricas de actualidad (basadas en tiempo) y participación
    • Utiliza una fórmula ponderada: 70% actualidad + 30% participación
  • Recuperación de Contexto:
    • Combina similitud vectorial (60%) con puntuaciones de importancia (40%)
    • Utiliza GPT-4o para analizar y mejorar la comprensión de los contextos recuperados
  1. Implementación de Ejemplo
  • El código de demostración muestra cómo:
    • Inicializar el sistema con conversaciones de ejemplo sobre frameworks de aprendizaje automático
    • Recuperar contexto relevante basado en una consulta
    • Mostrar resultados con puntuaciones y análisis

Esta implementación muestra técnicas modernas para gestionar el historial de conversaciones, combinando búsqueda semántica, relevancia temporal y métricas de participación para proporcionar respuestas contextualmente apropiadas.

Este enfoque selectivo asegura que las respuestas sean focalizadas y relevantes mientras mantiene la eficiencia computacional. Por ejemplo, en un escenario de soporte técnico, cuando un usuario pregunta sobre la resolución de problemas de una función específica del software, el sistema recuperaría solo las conversaciones previas sobre esa función y mensajes de error relacionados, en lugar de cargar todo su historial de soporte.

Al implementar estos métodos de recuperación, el sistema puede mantener la conciencia contextual de una conversación humana mientras opera dentro de límites computacionales prácticos.

Gestión Personalizada:

Construir una memoria a largo plazo efectiva requiere un diseño de sistema cuidadoso y la consideración de múltiples factores. Exploremos los componentes clave:

1. Arquitectura de Almacenamiento

Las estructuras de almacenamiento eficientes son cruciales para gestionar el historial de conversaciones. Esto puede incluir:

  • Bases de datos distribuidas para escalabilidad
    • Uso de MongoDB para datos de conversación no estructurados
    • Implementación de Redis para interacciones recientes de acceso rápido

2. Mecanismos de Recuperación

Los algoritmos de recuperación inteligente aseguran un acceso rápido a la información relevante:

  • Búsqueda semántica usando embeddings
    • Ejemplo: Convertir "¿Cómo restablezco mi contraseña?" en un vector para encontrar consultas similares anteriores
  • Clasificación contextual
    • Ejemplo: Priorizar conversaciones recientes de soporte técnico cuando el usuario reporta un error

3. Compresión de Datos y Resumen

Métodos para mantener la eficiencia mientras se preserva el significado:

  • Resumen automático de conversaciones
    • Ejemplo: Condensar un hilo de 30 mensajes sobre requisitos de proyecto en puntos clave
  • Técnicas de compresión inteligente
    • Ejemplo: Almacenar patrones comunes como plantillas en lugar de conversaciones completas

4. Gestión de Limitaciones del Sistema

Equilibrar capacidades con recursos:

  • Cuotas de almacenamiento por usuario/conversación
    • Ejemplo: Limitar el almacenamiento a 6 meses de historial de conversación por defecto
  • Asignación de poder de procesamiento
    • Ejemplo: Usar procesamiento por lotes para análisis histórico durante horas valle

5. Privacidad y Seguridad

Consideraciones críticas para el manejo de datos:

  • Cifrado de conversaciones almacenadas
    • Ejemplo: Usar cifrado AES-256 para todos los datos de conversación
  • Gestión del consentimiento del usuario
    • Ejemplo: Permitir que los usuarios opten por no participar en el almacenamiento a largo plazo

6. Ciclo de Vida de la Información

Gestionar datos durante su vida útil:

  • Reglas de archivo automatizado
    • Ejemplo: Mover conversaciones de más de 1 año a almacenamiento frío
  • Políticas de degradación de datos
    • Ejemplo: Eliminar automáticamente información personal después de períodos específicos
  • Evaluación regular de relevancia
    • Ejemplo: Usar métricas de participación para determinar qué información retener

Aquí hay una implementación de código:

import json
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import openai

class ConversationManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.storage = {}
        self.user_preferences = {}
        
    def summarize_conversation(self, messages: List[Dict]) -> str:
        """Summarize a conversation thread using GPT-4o."""
        try:
            conversation_text = "\n".join([f"{msg['role']}: {msg['content']}" for msg in messages])
            response = openai.ChatCompletion.create(
                model="gpt-4o",
                messages=[
                    {"role": "system", "content": "Please summarize this conversation in 3 key points."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            # Fallback to simple summarization if API call fails
            summary = []
            for msg in messages[-3:]:  # Take last 3 messages
                if len(msg['content']) > 100:
                    summary.append(f"Key point: {msg['content'][:100]}...")
                else:
                    summary.append(msg['content'])
            return "\n".join(summary)
    
    def store_conversation(self, user_id: str, conversation: List[Dict]) -> bool:
        """Store conversation with quota and privacy checks."""
        # Check storage quota
        if len(self.storage.get(user_id, [])) >= 1000:  # Example quota
            self._archive_old_conversations(user_id)
            
        # Check user consent
        if not self.user_preferences.get(user_id, {}).get('storage_consent', True):
            return False
            
        # Generate embedding for semantic search
        conversation_text = " ".join(msg['content'] for msg in conversation)
        try:
            embedding = openai.Embedding.create(
                input=conversation_text,
                model="text-embedding-ada-002"
            )
            embedding_vector = embedding['data'][0]['embedding']
        except Exception:
            embedding_vector = None
            
        # Store conversation with summary and embedding
        summary = self.summarize_conversation(conversation)
        if user_id not in self.storage:
            self.storage[user_id] = []
        self.storage[user_id].append({
            'timestamp': datetime.now(),
            'summary': summary,
            'conversation': conversation,
            'embedding': embedding_vector
        })
        return True
    
    def _archive_old_conversations(self, user_id: str) -> None:
        """Archive conversations older than 6 months."""
        cutoff_date = datetime.now() - timedelta(days=180)
        current = self.storage.get(user_id, [])
        self.storage[user_id] = [
            conv for conv in current 
            if conv['timestamp'] > cutoff_date
        ]
    
    def get_relevant_context(self, user_id: str, query: str) -> Optional[str]:
        """Retrieve relevant context using semantic search."""
        if user_id not in self.storage:
            return None
            
        try:
            # Get query embedding
            query_embedding = openai.Embedding.create(
                input=query,
                model="text-embedding-ada-002"
            )
            query_vector = query_embedding['data'][0]['embedding']
            
            # Find most relevant conversations
            relevant_contexts = []
            for conv in self.storage[user_id]:
                if conv['embedding']:
                    relevance_score = self._calculate_similarity(
                        query_vector,
                        conv['embedding']
                    )
                    if relevance_score > 0.7:  # Threshold
                        relevant_contexts.append(conv['summary'])
                        
            return relevant_contexts[0] if relevant_contexts else None
        except Exception:
            # Fallback to simple word matching if embedding fails
            return self._simple_context_search(user_id, query)
    
    def _calculate_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """Calculate cosine similarity between two vectors."""
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
    
    def _simple_context_search(self, user_id: str, query: str) -> Optional[str]:
        """Simple relevance calculation using word overlap."""
        query_words = set(query.lower().split())
        best_score = 0
        best_summary = None
        
        for conv in self.storage[user_id]:
            summary_words = set(conv['summary'].lower().split())
            score = len(query_words & summary_words) / len(query_words)
            if score > best_score:
                best_score = score
                best_summary = conv['summary']
                
        return best_summary if best_score > 0.3 else None

# Example usage
def demonstrate_conversation_management():
    manager = ConversationManager("your-openai-api-key-here")
    
    # Store a conversation
    user_id = "user123"
    conversation = [
        {"role": "user", "content": "How do I implement encryption?"},
        {"role": "assistant", "content": "Here's a detailed guide..."},
        {"role": "user", "content": "Thanks, that helps!"}
    ]
    
    # Set user preferences
    manager.user_preferences[user_id] = {'storage_consent': True}
    
    # Store the conversation
    stored = manager.store_conversation(user_id, conversation)
    print(f"Conversation stored: {stored}")
    
    # Later, retrieve relevant context
    context = manager.get_relevant_context(user_id, "encryption implementation")
    print(f"Retrieved context: {context}")

if __name__ == "__main__":
    demonstrate_conversation_management()

Este código implementa una clase ConversationManager para gestionar conversaciones de IA con memoria y recuperación de contexto.

Aquí están los componentes principales:

Funcionalidad Central:

  • Almacenamiento de Conversaciones:
    • Almacena conversaciones con marcas de tiempo, resúmenes y embeddings
    • Implementa cuotas de almacenamiento y verificaciones de consentimiento del usuario
    • Archiva conversaciones con más de 6 meses de antigüedad
  • Resumen de Conversaciones:
    • Utiliza GPT-4o para crear resúmenes concisos de conversaciones
    • Incluye mecanismo de respaldo cuando fallan las llamadas a la API
    • Almacena resúmenes para una recuperación eficiente
  • Búsqueda Semántica:
    • Genera embeddings usando el modelo de embedding de OpenAI
    • Implementa similitud del coseno para encontrar conversaciones relevantes
    • Incluye respaldo a coincidencia simple de palabras cuando fallan los embeddings

Características Principales:

  • Controles de Privacidad:
    • Verifica el consentimiento del usuario antes de almacenar conversaciones
    • Gestiona preferencias de usuario y consentimiento de almacenamiento
  • Gestión de Memoria:
    • Implementa cuotas de almacenamiento (1000 conversaciones por usuario)
    • Archiva conversaciones antiguas automáticamente
    • Utiliza búsqueda semántica para recuperar contexto relevante

Ejemplo de Uso:

  • El código demuestra:
    • Almacenamiento de una conversación sobre encriptación
    • Configuración de preferencias de usuario
    • Recuperación de contexto relevante basado en consultas

Esta implementación se centra en equilibrar el almacenamiento eficiente de conversaciones con la recuperación inteligente, mientras mantiene la privacidad del usuario y el rendimiento del sistema.

Este ejemplo demuestra la aplicación práctica de los conceptos discutidos anteriormente, incluyendo compresión de datos, limitaciones del sistema, controles de privacidad y gestión del ciclo de vida de la información. El código proporciona una base que puede extenderse con características más sofisticadas como resumen basado en aprendizaje automático o esquemas de encriptación avanzados.

Un Ejemplo Completo: Simulando Memoria a Largo Plazo

Exploremos un ejemplo práctico que demuestra cómo implementar la memoria de conversación en aplicaciones de IA. Este ejemplo muestra dos componentes clave: guardar el historial de conversación para referencia futura y recuperar el contexto relevante al comenzar una nueva sesión de conversación. Para mantener el ejemplo sencillo y enfocarnos en los conceptos principales, usaremos un enfoque simple de almacenamiento en memoria usando una variable, aunque en un entorno de producción típicamente usarías un sistema de base de datos o almacenamiento persistente.

Este ejemplo sirve para ilustrar varios conceptos importantes:

  • Cómo capturar y almacenar historial de conversación significativo
    • La mecánica de guardar información contextual para referencia futura
    • Métodos para recuperar y utilizar contexto previo de conversación
  • Cómo mantener la continuidad de conversación a través de múltiples sesiones
    • Técnicas para integrar contexto pasado en nuevas conversaciones
    • Estrategias para gestionar el estado de la conversación

# Comprehensive example of conversation memory management with OpenAI API

from typing import List, Dict, Optional
import json
from datetime import datetime
import openai
from dataclasses import dataclass
from enum import Enum

class MemoryType(Enum):
    SHORT_TERM = "short_term"
    LONG_TERM = "long_term"
    SEMANTIC = "semantic"

@dataclass
class Message:
    role: str  # system, user, or assistant
    content: str
    timestamp: datetime
    metadata: Dict = None

class ConversationMemoryManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.long_term_memory = []
        self.semantic_memory = {}  # Store embeddings for semantic search
        self.active_conversations = {}
        self.max_memory_size = 1000
        self.model = "gpt-4o"  # OpenAI model to use
        
    def save_conversation(self, conversation_id: str, messages: List[Message]) -> bool:
        """
        Save conversation with metadata and timestamps.
        Returns success status.
        """
        try:
            # Generate embeddings for semantic search
            conversation_text = " ".join(msg.content for msg in messages)
            embedding = self._get_embedding(conversation_text)
            
            conversation_data = {
                "id": conversation_id,
                "timestamp": datetime.now(),
                "messages": [self._message_to_dict(msg) for msg in messages],
                "summary": self._generate_summary(messages),
                "embedding": embedding
            }
            
            # Implement memory management
            if len(self.long_term_memory) >= self.max_memory_size:
                self._prune_old_conversations()
                
            self.long_term_memory.append(conversation_data)
            self._update_semantic_memory(conversation_data)
            return True
        except Exception as e:
            print(f"Error saving conversation: {e}")
            return False
    
    def retrieve_context(self, 
                        conversation_id: str, 
                        query: str = None,
                        memory_type: MemoryType = MemoryType.LONG_TERM) -> Optional[str]:
        """
        Retrieve context based on memory type and query.
        Uses OpenAI embeddings for semantic search.
        """
        if memory_type == MemoryType.SEMANTIC and query:
            return self._semantic_search(query)
        elif memory_type == MemoryType.LONG_TERM:
            return self._get_latest_context(conversation_id)
        return None

    def _get_embedding(self, text: str) -> List[float]:
        """
        Get embeddings using OpenAI's embedding model.
        """
        response = openai.Embedding.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response['data'][0]['embedding']

    def _semantic_search(self, query: str) -> Optional[str]:
        """
        Perform semantic search using OpenAI embeddings.
        """
        if not self.semantic_memory:
            return None
            
        query_embedding = self._get_embedding(query)
        
        # Calculate cosine similarity with stored embeddings
        best_match = None
        best_score = -1
        
        for conv_id, conv_data in self.semantic_memory.items():
            similarity = self._cosine_similarity(query_embedding, conv_data["embedding"])
            if similarity > best_score:
                best_score = similarity
                best_match = conv_data["summary"]
        
        return best_match if best_score > 0.7 else None

    def _cosine_similarity(self, vec1: List[float], vec2: List[float]) -> float:
        """
        Calculate cosine similarity between two vectors.
        """
        import numpy as np
        return np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))

    def _get_latest_context(self, conversation_id: str) -> Optional[str]:
        """
        Retrieve the most recent relevant context.
        """
        relevant_convs = [
            conv for conv in self.long_term_memory 
            if conv["id"] == conversation_id
        ]
        
        if not relevant_convs:
            return None
            
        latest_conv = max(relevant_convs, key=lambda x: x["timestamp"])
        return latest_conv["summary"]

    def _generate_summary(self, messages: List[Message]) -> str:
        """
        Generate a summary using OpenAI's GPT-4o model.
        """
        try:
            conversation_text = "\n".join([f"{msg.role}: {msg.content}" for msg in messages])
            response = openai.ChatCompletion.create(
                model=self.model,
                messages=[
                    {"role": "system", "content": "Please provide a brief summary of the following conversation."},
                    {"role": "user", "content": conversation_text}
                ],
                max_tokens=150
            )
            return response.choices[0].message.content
        except Exception as e:
            print(f"Error generating summary: {e}")
            # Fallback to simple summary
            key_messages = [msg for msg in messages if msg.role == "assistant"][-3:]
            return " ".join(msg.content[:100] + "..." for msg in key_messages)

    def _message_to_dict(self, message: Message) -> Dict:
        """
        Convert Message object to dictionary format compatible with OpenAI API.
        """
        return {
            "role": message.role,
            "content": message.content,
            "timestamp": message.timestamp.isoformat(),
            "metadata": message.metadata or {}
        }

    def _prune_old_conversations(self) -> None:
        """
        Remove oldest conversations when reaching memory limit.
        """
        self.long_term_memory.sort(key=lambda x: x["timestamp"])
        self.long_term_memory = self.long_term_memory[-self.max_memory_size:]

    def _update_semantic_memory(self, conversation_data: Dict) -> None:
        """
        Update semantic memory with conversation embeddings.
        """
        self.semantic_memory[conversation_data["id"]] = {
            "embedding": conversation_data["embedding"],
            "summary": conversation_data["summary"]
        }

# Example usage
def demonstrate_conversation_memory():
    # Initialize memory manager with OpenAI API key
    memory_manager = ConversationMemoryManager("your-api-key-here")
    
    # Create sample conversation
    conversation_id = "conv_123"
    messages = [
        Message(
            role="system",
            content="You are a helpful assistant that explains concepts clearly.",
            timestamp=datetime.now()
        ),
        Message(
            role="user",
            content="What is a class in object-oriented programming?",
            timestamp=datetime.now()
        ),
        Message(
            role="assistant",
            content="A class in OOP is a blueprint for creating objects, defining their properties and behaviors.",
            timestamp=datetime.now()
        )
    ]
    
    # Save conversation
    memory_manager.save_conversation(conversation_id, messages)
    
    # Retrieve context using different methods
    long_term_context = memory_manager.retrieve_context(
        conversation_id,
        memory_type=MemoryType.LONG_TERM
    )
    print("Long-term Context:", long_term_context)
    
    semantic_context = memory_manager.retrieve_context(
        conversation_id,
        query="How do classes work in programming?",
        memory_type=MemoryType.SEMANTIC
    )
    print("Semantic Context:", semantic_context)

if __name__ == "__main__":
    demonstrate_conversation_memory()

Este código de ejemplo implementa un sistema integral de gestión de memoria de conversación. Estos son los componentes principales:

1. Clases principales y estructuras de datos

  • El enum MemoryType define tres tipos de memoria: corto plazo, largo plazo y semántica
  • La dataclass Message almacena mensajes de conversación con rol, contenido, marca de tiempo y metadatos

2. Clase ConversationMemoryManager

  • Gestiona tres tipos de almacenamiento:
    • Memoria a largo plazo: Almacena conversaciones completas
    • Memoria semántica: Almacena embeddings para búsqueda semántica
    • Conversaciones activas: Maneja conversaciones en curso

3. Características principales

  • Guardado de conversaciones: Almacena conversaciones con metadatos, marcas de tiempo y embeddings
  • Recuperación de contexto: Admite tanto recuperación directa como búsqueda semántica
  • Gestión de memoria: Implementa poda al alcanzar el tamaño máximo de memoria (1000 conversaciones)
  • Resumen automático: Genera resúmenes de conversación usando el modelo GPT de OpenAI

4. Características avanzadas

  • Búsqueda semántica usando embeddings de OpenAI y similitud del coseno
  • Mecanismos de respaldo para la generación de resúmenes si la API de OpenAI falla
  • Poda eficiente de memoria para mantener el rendimiento del sistema

El código demuestra la implementación tanto de búsqueda semántica como de almacenamiento tradicional de conversaciones, haciéndolo adecuado para aplicaciones que requieren una gestión sofisticada de memoria de conversación.

Entender la interacción entre la memoria a corto y largo plazo es crucial para diseñar conversaciones efectivas de múltiples turnos en sistemas de IA. Analicemos estos dos tipos de memoria y sus roles:

La memoria a corto plazo opera dentro del contexto inmediato de una conversación. Se maneja automáticamente durante cada llamada a la API, manteniendo el flujo actual del diálogo y los intercambios recientes. Este tipo de memoria es esencial para comprender el contexto inmediato, las referencias y mantener la coherencia dentro de una única sesión de conversación.

La memoria a largo plazo, por otro lado, requiere una implementación más sofisticada. Involucra:

  • Almacenamiento persistente del historial de conversaciones en bases de datos o sistemas de almacenamiento externos
  • Mecanismos inteligentes de recuperación para seleccionar contexto histórico relevante
  • Decisiones estratégicas sobre qué información almacenar y recuperar
  • Métodos para gestionar limitaciones de almacenamiento y limpiar datos antiguos

Cuando combinas estos dos enfoques de memoria de manera efectiva, puedes crear aplicaciones de IA que demuestren:

  • Conciencia contextual a través de múltiples conversaciones
  • Flujo de conversación natural que se siente humano
  • Capacidad para hacer referencia y construir sobre interacciones pasadas
  • Comprensión consistente de las preferencias e historial del usuario

La clave del éxito radica en encontrar el equilibrio adecuado entre estos tipos de memoria e implementarlos de una manera que mejore la experiencia del usuario mientras se gestionan eficientemente los recursos del sistema.