Menu iconMenu icon
OpenAI API Biblia Volumen 1

Capítulo 7: Memoria y Conversaciones de Varios Turnos

7.3 Almacenamiento y Recuperación de Interacciones Pasadas

En el mundo real, las conversaciones humanas se construyen sobre la historia compartida e interacciones previas. Cuando hablamos con alguien que conocemos, naturalmente recurrimos a nuestras experiencias pasadas con ellos - sus preferencias, discusiones previas y el contexto que hemos construido juntos. Este sistema natural de memoria es lo que hace que nuestras conversaciones se sientan continuas y personalmente significativas.

Si bien los modelos de lenguaje de OpenAI no poseen inherentemente capacidades de memoria a largo plazo, los desarrolladores pueden crear sistemas sofisticados para replicar este proceso natural de memoria. Al implementar un sistema de almacenamiento y recuperación para interacciones pasadas, puedes crear un asistente de IA que parece "recordar" conversaciones previas. Esto implica registrar cuidadosamente las interacciones del usuario, almacenar contexto relevante y recuperar estratégicamente esta información cuando sea necesario.

Esta sección demuestra cómo construir un sistema de memoria ligero pero poderoso que mejora las capacidades de tu asistente de IA. Al mantener el historial de conversación y las preferencias del usuario a través de múltiples sesiones, puedes crear interacciones más significativas que se sienten menos como intercambios aislados y más como conversaciones continuas. Tu asistente podrá hacer referencia a discusiones pasadas, recordar preferencias del usuario y mantener conciencia del contexto - haciéndolo sentir más como interactuar con un colega conocedor que comenzar de nuevo con cada interacción.

7.3.1 ¿Por qué Almacenar las Interacciones?

El almacenamiento de interacciones pasadas desbloquea varias capacidades poderosas que mejoran la habilidad de la IA para proporcionar respuestas significativas y contextuales:

Respuestas Personalizadas

El sistema aprende y se adapta a usuarios individuales manteniendo un perfil detallado de sus interacciones y preferencias a lo largo del tiempo. Esta personalización ocurre en múltiples niveles:

  1. Estilo de Comunicación: El sistema rastrea cómo los usuarios se expresan analizando múltiples aspectos de sus patrones de comunicación:
    • Nivel de formalidad: Si utilizan lenguaje casual ("¡hola!") o un trato formal ("Estimado Señor/Señora")
    • Uso del humor: Su tendencia a usar bromas, emojis o lenguaje juguetón
    • Ritmo de conversación: Si prefieren intercambios rápidos o discusiones detalladas y extensas
    • Elecciones de vocabulario: Lenguaje técnico vs. simplificado
    • Referencias culturales: Profesionales, académicas o de cultura popular

Por ejemplo, si un usuario utiliza consistentemente lenguaje informal como "hola" y "¡gracias!" con emojis, el sistema se adapta respondiendo en un tono amistoso y casual. Por el contrario, cuando interactúa con usuarios empresariales que mantienen un lenguaje formal y términos profesionales, el sistema automáticamente se ajusta para usar la etiqueta empresarial apropiada y terminología estándar de la industria.

Esta comunicación adaptativa asegura interacciones más naturales y efectivas al coincidir con el estilo y preferencias de comunicación únicos de cada usuario.

  1. Competencia Técnica: Al analizar interacciones pasadas, el sistema evalúa los niveles de experiencia de los usuarios en diferentes dominios. Esto le permite ajustar automáticamente sus explicaciones basándose en el conocimiento demostrado.

Por ejemplo, al discutir programación, el sistema puede usar terminología avanzada como "polimorfismo" e "inyección de dependencias" con desarrolladores experimentados, mientras ofrece explicaciones más simples usando analogías del mundo real para principiantes. El sistema refina continuamente esta evaluación a través de interacciones continuas - si un usuario demuestra mayor comprensión con el tiempo, la profundidad técnica de las explicaciones se ajusta en consecuencia. Este enfoque adaptativo asegura que los expertos no se vean ralentizados por explicaciones básicas mientras que los principiantes no se vean abrumados por detalles técnicos complejos.

  1. Contexto Histórico: El sistema mantiene registros completos de discusiones previas, proyectos y decisiones, permitiéndole hacer referencia a conversaciones pasadas con precisión y relevancia. Este seguimiento histórico opera en múltiples niveles:
    • Seguimiento de Conversaciones: El sistema puede seguir la progresión de temas específicos a través de múltiples sesiones, entendiendo cómo las discusiones evolucionan y se construyen unas sobre otras.
    • Hitos del Proyecto: Las decisiones importantes, acuerdos y actualizaciones del proyecto se registran y pueden ser referenciados para mantener consistencia en discusiones futuras.
    • Evolución de Preferencias del Usuario: El sistema rastrea cómo las preferencias y requisitos del usuario cambian con el tiempo, adaptando sus respuestas en consecuencia.
    • Referencias Contextuales: Al abordar temas actuales, el sistema puede hacer referencia inteligentemente a discusiones pasadas relacionadas para proporcionar respuestas más informadas y matizadas.

Esta gestión sofisticada del contexto crea una experiencia conversacional fluida donde los usuarios se sienten comprendidos y valorados, ya que el sistema demuestra consciencia de su historial y necesidades continuas. Por ejemplo, si un usuario discutió previamente desafíos con un marco de programación específico, el sistema puede hacer referencia a esas conversaciones anteriores al proporcionar nuevas soluciones o actualizaciones.

  1. Preferencias de Personalización: El sistema mantiene y aplica preferencias detalladas del usuario a través de sesiones, incluyendo:
    • Idioma preferido y variaciones regionales
      • Selección de idioma (por ejemplo, inglés, español, mandarín)
      • Dialectos regionales y localizaciones
      • Unidades de moneda y medida
    • Preferencias de formato (viñetas vs. párrafos)
      • Preferencias de estructura de documento (jerárquico vs. plano)
      • Organización visual (listas, tablas o texto fluido)
      • Convenciones de formato de código cuando aplique
    • Nivel de detalle deseado en respuestas
      • Resúmenes breves vs. explicaciones exhaustivas
      • Profundidad técnica del contenido
      • Inclusión de ejemplos y analogías
    • Terminología específica o convenciones de nomenclatura
      • Vocabulario específico de la industria
      • Marcos técnicos o metodologías preferidas
      • Terminología específica de la empresa
    • Zonas horarias y horarios laborales
      • Preferencias de programación de reuniones
      • Preferencias de tiempo para notificaciones
      • Ventanas de disponibilidad para comunicación sincrónica

Este enfoque integral de personalización ayuda a crear una interacción más natural, eficiente y atractiva que se siente adaptada a las necesidades y preferencias individuales de cada usuario.

Ejemplo: Implementación de Respuestas Personalizadas

Aquí hay una implementación integral de un sistema de personalización que se adapta a los estilos de comunicación del usuario:

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

class UserProfile:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.communication_style = {
            "formality_level": 0.5,  # 0 = casual, 1 = formal
            "technical_level": 0.5,   # 0 = beginner, 1 = expert
            "verbosity": 0.5,         # 0 = concise, 1 = detailed
            "emoji_usage": False
        }
        self.preferences = {
            "language": "en",
            "timezone": "UTC",
            "topics_of_interest": []
        }
        self.interaction_history = []

class PersonalizedAIAssistant:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.profiles_dir = "user_profiles"
        os.makedirs(self.profiles_dir, exist_ok=True)
        self.users: Dict[str, UserProfile] = {}

    def _get_profile_path(self, user_id: str) -> str:
        return os.path.join(self.profiles_dir, f"{user_id}.json")

    def load_user_profile(self, user_id: str) -> UserProfile:
        if user_id in self.users:
            return self.users[user_id]

        profile_path = self._get_profile_path(user_id)
        if os.path.exists(profile_path):
            with open(profile_path, 'r') as f:
                data = json.load(f)
                profile = UserProfile(user_id)
                profile.communication_style = data.get('communication_style', profile.communication_style)
                profile.preferences = data.get('preferences', profile.preferences)
                profile.interaction_history = data.get('interaction_history', [])
        else:
            profile = UserProfile(user_id)

        self.users[user_id] = profile
        return profile

    def save_user_profile(self, profile: UserProfile):
        data = {
            'communication_style': profile.communication_style,
            'preferences': profile.preferences,
            'interaction_history': profile.interaction_history
        }
        with open(self._get_profile_path(profile.user_id), 'w') as f:
            json.dump(data, f, indent=2)

    def analyze_message(self, message: str) -> dict:
        """Analyze user message to update communication style metrics."""
        return {
            "formality_level": 0.8 if any(word in message.lower() for word in 
                ['please', 'thank you', 'sir', 'madam']) else 0.2,
            "technical_level": 0.8 if any(word in message.lower() for word in 
                ['api', 'function', 'implementation', 'code']) else 0.3,
            "emoji_usage": '😊' in message or '👍' in message
        }

    def generate_system_prompt(self, profile: UserProfile) -> str:
        """Create personalized system prompt based on user profile."""
        style = "formal" if profile.communication_style["formality_level"] > 0.5 else "casual"
        tech_level = "technical" if profile.communication_style["technical_level"] > 0.5 else "simple"
        
        return f"""You are a helpful assistant that communicates in a {style} style.
                  Use {tech_level} language and {'feel free to use emojis' 
                  if profile.communication_style['emoji_usage'] else 'avoid using emojis'}.
                  Communicate {'in detail' if profile.communication_style['verbosity'] > 0.5 
                  else 'concisely'}."""

    async def get_response(self, user_id: str, message: str) -> str:
        profile = self.load_user_profile(user_id)
        
        # Analyze and update user's communication style
        analysis = self.analyze_message(message)
        profile.communication_style.update(analysis)
        
        # Prepare conversation context
        messages = [
            {"role": "system", "content": self.generate_system_prompt(profile)},
            {"role": "user", "content": message}
        ]

        # Add relevant history if available
        if profile.interaction_history:
            recent_history = profile.interaction_history[-3:]  # Last 3 interactions
            messages[1:1] = recent_history

        # Get AI response
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            temperature=0.7,
            max_tokens=150
        )

        # Store interaction
        interaction = {
            "timestamp": datetime.utcnow().isoformat(),
            "user_message": message,
            "assistant_response": response.choices[0].message.content
        }
        profile.interaction_history.append(interaction)
        
        # Save updated profile
        self.save_user_profile(profile)
        
        return response.choices[0].message.content

# Usage example
if __name__ == "__main__":
    assistant = PersonalizedAIAssistant("your-api-key-here")
    
    # Example interactions
    responses = [
        assistant.get_response("user123", "Hey there! Can you help me with Python? 😊"),
        assistant.get_response("user123", "Could you explain the technical implementation of APIs?"),
        assistant.get_response("user123", "Dear Sir, I require assistance with programming.")
    ]

Desglose del Código:

  1. Estructura de Clases:
    • La clase UserProfile mantiene la información individual del usuario:
      • Métricas de estilo de comunicación (formalidad, nivel técnico, etc.)
      • Preferencias personales (idioma, zona horaria)
      • Historial de interacciones
    • La clase PersonalizedAIAssistant maneja la funcionalidad principal:
      • Gestión de perfiles (carga/guardado)
      • Análisis de mensajes
      • Generación de respuestas
  2. Características Principales:
    • Almacenamiento Persistente: Los perfiles se guardan como archivos JSON
    • Análisis de Estilo: Examina los mensajes para detectar patrones de comunicación
    • Generación Dinámica de Instrucciones: Genera indicaciones personalizadas del sistema
    • Gestión de Contexto: Mantiene el historial de conversaciones
  3. Aspectos de Personalización:
    • Estilo de Comunicación:
      • Detección del nivel de formalidad
      • Adaptación del lenguaje técnico
      • Seguimiento del uso de emojis
    • Adaptación de Respuestas:
      • Ajusta la verbosidad según las preferencias del usuario
      • Mantiene un estilo consistente en las interacciones
      • Incorpora el historial de conversaciones

Esta implementación demuestra cómo crear un asistente de IA que aprende y se adapta al estilo de comunicación de cada usuario mientras mantiene una memoria persistente de las interacciones. El sistema actualiza continuamente su comprensión de las preferencias del usuario y ajusta sus respuestas en consecuencia.

Reanudación de Sesiones

Los usuarios pueden retomar conversaciones después de pausas y hacer que la IA comprenda el contexto completo de las discusiones anteriores. Esta capacidad permite una continuidad fluida de la conversación, donde la IA mantiene la consciencia de interacciones previas, preferencias del usuario y contexto establecido. Por ejemplo, si un usuario discute un error de software el lunes y regresa el miércoles, la IA puede recordar los detalles específicos del error, las soluciones propuestas y cualquier intento de corrección sin requerir que el usuario repita la información.

Esta característica es particularmente valiosa para tareas complejas que abarcan múltiples sesiones, como la planificación de proyectos o la resolución de problemas técnicos. Durante la planificación de proyectos, la IA puede mantener registros de hitos previamente acordados, asignaciones de recursos y responsabilidades del equipo a través de múltiples sesiones de planificación. En escenarios de resolución de problemas técnicos, puede seguir la progresión de los intentos de depuración, recordar qué soluciones ya se probaron y construir sobre los pasos diagnósticos anteriores.

La IA puede hacer referencia a puntos específicos de conversaciones anteriores y mantener la continuidad durante días o incluso semanas. Esta consciencia del contexto a largo plazo permite que la IA haga sugerencias más informadas, evite discusiones redundantes y proporcione asistencia más personalizada basada en las interacciones históricas del usuario. Por ejemplo, si un usuario expresó previamente una preferencia por ciertos marcos de programación o metodologías, la IA puede incorporar estas preferencias en recomendaciones futuras sin requerir recordatorios explícitos.

Aquí hay una implementación práctica de la reanudación de sesiones:

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

class SessionManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.sessions: Dict[str, Dict] = {}
        
    def save_session(self, user_id: str, session_data: dict):
        """Save session data to persistent storage."""
        with open(f"sessions/{user_id}.json", "w") as f:
            json.dump(session_data, f)
            
    def load_session(self, user_id: str) -> Optional[dict]:
        """Load session data from storage."""
        try:
            with open(f"sessions/{user_id}.json", "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return None

class ConversationManager:
    def __init__(self, session_manager: SessionManager):
        self.session_manager = session_manager
        self.current_context: List[Dict] = []
        
    def prepare_context(self, user_id: str, new_message: str) -> List[Dict]:
        """Prepare conversation context including session history."""
        # Load previous session if exists
        session = self.session_manager.load_session(user_id)
        
        # Initialize context with system message
        context = [{
            "role": "system",
            "content": "You are a helpful assistant with memory of past conversations."
        }]
        
        # Add relevant history from previous session
        if session and 'history' in session:
            # Add last 5 messages from previous session for context
            context.extend(session['history'][-5:])
        
        # Add new message
        context.append({
            "role": "user",
            "content": new_message
        })
        
        return context

    async def process_message(self, user_id: str, message: str) -> str:
        """Process new message with session context."""
        context = self.prepare_context(user_id, message)
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=context,
                temperature=0.7,
                max_tokens=150
            )
            
            assistant_message = response.choices[0].message.content
            
            # Update session with new interaction
            session_data = {
                'last_interaction': datetime.now().isoformat(),
                'history': context + [{
                    "role": "assistant",
                    "content": assistant_message
                }]
            }
            self.session_manager.save_session(user_id, session_data)
            
            return assistant_message
            
        except Exception as e:
            print(f"Error processing message: {e}")
            return "I apologize, but I encountered an error processing your message."

# Example usage
async def main():
    session_manager = SessionManager("your-api-key-here")
    conversation_manager = ConversationManager(session_manager)
    
    # First interaction
    response1 = await conversation_manager.process_message(
        "user123",
        "What's the weather like today?"
    )
    print("Response 1:", response1)
    
    # Later interaction (session resumption)
    response2 = await conversation_manager.process_message(
        "user123",
        "What did we discuss earlier?"
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase SessionManager:
    • Maneja el almacenamiento persistente de datos de sesión
    • Proporciona métodos para guardar y cargar información de sesión
    • Mantiene archivos de sesión específicos para cada usuario
  2. Clase ConversationManager:
    • Gestiona el contexto e historial de conversaciones
    • Prepara el contexto combinando datos de sesiones previas con nuevos mensajes
    • Maneja la interacción con la API de OpenAI
  3. Características Principales:
    • Procesamiento Asíncrono: Utiliza async/await para llamadas eficientes a la API
    • Gestión de Contexto: Mantiene el historial relevante de conversaciones
    • Manejo de Errores: Incluye gestión robusta de errores
    • Persistencia de Sesión: Guarda conversaciones en disco para recuperación posterior
  4. Detalles de Implementación:
    • Utiliza JSON para almacenamiento de sesiones
    • Limita el contexto a los últimos 5 mensajes por eficiencia
    • Incluye seguimiento de marca temporal para gestión de sesiones
    • Mantiene roles de conversación (sistema, usuario, asistente)

Este ejemplo proporciona una base robusta para gestionar conversaciones multi-sesión mientras mantiene el contexto e historial del usuario. Es particularmente útil para aplicaciones que requieren memoria persistente de conversación a través de múltiples interacciones.

Conocimiento Persistente

El sistema mantiene un registro robusto y completo de toda la información significativa intercambiada durante las conversaciones. Esta arquitectura de conocimiento persistente opera en múltiples niveles:

  1. Gestión de Información Básica: El sistema captura y almacena datos operativos esenciales de manera estructurada. Esto incluye el seguimiento integral de entradas del calendario como reuniones y citas, con metadatos como asistentes y agendas. Los cronogramas de proyectos se mantienen con un seguimiento detallado de hitos, dependencias y transiciones de fase.

El sistema registra todos los plazos sistemáticamente, desde fechas límite a nivel de tarea hasta entregables principales del proyecto. Las actualizaciones regulares se almacenan cronológicamente, incluyendo informes diarios, cambios de estado y modificaciones del proyecto. Esta robusta arquitectura de información garantiza que todos los datos relacionados con la programación y los proyectos permanezcan fácilmente recuperables, respaldando una gestión eficiente de proyectos y la coordinación del equipo.

  1. Datos Específicos del Usuario: El sistema mantiene perfiles detallados de usuarios individuales que abarcan múltiples aspectos de sus interacciones:
    • Preferencias Personales: Incluyendo canales de comunicación preferidos, formatos de respuesta y áreas específicas de interés
    • Estilos de Comunicación: Seguimiento de si los usuarios prefieren lenguaje formal o casual, explicaciones técnicas o simplificadas, y sus preferencias típicas en la extensión de respuestas
    • Experiencia Técnica: Monitoreo y adaptación a los niveles demostrados de conocimiento de los usuarios en diferentes temas y ajuste de explicaciones en consecuencia
    • Patrones Históricos: Registro de tiempos de interacción, temas frecuentemente discutidos y preguntas o preocupaciones comunes
    • Patrones de Lenguaje: Anotación del uso de vocabulario, familiaridad con terminología técnica y ejemplos o analogías preferidas
    • Progreso de Aprendizaje: Seguimiento de cómo evoluciona la comprensión de los usuarios sobre varios temas a lo largo del tiempo

Este perfil integral del usuario permite que el sistema entregue respuestas cada vez más personalizadas que coincidan con las necesidades y preferencias únicas de cada usuario, creando una experiencia de interacción más efectiva y atractiva con el tiempo.

  1. Registro de Decisiones: Las decisiones críticas se documentan sistemáticamente de manera integral que incluye múltiples componentes clave:
    • Contexto: La situación completa de fondo, entorno empresarial y restricciones que enmarcaron la decisión
    • Fundamento: Razonamiento detallado detrás de la elección, incluyendo:
      • Análisis de alternativas consideradas
      • Evaluación y estrategias de mitigación de riesgos
      • Resultados esperados y métricas de éxito
    • Partes Interesadas: Documentación completa de:
      • Tomadores de decisiones y sus roles
      • Equipos y departamentos afectados
      • Partes externas involucradas
    • Plan de Implementación:
      • Estrategia de ejecución paso a paso
      • Detalles de asignación de recursos
      • Cronograma e hitos

Este proceso sistemático de documentación crea un rastro detallado y auditable que permite a los equipos:

  • Seguir la evolución de decisiones importantes
  • Comprender el contexto completo de elecciones pasadas
  • Aprender de experiencias previas
  • Tomar decisiones más informadas en el futuro
  • Mantener la responsabilidad y transparencia
  1. Gestión de Tareas: El sistema implementa un sistema integral de seguimiento de tareas que monitorea varios aspectos de la ejecución del proyecto:
    • Seguimiento de Asignaciones: Cada tarea está vinculada a miembros específicos del equipo o departamentos responsables de su finalización, asegurando una clara propiedad y responsabilidad
    • Gestión de Cronogramas: Se mantienen fechas límite detalladas, incluyendo tanto plazos finales como hitos intermedios, permitiendo una mejor gestión del tiempo
    • Monitoreo de Progreso: Se registran actualizaciones regulares de estado para seguir la progresión de tareas, incluyendo trabajo completado, obstáculos actuales y pasos restantes
    • Mapeo de Dependencias: El sistema mantiene un mapa claro de dependencias entre tareas, ayudando a los equipos a entender cómo los retrasos o cambios en una tarea podrían impactar a otras
    • Asignación de Recursos: Rastrea la distribución de trabajo y recursos entre los miembros del equipo para prevenir la sobrecarga y asegurar una ejecución eficiente del proyecto
  2. Detalles del Proyecto: El sistema mantiene documentación integral de aspectos técnicos incluyendo:
    • Especificaciones Técnicas:
      • Planos detallados de arquitectura del sistema
      • Documentación completa de API y puntos finales
      • Esquemas de base de datos y modelos de datos
      • Especificaciones de integración con terceros
    • Requisitos del Proyecto:
      • Requisitos y objetivos de negocio
      • Requisitos técnicos y restricciones
      • Historias de usuario y criterios de aceptación
      • Definiciones y límites de alcance
    • Desafíos y Soluciones:
      • Obstáculos técnicos identificados
      • Soluciones alternativas implementadas
      • Esfuerzos de optimización de rendimiento
      • Medidas y actualizaciones de seguridad
    • Registros de Implementación:
      • Documentación y ejemplos de código
      • Registros de decisiones de arquitectura
      • Estrategias y resultados de pruebas
      • Procedimientos de implementación

Esta base de conocimiento persistente integral sirve múltiples propósitos: previene la pérdida de información, permite referencias históricas precisas, apoya la toma de decisiones informada y permite la continuación fluida de discusiones complejas a través de múltiples sesiones. El sistema puede fácilmente recordar y contextualizar información de interacciones pasadas, haciendo cada conversación más eficiente y productiva.

Aquí hay una implementación integral del Conocimiento Persistente usando la API de OpenAI:

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

class PersistentKnowledge:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.encoding = tiktoken.encoding_for_model("gpt-4o")
        
    def count_tokens(self, text: str) -> int:
        """Count tokens in text using tiktoken"""
        return len(self.encoding.encode(text))
        
    def save_knowledge(self, user_id: str, category: str, data: Dict):
        """Save knowledge to persistent storage with categories"""
        filename = f"knowledge_{user_id}_{category}.json"
        timestamp = datetime.now().isoformat()
        
        data_with_metadata = {
            "timestamp": timestamp,
            "category": category,
            "content": data
        }
        
        try:
            with open(filename, "r") as f:
                existing_data = json.load(f)
        except FileNotFoundError:
            existing_data = []
            
        existing_data.append(data_with_metadata)
        
        with open(filename, "w") as f:
            json.dump(existing_data, f, indent=2)
            
    def retrieve_knowledge(self, user_id: str, category: str, 
                         max_tokens: int = 2000) -> List[Dict]:
        """Retrieve knowledge with token limit"""
        filename = f"knowledge_{user_id}_{category}.json"
        try:
            with open(filename, "r") as f:
                all_data = json.load(f)
        except FileNotFoundError:
            return []
            
        # Retrieve most recent entries within token limit
        retrieved_data = []
        current_tokens = 0
        
        for entry in reversed(all_data):
            content_str = json.dumps(entry["content"])
            tokens = self.count_tokens(content_str)
            
            if current_tokens + tokens <= max_tokens:
                retrieved_data.append(entry)
                current_tokens += tokens
            else:
                break
                
        return list(reversed(retrieved_data))
        
    async def get_ai_response(self, 
                            user_id: str,
                            current_input: str,
                            categories: List[str] = None) -> str:
        """Generate AI response with context from persistent knowledge"""
        
        # Build context from stored knowledge
        context = []
        if categories:
            for category in categories:
                knowledge = self.retrieve_knowledge(user_id, category)
                if knowledge:
                    context.append(f"\nRelevant {category} knowledge:")
                    for entry in knowledge:
                        context.append(json.dumps(entry["content"]))
                        
        # Prepare messages for API
        messages = [
            {
                "role": "system",
                "content": "You are an assistant with access to persistent knowledge. "
                          "Use this context to provide informed responses."
            },
            {
                "role": "user",
                "content": f"Context:\n{''.join(context)}\n\nCurrent query: {current_input}"
            }
        ]
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4",
                messages=messages,
                temperature=0.7,
                max_tokens=500
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"
            
class KnowledgeManager:
    def __init__(self, api_key: str):
        self.knowledge = PersistentKnowledge(api_key)
        
    async def process_interaction(self, 
                                user_id: str,
                                message: str,
                                categories: List[str] = None) -> str:
        """Process user interaction and maintain knowledge"""
        
        # Save user input
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "user", "message": message}
        )
        
        # Get AI response with context
        response = await self.knowledge.get_ai_response(
            user_id,
            message,
            categories
        )
        
        # Save AI response
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "assistant", "message": response}
        )
        
        return response

# Example usage
async def main():
    manager = KnowledgeManager("your-api-key")
    
    # First interaction
    response1 = await manager.process_interaction(
        "user123",
        "What's the best way to learn Python?",
        ["conversations", "preferences"]
    )
    print("Response 1:", response1)
    
    # Save user preference
    manager.knowledge.save_knowledge(
        "user123",
        "preferences",
        {"learning_style": "hands-on", "preferred_language": "Python"}
    )
    
    # Later interaction using stored knowledge
    response2 = await manager.process_interaction(
        "user123",
        "Can you suggest some projects based on my learning style?",
        ["conversations", "preferences"]
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase PersistentKnowledge:
    • Maneja el conteo de tokens usando tiktoken para la gestión del contexto
    • Implementa save_knowledge() para almacenar información categorizada
    • Proporciona retrieve_knowledge() con límites de tokens para la recuperación de contexto
    • Gestiona las interacciones de IA a través de get_ai_response()
  2. Clase KnowledgeManager:
    • Proporciona una interfaz de alto nivel para la gestión del conocimiento
    • Procesa las interacciones del usuario y mantiene el historial de conversaciones
    • Maneja el guardado tanto de las entradas del usuario como las respuestas de la IA
  3. Características Principales:
    • Almacenamiento Categorizado de Conocimiento: Organiza la información por usuario y categoría
    • Gestión de Tokens: Asegura que el contexto se mantenga dentro de los límites del modelo
    • Seguimiento de Metadatos: Incluye marcas de tiempo y categorías para todos los datos almacenados
    • Manejo de Errores: Gestión robusta de errores para operaciones de archivo y llamadas a la API
  4. Beneficios de la Implementación:
    • Escalable: Maneja múltiples usuarios y categorías de conocimiento
    • Eficiente: Utiliza conteo de tokens para optimizar el uso del contexto
    • Flexible: Admite varios tipos y categorías de conocimiento
    • Mantenible: Código bien estructurado con clara separación de responsabilidades

Esta implementación proporciona una base sólida para aplicaciones de IA que requieren conocimiento persistente a través de conversaciones. Sobresale en mantener las preferencias del usuario, historiales de conversación y otros datos continuos mientras gestiona eficientemente los límites de tokens.

Resumen de Conversaciones

Al mantener historiales detallados de conversaciones, el sistema puede generar resúmenes completos que capturan puntos clave, decisiones y elementos de acción. Estos resúmenes cumplen múltiples funciones críticas:

  1. Actualización de Contexto: Cuando los participantes comienzan nuevas sesiones de conversación, el sistema proporciona resúmenes concisos pero completos de discusiones previas. Estos resúmenes sirven como informes eficientes que:
    • Orientan rápidamente a los participantes sobre puntos clave de discusión
    • Destacan decisiones y resultados importantes
    • Identifican elementos de acción en curso
    • Refrescan la memoria sobre el contexto crítico
      Esto elimina el proceso que consume tiempo de revisar registros extensos de conversación y asegura que todos los participantes puedan involucrarse inmediatamente de manera productiva en la discusión actual con plena conciencia del contexto.
  2. Seguimiento del Progreso: Los resúmenes regulares sirven como un mecanismo integral de seguimiento para discusiones y proyectos en curso. Al mantener registros detallados de la evolución del proyecto, los equipos pueden:
    • Monitorear Fases de Desarrollo
      • Seguir la progresión desde conceptos iniciales hasta implementación
      • Documentar mejoras y refinamientos iterativos
      • Registrar puntos de inflexión clave en la dirección del proyecto
    • Analizar Historial de Decisiones
      • Capturar el contexto detrás de elecciones importantes
      • Documentar opciones alternativas consideradas
      • Seguir resultados de decisiones implementadas
    • Identificar Tendencias del Proyecto
      • Detectar desafíos o cuellos de botella recurrentes
      • Reconocer patrones exitosos para replicar
      • Monitorear velocidad y momentum
    • Facilitar Alineación del Equipo
      • Mantener entendimiento compartido del progreso
      • Permitir correcciones basadas en datos
      • Apoyar la asignación informada de recursos
  3. Extracción de Conocimiento: El sistema emplea técnicas avanzadas de análisis para identificar y extraer información crítica de las conversaciones, incluyendo:
    • Decisiones clave y su fundamento
      • Elecciones estratégicas realizadas durante las discusiones
      • Evidencia de respaldo y justificación
      • Opciones alternativas consideradas
    • Elementos de acción y sus responsables
      • Tareas específicas asignadas a miembros del equipo
      • Asignaciones claras de responsabilidad
      • Requisitos de seguimiento
    • Fechas límite y hitos importantes
      • Marcadores de línea temporal del proyecto
      • Fechas críticas de entrega
      • Programas de revisión y puntos de control
    • Preguntas o preocupaciones sin resolver
      • Problemas técnicos abiertos
      • Decisiones pendientes
      • Áreas que necesitan clarificación
    • Acuerdos y compromisos establecidos
      • Decisiones formales alcanzadas
      • Acuerdos de asignación de recursos
      • Compromisos de cronograma
  4. Generación de Informes: Los resúmenes pueden compilarse automáticamente en varios tipos de informes:
    • Informes ejecutivos
      • Visiones generales de alto nivel para interesados
      • Decisiones clave e implicaciones estratégicas
      • Resúmenes de asignación de recursos
    • Actas de reunión
      • Puntos detallados de discusión y resultados
      • Elementos de acción y asignados
      • Compromisos de cronograma establecidos
    • Actualizaciones de progreso
      • Logros de hitos y retrasos
      • Bloqueadores y desafíos actuales
      • Próximos pasos y prioridades
    • Informes de estado del proyecto
      • Indicadores generales de salud del proyecto
      • Métricas de utilización de recursos
      • Evaluaciones de riesgo y estrategias de mitigación

La capacidad de condensar y recordar información relevante no solo hace las conversaciones más eficientes y enfocadas, sino que también asegura que la información crítica nunca se pierda y pueda ser fácilmente accedida cuando sea necesario. Este enfoque sistemático para el resumen de conversaciones ayuda a mantener la claridad y continuidad a través de interacciones a largo plazo, especialmente en proyectos complejos o discusiones continuas que involucran múltiples participantes.

Ejemplo: Implementación de Resumen de Conversaciones

Aquí hay una implementación práctica de un resumidor de conversaciones usando la API de OpenAI:

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

class ConversationSummarizer:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        
    def create_summary_prompt(self, messages: List[Dict]) -> str:
        """Create a prompt for summarization from messages"""
        conversation = "\n".join([
            f"{msg['role'].title()}: {msg['content']}" 
            for msg in messages
        ])
        
        return f"""Please provide a concise summary of the following conversation, 
        highlighting key points, decisions, and action items:

        {conversation}
        
        Summary should include:
        1. Main topics discussed
        2. Key decisions made
        3. Action items and owners
        4. Unresolved questions
        """

    async def generate_summary(self, messages: List[Dict]) -> Dict:
        """Generate a structured summary of the conversation"""
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=[{
                    "role": "user",
                    "content": self.create_summary_prompt(messages)
                }],
                temperature=0.7,
                max_tokens=500
            )
            
            summary = response.choices[0].message.content
            
            return {
                "timestamp": datetime.now().isoformat(),
                "message_count": len(messages),
                "summary": summary
            }
            
        except Exception as e:
            return {
                "error": f"Failed to generate summary: {str(e)}",
                "timestamp": datetime.now().isoformat()
            }

    def save_summary(self, summary: Dict, filename: str = "summaries.json"):
        """Save summary to JSON file"""
        try:
            with open(filename, "r") as f:
                summaries = json.load(f)
        except FileNotFoundError:
            summaries = []
            
        summaries.append(summary)
        
        with open(filename, "w") as f:
            json.dump(summaries, f, indent=2)

# Example usage
async def main():
    summarizer = ConversationSummarizer("your-api-key")
    
    # Sample conversation
    messages = [
        {"role": "user", "content": "Let's discuss the new feature implementation."},
        {"role": "assistant", "content": "Sure! What specific aspects would you like to focus on?"},
        {"role": "user", "content": "We need to implement user authentication by next week."},
        {"role": "assistant", "content": "I understand. Let's break down the requirements and timeline."}
    ]
    
    # Generate and save summary
    summary = await summarizer.generate_summary(messages)
    summarizer.save_summary(summary)
    print("Summary:", summary["summary"])

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

Desglose del Código:

  1. Estructura de Clase:
    • La clase ConversationSummarizer maneja todas las operaciones de resumen
    • Inicialización con configuración de clave API
    • Métodos para creación de prompts, generación de resúmenes y almacenamiento
  2. Características Principales:
    • Generación estructurada de prompts para resúmenes consistentes
    • Llamadas API asíncronas para mejor rendimiento
    • Manejo y registro de errores
    • Almacenamiento persistente de resúmenes
  3. Beneficios de Implementación:
    • Escalable: Maneja conversaciones de diferentes longitudes
    • Salida Estructurada: Resúmenes organizados con información clave
    • Seguimiento Histórico: Mantiene historial de resúmenes
    • Resistente a Errores: Manejo y registro de errores robusto

Este ejemplo proporciona una forma confiable de generar y mantener resúmenes de conversaciones, facilitando el seguimiento del progreso de las discusiones y decisiones clave a lo largo del tiempo.

7.3.2 Arquitectura Central

Para crear un sistema de memoria efectivo para interacciones de IA, tres componentes esenciales trabajan juntos de manera coordinada para mantener el contexto y asegurar la continuidad conversacional. Estos componentes forman una arquitectura sofisticada que permite a los sistemas de IA acceder, procesar y utilizar información histórica de manera efectiva durante las conversaciones en curso.

El componente de almacenamiento preserva el historial de conversación, el mecanismo de recuperación obtiene de manera inteligente las interacciones pasadas relevantes, y el sistema de inyección incorpora perfectamente este contexto histórico en las conversaciones actuales.

Juntos, estos tres pilares crean una base robusta que permite a los sistemas de IA mantener diálogos significativos y conscientes del contexto a través de múltiples interacciones:

Almacenamiento

La base de la gestión de memoria donde todas las interacciones se guardan y preservan sistemáticamente para uso futuro. Este componente crítico sirve como columna vertebral de cualquier sistema de conversación de IA:

  • Puede utilizar varias soluciones de almacenamiento como archivos JSON, bases de datos SQL o almacenamiento en la nube
    • Los archivos JSON ofrecen simplicidad y portabilidad para aplicaciones más pequeñas
    • Las bases de datos SQL proporcionan consultas robustas e indexación para conjuntos de datos más grandes
    • El almacenamiento en la nube permite acceso escalable y distribuido a través de múltiples servicios
  • Debe incluir metadatos como marcas de tiempo e identificadores de usuario
    • Las marcas de tiempo permiten seguimiento cronológico y filtrado basado en tiempo
    • Los IDs de usuario mantienen hilos de conversación y personalización
    • Metadatos adicionales pueden rastrear temas y contextos de conversación
  • Debe estar organizado para recuperación y escalado eficientes
    • Implementar indexación adecuada para acceso rápido a datos relevantes
    • Usar particionamiento de datos para mejor rendimiento
    • Considerar estrategias de compresión para almacenamiento a largo plazo

Recuperación

El sistema inteligente para acceder y filtrar conversaciones pasadas relevantes sirve como un componente crucial en la gestión del historial de conversaciones:

  • Implementa algoritmos de búsqueda para encontrar datos históricos apropiados al contexto
    • Utiliza búsqueda semántica para coincidir temas y temáticas similares
    • Emplea coincidencia difusa para comparación flexible de texto
    • Indexa conversaciones para recuperación rápida
  • Utiliza parámetros como recencia, relevancia e hilo de conversación
    • Prioriza interacciones recientes para contexto inmediato
    • Pondera relevancia basada en puntajes de similitud de temas
    • Mantiene continuidad de hilos rastreando flujos de conversación
  • Gestiona límites de tokens seleccionando el contexto más importante
    • Implementa estrategias inteligentes de truncamiento
    • Prioriza información clave mientras elimina contenido redundante
    • Ajusta dinámicamente ventana de contexto según limitaciones del modelo

Inyección

El proceso de incorporar perfectamente el contexto histórico requiere un manejo cuidadoso para mantener la coherencia de la conversación:

  • Coloca estratégicamente mensajes recuperados en el flujo actual de conversación
    • Determina puntos óptimos de inserción para contexto histórico
    • Filtra y prioriza información histórica relevante
    • Equilibra contenido nuevo e histórico para un flujo natural
  • Mantiene orden apropiado de mensajes y relaciones
    • Preserva secuencia cronológica de interacciones
    • Respeta hilos de conversación y cadenas de respuestas
    • Enlaza temas y discusiones relacionadas apropiadamente
  • Asegura integración fluida del contexto sin interrumpir la conversación
    • Evita cambios abruptos de contexto o sobrecarga de información
    • Utiliza frases de transición y referencias naturales
    • Mantiene tono y estilo de conversación consistentes

7.3.3 Cómo Almacenar y Recuperar Historiales de Mensajes Basados en JSON en Python

En esta sección, exploraremos una implementación práctica que demuestra cómo crear un sistema de memoria persistente usando archivos JSON. Este enfoque ofrece una manera directa de mantener el contexto de conversación a través de múltiples sesiones mientras se mantiene escalable y fácil de mantener.

Nuestra implementación se centrará en tres aspectos clave: almacenar eficientemente historiales de mensajes en formato JSON, recuperar contexto de conversación relevante cuando sea necesario, y gestionar la estructura de datos para asegurar un rendimiento óptimo. Esta solución es particularmente útil para desarrolladores que construyen chatbots, asistentes virtuales o cualquier aplicación que requiera historial de conversación persistente.

Paso 1: Construir el Gestor de Memoria

Este módulo maneja el almacenamiento de interacciones de usuario en formato JSON y recupera solo las relevantes.

import os
import json
from typing import List, Dict

MEMORY_DIR = "user_memory"
os.makedirs(MEMORY_DIR, exist_ok=True)

# Constants
MAX_HISTORY_MESSAGES = 5  # Truncate history to last 5 messages to manage tokens

def get_memory_path(user_id: str) -> str:
    return os.path.join(MEMORY_DIR, f"{user_id}.json")

def load_history(user_id: str) -> List[Dict[str, str]]:
    path = get_memory_path(user_id)
    if not os.path.exists(path):
        return []
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        return []

def store_interaction(user_id: str, role: str, content: str) -> None:
    message = {"role": role, "content": content}
    path = get_memory_path(user_id)

    history = load_history(user_id)
    history.append(message)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=2)

def get_recent_history(user_id: str, limit: int = MAX_HISTORY_MESSAGES) -> List[Dict[str, str]]:
    history = load_history(user_id)
    return history[-limit:]

Analicemos este código:

  1. Configuración Inicial
  • Crea un directorio "user_memory" para almacenar los historiales de conversación
  • Establece un límite máximo de 5 mensajes para la gestión del historial
  1. Funciones Principales
  • get_memory_path(user_id): Crea una ruta de archivo JSON única para cada usuario
  • load_history(user_id):
    • Intenta leer el historial de conversación del usuario
    • Devuelve una lista vacía si el archivo no existe o está corrupto
  • store_interaction(user_id, role, content):
    • Guarda nuevos mensajes en el archivo de historial del usuario
    • Añade el mensaje al historial existente
    • Almacena en formato JSON con sangría apropiada
  • get_recent_history(user_id, limit):
    • Recupera los mensajes más recientes
    • Respeta el límite MAX_HISTORY_MESSAGES (5 mensajes)
  1. Características Principales
  • Almacenamiento persistente: Las conversaciones de cada usuario se guardan en archivos JSON separados
  • Escalabilidad: El sistema puede manejar múltiples usuarios con archivos individuales
  • Contexto controlado: Permite control específico sobre cuánto historial mantener
  • Fácil de depurar: El formato JSON facilita la inspección de conversaciones almacenadas

Paso 2: Crear el Motor de Chat Usando la API de OpenAI

Ahora integremos este sistema de memoria con la API de OpenAI. Cargaremos los mensajes anteriores, añadiremos el nuevo prompt, consultaremos el modelo y guardaremos la respuesta.

import openai
from dotenv import load_dotenv

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

SYSTEM_PROMPT = {
    "role": "system",
    "content": "You are a helpful assistant that remembers the user's previous messages."
}

def continue_conversation(user_id: str, user_input: str) -> str:
    # Validate input
    if not user_input.strip():
        return "Input cannot be empty."

    # Load memory and prepare messages
    recent_history = get_recent_history(user_id)
    messages = [SYSTEM_PROMPT] + recent_history + [{"role": "user", "content": user_input}]

    # Call OpenAI API
    try:
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=300,
            temperature=0.7
        )
        assistant_reply = response["choices"][0]["message"]["content"]

        # Store both messages
        store_interaction(user_id, "user", user_input)
        store_interaction(user_id, "assistant", assistant_reply)

        return assistant_reply

    except Exception as e:
        return f"Something went wrong: {e}"

Analicemos este código:

1. Configuración Inicial

  • Importa las bibliotecas necesarias (openai y dotenv)
  • Carga las variables de entorno y configura la clave API de OpenAI
  • Define un prompt de sistema que establece el rol del asistente

2. Función Principal: continue_conversation

  • Recibe user_id y user_input como parámetros
  • Validación de entrada para verificar mensajes vacíos
  • Carga el historial de conversación usando get_recent_history (definido en la sección anterior)
  • Construye el array de mensajes combinando: 
    • Prompt del sistema
    • Historial reciente de conversación
    • Entrada actual del usuario

3. Interacción con la API

  • Realiza la llamada a la API de OpenAI con parámetros: 
    • Utiliza el modelo "gpt-4o"
    • Establece max_tokens en 300
    • Usa una temperatura de 0.7 para una creatividad equilibrada
  • Extrae la respuesta del asistente de la respuesta

4. Gestión de Memoria

  • Almacena tanto la entrada del usuario como la respuesta del asistente usando store_interaction
  • Maneja los errores adecuadamente con un bloque try-except

Esta parte crea un sistema de conversación con estado que mantiene el contexto a través de múltiples interacciones mientras gestiona el flujo de conversación de manera eficiente.

Paso 3: Probar la Memoria de Conversación

if __name__ == "__main__":
    user_id = "user_456"

    print("User: What are the best Python libraries for data science?")
    reply1 = continue_conversation(user_id, "What are the best Python libraries for data science?")
    print("Assistant:", reply1)

    print("\nUser: Could you remind me which ones you mentioned?")
    reply2 = continue_conversation(user_id, "Could you remind me which ones you mentioned?")
    print("Assistant:", reply2)

Analicemos este ejemplo de código para probar la memoria de conversación:

1. Verificación del Punto de Entrada

  • El código utiliza el modismo estándar de Python if __name__ == "__main__": para asegurar que este código solo se ejecute cuando el archivo se ejecuta directamente

2. Configuración del Usuario

  • Crea un usuario de prueba con ID "user_456"

3. Flujo de Conversación de Prueba

  • Demuestra una conversación de dos turnos donde:
  • Primer turno: Pregunta sobre las bibliotecas de Python para ciencia de datos
  • Segundo turno: Pide un recordatorio de las bibliotecas mencionadas anteriormente, probando el sistema de memoria

4. Detalles de Implementación

  • Cada interacción utiliza la función continue_conversation() para:
  • Procesar la entrada del usuario
  • Generar y almacenar la respuesta
  • Imprimir tanto la entrada del usuario como la respuesta del asistente

Este código de prueba demuestra efectivamente cómo el sistema mantiene el contexto entre múltiples interacciones, permitiendo que el asistente haga referencia a respuestas anteriores al contestar preguntas de seguimiento.

Beneficios de Este Enfoque

  • Persistente: Todas las conversaciones se almacenan localmente por usuario, asegurando que no se pierda ningún historial de interacción. Esto significa que su aplicación puede mantener el contexto a través de múltiples sesiones, incluso si el servidor se reinicia o la aplicación se cierra.
  • Escalable (hasta cierto punto): Al almacenar el historial de conversación de cada usuario en su propio archivo JSON, el sistema puede manejar múltiples usuarios de manera eficiente. Este enfoque funciona bien para aplicaciones pequeñas y medianas, aunque para implementaciones muy grandes podría ser conveniente considerar una solución de base de datos.
  • Contexto controlable: El sistema le da control completo sobre cuánto historial de conversación incluir en cada interacción. Puede ajustar el tamaño de la ventana de memoria, filtrar por relevancia o implementar lógica personalizada para seleccionar qué mensajes anteriores incluir en el contexto.
  • Legible: El formato de archivo JSON facilita la inspección, depuración y modificación de las conversaciones almacenadas. Esto es invaluable durante el desarrollo y mantenimiento, ya que puede ver fácilmente el historial de conversación en cualquier editor de texto y validar la estructura de datos.

Mejoras Opcionales

  • Resumen: En lugar de almacenar cada mensaje textualmente, implementar resúmenes periódicos del historial de conversación. Esta técnica implica generar automáticamente resúmenes concisos de segmentos más largos de conversación, lo que ayuda a:
  • Reducir el uso de tokens en llamadas a la API
  • Mantener el contexto esencial mientras se eliminan detalles redundantes
  • Crear una estructura de memoria más eficiente

Por ejemplo, múltiples mensajes sobre un tema específico podrían condensarse en una única declaración resumida.

  • Búsqueda Vectorial (Avanzado): Transformar mensajes en vectores numéricos utilizando modelos de embedding, permitiendo una recuperación sofisticada basada en significado semántico. Este enfoque ofrece varias ventajas:
  • Descubrir mensajes históricos contextualmente relevantes incluso si utilizan palabras diferentes
  • Priorizar mensajes basados en su relevancia para la conversación actual
  • Permitir búsquedas rápidas de similitud a través de grandes historiales de conversación

Esto es particularmente útil para conversaciones de larga duración o cuando se necesita recordar contexto específico.

  • Gestión de Tokens: Implementar estrategias inteligentes de gestión de tokens para optimizar el uso de la ventana de contexto. Esto incluye:
  • Establecer límites dinámicos basados en la importancia de la conversación
  • Implementar poda inteligente de mensajes más antiguos y menos relevantes
  • Mantener un equilibrio entre el contexto reciente y la información histórica importante

Esto asegura que se mantenga dentro de los límites de tokens de la API mientras se preserva el contexto de conversación más valioso.

  • Mantener el prompt del sistema consistente a través de las interacciones
  • Mantener la redacción e instrucciones del prompt idénticas durante todo el ciclo de vida de la conversación
  • Usar control de versiones para rastrear cualquier cambio en el prompt del sistema a través de las implementaciones
  • Previene confusión y respuestas contradictorias manteniendo un contexto consistente
  • Asegura que la IA mantenga una personalidad y patrón de comportamiento confiable a través de las interacciones
  • No sobrecargue el contexto—almacene todo, pero recupere selectivamente
  • Implementar un sistema de almacenamiento integral que mantenga historiales completos de conversación en su base de datos
  • Desarrollar algoritmos de recuperación inteligentes que prioricen el contexto relevante para las llamadas a la API
  • Usar búsqueda semántica o similitud basada en embeddings para encontrar mensajes históricos pertinentes
  • Equilibrar el uso de tokens implementando estrategias inteligentes de poda para mensajes más antiguos
  • Etiquetar los mensajes almacenados claramente (rolecontenttimestamp) para filtrado o resumen futuro
  • Role: Identificar y etiquetar cuidadosamente las fuentes de los mensajes (sistema, usuario o asistente) para mantener un flujo de conversación claro y permitir el filtrado basado en roles
  • Content: Implementar estándares de formato consistentes para el contenido de los mensajes, incluyendo el manejo de caracteres especiales y manteniendo la integridad de los datos
  • Timestamp: Agregar metadatos temporales precisos para permitir operaciones sofisticadas basadas en tiempo como segmentación de conversación y puntuación de relevancia contextual

La memoria a largo plazo no es nativa de los modelos de chat de OpenAI (todavía), pero con una ingeniería cuidadosa, puede crear sistemas de memoria sofisticados. Esta limitación significa que por defecto, el modelo trata cada interacción como aislada, sin conocimiento de conversaciones anteriores. Sin embargo, los desarrolladores pueden implementar soluciones personalizadas para superar esta limitación.

Aquí hay una explicación detallada de cómo funciona: Mientras que el modelo en sí no mantiene memorias entre conversaciones, su aplicación actúa como un gestor de memoria. Almacena cada interacción en un formato estructurado, típicamente usando bases de datos o sistemas de archivos. Estos datos almacenados incluyen no solo el contenido de la conversación, sino también metadatos como marcas de tiempo, información del usuario y temas de conversación. Al gestionar cuidadosamente estas conversaciones almacenadas y recuperar selectivamente piezas relevantes, crea una ilusión de memoria continua - haciendo que la IA parezca "recordar" interacciones anteriores.

Este sistema de memoria transforma tu asistente de IA de varias formas poderosas:

  • Continuidad: El asistente puede hacer referencia a conversaciones pasadas y mantener el contexto durante períodos prolongados, creando interacciones fluidas que se construyen sobre discusiones previas. Por ejemplo, si un usuario menciona su preferencia por la programación en Python en una conversación, el sistema puede hacer referencia a esto en interacciones futuras.
  • Personalidad: Los patrones de respuesta consistentes y las preferencias recordadas crean una personalidad más distintiva. Esto incluye mantener un tono consistente, recordar las preferencias del usuario y adaptar los estilos de comunicación basados en interacciones anteriores.
  • Comprensión: Al acceder al contexto histórico, las respuestas se vuelven más informadas y personalizadas. El sistema puede recordar detalles específicos de conversaciones anteriores, haciendo que las interacciones se sientan más naturales y contextualmente conscientes.
  • Profundidad: La capacidad de construir sobre conversaciones previas permite interacciones más sofisticadas, posibilitando la resolución de problemas complejos y el soporte de proyectos a largo plazo.

Este enfoque escala notablemente bien a través de diferentes escenarios de uso, desde usuarios individuales hasta aplicaciones a nivel empresarial. Ya sea que estés construyendo un asistente personal para un único usuario o un sistema que sirva a miles, el principio fundamental sigue siendo el mismo: estás creando una capa de memoria inteligente que se sitúa entre el usuario y la API. Este enfoque arquitectónico proporciona varias capacidades clave:

  • Crecer: Acumular continuamente nuevas interacciones y aprendizajes, construyendo un rico historial de interacciones y preferencias del usuario a lo largo del tiempo. Esta base de conocimiento creciente se vuelve cada vez más valiosa para personalizar respuestas.
  • Resumir: Condensar historiales de conversación extensos en contextos manejables, utilizando técnicas avanzadas como agrupamiento semántico y puntuación de importancia para mantener la información más relevante.
  • Adaptar: Ajustar sus estrategias de recuperación basándose en patrones de conversación, aprendiendo qué tipos de contexto histórico son más valiosos para diferentes tipos de interacciones.

Todo esto mientras se aprovecha la misma API subyacente de OpenAI para el procesamiento del lenguaje. Esta combinación de gestión estructurada de memoria y procesamiento potente del lenguaje crea un sistema que puede mantener el contexto y la personalidad a través de múltiples conversaciones mientras se mantiene dentro de las restricciones técnicas de la API.

7.3 Almacenamiento y Recuperación de Interacciones Pasadas

En el mundo real, las conversaciones humanas se construyen sobre la historia compartida e interacciones previas. Cuando hablamos con alguien que conocemos, naturalmente recurrimos a nuestras experiencias pasadas con ellos - sus preferencias, discusiones previas y el contexto que hemos construido juntos. Este sistema natural de memoria es lo que hace que nuestras conversaciones se sientan continuas y personalmente significativas.

Si bien los modelos de lenguaje de OpenAI no poseen inherentemente capacidades de memoria a largo plazo, los desarrolladores pueden crear sistemas sofisticados para replicar este proceso natural de memoria. Al implementar un sistema de almacenamiento y recuperación para interacciones pasadas, puedes crear un asistente de IA que parece "recordar" conversaciones previas. Esto implica registrar cuidadosamente las interacciones del usuario, almacenar contexto relevante y recuperar estratégicamente esta información cuando sea necesario.

Esta sección demuestra cómo construir un sistema de memoria ligero pero poderoso que mejora las capacidades de tu asistente de IA. Al mantener el historial de conversación y las preferencias del usuario a través de múltiples sesiones, puedes crear interacciones más significativas que se sienten menos como intercambios aislados y más como conversaciones continuas. Tu asistente podrá hacer referencia a discusiones pasadas, recordar preferencias del usuario y mantener conciencia del contexto - haciéndolo sentir más como interactuar con un colega conocedor que comenzar de nuevo con cada interacción.

7.3.1 ¿Por qué Almacenar las Interacciones?

El almacenamiento de interacciones pasadas desbloquea varias capacidades poderosas que mejoran la habilidad de la IA para proporcionar respuestas significativas y contextuales:

Respuestas Personalizadas

El sistema aprende y se adapta a usuarios individuales manteniendo un perfil detallado de sus interacciones y preferencias a lo largo del tiempo. Esta personalización ocurre en múltiples niveles:

  1. Estilo de Comunicación: El sistema rastrea cómo los usuarios se expresan analizando múltiples aspectos de sus patrones de comunicación:
    • Nivel de formalidad: Si utilizan lenguaje casual ("¡hola!") o un trato formal ("Estimado Señor/Señora")
    • Uso del humor: Su tendencia a usar bromas, emojis o lenguaje juguetón
    • Ritmo de conversación: Si prefieren intercambios rápidos o discusiones detalladas y extensas
    • Elecciones de vocabulario: Lenguaje técnico vs. simplificado
    • Referencias culturales: Profesionales, académicas o de cultura popular

Por ejemplo, si un usuario utiliza consistentemente lenguaje informal como "hola" y "¡gracias!" con emojis, el sistema se adapta respondiendo en un tono amistoso y casual. Por el contrario, cuando interactúa con usuarios empresariales que mantienen un lenguaje formal y términos profesionales, el sistema automáticamente se ajusta para usar la etiqueta empresarial apropiada y terminología estándar de la industria.

Esta comunicación adaptativa asegura interacciones más naturales y efectivas al coincidir con el estilo y preferencias de comunicación únicos de cada usuario.

  1. Competencia Técnica: Al analizar interacciones pasadas, el sistema evalúa los niveles de experiencia de los usuarios en diferentes dominios. Esto le permite ajustar automáticamente sus explicaciones basándose en el conocimiento demostrado.

Por ejemplo, al discutir programación, el sistema puede usar terminología avanzada como "polimorfismo" e "inyección de dependencias" con desarrolladores experimentados, mientras ofrece explicaciones más simples usando analogías del mundo real para principiantes. El sistema refina continuamente esta evaluación a través de interacciones continuas - si un usuario demuestra mayor comprensión con el tiempo, la profundidad técnica de las explicaciones se ajusta en consecuencia. Este enfoque adaptativo asegura que los expertos no se vean ralentizados por explicaciones básicas mientras que los principiantes no se vean abrumados por detalles técnicos complejos.

  1. Contexto Histórico: El sistema mantiene registros completos de discusiones previas, proyectos y decisiones, permitiéndole hacer referencia a conversaciones pasadas con precisión y relevancia. Este seguimiento histórico opera en múltiples niveles:
    • Seguimiento de Conversaciones: El sistema puede seguir la progresión de temas específicos a través de múltiples sesiones, entendiendo cómo las discusiones evolucionan y se construyen unas sobre otras.
    • Hitos del Proyecto: Las decisiones importantes, acuerdos y actualizaciones del proyecto se registran y pueden ser referenciados para mantener consistencia en discusiones futuras.
    • Evolución de Preferencias del Usuario: El sistema rastrea cómo las preferencias y requisitos del usuario cambian con el tiempo, adaptando sus respuestas en consecuencia.
    • Referencias Contextuales: Al abordar temas actuales, el sistema puede hacer referencia inteligentemente a discusiones pasadas relacionadas para proporcionar respuestas más informadas y matizadas.

Esta gestión sofisticada del contexto crea una experiencia conversacional fluida donde los usuarios se sienten comprendidos y valorados, ya que el sistema demuestra consciencia de su historial y necesidades continuas. Por ejemplo, si un usuario discutió previamente desafíos con un marco de programación específico, el sistema puede hacer referencia a esas conversaciones anteriores al proporcionar nuevas soluciones o actualizaciones.

  1. Preferencias de Personalización: El sistema mantiene y aplica preferencias detalladas del usuario a través de sesiones, incluyendo:
    • Idioma preferido y variaciones regionales
      • Selección de idioma (por ejemplo, inglés, español, mandarín)
      • Dialectos regionales y localizaciones
      • Unidades de moneda y medida
    • Preferencias de formato (viñetas vs. párrafos)
      • Preferencias de estructura de documento (jerárquico vs. plano)
      • Organización visual (listas, tablas o texto fluido)
      • Convenciones de formato de código cuando aplique
    • Nivel de detalle deseado en respuestas
      • Resúmenes breves vs. explicaciones exhaustivas
      • Profundidad técnica del contenido
      • Inclusión de ejemplos y analogías
    • Terminología específica o convenciones de nomenclatura
      • Vocabulario específico de la industria
      • Marcos técnicos o metodologías preferidas
      • Terminología específica de la empresa
    • Zonas horarias y horarios laborales
      • Preferencias de programación de reuniones
      • Preferencias de tiempo para notificaciones
      • Ventanas de disponibilidad para comunicación sincrónica

Este enfoque integral de personalización ayuda a crear una interacción más natural, eficiente y atractiva que se siente adaptada a las necesidades y preferencias individuales de cada usuario.

Ejemplo: Implementación de Respuestas Personalizadas

Aquí hay una implementación integral de un sistema de personalización que se adapta a los estilos de comunicación del usuario:

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

class UserProfile:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.communication_style = {
            "formality_level": 0.5,  # 0 = casual, 1 = formal
            "technical_level": 0.5,   # 0 = beginner, 1 = expert
            "verbosity": 0.5,         # 0 = concise, 1 = detailed
            "emoji_usage": False
        }
        self.preferences = {
            "language": "en",
            "timezone": "UTC",
            "topics_of_interest": []
        }
        self.interaction_history = []

class PersonalizedAIAssistant:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.profiles_dir = "user_profiles"
        os.makedirs(self.profiles_dir, exist_ok=True)
        self.users: Dict[str, UserProfile] = {}

    def _get_profile_path(self, user_id: str) -> str:
        return os.path.join(self.profiles_dir, f"{user_id}.json")

    def load_user_profile(self, user_id: str) -> UserProfile:
        if user_id in self.users:
            return self.users[user_id]

        profile_path = self._get_profile_path(user_id)
        if os.path.exists(profile_path):
            with open(profile_path, 'r') as f:
                data = json.load(f)
                profile = UserProfile(user_id)
                profile.communication_style = data.get('communication_style', profile.communication_style)
                profile.preferences = data.get('preferences', profile.preferences)
                profile.interaction_history = data.get('interaction_history', [])
        else:
            profile = UserProfile(user_id)

        self.users[user_id] = profile
        return profile

    def save_user_profile(self, profile: UserProfile):
        data = {
            'communication_style': profile.communication_style,
            'preferences': profile.preferences,
            'interaction_history': profile.interaction_history
        }
        with open(self._get_profile_path(profile.user_id), 'w') as f:
            json.dump(data, f, indent=2)

    def analyze_message(self, message: str) -> dict:
        """Analyze user message to update communication style metrics."""
        return {
            "formality_level": 0.8 if any(word in message.lower() for word in 
                ['please', 'thank you', 'sir', 'madam']) else 0.2,
            "technical_level": 0.8 if any(word in message.lower() for word in 
                ['api', 'function', 'implementation', 'code']) else 0.3,
            "emoji_usage": '😊' in message or '👍' in message
        }

    def generate_system_prompt(self, profile: UserProfile) -> str:
        """Create personalized system prompt based on user profile."""
        style = "formal" if profile.communication_style["formality_level"] > 0.5 else "casual"
        tech_level = "technical" if profile.communication_style["technical_level"] > 0.5 else "simple"
        
        return f"""You are a helpful assistant that communicates in a {style} style.
                  Use {tech_level} language and {'feel free to use emojis' 
                  if profile.communication_style['emoji_usage'] else 'avoid using emojis'}.
                  Communicate {'in detail' if profile.communication_style['verbosity'] > 0.5 
                  else 'concisely'}."""

    async def get_response(self, user_id: str, message: str) -> str:
        profile = self.load_user_profile(user_id)
        
        # Analyze and update user's communication style
        analysis = self.analyze_message(message)
        profile.communication_style.update(analysis)
        
        # Prepare conversation context
        messages = [
            {"role": "system", "content": self.generate_system_prompt(profile)},
            {"role": "user", "content": message}
        ]

        # Add relevant history if available
        if profile.interaction_history:
            recent_history = profile.interaction_history[-3:]  # Last 3 interactions
            messages[1:1] = recent_history

        # Get AI response
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            temperature=0.7,
            max_tokens=150
        )

        # Store interaction
        interaction = {
            "timestamp": datetime.utcnow().isoformat(),
            "user_message": message,
            "assistant_response": response.choices[0].message.content
        }
        profile.interaction_history.append(interaction)
        
        # Save updated profile
        self.save_user_profile(profile)
        
        return response.choices[0].message.content

# Usage example
if __name__ == "__main__":
    assistant = PersonalizedAIAssistant("your-api-key-here")
    
    # Example interactions
    responses = [
        assistant.get_response("user123", "Hey there! Can you help me with Python? 😊"),
        assistant.get_response("user123", "Could you explain the technical implementation of APIs?"),
        assistant.get_response("user123", "Dear Sir, I require assistance with programming.")
    ]

Desglose del Código:

  1. Estructura de Clases:
    • La clase UserProfile mantiene la información individual del usuario:
      • Métricas de estilo de comunicación (formalidad, nivel técnico, etc.)
      • Preferencias personales (idioma, zona horaria)
      • Historial de interacciones
    • La clase PersonalizedAIAssistant maneja la funcionalidad principal:
      • Gestión de perfiles (carga/guardado)
      • Análisis de mensajes
      • Generación de respuestas
  2. Características Principales:
    • Almacenamiento Persistente: Los perfiles se guardan como archivos JSON
    • Análisis de Estilo: Examina los mensajes para detectar patrones de comunicación
    • Generación Dinámica de Instrucciones: Genera indicaciones personalizadas del sistema
    • Gestión de Contexto: Mantiene el historial de conversaciones
  3. Aspectos de Personalización:
    • Estilo de Comunicación:
      • Detección del nivel de formalidad
      • Adaptación del lenguaje técnico
      • Seguimiento del uso de emojis
    • Adaptación de Respuestas:
      • Ajusta la verbosidad según las preferencias del usuario
      • Mantiene un estilo consistente en las interacciones
      • Incorpora el historial de conversaciones

Esta implementación demuestra cómo crear un asistente de IA que aprende y se adapta al estilo de comunicación de cada usuario mientras mantiene una memoria persistente de las interacciones. El sistema actualiza continuamente su comprensión de las preferencias del usuario y ajusta sus respuestas en consecuencia.

Reanudación de Sesiones

Los usuarios pueden retomar conversaciones después de pausas y hacer que la IA comprenda el contexto completo de las discusiones anteriores. Esta capacidad permite una continuidad fluida de la conversación, donde la IA mantiene la consciencia de interacciones previas, preferencias del usuario y contexto establecido. Por ejemplo, si un usuario discute un error de software el lunes y regresa el miércoles, la IA puede recordar los detalles específicos del error, las soluciones propuestas y cualquier intento de corrección sin requerir que el usuario repita la información.

Esta característica es particularmente valiosa para tareas complejas que abarcan múltiples sesiones, como la planificación de proyectos o la resolución de problemas técnicos. Durante la planificación de proyectos, la IA puede mantener registros de hitos previamente acordados, asignaciones de recursos y responsabilidades del equipo a través de múltiples sesiones de planificación. En escenarios de resolución de problemas técnicos, puede seguir la progresión de los intentos de depuración, recordar qué soluciones ya se probaron y construir sobre los pasos diagnósticos anteriores.

La IA puede hacer referencia a puntos específicos de conversaciones anteriores y mantener la continuidad durante días o incluso semanas. Esta consciencia del contexto a largo plazo permite que la IA haga sugerencias más informadas, evite discusiones redundantes y proporcione asistencia más personalizada basada en las interacciones históricas del usuario. Por ejemplo, si un usuario expresó previamente una preferencia por ciertos marcos de programación o metodologías, la IA puede incorporar estas preferencias en recomendaciones futuras sin requerir recordatorios explícitos.

Aquí hay una implementación práctica de la reanudación de sesiones:

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

class SessionManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.sessions: Dict[str, Dict] = {}
        
    def save_session(self, user_id: str, session_data: dict):
        """Save session data to persistent storage."""
        with open(f"sessions/{user_id}.json", "w") as f:
            json.dump(session_data, f)
            
    def load_session(self, user_id: str) -> Optional[dict]:
        """Load session data from storage."""
        try:
            with open(f"sessions/{user_id}.json", "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return None

class ConversationManager:
    def __init__(self, session_manager: SessionManager):
        self.session_manager = session_manager
        self.current_context: List[Dict] = []
        
    def prepare_context(self, user_id: str, new_message: str) -> List[Dict]:
        """Prepare conversation context including session history."""
        # Load previous session if exists
        session = self.session_manager.load_session(user_id)
        
        # Initialize context with system message
        context = [{
            "role": "system",
            "content": "You are a helpful assistant with memory of past conversations."
        }]
        
        # Add relevant history from previous session
        if session and 'history' in session:
            # Add last 5 messages from previous session for context
            context.extend(session['history'][-5:])
        
        # Add new message
        context.append({
            "role": "user",
            "content": new_message
        })
        
        return context

    async def process_message(self, user_id: str, message: str) -> str:
        """Process new message with session context."""
        context = self.prepare_context(user_id, message)
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=context,
                temperature=0.7,
                max_tokens=150
            )
            
            assistant_message = response.choices[0].message.content
            
            # Update session with new interaction
            session_data = {
                'last_interaction': datetime.now().isoformat(),
                'history': context + [{
                    "role": "assistant",
                    "content": assistant_message
                }]
            }
            self.session_manager.save_session(user_id, session_data)
            
            return assistant_message
            
        except Exception as e:
            print(f"Error processing message: {e}")
            return "I apologize, but I encountered an error processing your message."

# Example usage
async def main():
    session_manager = SessionManager("your-api-key-here")
    conversation_manager = ConversationManager(session_manager)
    
    # First interaction
    response1 = await conversation_manager.process_message(
        "user123",
        "What's the weather like today?"
    )
    print("Response 1:", response1)
    
    # Later interaction (session resumption)
    response2 = await conversation_manager.process_message(
        "user123",
        "What did we discuss earlier?"
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase SessionManager:
    • Maneja el almacenamiento persistente de datos de sesión
    • Proporciona métodos para guardar y cargar información de sesión
    • Mantiene archivos de sesión específicos para cada usuario
  2. Clase ConversationManager:
    • Gestiona el contexto e historial de conversaciones
    • Prepara el contexto combinando datos de sesiones previas con nuevos mensajes
    • Maneja la interacción con la API de OpenAI
  3. Características Principales:
    • Procesamiento Asíncrono: Utiliza async/await para llamadas eficientes a la API
    • Gestión de Contexto: Mantiene el historial relevante de conversaciones
    • Manejo de Errores: Incluye gestión robusta de errores
    • Persistencia de Sesión: Guarda conversaciones en disco para recuperación posterior
  4. Detalles de Implementación:
    • Utiliza JSON para almacenamiento de sesiones
    • Limita el contexto a los últimos 5 mensajes por eficiencia
    • Incluye seguimiento de marca temporal para gestión de sesiones
    • Mantiene roles de conversación (sistema, usuario, asistente)

Este ejemplo proporciona una base robusta para gestionar conversaciones multi-sesión mientras mantiene el contexto e historial del usuario. Es particularmente útil para aplicaciones que requieren memoria persistente de conversación a través de múltiples interacciones.

Conocimiento Persistente

El sistema mantiene un registro robusto y completo de toda la información significativa intercambiada durante las conversaciones. Esta arquitectura de conocimiento persistente opera en múltiples niveles:

  1. Gestión de Información Básica: El sistema captura y almacena datos operativos esenciales de manera estructurada. Esto incluye el seguimiento integral de entradas del calendario como reuniones y citas, con metadatos como asistentes y agendas. Los cronogramas de proyectos se mantienen con un seguimiento detallado de hitos, dependencias y transiciones de fase.

El sistema registra todos los plazos sistemáticamente, desde fechas límite a nivel de tarea hasta entregables principales del proyecto. Las actualizaciones regulares se almacenan cronológicamente, incluyendo informes diarios, cambios de estado y modificaciones del proyecto. Esta robusta arquitectura de información garantiza que todos los datos relacionados con la programación y los proyectos permanezcan fácilmente recuperables, respaldando una gestión eficiente de proyectos y la coordinación del equipo.

  1. Datos Específicos del Usuario: El sistema mantiene perfiles detallados de usuarios individuales que abarcan múltiples aspectos de sus interacciones:
    • Preferencias Personales: Incluyendo canales de comunicación preferidos, formatos de respuesta y áreas específicas de interés
    • Estilos de Comunicación: Seguimiento de si los usuarios prefieren lenguaje formal o casual, explicaciones técnicas o simplificadas, y sus preferencias típicas en la extensión de respuestas
    • Experiencia Técnica: Monitoreo y adaptación a los niveles demostrados de conocimiento de los usuarios en diferentes temas y ajuste de explicaciones en consecuencia
    • Patrones Históricos: Registro de tiempos de interacción, temas frecuentemente discutidos y preguntas o preocupaciones comunes
    • Patrones de Lenguaje: Anotación del uso de vocabulario, familiaridad con terminología técnica y ejemplos o analogías preferidas
    • Progreso de Aprendizaje: Seguimiento de cómo evoluciona la comprensión de los usuarios sobre varios temas a lo largo del tiempo

Este perfil integral del usuario permite que el sistema entregue respuestas cada vez más personalizadas que coincidan con las necesidades y preferencias únicas de cada usuario, creando una experiencia de interacción más efectiva y atractiva con el tiempo.

  1. Registro de Decisiones: Las decisiones críticas se documentan sistemáticamente de manera integral que incluye múltiples componentes clave:
    • Contexto: La situación completa de fondo, entorno empresarial y restricciones que enmarcaron la decisión
    • Fundamento: Razonamiento detallado detrás de la elección, incluyendo:
      • Análisis de alternativas consideradas
      • Evaluación y estrategias de mitigación de riesgos
      • Resultados esperados y métricas de éxito
    • Partes Interesadas: Documentación completa de:
      • Tomadores de decisiones y sus roles
      • Equipos y departamentos afectados
      • Partes externas involucradas
    • Plan de Implementación:
      • Estrategia de ejecución paso a paso
      • Detalles de asignación de recursos
      • Cronograma e hitos

Este proceso sistemático de documentación crea un rastro detallado y auditable que permite a los equipos:

  • Seguir la evolución de decisiones importantes
  • Comprender el contexto completo de elecciones pasadas
  • Aprender de experiencias previas
  • Tomar decisiones más informadas en el futuro
  • Mantener la responsabilidad y transparencia
  1. Gestión de Tareas: El sistema implementa un sistema integral de seguimiento de tareas que monitorea varios aspectos de la ejecución del proyecto:
    • Seguimiento de Asignaciones: Cada tarea está vinculada a miembros específicos del equipo o departamentos responsables de su finalización, asegurando una clara propiedad y responsabilidad
    • Gestión de Cronogramas: Se mantienen fechas límite detalladas, incluyendo tanto plazos finales como hitos intermedios, permitiendo una mejor gestión del tiempo
    • Monitoreo de Progreso: Se registran actualizaciones regulares de estado para seguir la progresión de tareas, incluyendo trabajo completado, obstáculos actuales y pasos restantes
    • Mapeo de Dependencias: El sistema mantiene un mapa claro de dependencias entre tareas, ayudando a los equipos a entender cómo los retrasos o cambios en una tarea podrían impactar a otras
    • Asignación de Recursos: Rastrea la distribución de trabajo y recursos entre los miembros del equipo para prevenir la sobrecarga y asegurar una ejecución eficiente del proyecto
  2. Detalles del Proyecto: El sistema mantiene documentación integral de aspectos técnicos incluyendo:
    • Especificaciones Técnicas:
      • Planos detallados de arquitectura del sistema
      • Documentación completa de API y puntos finales
      • Esquemas de base de datos y modelos de datos
      • Especificaciones de integración con terceros
    • Requisitos del Proyecto:
      • Requisitos y objetivos de negocio
      • Requisitos técnicos y restricciones
      • Historias de usuario y criterios de aceptación
      • Definiciones y límites de alcance
    • Desafíos y Soluciones:
      • Obstáculos técnicos identificados
      • Soluciones alternativas implementadas
      • Esfuerzos de optimización de rendimiento
      • Medidas y actualizaciones de seguridad
    • Registros de Implementación:
      • Documentación y ejemplos de código
      • Registros de decisiones de arquitectura
      • Estrategias y resultados de pruebas
      • Procedimientos de implementación

Esta base de conocimiento persistente integral sirve múltiples propósitos: previene la pérdida de información, permite referencias históricas precisas, apoya la toma de decisiones informada y permite la continuación fluida de discusiones complejas a través de múltiples sesiones. El sistema puede fácilmente recordar y contextualizar información de interacciones pasadas, haciendo cada conversación más eficiente y productiva.

Aquí hay una implementación integral del Conocimiento Persistente usando la API de OpenAI:

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

class PersistentKnowledge:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.encoding = tiktoken.encoding_for_model("gpt-4o")
        
    def count_tokens(self, text: str) -> int:
        """Count tokens in text using tiktoken"""
        return len(self.encoding.encode(text))
        
    def save_knowledge(self, user_id: str, category: str, data: Dict):
        """Save knowledge to persistent storage with categories"""
        filename = f"knowledge_{user_id}_{category}.json"
        timestamp = datetime.now().isoformat()
        
        data_with_metadata = {
            "timestamp": timestamp,
            "category": category,
            "content": data
        }
        
        try:
            with open(filename, "r") as f:
                existing_data = json.load(f)
        except FileNotFoundError:
            existing_data = []
            
        existing_data.append(data_with_metadata)
        
        with open(filename, "w") as f:
            json.dump(existing_data, f, indent=2)
            
    def retrieve_knowledge(self, user_id: str, category: str, 
                         max_tokens: int = 2000) -> List[Dict]:
        """Retrieve knowledge with token limit"""
        filename = f"knowledge_{user_id}_{category}.json"
        try:
            with open(filename, "r") as f:
                all_data = json.load(f)
        except FileNotFoundError:
            return []
            
        # Retrieve most recent entries within token limit
        retrieved_data = []
        current_tokens = 0
        
        for entry in reversed(all_data):
            content_str = json.dumps(entry["content"])
            tokens = self.count_tokens(content_str)
            
            if current_tokens + tokens <= max_tokens:
                retrieved_data.append(entry)
                current_tokens += tokens
            else:
                break
                
        return list(reversed(retrieved_data))
        
    async def get_ai_response(self, 
                            user_id: str,
                            current_input: str,
                            categories: List[str] = None) -> str:
        """Generate AI response with context from persistent knowledge"""
        
        # Build context from stored knowledge
        context = []
        if categories:
            for category in categories:
                knowledge = self.retrieve_knowledge(user_id, category)
                if knowledge:
                    context.append(f"\nRelevant {category} knowledge:")
                    for entry in knowledge:
                        context.append(json.dumps(entry["content"]))
                        
        # Prepare messages for API
        messages = [
            {
                "role": "system",
                "content": "You are an assistant with access to persistent knowledge. "
                          "Use this context to provide informed responses."
            },
            {
                "role": "user",
                "content": f"Context:\n{''.join(context)}\n\nCurrent query: {current_input}"
            }
        ]
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4",
                messages=messages,
                temperature=0.7,
                max_tokens=500
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"
            
class KnowledgeManager:
    def __init__(self, api_key: str):
        self.knowledge = PersistentKnowledge(api_key)
        
    async def process_interaction(self, 
                                user_id: str,
                                message: str,
                                categories: List[str] = None) -> str:
        """Process user interaction and maintain knowledge"""
        
        # Save user input
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "user", "message": message}
        )
        
        # Get AI response with context
        response = await self.knowledge.get_ai_response(
            user_id,
            message,
            categories
        )
        
        # Save AI response
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "assistant", "message": response}
        )
        
        return response

# Example usage
async def main():
    manager = KnowledgeManager("your-api-key")
    
    # First interaction
    response1 = await manager.process_interaction(
        "user123",
        "What's the best way to learn Python?",
        ["conversations", "preferences"]
    )
    print("Response 1:", response1)
    
    # Save user preference
    manager.knowledge.save_knowledge(
        "user123",
        "preferences",
        {"learning_style": "hands-on", "preferred_language": "Python"}
    )
    
    # Later interaction using stored knowledge
    response2 = await manager.process_interaction(
        "user123",
        "Can you suggest some projects based on my learning style?",
        ["conversations", "preferences"]
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase PersistentKnowledge:
    • Maneja el conteo de tokens usando tiktoken para la gestión del contexto
    • Implementa save_knowledge() para almacenar información categorizada
    • Proporciona retrieve_knowledge() con límites de tokens para la recuperación de contexto
    • Gestiona las interacciones de IA a través de get_ai_response()
  2. Clase KnowledgeManager:
    • Proporciona una interfaz de alto nivel para la gestión del conocimiento
    • Procesa las interacciones del usuario y mantiene el historial de conversaciones
    • Maneja el guardado tanto de las entradas del usuario como las respuestas de la IA
  3. Características Principales:
    • Almacenamiento Categorizado de Conocimiento: Organiza la información por usuario y categoría
    • Gestión de Tokens: Asegura que el contexto se mantenga dentro de los límites del modelo
    • Seguimiento de Metadatos: Incluye marcas de tiempo y categorías para todos los datos almacenados
    • Manejo de Errores: Gestión robusta de errores para operaciones de archivo y llamadas a la API
  4. Beneficios de la Implementación:
    • Escalable: Maneja múltiples usuarios y categorías de conocimiento
    • Eficiente: Utiliza conteo de tokens para optimizar el uso del contexto
    • Flexible: Admite varios tipos y categorías de conocimiento
    • Mantenible: Código bien estructurado con clara separación de responsabilidades

Esta implementación proporciona una base sólida para aplicaciones de IA que requieren conocimiento persistente a través de conversaciones. Sobresale en mantener las preferencias del usuario, historiales de conversación y otros datos continuos mientras gestiona eficientemente los límites de tokens.

Resumen de Conversaciones

Al mantener historiales detallados de conversaciones, el sistema puede generar resúmenes completos que capturan puntos clave, decisiones y elementos de acción. Estos resúmenes cumplen múltiples funciones críticas:

  1. Actualización de Contexto: Cuando los participantes comienzan nuevas sesiones de conversación, el sistema proporciona resúmenes concisos pero completos de discusiones previas. Estos resúmenes sirven como informes eficientes que:
    • Orientan rápidamente a los participantes sobre puntos clave de discusión
    • Destacan decisiones y resultados importantes
    • Identifican elementos de acción en curso
    • Refrescan la memoria sobre el contexto crítico
      Esto elimina el proceso que consume tiempo de revisar registros extensos de conversación y asegura que todos los participantes puedan involucrarse inmediatamente de manera productiva en la discusión actual con plena conciencia del contexto.
  2. Seguimiento del Progreso: Los resúmenes regulares sirven como un mecanismo integral de seguimiento para discusiones y proyectos en curso. Al mantener registros detallados de la evolución del proyecto, los equipos pueden:
    • Monitorear Fases de Desarrollo
      • Seguir la progresión desde conceptos iniciales hasta implementación
      • Documentar mejoras y refinamientos iterativos
      • Registrar puntos de inflexión clave en la dirección del proyecto
    • Analizar Historial de Decisiones
      • Capturar el contexto detrás de elecciones importantes
      • Documentar opciones alternativas consideradas
      • Seguir resultados de decisiones implementadas
    • Identificar Tendencias del Proyecto
      • Detectar desafíos o cuellos de botella recurrentes
      • Reconocer patrones exitosos para replicar
      • Monitorear velocidad y momentum
    • Facilitar Alineación del Equipo
      • Mantener entendimiento compartido del progreso
      • Permitir correcciones basadas en datos
      • Apoyar la asignación informada de recursos
  3. Extracción de Conocimiento: El sistema emplea técnicas avanzadas de análisis para identificar y extraer información crítica de las conversaciones, incluyendo:
    • Decisiones clave y su fundamento
      • Elecciones estratégicas realizadas durante las discusiones
      • Evidencia de respaldo y justificación
      • Opciones alternativas consideradas
    • Elementos de acción y sus responsables
      • Tareas específicas asignadas a miembros del equipo
      • Asignaciones claras de responsabilidad
      • Requisitos de seguimiento
    • Fechas límite y hitos importantes
      • Marcadores de línea temporal del proyecto
      • Fechas críticas de entrega
      • Programas de revisión y puntos de control
    • Preguntas o preocupaciones sin resolver
      • Problemas técnicos abiertos
      • Decisiones pendientes
      • Áreas que necesitan clarificación
    • Acuerdos y compromisos establecidos
      • Decisiones formales alcanzadas
      • Acuerdos de asignación de recursos
      • Compromisos de cronograma
  4. Generación de Informes: Los resúmenes pueden compilarse automáticamente en varios tipos de informes:
    • Informes ejecutivos
      • Visiones generales de alto nivel para interesados
      • Decisiones clave e implicaciones estratégicas
      • Resúmenes de asignación de recursos
    • Actas de reunión
      • Puntos detallados de discusión y resultados
      • Elementos de acción y asignados
      • Compromisos de cronograma establecidos
    • Actualizaciones de progreso
      • Logros de hitos y retrasos
      • Bloqueadores y desafíos actuales
      • Próximos pasos y prioridades
    • Informes de estado del proyecto
      • Indicadores generales de salud del proyecto
      • Métricas de utilización de recursos
      • Evaluaciones de riesgo y estrategias de mitigación

La capacidad de condensar y recordar información relevante no solo hace las conversaciones más eficientes y enfocadas, sino que también asegura que la información crítica nunca se pierda y pueda ser fácilmente accedida cuando sea necesario. Este enfoque sistemático para el resumen de conversaciones ayuda a mantener la claridad y continuidad a través de interacciones a largo plazo, especialmente en proyectos complejos o discusiones continuas que involucran múltiples participantes.

Ejemplo: Implementación de Resumen de Conversaciones

Aquí hay una implementación práctica de un resumidor de conversaciones usando la API de OpenAI:

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

class ConversationSummarizer:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        
    def create_summary_prompt(self, messages: List[Dict]) -> str:
        """Create a prompt for summarization from messages"""
        conversation = "\n".join([
            f"{msg['role'].title()}: {msg['content']}" 
            for msg in messages
        ])
        
        return f"""Please provide a concise summary of the following conversation, 
        highlighting key points, decisions, and action items:

        {conversation}
        
        Summary should include:
        1. Main topics discussed
        2. Key decisions made
        3. Action items and owners
        4. Unresolved questions
        """

    async def generate_summary(self, messages: List[Dict]) -> Dict:
        """Generate a structured summary of the conversation"""
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=[{
                    "role": "user",
                    "content": self.create_summary_prompt(messages)
                }],
                temperature=0.7,
                max_tokens=500
            )
            
            summary = response.choices[0].message.content
            
            return {
                "timestamp": datetime.now().isoformat(),
                "message_count": len(messages),
                "summary": summary
            }
            
        except Exception as e:
            return {
                "error": f"Failed to generate summary: {str(e)}",
                "timestamp": datetime.now().isoformat()
            }

    def save_summary(self, summary: Dict, filename: str = "summaries.json"):
        """Save summary to JSON file"""
        try:
            with open(filename, "r") as f:
                summaries = json.load(f)
        except FileNotFoundError:
            summaries = []
            
        summaries.append(summary)
        
        with open(filename, "w") as f:
            json.dump(summaries, f, indent=2)

# Example usage
async def main():
    summarizer = ConversationSummarizer("your-api-key")
    
    # Sample conversation
    messages = [
        {"role": "user", "content": "Let's discuss the new feature implementation."},
        {"role": "assistant", "content": "Sure! What specific aspects would you like to focus on?"},
        {"role": "user", "content": "We need to implement user authentication by next week."},
        {"role": "assistant", "content": "I understand. Let's break down the requirements and timeline."}
    ]
    
    # Generate and save summary
    summary = await summarizer.generate_summary(messages)
    summarizer.save_summary(summary)
    print("Summary:", summary["summary"])

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

Desglose del Código:

  1. Estructura de Clase:
    • La clase ConversationSummarizer maneja todas las operaciones de resumen
    • Inicialización con configuración de clave API
    • Métodos para creación de prompts, generación de resúmenes y almacenamiento
  2. Características Principales:
    • Generación estructurada de prompts para resúmenes consistentes
    • Llamadas API asíncronas para mejor rendimiento
    • Manejo y registro de errores
    • Almacenamiento persistente de resúmenes
  3. Beneficios de Implementación:
    • Escalable: Maneja conversaciones de diferentes longitudes
    • Salida Estructurada: Resúmenes organizados con información clave
    • Seguimiento Histórico: Mantiene historial de resúmenes
    • Resistente a Errores: Manejo y registro de errores robusto

Este ejemplo proporciona una forma confiable de generar y mantener resúmenes de conversaciones, facilitando el seguimiento del progreso de las discusiones y decisiones clave a lo largo del tiempo.

7.3.2 Arquitectura Central

Para crear un sistema de memoria efectivo para interacciones de IA, tres componentes esenciales trabajan juntos de manera coordinada para mantener el contexto y asegurar la continuidad conversacional. Estos componentes forman una arquitectura sofisticada que permite a los sistemas de IA acceder, procesar y utilizar información histórica de manera efectiva durante las conversaciones en curso.

El componente de almacenamiento preserva el historial de conversación, el mecanismo de recuperación obtiene de manera inteligente las interacciones pasadas relevantes, y el sistema de inyección incorpora perfectamente este contexto histórico en las conversaciones actuales.

Juntos, estos tres pilares crean una base robusta que permite a los sistemas de IA mantener diálogos significativos y conscientes del contexto a través de múltiples interacciones:

Almacenamiento

La base de la gestión de memoria donde todas las interacciones se guardan y preservan sistemáticamente para uso futuro. Este componente crítico sirve como columna vertebral de cualquier sistema de conversación de IA:

  • Puede utilizar varias soluciones de almacenamiento como archivos JSON, bases de datos SQL o almacenamiento en la nube
    • Los archivos JSON ofrecen simplicidad y portabilidad para aplicaciones más pequeñas
    • Las bases de datos SQL proporcionan consultas robustas e indexación para conjuntos de datos más grandes
    • El almacenamiento en la nube permite acceso escalable y distribuido a través de múltiples servicios
  • Debe incluir metadatos como marcas de tiempo e identificadores de usuario
    • Las marcas de tiempo permiten seguimiento cronológico y filtrado basado en tiempo
    • Los IDs de usuario mantienen hilos de conversación y personalización
    • Metadatos adicionales pueden rastrear temas y contextos de conversación
  • Debe estar organizado para recuperación y escalado eficientes
    • Implementar indexación adecuada para acceso rápido a datos relevantes
    • Usar particionamiento de datos para mejor rendimiento
    • Considerar estrategias de compresión para almacenamiento a largo plazo

Recuperación

El sistema inteligente para acceder y filtrar conversaciones pasadas relevantes sirve como un componente crucial en la gestión del historial de conversaciones:

  • Implementa algoritmos de búsqueda para encontrar datos históricos apropiados al contexto
    • Utiliza búsqueda semántica para coincidir temas y temáticas similares
    • Emplea coincidencia difusa para comparación flexible de texto
    • Indexa conversaciones para recuperación rápida
  • Utiliza parámetros como recencia, relevancia e hilo de conversación
    • Prioriza interacciones recientes para contexto inmediato
    • Pondera relevancia basada en puntajes de similitud de temas
    • Mantiene continuidad de hilos rastreando flujos de conversación
  • Gestiona límites de tokens seleccionando el contexto más importante
    • Implementa estrategias inteligentes de truncamiento
    • Prioriza información clave mientras elimina contenido redundante
    • Ajusta dinámicamente ventana de contexto según limitaciones del modelo

Inyección

El proceso de incorporar perfectamente el contexto histórico requiere un manejo cuidadoso para mantener la coherencia de la conversación:

  • Coloca estratégicamente mensajes recuperados en el flujo actual de conversación
    • Determina puntos óptimos de inserción para contexto histórico
    • Filtra y prioriza información histórica relevante
    • Equilibra contenido nuevo e histórico para un flujo natural
  • Mantiene orden apropiado de mensajes y relaciones
    • Preserva secuencia cronológica de interacciones
    • Respeta hilos de conversación y cadenas de respuestas
    • Enlaza temas y discusiones relacionadas apropiadamente
  • Asegura integración fluida del contexto sin interrumpir la conversación
    • Evita cambios abruptos de contexto o sobrecarga de información
    • Utiliza frases de transición y referencias naturales
    • Mantiene tono y estilo de conversación consistentes

7.3.3 Cómo Almacenar y Recuperar Historiales de Mensajes Basados en JSON en Python

En esta sección, exploraremos una implementación práctica que demuestra cómo crear un sistema de memoria persistente usando archivos JSON. Este enfoque ofrece una manera directa de mantener el contexto de conversación a través de múltiples sesiones mientras se mantiene escalable y fácil de mantener.

Nuestra implementación se centrará en tres aspectos clave: almacenar eficientemente historiales de mensajes en formato JSON, recuperar contexto de conversación relevante cuando sea necesario, y gestionar la estructura de datos para asegurar un rendimiento óptimo. Esta solución es particularmente útil para desarrolladores que construyen chatbots, asistentes virtuales o cualquier aplicación que requiera historial de conversación persistente.

Paso 1: Construir el Gestor de Memoria

Este módulo maneja el almacenamiento de interacciones de usuario en formato JSON y recupera solo las relevantes.

import os
import json
from typing import List, Dict

MEMORY_DIR = "user_memory"
os.makedirs(MEMORY_DIR, exist_ok=True)

# Constants
MAX_HISTORY_MESSAGES = 5  # Truncate history to last 5 messages to manage tokens

def get_memory_path(user_id: str) -> str:
    return os.path.join(MEMORY_DIR, f"{user_id}.json")

def load_history(user_id: str) -> List[Dict[str, str]]:
    path = get_memory_path(user_id)
    if not os.path.exists(path):
        return []
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        return []

def store_interaction(user_id: str, role: str, content: str) -> None:
    message = {"role": role, "content": content}
    path = get_memory_path(user_id)

    history = load_history(user_id)
    history.append(message)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=2)

def get_recent_history(user_id: str, limit: int = MAX_HISTORY_MESSAGES) -> List[Dict[str, str]]:
    history = load_history(user_id)
    return history[-limit:]

Analicemos este código:

  1. Configuración Inicial
  • Crea un directorio "user_memory" para almacenar los historiales de conversación
  • Establece un límite máximo de 5 mensajes para la gestión del historial
  1. Funciones Principales
  • get_memory_path(user_id): Crea una ruta de archivo JSON única para cada usuario
  • load_history(user_id):
    • Intenta leer el historial de conversación del usuario
    • Devuelve una lista vacía si el archivo no existe o está corrupto
  • store_interaction(user_id, role, content):
    • Guarda nuevos mensajes en el archivo de historial del usuario
    • Añade el mensaje al historial existente
    • Almacena en formato JSON con sangría apropiada
  • get_recent_history(user_id, limit):
    • Recupera los mensajes más recientes
    • Respeta el límite MAX_HISTORY_MESSAGES (5 mensajes)
  1. Características Principales
  • Almacenamiento persistente: Las conversaciones de cada usuario se guardan en archivos JSON separados
  • Escalabilidad: El sistema puede manejar múltiples usuarios con archivos individuales
  • Contexto controlado: Permite control específico sobre cuánto historial mantener
  • Fácil de depurar: El formato JSON facilita la inspección de conversaciones almacenadas

Paso 2: Crear el Motor de Chat Usando la API de OpenAI

Ahora integremos este sistema de memoria con la API de OpenAI. Cargaremos los mensajes anteriores, añadiremos el nuevo prompt, consultaremos el modelo y guardaremos la respuesta.

import openai
from dotenv import load_dotenv

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

SYSTEM_PROMPT = {
    "role": "system",
    "content": "You are a helpful assistant that remembers the user's previous messages."
}

def continue_conversation(user_id: str, user_input: str) -> str:
    # Validate input
    if not user_input.strip():
        return "Input cannot be empty."

    # Load memory and prepare messages
    recent_history = get_recent_history(user_id)
    messages = [SYSTEM_PROMPT] + recent_history + [{"role": "user", "content": user_input}]

    # Call OpenAI API
    try:
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=300,
            temperature=0.7
        )
        assistant_reply = response["choices"][0]["message"]["content"]

        # Store both messages
        store_interaction(user_id, "user", user_input)
        store_interaction(user_id, "assistant", assistant_reply)

        return assistant_reply

    except Exception as e:
        return f"Something went wrong: {e}"

Analicemos este código:

1. Configuración Inicial

  • Importa las bibliotecas necesarias (openai y dotenv)
  • Carga las variables de entorno y configura la clave API de OpenAI
  • Define un prompt de sistema que establece el rol del asistente

2. Función Principal: continue_conversation

  • Recibe user_id y user_input como parámetros
  • Validación de entrada para verificar mensajes vacíos
  • Carga el historial de conversación usando get_recent_history (definido en la sección anterior)
  • Construye el array de mensajes combinando: 
    • Prompt del sistema
    • Historial reciente de conversación
    • Entrada actual del usuario

3. Interacción con la API

  • Realiza la llamada a la API de OpenAI con parámetros: 
    • Utiliza el modelo "gpt-4o"
    • Establece max_tokens en 300
    • Usa una temperatura de 0.7 para una creatividad equilibrada
  • Extrae la respuesta del asistente de la respuesta

4. Gestión de Memoria

  • Almacena tanto la entrada del usuario como la respuesta del asistente usando store_interaction
  • Maneja los errores adecuadamente con un bloque try-except

Esta parte crea un sistema de conversación con estado que mantiene el contexto a través de múltiples interacciones mientras gestiona el flujo de conversación de manera eficiente.

Paso 3: Probar la Memoria de Conversación

if __name__ == "__main__":
    user_id = "user_456"

    print("User: What are the best Python libraries for data science?")
    reply1 = continue_conversation(user_id, "What are the best Python libraries for data science?")
    print("Assistant:", reply1)

    print("\nUser: Could you remind me which ones you mentioned?")
    reply2 = continue_conversation(user_id, "Could you remind me which ones you mentioned?")
    print("Assistant:", reply2)

Analicemos este ejemplo de código para probar la memoria de conversación:

1. Verificación del Punto de Entrada

  • El código utiliza el modismo estándar de Python if __name__ == "__main__": para asegurar que este código solo se ejecute cuando el archivo se ejecuta directamente

2. Configuración del Usuario

  • Crea un usuario de prueba con ID "user_456"

3. Flujo de Conversación de Prueba

  • Demuestra una conversación de dos turnos donde:
  • Primer turno: Pregunta sobre las bibliotecas de Python para ciencia de datos
  • Segundo turno: Pide un recordatorio de las bibliotecas mencionadas anteriormente, probando el sistema de memoria

4. Detalles de Implementación

  • Cada interacción utiliza la función continue_conversation() para:
  • Procesar la entrada del usuario
  • Generar y almacenar la respuesta
  • Imprimir tanto la entrada del usuario como la respuesta del asistente

Este código de prueba demuestra efectivamente cómo el sistema mantiene el contexto entre múltiples interacciones, permitiendo que el asistente haga referencia a respuestas anteriores al contestar preguntas de seguimiento.

Beneficios de Este Enfoque

  • Persistente: Todas las conversaciones se almacenan localmente por usuario, asegurando que no se pierda ningún historial de interacción. Esto significa que su aplicación puede mantener el contexto a través de múltiples sesiones, incluso si el servidor se reinicia o la aplicación se cierra.
  • Escalable (hasta cierto punto): Al almacenar el historial de conversación de cada usuario en su propio archivo JSON, el sistema puede manejar múltiples usuarios de manera eficiente. Este enfoque funciona bien para aplicaciones pequeñas y medianas, aunque para implementaciones muy grandes podría ser conveniente considerar una solución de base de datos.
  • Contexto controlable: El sistema le da control completo sobre cuánto historial de conversación incluir en cada interacción. Puede ajustar el tamaño de la ventana de memoria, filtrar por relevancia o implementar lógica personalizada para seleccionar qué mensajes anteriores incluir en el contexto.
  • Legible: El formato de archivo JSON facilita la inspección, depuración y modificación de las conversaciones almacenadas. Esto es invaluable durante el desarrollo y mantenimiento, ya que puede ver fácilmente el historial de conversación en cualquier editor de texto y validar la estructura de datos.

Mejoras Opcionales

  • Resumen: En lugar de almacenar cada mensaje textualmente, implementar resúmenes periódicos del historial de conversación. Esta técnica implica generar automáticamente resúmenes concisos de segmentos más largos de conversación, lo que ayuda a:
  • Reducir el uso de tokens en llamadas a la API
  • Mantener el contexto esencial mientras se eliminan detalles redundantes
  • Crear una estructura de memoria más eficiente

Por ejemplo, múltiples mensajes sobre un tema específico podrían condensarse en una única declaración resumida.

  • Búsqueda Vectorial (Avanzado): Transformar mensajes en vectores numéricos utilizando modelos de embedding, permitiendo una recuperación sofisticada basada en significado semántico. Este enfoque ofrece varias ventajas:
  • Descubrir mensajes históricos contextualmente relevantes incluso si utilizan palabras diferentes
  • Priorizar mensajes basados en su relevancia para la conversación actual
  • Permitir búsquedas rápidas de similitud a través de grandes historiales de conversación

Esto es particularmente útil para conversaciones de larga duración o cuando se necesita recordar contexto específico.

  • Gestión de Tokens: Implementar estrategias inteligentes de gestión de tokens para optimizar el uso de la ventana de contexto. Esto incluye:
  • Establecer límites dinámicos basados en la importancia de la conversación
  • Implementar poda inteligente de mensajes más antiguos y menos relevantes
  • Mantener un equilibrio entre el contexto reciente y la información histórica importante

Esto asegura que se mantenga dentro de los límites de tokens de la API mientras se preserva el contexto de conversación más valioso.

  • Mantener el prompt del sistema consistente a través de las interacciones
  • Mantener la redacción e instrucciones del prompt idénticas durante todo el ciclo de vida de la conversación
  • Usar control de versiones para rastrear cualquier cambio en el prompt del sistema a través de las implementaciones
  • Previene confusión y respuestas contradictorias manteniendo un contexto consistente
  • Asegura que la IA mantenga una personalidad y patrón de comportamiento confiable a través de las interacciones
  • No sobrecargue el contexto—almacene todo, pero recupere selectivamente
  • Implementar un sistema de almacenamiento integral que mantenga historiales completos de conversación en su base de datos
  • Desarrollar algoritmos de recuperación inteligentes que prioricen el contexto relevante para las llamadas a la API
  • Usar búsqueda semántica o similitud basada en embeddings para encontrar mensajes históricos pertinentes
  • Equilibrar el uso de tokens implementando estrategias inteligentes de poda para mensajes más antiguos
  • Etiquetar los mensajes almacenados claramente (rolecontenttimestamp) para filtrado o resumen futuro
  • Role: Identificar y etiquetar cuidadosamente las fuentes de los mensajes (sistema, usuario o asistente) para mantener un flujo de conversación claro y permitir el filtrado basado en roles
  • Content: Implementar estándares de formato consistentes para el contenido de los mensajes, incluyendo el manejo de caracteres especiales y manteniendo la integridad de los datos
  • Timestamp: Agregar metadatos temporales precisos para permitir operaciones sofisticadas basadas en tiempo como segmentación de conversación y puntuación de relevancia contextual

La memoria a largo plazo no es nativa de los modelos de chat de OpenAI (todavía), pero con una ingeniería cuidadosa, puede crear sistemas de memoria sofisticados. Esta limitación significa que por defecto, el modelo trata cada interacción como aislada, sin conocimiento de conversaciones anteriores. Sin embargo, los desarrolladores pueden implementar soluciones personalizadas para superar esta limitación.

Aquí hay una explicación detallada de cómo funciona: Mientras que el modelo en sí no mantiene memorias entre conversaciones, su aplicación actúa como un gestor de memoria. Almacena cada interacción en un formato estructurado, típicamente usando bases de datos o sistemas de archivos. Estos datos almacenados incluyen no solo el contenido de la conversación, sino también metadatos como marcas de tiempo, información del usuario y temas de conversación. Al gestionar cuidadosamente estas conversaciones almacenadas y recuperar selectivamente piezas relevantes, crea una ilusión de memoria continua - haciendo que la IA parezca "recordar" interacciones anteriores.

Este sistema de memoria transforma tu asistente de IA de varias formas poderosas:

  • Continuidad: El asistente puede hacer referencia a conversaciones pasadas y mantener el contexto durante períodos prolongados, creando interacciones fluidas que se construyen sobre discusiones previas. Por ejemplo, si un usuario menciona su preferencia por la programación en Python en una conversación, el sistema puede hacer referencia a esto en interacciones futuras.
  • Personalidad: Los patrones de respuesta consistentes y las preferencias recordadas crean una personalidad más distintiva. Esto incluye mantener un tono consistente, recordar las preferencias del usuario y adaptar los estilos de comunicación basados en interacciones anteriores.
  • Comprensión: Al acceder al contexto histórico, las respuestas se vuelven más informadas y personalizadas. El sistema puede recordar detalles específicos de conversaciones anteriores, haciendo que las interacciones se sientan más naturales y contextualmente conscientes.
  • Profundidad: La capacidad de construir sobre conversaciones previas permite interacciones más sofisticadas, posibilitando la resolución de problemas complejos y el soporte de proyectos a largo plazo.

Este enfoque escala notablemente bien a través de diferentes escenarios de uso, desde usuarios individuales hasta aplicaciones a nivel empresarial. Ya sea que estés construyendo un asistente personal para un único usuario o un sistema que sirva a miles, el principio fundamental sigue siendo el mismo: estás creando una capa de memoria inteligente que se sitúa entre el usuario y la API. Este enfoque arquitectónico proporciona varias capacidades clave:

  • Crecer: Acumular continuamente nuevas interacciones y aprendizajes, construyendo un rico historial de interacciones y preferencias del usuario a lo largo del tiempo. Esta base de conocimiento creciente se vuelve cada vez más valiosa para personalizar respuestas.
  • Resumir: Condensar historiales de conversación extensos en contextos manejables, utilizando técnicas avanzadas como agrupamiento semántico y puntuación de importancia para mantener la información más relevante.
  • Adaptar: Ajustar sus estrategias de recuperación basándose en patrones de conversación, aprendiendo qué tipos de contexto histórico son más valiosos para diferentes tipos de interacciones.

Todo esto mientras se aprovecha la misma API subyacente de OpenAI para el procesamiento del lenguaje. Esta combinación de gestión estructurada de memoria y procesamiento potente del lenguaje crea un sistema que puede mantener el contexto y la personalidad a través de múltiples conversaciones mientras se mantiene dentro de las restricciones técnicas de la API.

7.3 Almacenamiento y Recuperación de Interacciones Pasadas

En el mundo real, las conversaciones humanas se construyen sobre la historia compartida e interacciones previas. Cuando hablamos con alguien que conocemos, naturalmente recurrimos a nuestras experiencias pasadas con ellos - sus preferencias, discusiones previas y el contexto que hemos construido juntos. Este sistema natural de memoria es lo que hace que nuestras conversaciones se sientan continuas y personalmente significativas.

Si bien los modelos de lenguaje de OpenAI no poseen inherentemente capacidades de memoria a largo plazo, los desarrolladores pueden crear sistemas sofisticados para replicar este proceso natural de memoria. Al implementar un sistema de almacenamiento y recuperación para interacciones pasadas, puedes crear un asistente de IA que parece "recordar" conversaciones previas. Esto implica registrar cuidadosamente las interacciones del usuario, almacenar contexto relevante y recuperar estratégicamente esta información cuando sea necesario.

Esta sección demuestra cómo construir un sistema de memoria ligero pero poderoso que mejora las capacidades de tu asistente de IA. Al mantener el historial de conversación y las preferencias del usuario a través de múltiples sesiones, puedes crear interacciones más significativas que se sienten menos como intercambios aislados y más como conversaciones continuas. Tu asistente podrá hacer referencia a discusiones pasadas, recordar preferencias del usuario y mantener conciencia del contexto - haciéndolo sentir más como interactuar con un colega conocedor que comenzar de nuevo con cada interacción.

7.3.1 ¿Por qué Almacenar las Interacciones?

El almacenamiento de interacciones pasadas desbloquea varias capacidades poderosas que mejoran la habilidad de la IA para proporcionar respuestas significativas y contextuales:

Respuestas Personalizadas

El sistema aprende y se adapta a usuarios individuales manteniendo un perfil detallado de sus interacciones y preferencias a lo largo del tiempo. Esta personalización ocurre en múltiples niveles:

  1. Estilo de Comunicación: El sistema rastrea cómo los usuarios se expresan analizando múltiples aspectos de sus patrones de comunicación:
    • Nivel de formalidad: Si utilizan lenguaje casual ("¡hola!") o un trato formal ("Estimado Señor/Señora")
    • Uso del humor: Su tendencia a usar bromas, emojis o lenguaje juguetón
    • Ritmo de conversación: Si prefieren intercambios rápidos o discusiones detalladas y extensas
    • Elecciones de vocabulario: Lenguaje técnico vs. simplificado
    • Referencias culturales: Profesionales, académicas o de cultura popular

Por ejemplo, si un usuario utiliza consistentemente lenguaje informal como "hola" y "¡gracias!" con emojis, el sistema se adapta respondiendo en un tono amistoso y casual. Por el contrario, cuando interactúa con usuarios empresariales que mantienen un lenguaje formal y términos profesionales, el sistema automáticamente se ajusta para usar la etiqueta empresarial apropiada y terminología estándar de la industria.

Esta comunicación adaptativa asegura interacciones más naturales y efectivas al coincidir con el estilo y preferencias de comunicación únicos de cada usuario.

  1. Competencia Técnica: Al analizar interacciones pasadas, el sistema evalúa los niveles de experiencia de los usuarios en diferentes dominios. Esto le permite ajustar automáticamente sus explicaciones basándose en el conocimiento demostrado.

Por ejemplo, al discutir programación, el sistema puede usar terminología avanzada como "polimorfismo" e "inyección de dependencias" con desarrolladores experimentados, mientras ofrece explicaciones más simples usando analogías del mundo real para principiantes. El sistema refina continuamente esta evaluación a través de interacciones continuas - si un usuario demuestra mayor comprensión con el tiempo, la profundidad técnica de las explicaciones se ajusta en consecuencia. Este enfoque adaptativo asegura que los expertos no se vean ralentizados por explicaciones básicas mientras que los principiantes no se vean abrumados por detalles técnicos complejos.

  1. Contexto Histórico: El sistema mantiene registros completos de discusiones previas, proyectos y decisiones, permitiéndole hacer referencia a conversaciones pasadas con precisión y relevancia. Este seguimiento histórico opera en múltiples niveles:
    • Seguimiento de Conversaciones: El sistema puede seguir la progresión de temas específicos a través de múltiples sesiones, entendiendo cómo las discusiones evolucionan y se construyen unas sobre otras.
    • Hitos del Proyecto: Las decisiones importantes, acuerdos y actualizaciones del proyecto se registran y pueden ser referenciados para mantener consistencia en discusiones futuras.
    • Evolución de Preferencias del Usuario: El sistema rastrea cómo las preferencias y requisitos del usuario cambian con el tiempo, adaptando sus respuestas en consecuencia.
    • Referencias Contextuales: Al abordar temas actuales, el sistema puede hacer referencia inteligentemente a discusiones pasadas relacionadas para proporcionar respuestas más informadas y matizadas.

Esta gestión sofisticada del contexto crea una experiencia conversacional fluida donde los usuarios se sienten comprendidos y valorados, ya que el sistema demuestra consciencia de su historial y necesidades continuas. Por ejemplo, si un usuario discutió previamente desafíos con un marco de programación específico, el sistema puede hacer referencia a esas conversaciones anteriores al proporcionar nuevas soluciones o actualizaciones.

  1. Preferencias de Personalización: El sistema mantiene y aplica preferencias detalladas del usuario a través de sesiones, incluyendo:
    • Idioma preferido y variaciones regionales
      • Selección de idioma (por ejemplo, inglés, español, mandarín)
      • Dialectos regionales y localizaciones
      • Unidades de moneda y medida
    • Preferencias de formato (viñetas vs. párrafos)
      • Preferencias de estructura de documento (jerárquico vs. plano)
      • Organización visual (listas, tablas o texto fluido)
      • Convenciones de formato de código cuando aplique
    • Nivel de detalle deseado en respuestas
      • Resúmenes breves vs. explicaciones exhaustivas
      • Profundidad técnica del contenido
      • Inclusión de ejemplos y analogías
    • Terminología específica o convenciones de nomenclatura
      • Vocabulario específico de la industria
      • Marcos técnicos o metodologías preferidas
      • Terminología específica de la empresa
    • Zonas horarias y horarios laborales
      • Preferencias de programación de reuniones
      • Preferencias de tiempo para notificaciones
      • Ventanas de disponibilidad para comunicación sincrónica

Este enfoque integral de personalización ayuda a crear una interacción más natural, eficiente y atractiva que se siente adaptada a las necesidades y preferencias individuales de cada usuario.

Ejemplo: Implementación de Respuestas Personalizadas

Aquí hay una implementación integral de un sistema de personalización que se adapta a los estilos de comunicación del usuario:

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

class UserProfile:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.communication_style = {
            "formality_level": 0.5,  # 0 = casual, 1 = formal
            "technical_level": 0.5,   # 0 = beginner, 1 = expert
            "verbosity": 0.5,         # 0 = concise, 1 = detailed
            "emoji_usage": False
        }
        self.preferences = {
            "language": "en",
            "timezone": "UTC",
            "topics_of_interest": []
        }
        self.interaction_history = []

class PersonalizedAIAssistant:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.profiles_dir = "user_profiles"
        os.makedirs(self.profiles_dir, exist_ok=True)
        self.users: Dict[str, UserProfile] = {}

    def _get_profile_path(self, user_id: str) -> str:
        return os.path.join(self.profiles_dir, f"{user_id}.json")

    def load_user_profile(self, user_id: str) -> UserProfile:
        if user_id in self.users:
            return self.users[user_id]

        profile_path = self._get_profile_path(user_id)
        if os.path.exists(profile_path):
            with open(profile_path, 'r') as f:
                data = json.load(f)
                profile = UserProfile(user_id)
                profile.communication_style = data.get('communication_style', profile.communication_style)
                profile.preferences = data.get('preferences', profile.preferences)
                profile.interaction_history = data.get('interaction_history', [])
        else:
            profile = UserProfile(user_id)

        self.users[user_id] = profile
        return profile

    def save_user_profile(self, profile: UserProfile):
        data = {
            'communication_style': profile.communication_style,
            'preferences': profile.preferences,
            'interaction_history': profile.interaction_history
        }
        with open(self._get_profile_path(profile.user_id), 'w') as f:
            json.dump(data, f, indent=2)

    def analyze_message(self, message: str) -> dict:
        """Analyze user message to update communication style metrics."""
        return {
            "formality_level": 0.8 if any(word in message.lower() for word in 
                ['please', 'thank you', 'sir', 'madam']) else 0.2,
            "technical_level": 0.8 if any(word in message.lower() for word in 
                ['api', 'function', 'implementation', 'code']) else 0.3,
            "emoji_usage": '😊' in message or '👍' in message
        }

    def generate_system_prompt(self, profile: UserProfile) -> str:
        """Create personalized system prompt based on user profile."""
        style = "formal" if profile.communication_style["formality_level"] > 0.5 else "casual"
        tech_level = "technical" if profile.communication_style["technical_level"] > 0.5 else "simple"
        
        return f"""You are a helpful assistant that communicates in a {style} style.
                  Use {tech_level} language and {'feel free to use emojis' 
                  if profile.communication_style['emoji_usage'] else 'avoid using emojis'}.
                  Communicate {'in detail' if profile.communication_style['verbosity'] > 0.5 
                  else 'concisely'}."""

    async def get_response(self, user_id: str, message: str) -> str:
        profile = self.load_user_profile(user_id)
        
        # Analyze and update user's communication style
        analysis = self.analyze_message(message)
        profile.communication_style.update(analysis)
        
        # Prepare conversation context
        messages = [
            {"role": "system", "content": self.generate_system_prompt(profile)},
            {"role": "user", "content": message}
        ]

        # Add relevant history if available
        if profile.interaction_history:
            recent_history = profile.interaction_history[-3:]  # Last 3 interactions
            messages[1:1] = recent_history

        # Get AI response
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            temperature=0.7,
            max_tokens=150
        )

        # Store interaction
        interaction = {
            "timestamp": datetime.utcnow().isoformat(),
            "user_message": message,
            "assistant_response": response.choices[0].message.content
        }
        profile.interaction_history.append(interaction)
        
        # Save updated profile
        self.save_user_profile(profile)
        
        return response.choices[0].message.content

# Usage example
if __name__ == "__main__":
    assistant = PersonalizedAIAssistant("your-api-key-here")
    
    # Example interactions
    responses = [
        assistant.get_response("user123", "Hey there! Can you help me with Python? 😊"),
        assistant.get_response("user123", "Could you explain the technical implementation of APIs?"),
        assistant.get_response("user123", "Dear Sir, I require assistance with programming.")
    ]

Desglose del Código:

  1. Estructura de Clases:
    • La clase UserProfile mantiene la información individual del usuario:
      • Métricas de estilo de comunicación (formalidad, nivel técnico, etc.)
      • Preferencias personales (idioma, zona horaria)
      • Historial de interacciones
    • La clase PersonalizedAIAssistant maneja la funcionalidad principal:
      • Gestión de perfiles (carga/guardado)
      • Análisis de mensajes
      • Generación de respuestas
  2. Características Principales:
    • Almacenamiento Persistente: Los perfiles se guardan como archivos JSON
    • Análisis de Estilo: Examina los mensajes para detectar patrones de comunicación
    • Generación Dinámica de Instrucciones: Genera indicaciones personalizadas del sistema
    • Gestión de Contexto: Mantiene el historial de conversaciones
  3. Aspectos de Personalización:
    • Estilo de Comunicación:
      • Detección del nivel de formalidad
      • Adaptación del lenguaje técnico
      • Seguimiento del uso de emojis
    • Adaptación de Respuestas:
      • Ajusta la verbosidad según las preferencias del usuario
      • Mantiene un estilo consistente en las interacciones
      • Incorpora el historial de conversaciones

Esta implementación demuestra cómo crear un asistente de IA que aprende y se adapta al estilo de comunicación de cada usuario mientras mantiene una memoria persistente de las interacciones. El sistema actualiza continuamente su comprensión de las preferencias del usuario y ajusta sus respuestas en consecuencia.

Reanudación de Sesiones

Los usuarios pueden retomar conversaciones después de pausas y hacer que la IA comprenda el contexto completo de las discusiones anteriores. Esta capacidad permite una continuidad fluida de la conversación, donde la IA mantiene la consciencia de interacciones previas, preferencias del usuario y contexto establecido. Por ejemplo, si un usuario discute un error de software el lunes y regresa el miércoles, la IA puede recordar los detalles específicos del error, las soluciones propuestas y cualquier intento de corrección sin requerir que el usuario repita la información.

Esta característica es particularmente valiosa para tareas complejas que abarcan múltiples sesiones, como la planificación de proyectos o la resolución de problemas técnicos. Durante la planificación de proyectos, la IA puede mantener registros de hitos previamente acordados, asignaciones de recursos y responsabilidades del equipo a través de múltiples sesiones de planificación. En escenarios de resolución de problemas técnicos, puede seguir la progresión de los intentos de depuración, recordar qué soluciones ya se probaron y construir sobre los pasos diagnósticos anteriores.

La IA puede hacer referencia a puntos específicos de conversaciones anteriores y mantener la continuidad durante días o incluso semanas. Esta consciencia del contexto a largo plazo permite que la IA haga sugerencias más informadas, evite discusiones redundantes y proporcione asistencia más personalizada basada en las interacciones históricas del usuario. Por ejemplo, si un usuario expresó previamente una preferencia por ciertos marcos de programación o metodologías, la IA puede incorporar estas preferencias en recomendaciones futuras sin requerir recordatorios explícitos.

Aquí hay una implementación práctica de la reanudación de sesiones:

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

class SessionManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.sessions: Dict[str, Dict] = {}
        
    def save_session(self, user_id: str, session_data: dict):
        """Save session data to persistent storage."""
        with open(f"sessions/{user_id}.json", "w") as f:
            json.dump(session_data, f)
            
    def load_session(self, user_id: str) -> Optional[dict]:
        """Load session data from storage."""
        try:
            with open(f"sessions/{user_id}.json", "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return None

class ConversationManager:
    def __init__(self, session_manager: SessionManager):
        self.session_manager = session_manager
        self.current_context: List[Dict] = []
        
    def prepare_context(self, user_id: str, new_message: str) -> List[Dict]:
        """Prepare conversation context including session history."""
        # Load previous session if exists
        session = self.session_manager.load_session(user_id)
        
        # Initialize context with system message
        context = [{
            "role": "system",
            "content": "You are a helpful assistant with memory of past conversations."
        }]
        
        # Add relevant history from previous session
        if session and 'history' in session:
            # Add last 5 messages from previous session for context
            context.extend(session['history'][-5:])
        
        # Add new message
        context.append({
            "role": "user",
            "content": new_message
        })
        
        return context

    async def process_message(self, user_id: str, message: str) -> str:
        """Process new message with session context."""
        context = self.prepare_context(user_id, message)
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=context,
                temperature=0.7,
                max_tokens=150
            )
            
            assistant_message = response.choices[0].message.content
            
            # Update session with new interaction
            session_data = {
                'last_interaction': datetime.now().isoformat(),
                'history': context + [{
                    "role": "assistant",
                    "content": assistant_message
                }]
            }
            self.session_manager.save_session(user_id, session_data)
            
            return assistant_message
            
        except Exception as e:
            print(f"Error processing message: {e}")
            return "I apologize, but I encountered an error processing your message."

# Example usage
async def main():
    session_manager = SessionManager("your-api-key-here")
    conversation_manager = ConversationManager(session_manager)
    
    # First interaction
    response1 = await conversation_manager.process_message(
        "user123",
        "What's the weather like today?"
    )
    print("Response 1:", response1)
    
    # Later interaction (session resumption)
    response2 = await conversation_manager.process_message(
        "user123",
        "What did we discuss earlier?"
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase SessionManager:
    • Maneja el almacenamiento persistente de datos de sesión
    • Proporciona métodos para guardar y cargar información de sesión
    • Mantiene archivos de sesión específicos para cada usuario
  2. Clase ConversationManager:
    • Gestiona el contexto e historial de conversaciones
    • Prepara el contexto combinando datos de sesiones previas con nuevos mensajes
    • Maneja la interacción con la API de OpenAI
  3. Características Principales:
    • Procesamiento Asíncrono: Utiliza async/await para llamadas eficientes a la API
    • Gestión de Contexto: Mantiene el historial relevante de conversaciones
    • Manejo de Errores: Incluye gestión robusta de errores
    • Persistencia de Sesión: Guarda conversaciones en disco para recuperación posterior
  4. Detalles de Implementación:
    • Utiliza JSON para almacenamiento de sesiones
    • Limita el contexto a los últimos 5 mensajes por eficiencia
    • Incluye seguimiento de marca temporal para gestión de sesiones
    • Mantiene roles de conversación (sistema, usuario, asistente)

Este ejemplo proporciona una base robusta para gestionar conversaciones multi-sesión mientras mantiene el contexto e historial del usuario. Es particularmente útil para aplicaciones que requieren memoria persistente de conversación a través de múltiples interacciones.

Conocimiento Persistente

El sistema mantiene un registro robusto y completo de toda la información significativa intercambiada durante las conversaciones. Esta arquitectura de conocimiento persistente opera en múltiples niveles:

  1. Gestión de Información Básica: El sistema captura y almacena datos operativos esenciales de manera estructurada. Esto incluye el seguimiento integral de entradas del calendario como reuniones y citas, con metadatos como asistentes y agendas. Los cronogramas de proyectos se mantienen con un seguimiento detallado de hitos, dependencias y transiciones de fase.

El sistema registra todos los plazos sistemáticamente, desde fechas límite a nivel de tarea hasta entregables principales del proyecto. Las actualizaciones regulares se almacenan cronológicamente, incluyendo informes diarios, cambios de estado y modificaciones del proyecto. Esta robusta arquitectura de información garantiza que todos los datos relacionados con la programación y los proyectos permanezcan fácilmente recuperables, respaldando una gestión eficiente de proyectos y la coordinación del equipo.

  1. Datos Específicos del Usuario: El sistema mantiene perfiles detallados de usuarios individuales que abarcan múltiples aspectos de sus interacciones:
    • Preferencias Personales: Incluyendo canales de comunicación preferidos, formatos de respuesta y áreas específicas de interés
    • Estilos de Comunicación: Seguimiento de si los usuarios prefieren lenguaje formal o casual, explicaciones técnicas o simplificadas, y sus preferencias típicas en la extensión de respuestas
    • Experiencia Técnica: Monitoreo y adaptación a los niveles demostrados de conocimiento de los usuarios en diferentes temas y ajuste de explicaciones en consecuencia
    • Patrones Históricos: Registro de tiempos de interacción, temas frecuentemente discutidos y preguntas o preocupaciones comunes
    • Patrones de Lenguaje: Anotación del uso de vocabulario, familiaridad con terminología técnica y ejemplos o analogías preferidas
    • Progreso de Aprendizaje: Seguimiento de cómo evoluciona la comprensión de los usuarios sobre varios temas a lo largo del tiempo

Este perfil integral del usuario permite que el sistema entregue respuestas cada vez más personalizadas que coincidan con las necesidades y preferencias únicas de cada usuario, creando una experiencia de interacción más efectiva y atractiva con el tiempo.

  1. Registro de Decisiones: Las decisiones críticas se documentan sistemáticamente de manera integral que incluye múltiples componentes clave:
    • Contexto: La situación completa de fondo, entorno empresarial y restricciones que enmarcaron la decisión
    • Fundamento: Razonamiento detallado detrás de la elección, incluyendo:
      • Análisis de alternativas consideradas
      • Evaluación y estrategias de mitigación de riesgos
      • Resultados esperados y métricas de éxito
    • Partes Interesadas: Documentación completa de:
      • Tomadores de decisiones y sus roles
      • Equipos y departamentos afectados
      • Partes externas involucradas
    • Plan de Implementación:
      • Estrategia de ejecución paso a paso
      • Detalles de asignación de recursos
      • Cronograma e hitos

Este proceso sistemático de documentación crea un rastro detallado y auditable que permite a los equipos:

  • Seguir la evolución de decisiones importantes
  • Comprender el contexto completo de elecciones pasadas
  • Aprender de experiencias previas
  • Tomar decisiones más informadas en el futuro
  • Mantener la responsabilidad y transparencia
  1. Gestión de Tareas: El sistema implementa un sistema integral de seguimiento de tareas que monitorea varios aspectos de la ejecución del proyecto:
    • Seguimiento de Asignaciones: Cada tarea está vinculada a miembros específicos del equipo o departamentos responsables de su finalización, asegurando una clara propiedad y responsabilidad
    • Gestión de Cronogramas: Se mantienen fechas límite detalladas, incluyendo tanto plazos finales como hitos intermedios, permitiendo una mejor gestión del tiempo
    • Monitoreo de Progreso: Se registran actualizaciones regulares de estado para seguir la progresión de tareas, incluyendo trabajo completado, obstáculos actuales y pasos restantes
    • Mapeo de Dependencias: El sistema mantiene un mapa claro de dependencias entre tareas, ayudando a los equipos a entender cómo los retrasos o cambios en una tarea podrían impactar a otras
    • Asignación de Recursos: Rastrea la distribución de trabajo y recursos entre los miembros del equipo para prevenir la sobrecarga y asegurar una ejecución eficiente del proyecto
  2. Detalles del Proyecto: El sistema mantiene documentación integral de aspectos técnicos incluyendo:
    • Especificaciones Técnicas:
      • Planos detallados de arquitectura del sistema
      • Documentación completa de API y puntos finales
      • Esquemas de base de datos y modelos de datos
      • Especificaciones de integración con terceros
    • Requisitos del Proyecto:
      • Requisitos y objetivos de negocio
      • Requisitos técnicos y restricciones
      • Historias de usuario y criterios de aceptación
      • Definiciones y límites de alcance
    • Desafíos y Soluciones:
      • Obstáculos técnicos identificados
      • Soluciones alternativas implementadas
      • Esfuerzos de optimización de rendimiento
      • Medidas y actualizaciones de seguridad
    • Registros de Implementación:
      • Documentación y ejemplos de código
      • Registros de decisiones de arquitectura
      • Estrategias y resultados de pruebas
      • Procedimientos de implementación

Esta base de conocimiento persistente integral sirve múltiples propósitos: previene la pérdida de información, permite referencias históricas precisas, apoya la toma de decisiones informada y permite la continuación fluida de discusiones complejas a través de múltiples sesiones. El sistema puede fácilmente recordar y contextualizar información de interacciones pasadas, haciendo cada conversación más eficiente y productiva.

Aquí hay una implementación integral del Conocimiento Persistente usando la API de OpenAI:

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

class PersistentKnowledge:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.encoding = tiktoken.encoding_for_model("gpt-4o")
        
    def count_tokens(self, text: str) -> int:
        """Count tokens in text using tiktoken"""
        return len(self.encoding.encode(text))
        
    def save_knowledge(self, user_id: str, category: str, data: Dict):
        """Save knowledge to persistent storage with categories"""
        filename = f"knowledge_{user_id}_{category}.json"
        timestamp = datetime.now().isoformat()
        
        data_with_metadata = {
            "timestamp": timestamp,
            "category": category,
            "content": data
        }
        
        try:
            with open(filename, "r") as f:
                existing_data = json.load(f)
        except FileNotFoundError:
            existing_data = []
            
        existing_data.append(data_with_metadata)
        
        with open(filename, "w") as f:
            json.dump(existing_data, f, indent=2)
            
    def retrieve_knowledge(self, user_id: str, category: str, 
                         max_tokens: int = 2000) -> List[Dict]:
        """Retrieve knowledge with token limit"""
        filename = f"knowledge_{user_id}_{category}.json"
        try:
            with open(filename, "r") as f:
                all_data = json.load(f)
        except FileNotFoundError:
            return []
            
        # Retrieve most recent entries within token limit
        retrieved_data = []
        current_tokens = 0
        
        for entry in reversed(all_data):
            content_str = json.dumps(entry["content"])
            tokens = self.count_tokens(content_str)
            
            if current_tokens + tokens <= max_tokens:
                retrieved_data.append(entry)
                current_tokens += tokens
            else:
                break
                
        return list(reversed(retrieved_data))
        
    async def get_ai_response(self, 
                            user_id: str,
                            current_input: str,
                            categories: List[str] = None) -> str:
        """Generate AI response with context from persistent knowledge"""
        
        # Build context from stored knowledge
        context = []
        if categories:
            for category in categories:
                knowledge = self.retrieve_knowledge(user_id, category)
                if knowledge:
                    context.append(f"\nRelevant {category} knowledge:")
                    for entry in knowledge:
                        context.append(json.dumps(entry["content"]))
                        
        # Prepare messages for API
        messages = [
            {
                "role": "system",
                "content": "You are an assistant with access to persistent knowledge. "
                          "Use this context to provide informed responses."
            },
            {
                "role": "user",
                "content": f"Context:\n{''.join(context)}\n\nCurrent query: {current_input}"
            }
        ]
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4",
                messages=messages,
                temperature=0.7,
                max_tokens=500
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"
            
class KnowledgeManager:
    def __init__(self, api_key: str):
        self.knowledge = PersistentKnowledge(api_key)
        
    async def process_interaction(self, 
                                user_id: str,
                                message: str,
                                categories: List[str] = None) -> str:
        """Process user interaction and maintain knowledge"""
        
        # Save user input
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "user", "message": message}
        )
        
        # Get AI response with context
        response = await self.knowledge.get_ai_response(
            user_id,
            message,
            categories
        )
        
        # Save AI response
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "assistant", "message": response}
        )
        
        return response

# Example usage
async def main():
    manager = KnowledgeManager("your-api-key")
    
    # First interaction
    response1 = await manager.process_interaction(
        "user123",
        "What's the best way to learn Python?",
        ["conversations", "preferences"]
    )
    print("Response 1:", response1)
    
    # Save user preference
    manager.knowledge.save_knowledge(
        "user123",
        "preferences",
        {"learning_style": "hands-on", "preferred_language": "Python"}
    )
    
    # Later interaction using stored knowledge
    response2 = await manager.process_interaction(
        "user123",
        "Can you suggest some projects based on my learning style?",
        ["conversations", "preferences"]
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase PersistentKnowledge:
    • Maneja el conteo de tokens usando tiktoken para la gestión del contexto
    • Implementa save_knowledge() para almacenar información categorizada
    • Proporciona retrieve_knowledge() con límites de tokens para la recuperación de contexto
    • Gestiona las interacciones de IA a través de get_ai_response()
  2. Clase KnowledgeManager:
    • Proporciona una interfaz de alto nivel para la gestión del conocimiento
    • Procesa las interacciones del usuario y mantiene el historial de conversaciones
    • Maneja el guardado tanto de las entradas del usuario como las respuestas de la IA
  3. Características Principales:
    • Almacenamiento Categorizado de Conocimiento: Organiza la información por usuario y categoría
    • Gestión de Tokens: Asegura que el contexto se mantenga dentro de los límites del modelo
    • Seguimiento de Metadatos: Incluye marcas de tiempo y categorías para todos los datos almacenados
    • Manejo de Errores: Gestión robusta de errores para operaciones de archivo y llamadas a la API
  4. Beneficios de la Implementación:
    • Escalable: Maneja múltiples usuarios y categorías de conocimiento
    • Eficiente: Utiliza conteo de tokens para optimizar el uso del contexto
    • Flexible: Admite varios tipos y categorías de conocimiento
    • Mantenible: Código bien estructurado con clara separación de responsabilidades

Esta implementación proporciona una base sólida para aplicaciones de IA que requieren conocimiento persistente a través de conversaciones. Sobresale en mantener las preferencias del usuario, historiales de conversación y otros datos continuos mientras gestiona eficientemente los límites de tokens.

Resumen de Conversaciones

Al mantener historiales detallados de conversaciones, el sistema puede generar resúmenes completos que capturan puntos clave, decisiones y elementos de acción. Estos resúmenes cumplen múltiples funciones críticas:

  1. Actualización de Contexto: Cuando los participantes comienzan nuevas sesiones de conversación, el sistema proporciona resúmenes concisos pero completos de discusiones previas. Estos resúmenes sirven como informes eficientes que:
    • Orientan rápidamente a los participantes sobre puntos clave de discusión
    • Destacan decisiones y resultados importantes
    • Identifican elementos de acción en curso
    • Refrescan la memoria sobre el contexto crítico
      Esto elimina el proceso que consume tiempo de revisar registros extensos de conversación y asegura que todos los participantes puedan involucrarse inmediatamente de manera productiva en la discusión actual con plena conciencia del contexto.
  2. Seguimiento del Progreso: Los resúmenes regulares sirven como un mecanismo integral de seguimiento para discusiones y proyectos en curso. Al mantener registros detallados de la evolución del proyecto, los equipos pueden:
    • Monitorear Fases de Desarrollo
      • Seguir la progresión desde conceptos iniciales hasta implementación
      • Documentar mejoras y refinamientos iterativos
      • Registrar puntos de inflexión clave en la dirección del proyecto
    • Analizar Historial de Decisiones
      • Capturar el contexto detrás de elecciones importantes
      • Documentar opciones alternativas consideradas
      • Seguir resultados de decisiones implementadas
    • Identificar Tendencias del Proyecto
      • Detectar desafíos o cuellos de botella recurrentes
      • Reconocer patrones exitosos para replicar
      • Monitorear velocidad y momentum
    • Facilitar Alineación del Equipo
      • Mantener entendimiento compartido del progreso
      • Permitir correcciones basadas en datos
      • Apoyar la asignación informada de recursos
  3. Extracción de Conocimiento: El sistema emplea técnicas avanzadas de análisis para identificar y extraer información crítica de las conversaciones, incluyendo:
    • Decisiones clave y su fundamento
      • Elecciones estratégicas realizadas durante las discusiones
      • Evidencia de respaldo y justificación
      • Opciones alternativas consideradas
    • Elementos de acción y sus responsables
      • Tareas específicas asignadas a miembros del equipo
      • Asignaciones claras de responsabilidad
      • Requisitos de seguimiento
    • Fechas límite y hitos importantes
      • Marcadores de línea temporal del proyecto
      • Fechas críticas de entrega
      • Programas de revisión y puntos de control
    • Preguntas o preocupaciones sin resolver
      • Problemas técnicos abiertos
      • Decisiones pendientes
      • Áreas que necesitan clarificación
    • Acuerdos y compromisos establecidos
      • Decisiones formales alcanzadas
      • Acuerdos de asignación de recursos
      • Compromisos de cronograma
  4. Generación de Informes: Los resúmenes pueden compilarse automáticamente en varios tipos de informes:
    • Informes ejecutivos
      • Visiones generales de alto nivel para interesados
      • Decisiones clave e implicaciones estratégicas
      • Resúmenes de asignación de recursos
    • Actas de reunión
      • Puntos detallados de discusión y resultados
      • Elementos de acción y asignados
      • Compromisos de cronograma establecidos
    • Actualizaciones de progreso
      • Logros de hitos y retrasos
      • Bloqueadores y desafíos actuales
      • Próximos pasos y prioridades
    • Informes de estado del proyecto
      • Indicadores generales de salud del proyecto
      • Métricas de utilización de recursos
      • Evaluaciones de riesgo y estrategias de mitigación

La capacidad de condensar y recordar información relevante no solo hace las conversaciones más eficientes y enfocadas, sino que también asegura que la información crítica nunca se pierda y pueda ser fácilmente accedida cuando sea necesario. Este enfoque sistemático para el resumen de conversaciones ayuda a mantener la claridad y continuidad a través de interacciones a largo plazo, especialmente en proyectos complejos o discusiones continuas que involucran múltiples participantes.

Ejemplo: Implementación de Resumen de Conversaciones

Aquí hay una implementación práctica de un resumidor de conversaciones usando la API de OpenAI:

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

class ConversationSummarizer:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        
    def create_summary_prompt(self, messages: List[Dict]) -> str:
        """Create a prompt for summarization from messages"""
        conversation = "\n".join([
            f"{msg['role'].title()}: {msg['content']}" 
            for msg in messages
        ])
        
        return f"""Please provide a concise summary of the following conversation, 
        highlighting key points, decisions, and action items:

        {conversation}
        
        Summary should include:
        1. Main topics discussed
        2. Key decisions made
        3. Action items and owners
        4. Unresolved questions
        """

    async def generate_summary(self, messages: List[Dict]) -> Dict:
        """Generate a structured summary of the conversation"""
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=[{
                    "role": "user",
                    "content": self.create_summary_prompt(messages)
                }],
                temperature=0.7,
                max_tokens=500
            )
            
            summary = response.choices[0].message.content
            
            return {
                "timestamp": datetime.now().isoformat(),
                "message_count": len(messages),
                "summary": summary
            }
            
        except Exception as e:
            return {
                "error": f"Failed to generate summary: {str(e)}",
                "timestamp": datetime.now().isoformat()
            }

    def save_summary(self, summary: Dict, filename: str = "summaries.json"):
        """Save summary to JSON file"""
        try:
            with open(filename, "r") as f:
                summaries = json.load(f)
        except FileNotFoundError:
            summaries = []
            
        summaries.append(summary)
        
        with open(filename, "w") as f:
            json.dump(summaries, f, indent=2)

# Example usage
async def main():
    summarizer = ConversationSummarizer("your-api-key")
    
    # Sample conversation
    messages = [
        {"role": "user", "content": "Let's discuss the new feature implementation."},
        {"role": "assistant", "content": "Sure! What specific aspects would you like to focus on?"},
        {"role": "user", "content": "We need to implement user authentication by next week."},
        {"role": "assistant", "content": "I understand. Let's break down the requirements and timeline."}
    ]
    
    # Generate and save summary
    summary = await summarizer.generate_summary(messages)
    summarizer.save_summary(summary)
    print("Summary:", summary["summary"])

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

Desglose del Código:

  1. Estructura de Clase:
    • La clase ConversationSummarizer maneja todas las operaciones de resumen
    • Inicialización con configuración de clave API
    • Métodos para creación de prompts, generación de resúmenes y almacenamiento
  2. Características Principales:
    • Generación estructurada de prompts para resúmenes consistentes
    • Llamadas API asíncronas para mejor rendimiento
    • Manejo y registro de errores
    • Almacenamiento persistente de resúmenes
  3. Beneficios de Implementación:
    • Escalable: Maneja conversaciones de diferentes longitudes
    • Salida Estructurada: Resúmenes organizados con información clave
    • Seguimiento Histórico: Mantiene historial de resúmenes
    • Resistente a Errores: Manejo y registro de errores robusto

Este ejemplo proporciona una forma confiable de generar y mantener resúmenes de conversaciones, facilitando el seguimiento del progreso de las discusiones y decisiones clave a lo largo del tiempo.

7.3.2 Arquitectura Central

Para crear un sistema de memoria efectivo para interacciones de IA, tres componentes esenciales trabajan juntos de manera coordinada para mantener el contexto y asegurar la continuidad conversacional. Estos componentes forman una arquitectura sofisticada que permite a los sistemas de IA acceder, procesar y utilizar información histórica de manera efectiva durante las conversaciones en curso.

El componente de almacenamiento preserva el historial de conversación, el mecanismo de recuperación obtiene de manera inteligente las interacciones pasadas relevantes, y el sistema de inyección incorpora perfectamente este contexto histórico en las conversaciones actuales.

Juntos, estos tres pilares crean una base robusta que permite a los sistemas de IA mantener diálogos significativos y conscientes del contexto a través de múltiples interacciones:

Almacenamiento

La base de la gestión de memoria donde todas las interacciones se guardan y preservan sistemáticamente para uso futuro. Este componente crítico sirve como columna vertebral de cualquier sistema de conversación de IA:

  • Puede utilizar varias soluciones de almacenamiento como archivos JSON, bases de datos SQL o almacenamiento en la nube
    • Los archivos JSON ofrecen simplicidad y portabilidad para aplicaciones más pequeñas
    • Las bases de datos SQL proporcionan consultas robustas e indexación para conjuntos de datos más grandes
    • El almacenamiento en la nube permite acceso escalable y distribuido a través de múltiples servicios
  • Debe incluir metadatos como marcas de tiempo e identificadores de usuario
    • Las marcas de tiempo permiten seguimiento cronológico y filtrado basado en tiempo
    • Los IDs de usuario mantienen hilos de conversación y personalización
    • Metadatos adicionales pueden rastrear temas y contextos de conversación
  • Debe estar organizado para recuperación y escalado eficientes
    • Implementar indexación adecuada para acceso rápido a datos relevantes
    • Usar particionamiento de datos para mejor rendimiento
    • Considerar estrategias de compresión para almacenamiento a largo plazo

Recuperación

El sistema inteligente para acceder y filtrar conversaciones pasadas relevantes sirve como un componente crucial en la gestión del historial de conversaciones:

  • Implementa algoritmos de búsqueda para encontrar datos históricos apropiados al contexto
    • Utiliza búsqueda semántica para coincidir temas y temáticas similares
    • Emplea coincidencia difusa para comparación flexible de texto
    • Indexa conversaciones para recuperación rápida
  • Utiliza parámetros como recencia, relevancia e hilo de conversación
    • Prioriza interacciones recientes para contexto inmediato
    • Pondera relevancia basada en puntajes de similitud de temas
    • Mantiene continuidad de hilos rastreando flujos de conversación
  • Gestiona límites de tokens seleccionando el contexto más importante
    • Implementa estrategias inteligentes de truncamiento
    • Prioriza información clave mientras elimina contenido redundante
    • Ajusta dinámicamente ventana de contexto según limitaciones del modelo

Inyección

El proceso de incorporar perfectamente el contexto histórico requiere un manejo cuidadoso para mantener la coherencia de la conversación:

  • Coloca estratégicamente mensajes recuperados en el flujo actual de conversación
    • Determina puntos óptimos de inserción para contexto histórico
    • Filtra y prioriza información histórica relevante
    • Equilibra contenido nuevo e histórico para un flujo natural
  • Mantiene orden apropiado de mensajes y relaciones
    • Preserva secuencia cronológica de interacciones
    • Respeta hilos de conversación y cadenas de respuestas
    • Enlaza temas y discusiones relacionadas apropiadamente
  • Asegura integración fluida del contexto sin interrumpir la conversación
    • Evita cambios abruptos de contexto o sobrecarga de información
    • Utiliza frases de transición y referencias naturales
    • Mantiene tono y estilo de conversación consistentes

7.3.3 Cómo Almacenar y Recuperar Historiales de Mensajes Basados en JSON en Python

En esta sección, exploraremos una implementación práctica que demuestra cómo crear un sistema de memoria persistente usando archivos JSON. Este enfoque ofrece una manera directa de mantener el contexto de conversación a través de múltiples sesiones mientras se mantiene escalable y fácil de mantener.

Nuestra implementación se centrará en tres aspectos clave: almacenar eficientemente historiales de mensajes en formato JSON, recuperar contexto de conversación relevante cuando sea necesario, y gestionar la estructura de datos para asegurar un rendimiento óptimo. Esta solución es particularmente útil para desarrolladores que construyen chatbots, asistentes virtuales o cualquier aplicación que requiera historial de conversación persistente.

Paso 1: Construir el Gestor de Memoria

Este módulo maneja el almacenamiento de interacciones de usuario en formato JSON y recupera solo las relevantes.

import os
import json
from typing import List, Dict

MEMORY_DIR = "user_memory"
os.makedirs(MEMORY_DIR, exist_ok=True)

# Constants
MAX_HISTORY_MESSAGES = 5  # Truncate history to last 5 messages to manage tokens

def get_memory_path(user_id: str) -> str:
    return os.path.join(MEMORY_DIR, f"{user_id}.json")

def load_history(user_id: str) -> List[Dict[str, str]]:
    path = get_memory_path(user_id)
    if not os.path.exists(path):
        return []
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        return []

def store_interaction(user_id: str, role: str, content: str) -> None:
    message = {"role": role, "content": content}
    path = get_memory_path(user_id)

    history = load_history(user_id)
    history.append(message)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=2)

def get_recent_history(user_id: str, limit: int = MAX_HISTORY_MESSAGES) -> List[Dict[str, str]]:
    history = load_history(user_id)
    return history[-limit:]

Analicemos este código:

  1. Configuración Inicial
  • Crea un directorio "user_memory" para almacenar los historiales de conversación
  • Establece un límite máximo de 5 mensajes para la gestión del historial
  1. Funciones Principales
  • get_memory_path(user_id): Crea una ruta de archivo JSON única para cada usuario
  • load_history(user_id):
    • Intenta leer el historial de conversación del usuario
    • Devuelve una lista vacía si el archivo no existe o está corrupto
  • store_interaction(user_id, role, content):
    • Guarda nuevos mensajes en el archivo de historial del usuario
    • Añade el mensaje al historial existente
    • Almacena en formato JSON con sangría apropiada
  • get_recent_history(user_id, limit):
    • Recupera los mensajes más recientes
    • Respeta el límite MAX_HISTORY_MESSAGES (5 mensajes)
  1. Características Principales
  • Almacenamiento persistente: Las conversaciones de cada usuario se guardan en archivos JSON separados
  • Escalabilidad: El sistema puede manejar múltiples usuarios con archivos individuales
  • Contexto controlado: Permite control específico sobre cuánto historial mantener
  • Fácil de depurar: El formato JSON facilita la inspección de conversaciones almacenadas

Paso 2: Crear el Motor de Chat Usando la API de OpenAI

Ahora integremos este sistema de memoria con la API de OpenAI. Cargaremos los mensajes anteriores, añadiremos el nuevo prompt, consultaremos el modelo y guardaremos la respuesta.

import openai
from dotenv import load_dotenv

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

SYSTEM_PROMPT = {
    "role": "system",
    "content": "You are a helpful assistant that remembers the user's previous messages."
}

def continue_conversation(user_id: str, user_input: str) -> str:
    # Validate input
    if not user_input.strip():
        return "Input cannot be empty."

    # Load memory and prepare messages
    recent_history = get_recent_history(user_id)
    messages = [SYSTEM_PROMPT] + recent_history + [{"role": "user", "content": user_input}]

    # Call OpenAI API
    try:
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=300,
            temperature=0.7
        )
        assistant_reply = response["choices"][0]["message"]["content"]

        # Store both messages
        store_interaction(user_id, "user", user_input)
        store_interaction(user_id, "assistant", assistant_reply)

        return assistant_reply

    except Exception as e:
        return f"Something went wrong: {e}"

Analicemos este código:

1. Configuración Inicial

  • Importa las bibliotecas necesarias (openai y dotenv)
  • Carga las variables de entorno y configura la clave API de OpenAI
  • Define un prompt de sistema que establece el rol del asistente

2. Función Principal: continue_conversation

  • Recibe user_id y user_input como parámetros
  • Validación de entrada para verificar mensajes vacíos
  • Carga el historial de conversación usando get_recent_history (definido en la sección anterior)
  • Construye el array de mensajes combinando: 
    • Prompt del sistema
    • Historial reciente de conversación
    • Entrada actual del usuario

3. Interacción con la API

  • Realiza la llamada a la API de OpenAI con parámetros: 
    • Utiliza el modelo "gpt-4o"
    • Establece max_tokens en 300
    • Usa una temperatura de 0.7 para una creatividad equilibrada
  • Extrae la respuesta del asistente de la respuesta

4. Gestión de Memoria

  • Almacena tanto la entrada del usuario como la respuesta del asistente usando store_interaction
  • Maneja los errores adecuadamente con un bloque try-except

Esta parte crea un sistema de conversación con estado que mantiene el contexto a través de múltiples interacciones mientras gestiona el flujo de conversación de manera eficiente.

Paso 3: Probar la Memoria de Conversación

if __name__ == "__main__":
    user_id = "user_456"

    print("User: What are the best Python libraries for data science?")
    reply1 = continue_conversation(user_id, "What are the best Python libraries for data science?")
    print("Assistant:", reply1)

    print("\nUser: Could you remind me which ones you mentioned?")
    reply2 = continue_conversation(user_id, "Could you remind me which ones you mentioned?")
    print("Assistant:", reply2)

Analicemos este ejemplo de código para probar la memoria de conversación:

1. Verificación del Punto de Entrada

  • El código utiliza el modismo estándar de Python if __name__ == "__main__": para asegurar que este código solo se ejecute cuando el archivo se ejecuta directamente

2. Configuración del Usuario

  • Crea un usuario de prueba con ID "user_456"

3. Flujo de Conversación de Prueba

  • Demuestra una conversación de dos turnos donde:
  • Primer turno: Pregunta sobre las bibliotecas de Python para ciencia de datos
  • Segundo turno: Pide un recordatorio de las bibliotecas mencionadas anteriormente, probando el sistema de memoria

4. Detalles de Implementación

  • Cada interacción utiliza la función continue_conversation() para:
  • Procesar la entrada del usuario
  • Generar y almacenar la respuesta
  • Imprimir tanto la entrada del usuario como la respuesta del asistente

Este código de prueba demuestra efectivamente cómo el sistema mantiene el contexto entre múltiples interacciones, permitiendo que el asistente haga referencia a respuestas anteriores al contestar preguntas de seguimiento.

Beneficios de Este Enfoque

  • Persistente: Todas las conversaciones se almacenan localmente por usuario, asegurando que no se pierda ningún historial de interacción. Esto significa que su aplicación puede mantener el contexto a través de múltiples sesiones, incluso si el servidor se reinicia o la aplicación se cierra.
  • Escalable (hasta cierto punto): Al almacenar el historial de conversación de cada usuario en su propio archivo JSON, el sistema puede manejar múltiples usuarios de manera eficiente. Este enfoque funciona bien para aplicaciones pequeñas y medianas, aunque para implementaciones muy grandes podría ser conveniente considerar una solución de base de datos.
  • Contexto controlable: El sistema le da control completo sobre cuánto historial de conversación incluir en cada interacción. Puede ajustar el tamaño de la ventana de memoria, filtrar por relevancia o implementar lógica personalizada para seleccionar qué mensajes anteriores incluir en el contexto.
  • Legible: El formato de archivo JSON facilita la inspección, depuración y modificación de las conversaciones almacenadas. Esto es invaluable durante el desarrollo y mantenimiento, ya que puede ver fácilmente el historial de conversación en cualquier editor de texto y validar la estructura de datos.

Mejoras Opcionales

  • Resumen: En lugar de almacenar cada mensaje textualmente, implementar resúmenes periódicos del historial de conversación. Esta técnica implica generar automáticamente resúmenes concisos de segmentos más largos de conversación, lo que ayuda a:
  • Reducir el uso de tokens en llamadas a la API
  • Mantener el contexto esencial mientras se eliminan detalles redundantes
  • Crear una estructura de memoria más eficiente

Por ejemplo, múltiples mensajes sobre un tema específico podrían condensarse en una única declaración resumida.

  • Búsqueda Vectorial (Avanzado): Transformar mensajes en vectores numéricos utilizando modelos de embedding, permitiendo una recuperación sofisticada basada en significado semántico. Este enfoque ofrece varias ventajas:
  • Descubrir mensajes históricos contextualmente relevantes incluso si utilizan palabras diferentes
  • Priorizar mensajes basados en su relevancia para la conversación actual
  • Permitir búsquedas rápidas de similitud a través de grandes historiales de conversación

Esto es particularmente útil para conversaciones de larga duración o cuando se necesita recordar contexto específico.

  • Gestión de Tokens: Implementar estrategias inteligentes de gestión de tokens para optimizar el uso de la ventana de contexto. Esto incluye:
  • Establecer límites dinámicos basados en la importancia de la conversación
  • Implementar poda inteligente de mensajes más antiguos y menos relevantes
  • Mantener un equilibrio entre el contexto reciente y la información histórica importante

Esto asegura que se mantenga dentro de los límites de tokens de la API mientras se preserva el contexto de conversación más valioso.

  • Mantener el prompt del sistema consistente a través de las interacciones
  • Mantener la redacción e instrucciones del prompt idénticas durante todo el ciclo de vida de la conversación
  • Usar control de versiones para rastrear cualquier cambio en el prompt del sistema a través de las implementaciones
  • Previene confusión y respuestas contradictorias manteniendo un contexto consistente
  • Asegura que la IA mantenga una personalidad y patrón de comportamiento confiable a través de las interacciones
  • No sobrecargue el contexto—almacene todo, pero recupere selectivamente
  • Implementar un sistema de almacenamiento integral que mantenga historiales completos de conversación en su base de datos
  • Desarrollar algoritmos de recuperación inteligentes que prioricen el contexto relevante para las llamadas a la API
  • Usar búsqueda semántica o similitud basada en embeddings para encontrar mensajes históricos pertinentes
  • Equilibrar el uso de tokens implementando estrategias inteligentes de poda para mensajes más antiguos
  • Etiquetar los mensajes almacenados claramente (rolecontenttimestamp) para filtrado o resumen futuro
  • Role: Identificar y etiquetar cuidadosamente las fuentes de los mensajes (sistema, usuario o asistente) para mantener un flujo de conversación claro y permitir el filtrado basado en roles
  • Content: Implementar estándares de formato consistentes para el contenido de los mensajes, incluyendo el manejo de caracteres especiales y manteniendo la integridad de los datos
  • Timestamp: Agregar metadatos temporales precisos para permitir operaciones sofisticadas basadas en tiempo como segmentación de conversación y puntuación de relevancia contextual

La memoria a largo plazo no es nativa de los modelos de chat de OpenAI (todavía), pero con una ingeniería cuidadosa, puede crear sistemas de memoria sofisticados. Esta limitación significa que por defecto, el modelo trata cada interacción como aislada, sin conocimiento de conversaciones anteriores. Sin embargo, los desarrolladores pueden implementar soluciones personalizadas para superar esta limitación.

Aquí hay una explicación detallada de cómo funciona: Mientras que el modelo en sí no mantiene memorias entre conversaciones, su aplicación actúa como un gestor de memoria. Almacena cada interacción en un formato estructurado, típicamente usando bases de datos o sistemas de archivos. Estos datos almacenados incluyen no solo el contenido de la conversación, sino también metadatos como marcas de tiempo, información del usuario y temas de conversación. Al gestionar cuidadosamente estas conversaciones almacenadas y recuperar selectivamente piezas relevantes, crea una ilusión de memoria continua - haciendo que la IA parezca "recordar" interacciones anteriores.

Este sistema de memoria transforma tu asistente de IA de varias formas poderosas:

  • Continuidad: El asistente puede hacer referencia a conversaciones pasadas y mantener el contexto durante períodos prolongados, creando interacciones fluidas que se construyen sobre discusiones previas. Por ejemplo, si un usuario menciona su preferencia por la programación en Python en una conversación, el sistema puede hacer referencia a esto en interacciones futuras.
  • Personalidad: Los patrones de respuesta consistentes y las preferencias recordadas crean una personalidad más distintiva. Esto incluye mantener un tono consistente, recordar las preferencias del usuario y adaptar los estilos de comunicación basados en interacciones anteriores.
  • Comprensión: Al acceder al contexto histórico, las respuestas se vuelven más informadas y personalizadas. El sistema puede recordar detalles específicos de conversaciones anteriores, haciendo que las interacciones se sientan más naturales y contextualmente conscientes.
  • Profundidad: La capacidad de construir sobre conversaciones previas permite interacciones más sofisticadas, posibilitando la resolución de problemas complejos y el soporte de proyectos a largo plazo.

Este enfoque escala notablemente bien a través de diferentes escenarios de uso, desde usuarios individuales hasta aplicaciones a nivel empresarial. Ya sea que estés construyendo un asistente personal para un único usuario o un sistema que sirva a miles, el principio fundamental sigue siendo el mismo: estás creando una capa de memoria inteligente que se sitúa entre el usuario y la API. Este enfoque arquitectónico proporciona varias capacidades clave:

  • Crecer: Acumular continuamente nuevas interacciones y aprendizajes, construyendo un rico historial de interacciones y preferencias del usuario a lo largo del tiempo. Esta base de conocimiento creciente se vuelve cada vez más valiosa para personalizar respuestas.
  • Resumir: Condensar historiales de conversación extensos en contextos manejables, utilizando técnicas avanzadas como agrupamiento semántico y puntuación de importancia para mantener la información más relevante.
  • Adaptar: Ajustar sus estrategias de recuperación basándose en patrones de conversación, aprendiendo qué tipos de contexto histórico son más valiosos para diferentes tipos de interacciones.

Todo esto mientras se aprovecha la misma API subyacente de OpenAI para el procesamiento del lenguaje. Esta combinación de gestión estructurada de memoria y procesamiento potente del lenguaje crea un sistema que puede mantener el contexto y la personalidad a través de múltiples conversaciones mientras se mantiene dentro de las restricciones técnicas de la API.

7.3 Almacenamiento y Recuperación de Interacciones Pasadas

En el mundo real, las conversaciones humanas se construyen sobre la historia compartida e interacciones previas. Cuando hablamos con alguien que conocemos, naturalmente recurrimos a nuestras experiencias pasadas con ellos - sus preferencias, discusiones previas y el contexto que hemos construido juntos. Este sistema natural de memoria es lo que hace que nuestras conversaciones se sientan continuas y personalmente significativas.

Si bien los modelos de lenguaje de OpenAI no poseen inherentemente capacidades de memoria a largo plazo, los desarrolladores pueden crear sistemas sofisticados para replicar este proceso natural de memoria. Al implementar un sistema de almacenamiento y recuperación para interacciones pasadas, puedes crear un asistente de IA que parece "recordar" conversaciones previas. Esto implica registrar cuidadosamente las interacciones del usuario, almacenar contexto relevante y recuperar estratégicamente esta información cuando sea necesario.

Esta sección demuestra cómo construir un sistema de memoria ligero pero poderoso que mejora las capacidades de tu asistente de IA. Al mantener el historial de conversación y las preferencias del usuario a través de múltiples sesiones, puedes crear interacciones más significativas que se sienten menos como intercambios aislados y más como conversaciones continuas. Tu asistente podrá hacer referencia a discusiones pasadas, recordar preferencias del usuario y mantener conciencia del contexto - haciéndolo sentir más como interactuar con un colega conocedor que comenzar de nuevo con cada interacción.

7.3.1 ¿Por qué Almacenar las Interacciones?

El almacenamiento de interacciones pasadas desbloquea varias capacidades poderosas que mejoran la habilidad de la IA para proporcionar respuestas significativas y contextuales:

Respuestas Personalizadas

El sistema aprende y se adapta a usuarios individuales manteniendo un perfil detallado de sus interacciones y preferencias a lo largo del tiempo. Esta personalización ocurre en múltiples niveles:

  1. Estilo de Comunicación: El sistema rastrea cómo los usuarios se expresan analizando múltiples aspectos de sus patrones de comunicación:
    • Nivel de formalidad: Si utilizan lenguaje casual ("¡hola!") o un trato formal ("Estimado Señor/Señora")
    • Uso del humor: Su tendencia a usar bromas, emojis o lenguaje juguetón
    • Ritmo de conversación: Si prefieren intercambios rápidos o discusiones detalladas y extensas
    • Elecciones de vocabulario: Lenguaje técnico vs. simplificado
    • Referencias culturales: Profesionales, académicas o de cultura popular

Por ejemplo, si un usuario utiliza consistentemente lenguaje informal como "hola" y "¡gracias!" con emojis, el sistema se adapta respondiendo en un tono amistoso y casual. Por el contrario, cuando interactúa con usuarios empresariales que mantienen un lenguaje formal y términos profesionales, el sistema automáticamente se ajusta para usar la etiqueta empresarial apropiada y terminología estándar de la industria.

Esta comunicación adaptativa asegura interacciones más naturales y efectivas al coincidir con el estilo y preferencias de comunicación únicos de cada usuario.

  1. Competencia Técnica: Al analizar interacciones pasadas, el sistema evalúa los niveles de experiencia de los usuarios en diferentes dominios. Esto le permite ajustar automáticamente sus explicaciones basándose en el conocimiento demostrado.

Por ejemplo, al discutir programación, el sistema puede usar terminología avanzada como "polimorfismo" e "inyección de dependencias" con desarrolladores experimentados, mientras ofrece explicaciones más simples usando analogías del mundo real para principiantes. El sistema refina continuamente esta evaluación a través de interacciones continuas - si un usuario demuestra mayor comprensión con el tiempo, la profundidad técnica de las explicaciones se ajusta en consecuencia. Este enfoque adaptativo asegura que los expertos no se vean ralentizados por explicaciones básicas mientras que los principiantes no se vean abrumados por detalles técnicos complejos.

  1. Contexto Histórico: El sistema mantiene registros completos de discusiones previas, proyectos y decisiones, permitiéndole hacer referencia a conversaciones pasadas con precisión y relevancia. Este seguimiento histórico opera en múltiples niveles:
    • Seguimiento de Conversaciones: El sistema puede seguir la progresión de temas específicos a través de múltiples sesiones, entendiendo cómo las discusiones evolucionan y se construyen unas sobre otras.
    • Hitos del Proyecto: Las decisiones importantes, acuerdos y actualizaciones del proyecto se registran y pueden ser referenciados para mantener consistencia en discusiones futuras.
    • Evolución de Preferencias del Usuario: El sistema rastrea cómo las preferencias y requisitos del usuario cambian con el tiempo, adaptando sus respuestas en consecuencia.
    • Referencias Contextuales: Al abordar temas actuales, el sistema puede hacer referencia inteligentemente a discusiones pasadas relacionadas para proporcionar respuestas más informadas y matizadas.

Esta gestión sofisticada del contexto crea una experiencia conversacional fluida donde los usuarios se sienten comprendidos y valorados, ya que el sistema demuestra consciencia de su historial y necesidades continuas. Por ejemplo, si un usuario discutió previamente desafíos con un marco de programación específico, el sistema puede hacer referencia a esas conversaciones anteriores al proporcionar nuevas soluciones o actualizaciones.

  1. Preferencias de Personalización: El sistema mantiene y aplica preferencias detalladas del usuario a través de sesiones, incluyendo:
    • Idioma preferido y variaciones regionales
      • Selección de idioma (por ejemplo, inglés, español, mandarín)
      • Dialectos regionales y localizaciones
      • Unidades de moneda y medida
    • Preferencias de formato (viñetas vs. párrafos)
      • Preferencias de estructura de documento (jerárquico vs. plano)
      • Organización visual (listas, tablas o texto fluido)
      • Convenciones de formato de código cuando aplique
    • Nivel de detalle deseado en respuestas
      • Resúmenes breves vs. explicaciones exhaustivas
      • Profundidad técnica del contenido
      • Inclusión de ejemplos y analogías
    • Terminología específica o convenciones de nomenclatura
      • Vocabulario específico de la industria
      • Marcos técnicos o metodologías preferidas
      • Terminología específica de la empresa
    • Zonas horarias y horarios laborales
      • Preferencias de programación de reuniones
      • Preferencias de tiempo para notificaciones
      • Ventanas de disponibilidad para comunicación sincrónica

Este enfoque integral de personalización ayuda a crear una interacción más natural, eficiente y atractiva que se siente adaptada a las necesidades y preferencias individuales de cada usuario.

Ejemplo: Implementación de Respuestas Personalizadas

Aquí hay una implementación integral de un sistema de personalización que se adapta a los estilos de comunicación del usuario:

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

class UserProfile:
    def __init__(self, user_id: str):
        self.user_id = user_id
        self.communication_style = {
            "formality_level": 0.5,  # 0 = casual, 1 = formal
            "technical_level": 0.5,   # 0 = beginner, 1 = expert
            "verbosity": 0.5,         # 0 = concise, 1 = detailed
            "emoji_usage": False
        }
        self.preferences = {
            "language": "en",
            "timezone": "UTC",
            "topics_of_interest": []
        }
        self.interaction_history = []

class PersonalizedAIAssistant:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.profiles_dir = "user_profiles"
        os.makedirs(self.profiles_dir, exist_ok=True)
        self.users: Dict[str, UserProfile] = {}

    def _get_profile_path(self, user_id: str) -> str:
        return os.path.join(self.profiles_dir, f"{user_id}.json")

    def load_user_profile(self, user_id: str) -> UserProfile:
        if user_id in self.users:
            return self.users[user_id]

        profile_path = self._get_profile_path(user_id)
        if os.path.exists(profile_path):
            with open(profile_path, 'r') as f:
                data = json.load(f)
                profile = UserProfile(user_id)
                profile.communication_style = data.get('communication_style', profile.communication_style)
                profile.preferences = data.get('preferences', profile.preferences)
                profile.interaction_history = data.get('interaction_history', [])
        else:
            profile = UserProfile(user_id)

        self.users[user_id] = profile
        return profile

    def save_user_profile(self, profile: UserProfile):
        data = {
            'communication_style': profile.communication_style,
            'preferences': profile.preferences,
            'interaction_history': profile.interaction_history
        }
        with open(self._get_profile_path(profile.user_id), 'w') as f:
            json.dump(data, f, indent=2)

    def analyze_message(self, message: str) -> dict:
        """Analyze user message to update communication style metrics."""
        return {
            "formality_level": 0.8 if any(word in message.lower() for word in 
                ['please', 'thank you', 'sir', 'madam']) else 0.2,
            "technical_level": 0.8 if any(word in message.lower() for word in 
                ['api', 'function', 'implementation', 'code']) else 0.3,
            "emoji_usage": '😊' in message or '👍' in message
        }

    def generate_system_prompt(self, profile: UserProfile) -> str:
        """Create personalized system prompt based on user profile."""
        style = "formal" if profile.communication_style["formality_level"] > 0.5 else "casual"
        tech_level = "technical" if profile.communication_style["technical_level"] > 0.5 else "simple"
        
        return f"""You are a helpful assistant that communicates in a {style} style.
                  Use {tech_level} language and {'feel free to use emojis' 
                  if profile.communication_style['emoji_usage'] else 'avoid using emojis'}.
                  Communicate {'in detail' if profile.communication_style['verbosity'] > 0.5 
                  else 'concisely'}."""

    async def get_response(self, user_id: str, message: str) -> str:
        profile = self.load_user_profile(user_id)
        
        # Analyze and update user's communication style
        analysis = self.analyze_message(message)
        profile.communication_style.update(analysis)
        
        # Prepare conversation context
        messages = [
            {"role": "system", "content": self.generate_system_prompt(profile)},
            {"role": "user", "content": message}
        ]

        # Add relevant history if available
        if profile.interaction_history:
            recent_history = profile.interaction_history[-3:]  # Last 3 interactions
            messages[1:1] = recent_history

        # Get AI response
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            temperature=0.7,
            max_tokens=150
        )

        # Store interaction
        interaction = {
            "timestamp": datetime.utcnow().isoformat(),
            "user_message": message,
            "assistant_response": response.choices[0].message.content
        }
        profile.interaction_history.append(interaction)
        
        # Save updated profile
        self.save_user_profile(profile)
        
        return response.choices[0].message.content

# Usage example
if __name__ == "__main__":
    assistant = PersonalizedAIAssistant("your-api-key-here")
    
    # Example interactions
    responses = [
        assistant.get_response("user123", "Hey there! Can you help me with Python? 😊"),
        assistant.get_response("user123", "Could you explain the technical implementation of APIs?"),
        assistant.get_response("user123", "Dear Sir, I require assistance with programming.")
    ]

Desglose del Código:

  1. Estructura de Clases:
    • La clase UserProfile mantiene la información individual del usuario:
      • Métricas de estilo de comunicación (formalidad, nivel técnico, etc.)
      • Preferencias personales (idioma, zona horaria)
      • Historial de interacciones
    • La clase PersonalizedAIAssistant maneja la funcionalidad principal:
      • Gestión de perfiles (carga/guardado)
      • Análisis de mensajes
      • Generación de respuestas
  2. Características Principales:
    • Almacenamiento Persistente: Los perfiles se guardan como archivos JSON
    • Análisis de Estilo: Examina los mensajes para detectar patrones de comunicación
    • Generación Dinámica de Instrucciones: Genera indicaciones personalizadas del sistema
    • Gestión de Contexto: Mantiene el historial de conversaciones
  3. Aspectos de Personalización:
    • Estilo de Comunicación:
      • Detección del nivel de formalidad
      • Adaptación del lenguaje técnico
      • Seguimiento del uso de emojis
    • Adaptación de Respuestas:
      • Ajusta la verbosidad según las preferencias del usuario
      • Mantiene un estilo consistente en las interacciones
      • Incorpora el historial de conversaciones

Esta implementación demuestra cómo crear un asistente de IA que aprende y se adapta al estilo de comunicación de cada usuario mientras mantiene una memoria persistente de las interacciones. El sistema actualiza continuamente su comprensión de las preferencias del usuario y ajusta sus respuestas en consecuencia.

Reanudación de Sesiones

Los usuarios pueden retomar conversaciones después de pausas y hacer que la IA comprenda el contexto completo de las discusiones anteriores. Esta capacidad permite una continuidad fluida de la conversación, donde la IA mantiene la consciencia de interacciones previas, preferencias del usuario y contexto establecido. Por ejemplo, si un usuario discute un error de software el lunes y regresa el miércoles, la IA puede recordar los detalles específicos del error, las soluciones propuestas y cualquier intento de corrección sin requerir que el usuario repita la información.

Esta característica es particularmente valiosa para tareas complejas que abarcan múltiples sesiones, como la planificación de proyectos o la resolución de problemas técnicos. Durante la planificación de proyectos, la IA puede mantener registros de hitos previamente acordados, asignaciones de recursos y responsabilidades del equipo a través de múltiples sesiones de planificación. En escenarios de resolución de problemas técnicos, puede seguir la progresión de los intentos de depuración, recordar qué soluciones ya se probaron y construir sobre los pasos diagnósticos anteriores.

La IA puede hacer referencia a puntos específicos de conversaciones anteriores y mantener la continuidad durante días o incluso semanas. Esta consciencia del contexto a largo plazo permite que la IA haga sugerencias más informadas, evite discusiones redundantes y proporcione asistencia más personalizada basada en las interacciones históricas del usuario. Por ejemplo, si un usuario expresó previamente una preferencia por ciertos marcos de programación o metodologías, la IA puede incorporar estas preferencias en recomendaciones futuras sin requerir recordatorios explícitos.

Aquí hay una implementación práctica de la reanudación de sesiones:

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

class SessionManager:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.sessions: Dict[str, Dict] = {}
        
    def save_session(self, user_id: str, session_data: dict):
        """Save session data to persistent storage."""
        with open(f"sessions/{user_id}.json", "w") as f:
            json.dump(session_data, f)
            
    def load_session(self, user_id: str) -> Optional[dict]:
        """Load session data from storage."""
        try:
            with open(f"sessions/{user_id}.json", "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return None

class ConversationManager:
    def __init__(self, session_manager: SessionManager):
        self.session_manager = session_manager
        self.current_context: List[Dict] = []
        
    def prepare_context(self, user_id: str, new_message: str) -> List[Dict]:
        """Prepare conversation context including session history."""
        # Load previous session if exists
        session = self.session_manager.load_session(user_id)
        
        # Initialize context with system message
        context = [{
            "role": "system",
            "content": "You are a helpful assistant with memory of past conversations."
        }]
        
        # Add relevant history from previous session
        if session and 'history' in session:
            # Add last 5 messages from previous session for context
            context.extend(session['history'][-5:])
        
        # Add new message
        context.append({
            "role": "user",
            "content": new_message
        })
        
        return context

    async def process_message(self, user_id: str, message: str) -> str:
        """Process new message with session context."""
        context = self.prepare_context(user_id, message)
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=context,
                temperature=0.7,
                max_tokens=150
            )
            
            assistant_message = response.choices[0].message.content
            
            # Update session with new interaction
            session_data = {
                'last_interaction': datetime.now().isoformat(),
                'history': context + [{
                    "role": "assistant",
                    "content": assistant_message
                }]
            }
            self.session_manager.save_session(user_id, session_data)
            
            return assistant_message
            
        except Exception as e:
            print(f"Error processing message: {e}")
            return "I apologize, but I encountered an error processing your message."

# Example usage
async def main():
    session_manager = SessionManager("your-api-key-here")
    conversation_manager = ConversationManager(session_manager)
    
    # First interaction
    response1 = await conversation_manager.process_message(
        "user123",
        "What's the weather like today?"
    )
    print("Response 1:", response1)
    
    # Later interaction (session resumption)
    response2 = await conversation_manager.process_message(
        "user123",
        "What did we discuss earlier?"
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase SessionManager:
    • Maneja el almacenamiento persistente de datos de sesión
    • Proporciona métodos para guardar y cargar información de sesión
    • Mantiene archivos de sesión específicos para cada usuario
  2. Clase ConversationManager:
    • Gestiona el contexto e historial de conversaciones
    • Prepara el contexto combinando datos de sesiones previas con nuevos mensajes
    • Maneja la interacción con la API de OpenAI
  3. Características Principales:
    • Procesamiento Asíncrono: Utiliza async/await para llamadas eficientes a la API
    • Gestión de Contexto: Mantiene el historial relevante de conversaciones
    • Manejo de Errores: Incluye gestión robusta de errores
    • Persistencia de Sesión: Guarda conversaciones en disco para recuperación posterior
  4. Detalles de Implementación:
    • Utiliza JSON para almacenamiento de sesiones
    • Limita el contexto a los últimos 5 mensajes por eficiencia
    • Incluye seguimiento de marca temporal para gestión de sesiones
    • Mantiene roles de conversación (sistema, usuario, asistente)

Este ejemplo proporciona una base robusta para gestionar conversaciones multi-sesión mientras mantiene el contexto e historial del usuario. Es particularmente útil para aplicaciones que requieren memoria persistente de conversación a través de múltiples interacciones.

Conocimiento Persistente

El sistema mantiene un registro robusto y completo de toda la información significativa intercambiada durante las conversaciones. Esta arquitectura de conocimiento persistente opera en múltiples niveles:

  1. Gestión de Información Básica: El sistema captura y almacena datos operativos esenciales de manera estructurada. Esto incluye el seguimiento integral de entradas del calendario como reuniones y citas, con metadatos como asistentes y agendas. Los cronogramas de proyectos se mantienen con un seguimiento detallado de hitos, dependencias y transiciones de fase.

El sistema registra todos los plazos sistemáticamente, desde fechas límite a nivel de tarea hasta entregables principales del proyecto. Las actualizaciones regulares se almacenan cronológicamente, incluyendo informes diarios, cambios de estado y modificaciones del proyecto. Esta robusta arquitectura de información garantiza que todos los datos relacionados con la programación y los proyectos permanezcan fácilmente recuperables, respaldando una gestión eficiente de proyectos y la coordinación del equipo.

  1. Datos Específicos del Usuario: El sistema mantiene perfiles detallados de usuarios individuales que abarcan múltiples aspectos de sus interacciones:
    • Preferencias Personales: Incluyendo canales de comunicación preferidos, formatos de respuesta y áreas específicas de interés
    • Estilos de Comunicación: Seguimiento de si los usuarios prefieren lenguaje formal o casual, explicaciones técnicas o simplificadas, y sus preferencias típicas en la extensión de respuestas
    • Experiencia Técnica: Monitoreo y adaptación a los niveles demostrados de conocimiento de los usuarios en diferentes temas y ajuste de explicaciones en consecuencia
    • Patrones Históricos: Registro de tiempos de interacción, temas frecuentemente discutidos y preguntas o preocupaciones comunes
    • Patrones de Lenguaje: Anotación del uso de vocabulario, familiaridad con terminología técnica y ejemplos o analogías preferidas
    • Progreso de Aprendizaje: Seguimiento de cómo evoluciona la comprensión de los usuarios sobre varios temas a lo largo del tiempo

Este perfil integral del usuario permite que el sistema entregue respuestas cada vez más personalizadas que coincidan con las necesidades y preferencias únicas de cada usuario, creando una experiencia de interacción más efectiva y atractiva con el tiempo.

  1. Registro de Decisiones: Las decisiones críticas se documentan sistemáticamente de manera integral que incluye múltiples componentes clave:
    • Contexto: La situación completa de fondo, entorno empresarial y restricciones que enmarcaron la decisión
    • Fundamento: Razonamiento detallado detrás de la elección, incluyendo:
      • Análisis de alternativas consideradas
      • Evaluación y estrategias de mitigación de riesgos
      • Resultados esperados y métricas de éxito
    • Partes Interesadas: Documentación completa de:
      • Tomadores de decisiones y sus roles
      • Equipos y departamentos afectados
      • Partes externas involucradas
    • Plan de Implementación:
      • Estrategia de ejecución paso a paso
      • Detalles de asignación de recursos
      • Cronograma e hitos

Este proceso sistemático de documentación crea un rastro detallado y auditable que permite a los equipos:

  • Seguir la evolución de decisiones importantes
  • Comprender el contexto completo de elecciones pasadas
  • Aprender de experiencias previas
  • Tomar decisiones más informadas en el futuro
  • Mantener la responsabilidad y transparencia
  1. Gestión de Tareas: El sistema implementa un sistema integral de seguimiento de tareas que monitorea varios aspectos de la ejecución del proyecto:
    • Seguimiento de Asignaciones: Cada tarea está vinculada a miembros específicos del equipo o departamentos responsables de su finalización, asegurando una clara propiedad y responsabilidad
    • Gestión de Cronogramas: Se mantienen fechas límite detalladas, incluyendo tanto plazos finales como hitos intermedios, permitiendo una mejor gestión del tiempo
    • Monitoreo de Progreso: Se registran actualizaciones regulares de estado para seguir la progresión de tareas, incluyendo trabajo completado, obstáculos actuales y pasos restantes
    • Mapeo de Dependencias: El sistema mantiene un mapa claro de dependencias entre tareas, ayudando a los equipos a entender cómo los retrasos o cambios en una tarea podrían impactar a otras
    • Asignación de Recursos: Rastrea la distribución de trabajo y recursos entre los miembros del equipo para prevenir la sobrecarga y asegurar una ejecución eficiente del proyecto
  2. Detalles del Proyecto: El sistema mantiene documentación integral de aspectos técnicos incluyendo:
    • Especificaciones Técnicas:
      • Planos detallados de arquitectura del sistema
      • Documentación completa de API y puntos finales
      • Esquemas de base de datos y modelos de datos
      • Especificaciones de integración con terceros
    • Requisitos del Proyecto:
      • Requisitos y objetivos de negocio
      • Requisitos técnicos y restricciones
      • Historias de usuario y criterios de aceptación
      • Definiciones y límites de alcance
    • Desafíos y Soluciones:
      • Obstáculos técnicos identificados
      • Soluciones alternativas implementadas
      • Esfuerzos de optimización de rendimiento
      • Medidas y actualizaciones de seguridad
    • Registros de Implementación:
      • Documentación y ejemplos de código
      • Registros de decisiones de arquitectura
      • Estrategias y resultados de pruebas
      • Procedimientos de implementación

Esta base de conocimiento persistente integral sirve múltiples propósitos: previene la pérdida de información, permite referencias históricas precisas, apoya la toma de decisiones informada y permite la continuación fluida de discusiones complejas a través de múltiples sesiones. El sistema puede fácilmente recordar y contextualizar información de interacciones pasadas, haciendo cada conversación más eficiente y productiva.

Aquí hay una implementación integral del Conocimiento Persistente usando la API de OpenAI:

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

class PersistentKnowledge:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        self.encoding = tiktoken.encoding_for_model("gpt-4o")
        
    def count_tokens(self, text: str) -> int:
        """Count tokens in text using tiktoken"""
        return len(self.encoding.encode(text))
        
    def save_knowledge(self, user_id: str, category: str, data: Dict):
        """Save knowledge to persistent storage with categories"""
        filename = f"knowledge_{user_id}_{category}.json"
        timestamp = datetime.now().isoformat()
        
        data_with_metadata = {
            "timestamp": timestamp,
            "category": category,
            "content": data
        }
        
        try:
            with open(filename, "r") as f:
                existing_data = json.load(f)
        except FileNotFoundError:
            existing_data = []
            
        existing_data.append(data_with_metadata)
        
        with open(filename, "w") as f:
            json.dump(existing_data, f, indent=2)
            
    def retrieve_knowledge(self, user_id: str, category: str, 
                         max_tokens: int = 2000) -> List[Dict]:
        """Retrieve knowledge with token limit"""
        filename = f"knowledge_{user_id}_{category}.json"
        try:
            with open(filename, "r") as f:
                all_data = json.load(f)
        except FileNotFoundError:
            return []
            
        # Retrieve most recent entries within token limit
        retrieved_data = []
        current_tokens = 0
        
        for entry in reversed(all_data):
            content_str = json.dumps(entry["content"])
            tokens = self.count_tokens(content_str)
            
            if current_tokens + tokens <= max_tokens:
                retrieved_data.append(entry)
                current_tokens += tokens
            else:
                break
                
        return list(reversed(retrieved_data))
        
    async def get_ai_response(self, 
                            user_id: str,
                            current_input: str,
                            categories: List[str] = None) -> str:
        """Generate AI response with context from persistent knowledge"""
        
        # Build context from stored knowledge
        context = []
        if categories:
            for category in categories:
                knowledge = self.retrieve_knowledge(user_id, category)
                if knowledge:
                    context.append(f"\nRelevant {category} knowledge:")
                    for entry in knowledge:
                        context.append(json.dumps(entry["content"]))
                        
        # Prepare messages for API
        messages = [
            {
                "role": "system",
                "content": "You are an assistant with access to persistent knowledge. "
                          "Use this context to provide informed responses."
            },
            {
                "role": "user",
                "content": f"Context:\n{''.join(context)}\n\nCurrent query: {current_input}"
            }
        ]
        
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4",
                messages=messages,
                temperature=0.7,
                max_tokens=500
            )
            return response.choices[0].message.content
        except Exception as e:
            return f"Error generating response: {str(e)}"
            
class KnowledgeManager:
    def __init__(self, api_key: str):
        self.knowledge = PersistentKnowledge(api_key)
        
    async def process_interaction(self, 
                                user_id: str,
                                message: str,
                                categories: List[str] = None) -> str:
        """Process user interaction and maintain knowledge"""
        
        # Save user input
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "user", "message": message}
        )
        
        # Get AI response with context
        response = await self.knowledge.get_ai_response(
            user_id,
            message,
            categories
        )
        
        # Save AI response
        self.knowledge.save_knowledge(
            user_id,
            "conversations",
            {"role": "assistant", "message": response}
        )
        
        return response

# Example usage
async def main():
    manager = KnowledgeManager("your-api-key")
    
    # First interaction
    response1 = await manager.process_interaction(
        "user123",
        "What's the best way to learn Python?",
        ["conversations", "preferences"]
    )
    print("Response 1:", response1)
    
    # Save user preference
    manager.knowledge.save_knowledge(
        "user123",
        "preferences",
        {"learning_style": "hands-on", "preferred_language": "Python"}
    )
    
    # Later interaction using stored knowledge
    response2 = await manager.process_interaction(
        "user123",
        "Can you suggest some projects based on my learning style?",
        ["conversations", "preferences"]
    )
    print("Response 2:", response2)

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

Desglose del Código:

  1. Clase PersistentKnowledge:
    • Maneja el conteo de tokens usando tiktoken para la gestión del contexto
    • Implementa save_knowledge() para almacenar información categorizada
    • Proporciona retrieve_knowledge() con límites de tokens para la recuperación de contexto
    • Gestiona las interacciones de IA a través de get_ai_response()
  2. Clase KnowledgeManager:
    • Proporciona una interfaz de alto nivel para la gestión del conocimiento
    • Procesa las interacciones del usuario y mantiene el historial de conversaciones
    • Maneja el guardado tanto de las entradas del usuario como las respuestas de la IA
  3. Características Principales:
    • Almacenamiento Categorizado de Conocimiento: Organiza la información por usuario y categoría
    • Gestión de Tokens: Asegura que el contexto se mantenga dentro de los límites del modelo
    • Seguimiento de Metadatos: Incluye marcas de tiempo y categorías para todos los datos almacenados
    • Manejo de Errores: Gestión robusta de errores para operaciones de archivo y llamadas a la API
  4. Beneficios de la Implementación:
    • Escalable: Maneja múltiples usuarios y categorías de conocimiento
    • Eficiente: Utiliza conteo de tokens para optimizar el uso del contexto
    • Flexible: Admite varios tipos y categorías de conocimiento
    • Mantenible: Código bien estructurado con clara separación de responsabilidades

Esta implementación proporciona una base sólida para aplicaciones de IA que requieren conocimiento persistente a través de conversaciones. Sobresale en mantener las preferencias del usuario, historiales de conversación y otros datos continuos mientras gestiona eficientemente los límites de tokens.

Resumen de Conversaciones

Al mantener historiales detallados de conversaciones, el sistema puede generar resúmenes completos que capturan puntos clave, decisiones y elementos de acción. Estos resúmenes cumplen múltiples funciones críticas:

  1. Actualización de Contexto: Cuando los participantes comienzan nuevas sesiones de conversación, el sistema proporciona resúmenes concisos pero completos de discusiones previas. Estos resúmenes sirven como informes eficientes que:
    • Orientan rápidamente a los participantes sobre puntos clave de discusión
    • Destacan decisiones y resultados importantes
    • Identifican elementos de acción en curso
    • Refrescan la memoria sobre el contexto crítico
      Esto elimina el proceso que consume tiempo de revisar registros extensos de conversación y asegura que todos los participantes puedan involucrarse inmediatamente de manera productiva en la discusión actual con plena conciencia del contexto.
  2. Seguimiento del Progreso: Los resúmenes regulares sirven como un mecanismo integral de seguimiento para discusiones y proyectos en curso. Al mantener registros detallados de la evolución del proyecto, los equipos pueden:
    • Monitorear Fases de Desarrollo
      • Seguir la progresión desde conceptos iniciales hasta implementación
      • Documentar mejoras y refinamientos iterativos
      • Registrar puntos de inflexión clave en la dirección del proyecto
    • Analizar Historial de Decisiones
      • Capturar el contexto detrás de elecciones importantes
      • Documentar opciones alternativas consideradas
      • Seguir resultados de decisiones implementadas
    • Identificar Tendencias del Proyecto
      • Detectar desafíos o cuellos de botella recurrentes
      • Reconocer patrones exitosos para replicar
      • Monitorear velocidad y momentum
    • Facilitar Alineación del Equipo
      • Mantener entendimiento compartido del progreso
      • Permitir correcciones basadas en datos
      • Apoyar la asignación informada de recursos
  3. Extracción de Conocimiento: El sistema emplea técnicas avanzadas de análisis para identificar y extraer información crítica de las conversaciones, incluyendo:
    • Decisiones clave y su fundamento
      • Elecciones estratégicas realizadas durante las discusiones
      • Evidencia de respaldo y justificación
      • Opciones alternativas consideradas
    • Elementos de acción y sus responsables
      • Tareas específicas asignadas a miembros del equipo
      • Asignaciones claras de responsabilidad
      • Requisitos de seguimiento
    • Fechas límite y hitos importantes
      • Marcadores de línea temporal del proyecto
      • Fechas críticas de entrega
      • Programas de revisión y puntos de control
    • Preguntas o preocupaciones sin resolver
      • Problemas técnicos abiertos
      • Decisiones pendientes
      • Áreas que necesitan clarificación
    • Acuerdos y compromisos establecidos
      • Decisiones formales alcanzadas
      • Acuerdos de asignación de recursos
      • Compromisos de cronograma
  4. Generación de Informes: Los resúmenes pueden compilarse automáticamente en varios tipos de informes:
    • Informes ejecutivos
      • Visiones generales de alto nivel para interesados
      • Decisiones clave e implicaciones estratégicas
      • Resúmenes de asignación de recursos
    • Actas de reunión
      • Puntos detallados de discusión y resultados
      • Elementos de acción y asignados
      • Compromisos de cronograma establecidos
    • Actualizaciones de progreso
      • Logros de hitos y retrasos
      • Bloqueadores y desafíos actuales
      • Próximos pasos y prioridades
    • Informes de estado del proyecto
      • Indicadores generales de salud del proyecto
      • Métricas de utilización de recursos
      • Evaluaciones de riesgo y estrategias de mitigación

La capacidad de condensar y recordar información relevante no solo hace las conversaciones más eficientes y enfocadas, sino que también asegura que la información crítica nunca se pierda y pueda ser fácilmente accedida cuando sea necesario. Este enfoque sistemático para el resumen de conversaciones ayuda a mantener la claridad y continuidad a través de interacciones a largo plazo, especialmente en proyectos complejos o discusiones continuas que involucran múltiples participantes.

Ejemplo: Implementación de Resumen de Conversaciones

Aquí hay una implementación práctica de un resumidor de conversaciones usando la API de OpenAI:

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

class ConversationSummarizer:
    def __init__(self, api_key: str):
        self.api_key = api_key
        openai.api_key = api_key
        
    def create_summary_prompt(self, messages: List[Dict]) -> str:
        """Create a prompt for summarization from messages"""
        conversation = "\n".join([
            f"{msg['role'].title()}: {msg['content']}" 
            for msg in messages
        ])
        
        return f"""Please provide a concise summary of the following conversation, 
        highlighting key points, decisions, and action items:

        {conversation}
        
        Summary should include:
        1. Main topics discussed
        2. Key decisions made
        3. Action items and owners
        4. Unresolved questions
        """

    async def generate_summary(self, messages: List[Dict]) -> Dict:
        """Generate a structured summary of the conversation"""
        try:
            response = await openai.ChatCompletion.acreate(
                model="gpt-4o",
                messages=[{
                    "role": "user",
                    "content": self.create_summary_prompt(messages)
                }],
                temperature=0.7,
                max_tokens=500
            )
            
            summary = response.choices[0].message.content
            
            return {
                "timestamp": datetime.now().isoformat(),
                "message_count": len(messages),
                "summary": summary
            }
            
        except Exception as e:
            return {
                "error": f"Failed to generate summary: {str(e)}",
                "timestamp": datetime.now().isoformat()
            }

    def save_summary(self, summary: Dict, filename: str = "summaries.json"):
        """Save summary to JSON file"""
        try:
            with open(filename, "r") as f:
                summaries = json.load(f)
        except FileNotFoundError:
            summaries = []
            
        summaries.append(summary)
        
        with open(filename, "w") as f:
            json.dump(summaries, f, indent=2)

# Example usage
async def main():
    summarizer = ConversationSummarizer("your-api-key")
    
    # Sample conversation
    messages = [
        {"role": "user", "content": "Let's discuss the new feature implementation."},
        {"role": "assistant", "content": "Sure! What specific aspects would you like to focus on?"},
        {"role": "user", "content": "We need to implement user authentication by next week."},
        {"role": "assistant", "content": "I understand. Let's break down the requirements and timeline."}
    ]
    
    # Generate and save summary
    summary = await summarizer.generate_summary(messages)
    summarizer.save_summary(summary)
    print("Summary:", summary["summary"])

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

Desglose del Código:

  1. Estructura de Clase:
    • La clase ConversationSummarizer maneja todas las operaciones de resumen
    • Inicialización con configuración de clave API
    • Métodos para creación de prompts, generación de resúmenes y almacenamiento
  2. Características Principales:
    • Generación estructurada de prompts para resúmenes consistentes
    • Llamadas API asíncronas para mejor rendimiento
    • Manejo y registro de errores
    • Almacenamiento persistente de resúmenes
  3. Beneficios de Implementación:
    • Escalable: Maneja conversaciones de diferentes longitudes
    • Salida Estructurada: Resúmenes organizados con información clave
    • Seguimiento Histórico: Mantiene historial de resúmenes
    • Resistente a Errores: Manejo y registro de errores robusto

Este ejemplo proporciona una forma confiable de generar y mantener resúmenes de conversaciones, facilitando el seguimiento del progreso de las discusiones y decisiones clave a lo largo del tiempo.

7.3.2 Arquitectura Central

Para crear un sistema de memoria efectivo para interacciones de IA, tres componentes esenciales trabajan juntos de manera coordinada para mantener el contexto y asegurar la continuidad conversacional. Estos componentes forman una arquitectura sofisticada que permite a los sistemas de IA acceder, procesar y utilizar información histórica de manera efectiva durante las conversaciones en curso.

El componente de almacenamiento preserva el historial de conversación, el mecanismo de recuperación obtiene de manera inteligente las interacciones pasadas relevantes, y el sistema de inyección incorpora perfectamente este contexto histórico en las conversaciones actuales.

Juntos, estos tres pilares crean una base robusta que permite a los sistemas de IA mantener diálogos significativos y conscientes del contexto a través de múltiples interacciones:

Almacenamiento

La base de la gestión de memoria donde todas las interacciones se guardan y preservan sistemáticamente para uso futuro. Este componente crítico sirve como columna vertebral de cualquier sistema de conversación de IA:

  • Puede utilizar varias soluciones de almacenamiento como archivos JSON, bases de datos SQL o almacenamiento en la nube
    • Los archivos JSON ofrecen simplicidad y portabilidad para aplicaciones más pequeñas
    • Las bases de datos SQL proporcionan consultas robustas e indexación para conjuntos de datos más grandes
    • El almacenamiento en la nube permite acceso escalable y distribuido a través de múltiples servicios
  • Debe incluir metadatos como marcas de tiempo e identificadores de usuario
    • Las marcas de tiempo permiten seguimiento cronológico y filtrado basado en tiempo
    • Los IDs de usuario mantienen hilos de conversación y personalización
    • Metadatos adicionales pueden rastrear temas y contextos de conversación
  • Debe estar organizado para recuperación y escalado eficientes
    • Implementar indexación adecuada para acceso rápido a datos relevantes
    • Usar particionamiento de datos para mejor rendimiento
    • Considerar estrategias de compresión para almacenamiento a largo plazo

Recuperación

El sistema inteligente para acceder y filtrar conversaciones pasadas relevantes sirve como un componente crucial en la gestión del historial de conversaciones:

  • Implementa algoritmos de búsqueda para encontrar datos históricos apropiados al contexto
    • Utiliza búsqueda semántica para coincidir temas y temáticas similares
    • Emplea coincidencia difusa para comparación flexible de texto
    • Indexa conversaciones para recuperación rápida
  • Utiliza parámetros como recencia, relevancia e hilo de conversación
    • Prioriza interacciones recientes para contexto inmediato
    • Pondera relevancia basada en puntajes de similitud de temas
    • Mantiene continuidad de hilos rastreando flujos de conversación
  • Gestiona límites de tokens seleccionando el contexto más importante
    • Implementa estrategias inteligentes de truncamiento
    • Prioriza información clave mientras elimina contenido redundante
    • Ajusta dinámicamente ventana de contexto según limitaciones del modelo

Inyección

El proceso de incorporar perfectamente el contexto histórico requiere un manejo cuidadoso para mantener la coherencia de la conversación:

  • Coloca estratégicamente mensajes recuperados en el flujo actual de conversación
    • Determina puntos óptimos de inserción para contexto histórico
    • Filtra y prioriza información histórica relevante
    • Equilibra contenido nuevo e histórico para un flujo natural
  • Mantiene orden apropiado de mensajes y relaciones
    • Preserva secuencia cronológica de interacciones
    • Respeta hilos de conversación y cadenas de respuestas
    • Enlaza temas y discusiones relacionadas apropiadamente
  • Asegura integración fluida del contexto sin interrumpir la conversación
    • Evita cambios abruptos de contexto o sobrecarga de información
    • Utiliza frases de transición y referencias naturales
    • Mantiene tono y estilo de conversación consistentes

7.3.3 Cómo Almacenar y Recuperar Historiales de Mensajes Basados en JSON en Python

En esta sección, exploraremos una implementación práctica que demuestra cómo crear un sistema de memoria persistente usando archivos JSON. Este enfoque ofrece una manera directa de mantener el contexto de conversación a través de múltiples sesiones mientras se mantiene escalable y fácil de mantener.

Nuestra implementación se centrará en tres aspectos clave: almacenar eficientemente historiales de mensajes en formato JSON, recuperar contexto de conversación relevante cuando sea necesario, y gestionar la estructura de datos para asegurar un rendimiento óptimo. Esta solución es particularmente útil para desarrolladores que construyen chatbots, asistentes virtuales o cualquier aplicación que requiera historial de conversación persistente.

Paso 1: Construir el Gestor de Memoria

Este módulo maneja el almacenamiento de interacciones de usuario en formato JSON y recupera solo las relevantes.

import os
import json
from typing import List, Dict

MEMORY_DIR = "user_memory"
os.makedirs(MEMORY_DIR, exist_ok=True)

# Constants
MAX_HISTORY_MESSAGES = 5  # Truncate history to last 5 messages to manage tokens

def get_memory_path(user_id: str) -> str:
    return os.path.join(MEMORY_DIR, f"{user_id}.json")

def load_history(user_id: str) -> List[Dict[str, str]]:
    path = get_memory_path(user_id)
    if not os.path.exists(path):
        return []
    try:
        with open(path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        return []

def store_interaction(user_id: str, role: str, content: str) -> None:
    message = {"role": role, "content": content}
    path = get_memory_path(user_id)

    history = load_history(user_id)
    history.append(message)

    with open(path, "w", encoding="utf-8") as f:
        json.dump(history, f, indent=2)

def get_recent_history(user_id: str, limit: int = MAX_HISTORY_MESSAGES) -> List[Dict[str, str]]:
    history = load_history(user_id)
    return history[-limit:]

Analicemos este código:

  1. Configuración Inicial
  • Crea un directorio "user_memory" para almacenar los historiales de conversación
  • Establece un límite máximo de 5 mensajes para la gestión del historial
  1. Funciones Principales
  • get_memory_path(user_id): Crea una ruta de archivo JSON única para cada usuario
  • load_history(user_id):
    • Intenta leer el historial de conversación del usuario
    • Devuelve una lista vacía si el archivo no existe o está corrupto
  • store_interaction(user_id, role, content):
    • Guarda nuevos mensajes en el archivo de historial del usuario
    • Añade el mensaje al historial existente
    • Almacena en formato JSON con sangría apropiada
  • get_recent_history(user_id, limit):
    • Recupera los mensajes más recientes
    • Respeta el límite MAX_HISTORY_MESSAGES (5 mensajes)
  1. Características Principales
  • Almacenamiento persistente: Las conversaciones de cada usuario se guardan en archivos JSON separados
  • Escalabilidad: El sistema puede manejar múltiples usuarios con archivos individuales
  • Contexto controlado: Permite control específico sobre cuánto historial mantener
  • Fácil de depurar: El formato JSON facilita la inspección de conversaciones almacenadas

Paso 2: Crear el Motor de Chat Usando la API de OpenAI

Ahora integremos este sistema de memoria con la API de OpenAI. Cargaremos los mensajes anteriores, añadiremos el nuevo prompt, consultaremos el modelo y guardaremos la respuesta.

import openai
from dotenv import load_dotenv

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

SYSTEM_PROMPT = {
    "role": "system",
    "content": "You are a helpful assistant that remembers the user's previous messages."
}

def continue_conversation(user_id: str, user_input: str) -> str:
    # Validate input
    if not user_input.strip():
        return "Input cannot be empty."

    # Load memory and prepare messages
    recent_history = get_recent_history(user_id)
    messages = [SYSTEM_PROMPT] + recent_history + [{"role": "user", "content": user_input}]

    # Call OpenAI API
    try:
        response = openai.ChatCompletion.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=300,
            temperature=0.7
        )
        assistant_reply = response["choices"][0]["message"]["content"]

        # Store both messages
        store_interaction(user_id, "user", user_input)
        store_interaction(user_id, "assistant", assistant_reply)

        return assistant_reply

    except Exception as e:
        return f"Something went wrong: {e}"

Analicemos este código:

1. Configuración Inicial

  • Importa las bibliotecas necesarias (openai y dotenv)
  • Carga las variables de entorno y configura la clave API de OpenAI
  • Define un prompt de sistema que establece el rol del asistente

2. Función Principal: continue_conversation

  • Recibe user_id y user_input como parámetros
  • Validación de entrada para verificar mensajes vacíos
  • Carga el historial de conversación usando get_recent_history (definido en la sección anterior)
  • Construye el array de mensajes combinando: 
    • Prompt del sistema
    • Historial reciente de conversación
    • Entrada actual del usuario

3. Interacción con la API

  • Realiza la llamada a la API de OpenAI con parámetros: 
    • Utiliza el modelo "gpt-4o"
    • Establece max_tokens en 300
    • Usa una temperatura de 0.7 para una creatividad equilibrada
  • Extrae la respuesta del asistente de la respuesta

4. Gestión de Memoria

  • Almacena tanto la entrada del usuario como la respuesta del asistente usando store_interaction
  • Maneja los errores adecuadamente con un bloque try-except

Esta parte crea un sistema de conversación con estado que mantiene el contexto a través de múltiples interacciones mientras gestiona el flujo de conversación de manera eficiente.

Paso 3: Probar la Memoria de Conversación

if __name__ == "__main__":
    user_id = "user_456"

    print("User: What are the best Python libraries for data science?")
    reply1 = continue_conversation(user_id, "What are the best Python libraries for data science?")
    print("Assistant:", reply1)

    print("\nUser: Could you remind me which ones you mentioned?")
    reply2 = continue_conversation(user_id, "Could you remind me which ones you mentioned?")
    print("Assistant:", reply2)

Analicemos este ejemplo de código para probar la memoria de conversación:

1. Verificación del Punto de Entrada

  • El código utiliza el modismo estándar de Python if __name__ == "__main__": para asegurar que este código solo se ejecute cuando el archivo se ejecuta directamente

2. Configuración del Usuario

  • Crea un usuario de prueba con ID "user_456"

3. Flujo de Conversación de Prueba

  • Demuestra una conversación de dos turnos donde:
  • Primer turno: Pregunta sobre las bibliotecas de Python para ciencia de datos
  • Segundo turno: Pide un recordatorio de las bibliotecas mencionadas anteriormente, probando el sistema de memoria

4. Detalles de Implementación

  • Cada interacción utiliza la función continue_conversation() para:
  • Procesar la entrada del usuario
  • Generar y almacenar la respuesta
  • Imprimir tanto la entrada del usuario como la respuesta del asistente

Este código de prueba demuestra efectivamente cómo el sistema mantiene el contexto entre múltiples interacciones, permitiendo que el asistente haga referencia a respuestas anteriores al contestar preguntas de seguimiento.

Beneficios de Este Enfoque

  • Persistente: Todas las conversaciones se almacenan localmente por usuario, asegurando que no se pierda ningún historial de interacción. Esto significa que su aplicación puede mantener el contexto a través de múltiples sesiones, incluso si el servidor se reinicia o la aplicación se cierra.
  • Escalable (hasta cierto punto): Al almacenar el historial de conversación de cada usuario en su propio archivo JSON, el sistema puede manejar múltiples usuarios de manera eficiente. Este enfoque funciona bien para aplicaciones pequeñas y medianas, aunque para implementaciones muy grandes podría ser conveniente considerar una solución de base de datos.
  • Contexto controlable: El sistema le da control completo sobre cuánto historial de conversación incluir en cada interacción. Puede ajustar el tamaño de la ventana de memoria, filtrar por relevancia o implementar lógica personalizada para seleccionar qué mensajes anteriores incluir en el contexto.
  • Legible: El formato de archivo JSON facilita la inspección, depuración y modificación de las conversaciones almacenadas. Esto es invaluable durante el desarrollo y mantenimiento, ya que puede ver fácilmente el historial de conversación en cualquier editor de texto y validar la estructura de datos.

Mejoras Opcionales

  • Resumen: En lugar de almacenar cada mensaje textualmente, implementar resúmenes periódicos del historial de conversación. Esta técnica implica generar automáticamente resúmenes concisos de segmentos más largos de conversación, lo que ayuda a:
  • Reducir el uso de tokens en llamadas a la API
  • Mantener el contexto esencial mientras se eliminan detalles redundantes
  • Crear una estructura de memoria más eficiente

Por ejemplo, múltiples mensajes sobre un tema específico podrían condensarse en una única declaración resumida.

  • Búsqueda Vectorial (Avanzado): Transformar mensajes en vectores numéricos utilizando modelos de embedding, permitiendo una recuperación sofisticada basada en significado semántico. Este enfoque ofrece varias ventajas:
  • Descubrir mensajes históricos contextualmente relevantes incluso si utilizan palabras diferentes
  • Priorizar mensajes basados en su relevancia para la conversación actual
  • Permitir búsquedas rápidas de similitud a través de grandes historiales de conversación

Esto es particularmente útil para conversaciones de larga duración o cuando se necesita recordar contexto específico.

  • Gestión de Tokens: Implementar estrategias inteligentes de gestión de tokens para optimizar el uso de la ventana de contexto. Esto incluye:
  • Establecer límites dinámicos basados en la importancia de la conversación
  • Implementar poda inteligente de mensajes más antiguos y menos relevantes
  • Mantener un equilibrio entre el contexto reciente y la información histórica importante

Esto asegura que se mantenga dentro de los límites de tokens de la API mientras se preserva el contexto de conversación más valioso.

  • Mantener el prompt del sistema consistente a través de las interacciones
  • Mantener la redacción e instrucciones del prompt idénticas durante todo el ciclo de vida de la conversación
  • Usar control de versiones para rastrear cualquier cambio en el prompt del sistema a través de las implementaciones
  • Previene confusión y respuestas contradictorias manteniendo un contexto consistente
  • Asegura que la IA mantenga una personalidad y patrón de comportamiento confiable a través de las interacciones
  • No sobrecargue el contexto—almacene todo, pero recupere selectivamente
  • Implementar un sistema de almacenamiento integral que mantenga historiales completos de conversación en su base de datos
  • Desarrollar algoritmos de recuperación inteligentes que prioricen el contexto relevante para las llamadas a la API
  • Usar búsqueda semántica o similitud basada en embeddings para encontrar mensajes históricos pertinentes
  • Equilibrar el uso de tokens implementando estrategias inteligentes de poda para mensajes más antiguos
  • Etiquetar los mensajes almacenados claramente (rolecontenttimestamp) para filtrado o resumen futuro
  • Role: Identificar y etiquetar cuidadosamente las fuentes de los mensajes (sistema, usuario o asistente) para mantener un flujo de conversación claro y permitir el filtrado basado en roles
  • Content: Implementar estándares de formato consistentes para el contenido de los mensajes, incluyendo el manejo de caracteres especiales y manteniendo la integridad de los datos
  • Timestamp: Agregar metadatos temporales precisos para permitir operaciones sofisticadas basadas en tiempo como segmentación de conversación y puntuación de relevancia contextual

La memoria a largo plazo no es nativa de los modelos de chat de OpenAI (todavía), pero con una ingeniería cuidadosa, puede crear sistemas de memoria sofisticados. Esta limitación significa que por defecto, el modelo trata cada interacción como aislada, sin conocimiento de conversaciones anteriores. Sin embargo, los desarrolladores pueden implementar soluciones personalizadas para superar esta limitación.

Aquí hay una explicación detallada de cómo funciona: Mientras que el modelo en sí no mantiene memorias entre conversaciones, su aplicación actúa como un gestor de memoria. Almacena cada interacción en un formato estructurado, típicamente usando bases de datos o sistemas de archivos. Estos datos almacenados incluyen no solo el contenido de la conversación, sino también metadatos como marcas de tiempo, información del usuario y temas de conversación. Al gestionar cuidadosamente estas conversaciones almacenadas y recuperar selectivamente piezas relevantes, crea una ilusión de memoria continua - haciendo que la IA parezca "recordar" interacciones anteriores.

Este sistema de memoria transforma tu asistente de IA de varias formas poderosas:

  • Continuidad: El asistente puede hacer referencia a conversaciones pasadas y mantener el contexto durante períodos prolongados, creando interacciones fluidas que se construyen sobre discusiones previas. Por ejemplo, si un usuario menciona su preferencia por la programación en Python en una conversación, el sistema puede hacer referencia a esto en interacciones futuras.
  • Personalidad: Los patrones de respuesta consistentes y las preferencias recordadas crean una personalidad más distintiva. Esto incluye mantener un tono consistente, recordar las preferencias del usuario y adaptar los estilos de comunicación basados en interacciones anteriores.
  • Comprensión: Al acceder al contexto histórico, las respuestas se vuelven más informadas y personalizadas. El sistema puede recordar detalles específicos de conversaciones anteriores, haciendo que las interacciones se sientan más naturales y contextualmente conscientes.
  • Profundidad: La capacidad de construir sobre conversaciones previas permite interacciones más sofisticadas, posibilitando la resolución de problemas complejos y el soporte de proyectos a largo plazo.

Este enfoque escala notablemente bien a través de diferentes escenarios de uso, desde usuarios individuales hasta aplicaciones a nivel empresarial. Ya sea que estés construyendo un asistente personal para un único usuario o un sistema que sirva a miles, el principio fundamental sigue siendo el mismo: estás creando una capa de memoria inteligente que se sitúa entre el usuario y la API. Este enfoque arquitectónico proporciona varias capacidades clave:

  • Crecer: Acumular continuamente nuevas interacciones y aprendizajes, construyendo un rico historial de interacciones y preferencias del usuario a lo largo del tiempo. Esta base de conocimiento creciente se vuelve cada vez más valiosa para personalizar respuestas.
  • Resumir: Condensar historiales de conversación extensos en contextos manejables, utilizando técnicas avanzadas como agrupamiento semántico y puntuación de importancia para mantener la información más relevante.
  • Adaptar: Ajustar sus estrategias de recuperación basándose en patrones de conversación, aprendiendo qué tipos de contexto histórico son más valiosos para diferentes tipos de interacciones.

Todo esto mientras se aprovecha la misma API subyacente de OpenAI para el procesamiento del lenguaje. Esta combinación de gestión estructurada de memoria y procesamiento potente del lenguaje crea un sistema que puede mantener el contexto y la personalidad a través de múltiples conversaciones mientras se mantiene dentro de las restricciones técnicas de la API.