|
|
""" |
|
|
Contextual Personalization & User Profiling System |
|
|
=============================================== |
|
|
|
|
|
Advanced user profiling system that builds user-specific contextual profiles, |
|
|
continuously updates them based on interactions, and enables behavioral adaptation. |
|
|
""" |
|
|
|
|
|
import asyncio |
|
|
import json |
|
|
import logging |
|
|
from datetime import datetime, timedelta |
|
|
from typing import Dict, List, Any, Optional, Set, Tuple, Union |
|
|
from dataclasses import dataclass, field, asdict |
|
|
from enum import Enum |
|
|
import numpy as np |
|
|
from collections import defaultdict, deque |
|
|
import hashlib |
|
|
from sklearn.metrics.pairwise import cosine_similarity |
|
|
from sklearn.cluster import DBSCAN |
|
|
from sklearn.decomposition import PCA |
|
|
|
|
|
from ai_agent_framework.core.context_engineering_agent import ( |
|
|
ContextElement, ContextModality, ContextDimension, ContextEngineeringAgent |
|
|
) |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
class ProfileType(Enum): |
|
|
"""Types of user profiles.""" |
|
|
BEHAVIORAL = "behavioral" |
|
|
PREFERENTIAL = "preferential" |
|
|
CONTEXTUAL = "contextual" |
|
|
INTERACTION = "interaction" |
|
|
LEARNING = "learning" |
|
|
COLLABORATIVE = "collaborative" |
|
|
TEMPORAL = "temporal" |
|
|
|
|
|
|
|
|
class LearningType(Enum): |
|
|
"""Types of learning patterns.""" |
|
|
GRADUAL = "gradual" |
|
|
RAPID = "rapid" |
|
|
CYCLICAL = "cyclical" |
|
|
EVENT_DRIVEN = "event_driven" |
|
|
ADAPTIVE = "adaptive" |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class UserInteraction: |
|
|
"""Represents a user interaction with the system.""" |
|
|
interaction_id: str |
|
|
user_id: str |
|
|
interaction_type: str |
|
|
content: Dict[str, Any] |
|
|
context: Dict[str, Any] |
|
|
timestamp: datetime |
|
|
duration: float |
|
|
success: bool |
|
|
satisfaction_score: Optional[float] = None |
|
|
adaptation_needed: bool = False |
|
|
|
|
|
def __post_init__(self): |
|
|
if not self.interaction_id: |
|
|
self.interaction_id = f"interaction_{int(time.time())}_{hash(str(self.content))}" |
|
|
if not self.timestamp: |
|
|
self.timestamp = datetime.utcnow() |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class UserPreference: |
|
|
"""Represents a user preference.""" |
|
|
preference_id: str |
|
|
user_id: str |
|
|
category: str |
|
|
preference_type: str |
|
|
value: Any |
|
|
confidence: float |
|
|
stability: float |
|
|
last_updated: datetime |
|
|
evidence_count: int |
|
|
|
|
|
def __post_init__(self): |
|
|
if not self.preference_id: |
|
|
self.preference_id = f"pref_{self.user_id}_{self.category}_{hash(str(self.value))}" |
|
|
if not self.last_updated: |
|
|
self.last_updated = datetime.utcnow() |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class ContextualPattern: |
|
|
"""Represents a contextual usage pattern.""" |
|
|
pattern_id: str |
|
|
user_id: str |
|
|
pattern_type: str |
|
|
context_elements: Set[str] |
|
|
frequency: float |
|
|
success_rate: float |
|
|
last_observed: datetime |
|
|
confidence: float |
|
|
|
|
|
def __post_init__(self): |
|
|
if not self.pattern_id: |
|
|
self.pattern_id = f"pattern_{self.user_id}_{self.pattern_type}_{int(time.time())}" |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class UserProfile: |
|
|
"""Comprehensive user profile for contextual personalization.""" |
|
|
user_id: str |
|
|
profile_type: ProfileType |
|
|
data: Dict[str, Any] |
|
|
created_at: datetime |
|
|
updated_at: datetime |
|
|
version: int |
|
|
completeness_score: float |
|
|
confidence_score: float |
|
|
|
|
|
def __post_init__(self): |
|
|
if not self.created_at: |
|
|
self.created_at = datetime.utcnow() |
|
|
if not self.updated_at: |
|
|
self.updated_at = self.created_at |
|
|
if self.version == 0: |
|
|
self.version = 1 |
|
|
|
|
|
|
|
|
class ContextualPersonalizationEngine: |
|
|
"""Core engine for contextual personalization and user profiling.""" |
|
|
|
|
|
def __init__(self): |
|
|
self.user_profiles = {} |
|
|
self.interaction_history = {} |
|
|
self.preference_database = {} |
|
|
self.pattern_database = {} |
|
|
|
|
|
self.profile_weights = { |
|
|
ProfileType.BEHAVIORAL: 0.25, |
|
|
ProfileType.PREFERENTIAL: 0.20, |
|
|
ProfileType.CONTEXTUAL: 0.20, |
|
|
ProfileType.INTERACTION: 0.15, |
|
|
ProfileType.LEARNING: 0.10, |
|
|
ProfileType.COLLABORATIVE: 0.05, |
|
|
ProfileType.TEMPORAL: 0.05 |
|
|
} |
|
|
|
|
|
self.learning_algorithms = { |
|
|
"incremental": self._incremental_learning, |
|
|
"batch": self._batch_learning, |
|
|
"reinforcement": self._reinforcement_learning, |
|
|
"association": self._association_learning |
|
|
} |
|
|
|
|
|
self.adaptation_strategies = { |
|
|
"gradual": self._gradual_adaptation, |
|
|
"immediate": self._immediate_adaptation, |
|
|
"predictive": self._predictive_adaptation |
|
|
} |
|
|
|
|
|
async def process_user_interaction(self, interaction: UserInteraction) -> Dict[str, Any]: |
|
|
"""Process a new user interaction and update profiles.""" |
|
|
|
|
|
try: |
|
|
|
|
|
insights = await self._extract_interaction_insights(interaction) |
|
|
|
|
|
|
|
|
updated_profiles = await self._update_profiles_from_interaction(interaction, insights) |
|
|
|
|
|
|
|
|
new_patterns = await self._identify_contextual_patterns(interaction, insights) |
|
|
|
|
|
|
|
|
updated_preferences = await self._update_preferences(interaction, insights) |
|
|
|
|
|
|
|
|
adaptations = await self._generate_adaptation_recommendations( |
|
|
interaction, updated_profiles, insights |
|
|
) |
|
|
|
|
|
return { |
|
|
"interaction_id": interaction.interaction_id, |
|
|
"insights": insights, |
|
|
"updated_profiles": updated_profiles, |
|
|
"new_patterns": [asdict(pattern) for pattern in new_patterns], |
|
|
"updated_preferences": updated_preferences, |
|
|
"adaptation_recommendations": adaptations, |
|
|
"processing_success": True |
|
|
} |
|
|
|
|
|
except Exception as e: |
|
|
logger.error(f"Failed to process user interaction: {e}") |
|
|
return { |
|
|
"interaction_id": interaction.interaction_id, |
|
|
"error": str(e), |
|
|
"processing_success": False |
|
|
} |
|
|
|
|
|
async def build_user_profile( |
|
|
self, |
|
|
user_id: str, |
|
|
profile_type: ProfileType, |
|
|
include_interaction_history: bool = True |
|
|
) -> UserProfile: |
|
|
"""Build a comprehensive user profile.""" |
|
|
|
|
|
|
|
|
interaction_data = self.interaction_history.get(user_id, []) |
|
|
preference_data = self.preference_database.get(user_id, []) |
|
|
pattern_data = self.pattern_database.get(user_id, []) |
|
|
|
|
|
if not interaction_data and not preference_data: |
|
|
return await self._create_empty_profile(user_id, profile_type) |
|
|
|
|
|
|
|
|
if profile_type == ProfileType.BEHAVIORAL: |
|
|
return await self._build_behavioral_profile(user_id, interaction_data, preference_data) |
|
|
elif profile_type == ProfileType.PREFERENTIAL: |
|
|
return await self._build_preferential_profile(user_id, preference_data, interaction_data) |
|
|
elif profile_type == ProfileType.CONTEXTUAL: |
|
|
return await self._build_contextual_profile(user_id, interaction_data, pattern_data) |
|
|
elif profile_type == ProfileType.INTERACTION: |
|
|
return await self._build_interaction_profile(user_id, interaction_data) |
|
|
elif profile_type == ProfileType.LEARNING: |
|
|
return await self._build_learning_profile(user_id, interaction_data) |
|
|
elif profile_type == ProfileType.COLLABORATIVE: |
|
|
return await self._build_collaborative_profile(user_id, interaction_data, pattern_data) |
|
|
elif profile_type == ProfileType.TEMPORAL: |
|
|
return await self._build_temporal_profile(user_id, interaction_data, pattern_data) |
|
|
else: |
|
|
return await self._build_generic_profile(user_id, profile_type, interaction_data) |
|
|
|
|
|
async def update_cross_session_context( |
|
|
self, |
|
|
user_id: str, |
|
|
current_context: Dict[str, Any], |
|
|
session_duration: float |
|
|
) -> Dict[str, Any]: |
|
|
"""Update and maintain cross-session context continuity.""" |
|
|
|
|
|
|
|
|
profile = await self.get_user_profile(user_id, ProfileType.CONTEXTUAL) |
|
|
|
|
|
|
|
|
session_context = { |
|
|
"session_start": datetime.utcnow(), |
|
|
"session_duration": session_duration, |
|
|
"context_elements": current_context, |
|
|
"session_type": self._classify_session_type(current_context) |
|
|
} |
|
|
|
|
|
|
|
|
persistent_context = await self._update_persistent_context( |
|
|
profile.data.get("persistent_context", {}), |
|
|
session_context |
|
|
) |
|
|
|
|
|
|
|
|
context_patterns = await self._identify_cross_session_patterns( |
|
|
user_id, persistent_context, session_context |
|
|
) |
|
|
|
|
|
|
|
|
continuity_recommendations = await self._generate_continuity_recommendations( |
|
|
user_id, persistent_context, context_patterns |
|
|
) |
|
|
|
|
|
|
|
|
updated_data = profile.data.copy() |
|
|
updated_data.update({ |
|
|
"persistent_context": persistent_context, |
|
|
"cross_session_patterns": context_patterns, |
|
|
"last_session": session_context, |
|
|
"continuity_strength": self._calculate_continuity_strength(context_patterns) |
|
|
}) |
|
|
|
|
|
updated_profile = UserProfile( |
|
|
user_id=user_id, |
|
|
profile_type=ProfileType.CONTEXTUAL, |
|
|
data=updated_data, |
|
|
created_at=profile.created_at, |
|
|
updated_at=datetime.utcnow(), |
|
|
version=profile.version + 1, |
|
|
completeness_score=self._calculate_profile_completeness(updated_data), |
|
|
confidence_score=self._calculate_profile_confidence(updated_data) |
|
|
) |
|
|
|
|
|
|
|
|
await self._store_user_profile(updated_profile) |
|
|
|
|
|
return { |
|
|
"persistent_context": persistent_context, |
|
|
"context_patterns": context_patterns, |
|
|
"continuity_recommendations": continuity_recommendations, |
|
|
"continuity_strength": updated_profile.data.get("continuity_strength", 0.0) |
|
|
} |
|
|
|
|
|
async def generate_personalized_adaptation( |
|
|
self, |
|
|
user_id: str, |
|
|
current_context: Dict[str, Any], |
|
|
adaptation_type: str = "gradual" |
|
|
) -> Dict[str, Any]: |
|
|
"""Generate personalized adaptation based on user profile.""" |
|
|
|
|
|
|
|
|
profiles = await self._get_user_profiles(user_id) |
|
|
|
|
|
|
|
|
user_characteristics = await self._extract_user_characteristics(profiles) |
|
|
|
|
|
|
|
|
context_analysis = await self._analyze_current_context(current_context, user_characteristics) |
|
|
|
|
|
|
|
|
adaptation_strategy = await self.adaptation_strategies.get( |
|
|
adaptation_type, self._gradual_adaptation |
|
|
)(user_id, context_analysis, user_characteristics) |
|
|
|
|
|
|
|
|
validated_adaptation = await self._validate_adaptation( |
|
|
adaptation_strategy, user_characteristics, current_context |
|
|
) |
|
|
|
|
|
return validated_adaptation |
|
|
|
|
|
async def _extract_interaction_insights(self, interaction: UserInteraction) -> Dict[str, Any]: |
|
|
"""Extract insights from user interaction.""" |
|
|
|
|
|
insights = { |
|
|
"interaction_complexity": self._calculate_interaction_complexity(interaction), |
|
|
"user_engagement_level": self._calculate_engagement_level(interaction), |
|
|
"context_sensitivity": self._calculate_context_sensitivity(interaction), |
|
|
"learning_velocity": self._calculate_learning_velocity(interaction), |
|
|
"preference_signals": self._extract_preference_signals(interaction), |
|
|
"behavioral_patterns": self._extract_behavioral_patterns(interaction), |
|
|
"success_factors": self._identify_success_factors(interaction), |
|
|
"adaptation_triggers": self._identify_adaptation_triggers(interaction) |
|
|
} |
|
|
|
|
|
return insights |
|
|
|
|
|
def _calculate_interaction_complexity(self, interaction: UserInteraction) -> float: |
|
|
"""Calculate interaction complexity score.""" |
|
|
|
|
|
content_complexity = 0.0 |
|
|
context_complexity = 0.0 |
|
|
duration_factor = min(1.0, interaction.duration / 3600) |
|
|
|
|
|
|
|
|
content_size = len(str(interaction.content)) |
|
|
if content_size > 10000: |
|
|
content_complexity = 1.0 |
|
|
elif content_size > 1000: |
|
|
content_complexity = 0.7 |
|
|
elif content_size > 100: |
|
|
content_complexity = 0.4 |
|
|
else: |
|
|
content_complexity = 0.2 |
|
|
|
|
|
|
|
|
context_size = len(str(interaction.context)) |
|
|
if context_size > 5000: |
|
|
context_complexity = 1.0 |
|
|
elif context_size > 500: |
|
|
context_complexity = 0.7 |
|
|
elif context_size > 50: |
|
|
context_complexity = 0.4 |
|
|
else: |
|
|
context_complexity = 0.1 |
|
|
|
|
|
|
|
|
complexity = (content_complexity + context_complexity) * 0.4 + duration_factor * 0.2 |
|
|
return min(1.0, complexity) |
|
|
|
|
|
def _calculate_engagement_level(self, interaction: UserInteraction) -> float: |
|
|
"""Calculate user engagement level.""" |
|
|
|
|
|
|
|
|
duration_score = min(1.0, interaction.duration / 1800) |
|
|
|
|
|
success_score = 1.0 if interaction.success else 0.3 |
|
|
|
|
|
interaction_type_diversity = len(set( |
|
|
interaction.content.get("interaction_types", []) |
|
|
)) / 10 |
|
|
|
|
|
context_richness = len(interaction.context) / 20 |
|
|
|
|
|
|
|
|
engagement = ( |
|
|
duration_score * 0.3 + |
|
|
success_score * 0.3 + |
|
|
min(1.0, interaction_type_diversity) * 0.2 + |
|
|
min(1.0, context_richness) * 0.2 |
|
|
) |
|
|
|
|
|
return min(1.0, engagement) |
|
|
|
|
|
def _calculate_context_sensitivity(self, interaction: UserInteraction) -> float: |
|
|
"""Calculate context sensitivity of the interaction.""" |
|
|
|
|
|
|
|
|
context_dependent_elements = 0 |
|
|
total_elements = 0 |
|
|
|
|
|
|
|
|
content_str = json.dumps(interaction.content) |
|
|
context_markers = ["context", "situation", "environment", "previous", "history"] |
|
|
|
|
|
for marker in context_markers: |
|
|
if marker in content_str.lower(): |
|
|
context_dependent_elements += 1 |
|
|
|
|
|
total_elements += len(context_markers) |
|
|
|
|
|
|
|
|
context_size = len(interaction.context) |
|
|
context_richness = min(1.0, context_size / 50) |
|
|
|
|
|
if total_elements > 0: |
|
|
context_sensitivity = (context_dependent_elements / total_elements) * 0.6 + context_richness * 0.4 |
|
|
else: |
|
|
context_sensitivity = context_richness |
|
|
|
|
|
return min(1.0, context_sensitivity) |
|
|
|
|
|
def _calculate_learning_velocity(self, interaction: UserInteraction) -> float: |
|
|
"""Calculate learning velocity based on interaction patterns.""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time_taken = interaction.duration |
|
|
success = interaction.success |
|
|
adaptation_needed = interaction.adaptation_needed |
|
|
|
|
|
|
|
|
if time_taken < 300: |
|
|
velocity = 1.0 if success else 0.7 |
|
|
elif time_taken < 900: |
|
|
velocity = 0.8 if success else 0.5 |
|
|
else: |
|
|
velocity = 0.6 if success else 0.3 |
|
|
|
|
|
|
|
|
if adaptation_needed: |
|
|
velocity *= 0.8 |
|
|
|
|
|
return min(1.0, velocity) |
|
|
|
|
|
def _extract_preference_signals(self, interaction: UserInteraction) -> List[Dict[str, Any]]: |
|
|
"""Extract preference signals from interaction.""" |
|
|
|
|
|
signals = [] |
|
|
content = interaction.content |
|
|
context = interaction.context |
|
|
|
|
|
|
|
|
if "preferences" in content: |
|
|
for pref_category, pref_value in content["preferences"].items(): |
|
|
signals.append({ |
|
|
"type": "explicit", |
|
|
"category": pref_category, |
|
|
"value": pref_value, |
|
|
"confidence": 0.9, |
|
|
"timestamp": interaction.timestamp |
|
|
}) |
|
|
|
|
|
|
|
|
if "choices" in content: |
|
|
for choice in content["choices"]: |
|
|
signals.append({ |
|
|
"type": "implicit", |
|
|
"category": choice.get("category", "unknown"), |
|
|
"value": choice.get("selected", choice.get("value")), |
|
|
"confidence": 0.7, |
|
|
"timestamp": interaction.timestamp |
|
|
}) |
|
|
|
|
|
|
|
|
if "interaction_style" in context: |
|
|
signals.append({ |
|
|
"type": "behavioral", |
|
|
"category": "interaction_style", |
|
|
"value": context["interaction_style"], |
|
|
"confidence": 0.8, |
|
|
"timestamp": interaction.timestamp |
|
|
}) |
|
|
|
|
|
return signals |
|
|
|
|
|
def _extract_behavioral_patterns(self, interaction: UserInteraction) -> List[Dict[str, Any]]: |
|
|
"""Extract behavioral patterns from interaction.""" |
|
|
|
|
|
patterns = [] |
|
|
|
|
|
|
|
|
if "timestamp" in interaction.context: |
|
|
hour = interaction.timestamp.hour |
|
|
patterns.append({ |
|
|
"type": "temporal", |
|
|
"pattern": f"active_at_hour_{hour}", |
|
|
"strength": 1.0, |
|
|
"context": {"hour": hour} |
|
|
}) |
|
|
|
|
|
|
|
|
if "interaction_type" in interaction.content: |
|
|
patterns.append({ |
|
|
"type": "interaction_style", |
|
|
"pattern": f"prefers_{interaction.content['interaction_type']}", |
|
|
"strength": 0.8, |
|
|
"context": interaction.content["interaction_type"] |
|
|
}) |
|
|
|
|
|
|
|
|
if interaction.success: |
|
|
patterns.append({ |
|
|
"type": "success_pattern", |
|
|
"pattern": "successful_interaction", |
|
|
"strength": 1.0, |
|
|
"context": {"duration": interaction.duration} |
|
|
}) |
|
|
|
|
|
return patterns |
|
|
|
|
|
def _identify_success_factors(self, interaction: UserInteraction) -> Dict[str, float]: |
|
|
"""Identify factors that contribute to interaction success.""" |
|
|
|
|
|
factors = {} |
|
|
|
|
|
|
|
|
optimal_duration = 600 |
|
|
duration_ratio = 1.0 - abs(interaction.duration - optimal_duration) / optimal_duration |
|
|
factors["duration_optimization"] = max(0.0, duration_ratio) |
|
|
|
|
|
|
|
|
context_richness = min(1.0, len(interaction.context) / 20) |
|
|
factors["context_richness"] = context_richness |
|
|
|
|
|
|
|
|
engagement = self._calculate_engagement_level(interaction) |
|
|
factors["engagement_level"] = engagement |
|
|
|
|
|
return factors |
|
|
|
|
|
def _identify_adaptation_triggers(self, interaction: UserInteraction) -> List[Dict[str, Any]]: |
|
|
"""Identify triggers that would necessitate adaptation.""" |
|
|
|
|
|
triggers = [] |
|
|
|
|
|
|
|
|
if not interaction.success: |
|
|
triggers.append({ |
|
|
"type": "performance", |
|
|
"trigger": "interaction_failed", |
|
|
"severity": 0.8, |
|
|
"timestamp": interaction.timestamp |
|
|
}) |
|
|
|
|
|
|
|
|
engagement = self._calculate_engagement_level(interaction) |
|
|
if engagement < 0.5: |
|
|
triggers.append({ |
|
|
"type": "engagement", |
|
|
"trigger": "low_engagement", |
|
|
"severity": 0.6, |
|
|
"context": {"engagement": engagement} |
|
|
}) |
|
|
|
|
|
|
|
|
if interaction.duration > 3600: |
|
|
triggers.append({ |
|
|
"type": "duration", |
|
|
"trigger": "prolonged_interaction", |
|
|
"severity": 0.4, |
|
|
"context": {"duration": interaction.duration} |
|
|
}) |
|
|
|
|
|
return triggers |
|
|
|
|
|
|
|
|
|
|
|
async def _build_behavioral_profile( |
|
|
self, |
|
|
user_id: str, |
|
|
interactions: List[UserInteraction], |
|
|
preferences: List[UserPreference] |
|
|
) -> UserProfile: |
|
|
"""Build behavioral profile for user.""" |
|
|
|
|
|
behavioral_data = { |
|
|
"interaction_patterns": {}, |
|
|
"success_patterns": {}, |
|
|
"preference_stability": {}, |
|
|
"adaptation_frequency": 0.0, |
|
|
"learning_style": "unknown", |
|
|
"communication_style": "unknown", |
|
|
"problem_solving_approach": "unknown" |
|
|
} |
|
|
|
|
|
|
|
|
interaction_times = [interaction.timestamp for interaction in interactions] |
|
|
if interaction_times: |
|
|
|
|
|
hours = [interaction.timestamp.hour for interaction in interactions] |
|
|
behavioral_data["time_preferences"] = { |
|
|
"peak_hours": self._find_peak_hours(hours), |
|
|
"session_duration_pattern": self._analyze_duration_patterns(interactions) |
|
|
} |
|
|
|
|
|
|
|
|
successful_interactions = [i for i in interactions if i.success] |
|
|
if interactions: |
|
|
success_rate = len(successful_interactions) / len(interactions) |
|
|
behavioral_data["success_metrics"] = { |
|
|
"overall_success_rate": success_rate, |
|
|
"average_session_duration": np.mean([i.duration for i in interactions]), |
|
|
"adaptation_frequency": np.mean([i.adaptation_needed for i in interactions]) |
|
|
} |
|
|
|
|
|
|
|
|
communication_patterns = self._analyze_communication_style(interactions) |
|
|
behavioral_data.update(communication_patterns) |
|
|
|
|
|
|
|
|
learning_style = self._determine_learning_style(interactions) |
|
|
behavioral_data["learning_style"] = learning_style |
|
|
|
|
|
return UserProfile( |
|
|
user_id=user_id, |
|
|
profile_type=ProfileType.BEHAVIORAL, |
|
|
data=behavioral_data, |
|
|
created_at=datetime.utcnow(), |
|
|
updated_at=datetime.utcnow(), |
|
|
version=1, |
|
|
completeness_score=self._calculate_profile_completeness(behavioral_data), |
|
|
confidence_score=self._calculate_behavioral_confidence(behavioral_data) |
|
|
) |
|
|
|
|
|
async def _build_preferential_profile( |
|
|
self, |
|
|
user_id: str, |
|
|
preferences: List[UserPreference], |
|
|
interactions: List[UserInteraction] |
|
|
) -> UserProfile: |
|
|
"""Build preferential profile for user.""" |
|
|
|
|
|
pref_data = { |
|
|
"explicit_preferences": {}, |
|
|
"implicit_preferences": {}, |
|
|
"preference_confidence": {}, |
|
|
"preference_stability": {}, |
|
|
"conflict_resolution": "unknown", |
|
|
"adaptation_to_new": "unknown" |
|
|
} |
|
|
|
|
|
|
|
|
for pref in preferences: |
|
|
if pref.confidence > 0.7: |
|
|
if pref.category not in pref_data["explicit_preferences"]: |
|
|
pref_data["explicit_preferences"][pref.category] = {} |
|
|
|
|
|
pref_data["explicit_preferences"][pref.category][pref.preference_type] = { |
|
|
"value": pref.value, |
|
|
"confidence": pref.confidence, |
|
|
"stability": pref.stability |
|
|
} |
|
|
|
|
|
|
|
|
implicit_prefs = self._extract_implicit_preferences(interactions) |
|
|
pref_data["implicit_preferences"] = implicit_prefs |
|
|
|
|
|
|
|
|
if preferences: |
|
|
avg_confidence = np.mean([p.confidence for p in preferences]) |
|
|
avg_stability = np.mean([p.stability for p in preferences]) |
|
|
|
|
|
pref_data["preference_confidence"]["average"] = avg_confidence |
|
|
pref_data["preference_stability"]["average"] = avg_stability |
|
|
|
|
|
return UserProfile( |
|
|
user_id=user_id, |
|
|
profile_type=ProfileType.PREFERENTIAL, |
|
|
data=pref_data, |
|
|
created_at=datetime.utcnow(), |
|
|
updated_at=datetime.utcnow(), |
|
|
version=1, |
|
|
completeness_score=self._calculate_profile_completeness(pref_data), |
|
|
confidence_score=self._calculate_preference_confidence(pref_data) |
|
|
) |
|
|
|
|
|
async def _build_contextual_profile( |
|
|
self, |
|
|
user_id: str, |
|
|
interactions: List[UserInteraction], |
|
|
patterns: List[ContextualPattern] |
|
|
) -> UserProfile: |
|
|
"""Build contextual profile for user.""" |
|
|
|
|
|
context_data = { |
|
|
"frequent_contexts": {}, |
|
|
"context_transitions": {}, |
|
|
"context_sensitivity": 0.0, |
|
|
"persistent_context": {}, |
|
|
"cross_session_patterns": [], |
|
|
"context_evolution": {} |
|
|
} |
|
|
|
|
|
|
|
|
all_contexts = [] |
|
|
for interaction in interactions: |
|
|
all_contexts.append(interaction.context) |
|
|
|
|
|
if all_contexts: |
|
|
|
|
|
common_elements = self._find_common_context_elements(all_contexts) |
|
|
context_data["frequent_contexts"] = common_elements |
|
|
|
|
|
|
|
|
context_data["context_sensitivity"] = self._calculate_overall_context_sensitivity(interactions) |
|
|
|
|
|
|
|
|
pattern_analysis = self._analyze_contextual_patterns(patterns) |
|
|
context_data.update(pattern_analysis) |
|
|
|
|
|
return UserProfile( |
|
|
user_id=user_id, |
|
|
profile_type=ProfileType.CONTEXTUAL, |
|
|
data=context_data, |
|
|
created_at=datetime.utcnow(), |
|
|
updated_at=datetime.utcnow(), |
|
|
version=1, |
|
|
completeness_score=self._calculate_profile_completeness(context_data), |
|
|
confidence_score=self._calculate_contextual_confidence(context_data) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def _find_peak_hours(self, hours: List[int]) -> Dict[int, int]: |
|
|
"""Find peak activity hours.""" |
|
|
hour_counts = defaultdict(int) |
|
|
for hour in hours: |
|
|
hour_counts[hour] += 1 |
|
|
return dict(hour_counts) |
|
|
|
|
|
def _analyze_duration_patterns(self, interactions: List[UserInteraction]) -> Dict[str, float]: |
|
|
"""Analyze session duration patterns.""" |
|
|
durations = [interaction.duration for interaction in interactions] |
|
|
|
|
|
return { |
|
|
"average_duration": np.mean(durations), |
|
|
"median_duration": np.median(durations), |
|
|
"std_duration": np.std(durations), |
|
|
"short_sessions": len([d for d in durations if d < 300]), |
|
|
"long_sessions": len([d for d in durations if d > 1800]) |
|
|
} |
|
|
|
|
|
def _analyze_communication_style(self, interactions: List[UserInteraction]) -> Dict[str, Any]: |
|
|
"""Analyze user's communication style.""" |
|
|
|
|
|
|
|
|
if not interactions: |
|
|
return { |
|
|
"communication_style": "unknown", |
|
|
"verbosity": 0.0, |
|
|
"formality": 0.0 |
|
|
} |
|
|
|
|
|
|
|
|
total_content = "" |
|
|
for interaction in interactions: |
|
|
total_content += json.dumps(interaction.content) + " " |
|
|
|
|
|
|
|
|
formal_indicators = ["please", "thank you", "would you", "could you"] |
|
|
informal_indicators = ["yeah", "ok", "cool", "awesome"] |
|
|
|
|
|
formal_count = sum(total_content.lower().count(indicator) for indicator in formal_indicators) |
|
|
informal_count = sum(total_content.lower().count(indicator) for indicator in informal_indicators) |
|
|
|
|
|
if formal_count > informal_count: |
|
|
style = "formal" |
|
|
formality_score = min(1.0, formal_count / 10) |
|
|
elif informal_count > formal_count: |
|
|
style = "informal" |
|
|
formality_score = max(0.0, 1.0 - informal_count / 10) |
|
|
else: |
|
|
style = "neutral" |
|
|
formality_score = 0.5 |
|
|
|
|
|
|
|
|
avg_content_size = np.mean([len(json.dumps(i.content)) for i in interactions]) |
|
|
verbosity_score = min(1.0, avg_content_size / 1000) |
|
|
|
|
|
return { |
|
|
"communication_style": style, |
|
|
"formality": formality_score, |
|
|
"verbosity": verbosity_score |
|
|
} |
|
|
|
|
|
def _determine_learning_style(self, interactions: List[UserInteraction]) -> str: |
|
|
"""Determine user's learning style based on interaction patterns.""" |
|
|
|
|
|
if not interactions: |
|
|
return "unknown" |
|
|
|
|
|
|
|
|
adaptation_rates = [interaction.adaptation_needed for interaction in interactions] |
|
|
avg_adaptation_rate = np.mean(adaptation_rates) |
|
|
|
|
|
|
|
|
success_patterns = [interaction.success for interaction in interactions] |
|
|
success_improvement = self._calculate_success_improvement(success_patterns) |
|
|
|
|
|
|
|
|
if avg_adaptation_rate > 0.7: |
|
|
return "adaptive_learner" |
|
|
elif success_improvement > 0.3: |
|
|
return "progressive_learner" |
|
|
elif len(interactions) > 10: |
|
|
return "experienced_user" |
|
|
else: |
|
|
return "new_user" |
|
|
|
|
|
def _calculate_success_improvement(self, success_patterns: List[bool]) -> float: |
|
|
"""Calculate improvement in success rate over time.""" |
|
|
|
|
|
if len(success_patterns) < 5: |
|
|
return 0.0 |
|
|
|
|
|
|
|
|
mid_point = len(success_patterns) // 2 |
|
|
early_success = np.mean(success_patterns[:mid_point]) |
|
|
late_success = np.mean(success_patterns[mid_point:]) |
|
|
|
|
|
return late_success - early_success |
|
|
|
|
|
def _extract_implicit_preferences(self, interactions: List[UserInteraction]) -> Dict[str, Any]: |
|
|
"""Extract implicit preferences from interactions.""" |
|
|
|
|
|
implicit_prefs = { |
|
|
"feature_usage": {}, |
|
|
"interaction_patterns": {}, |
|
|
"success_patterns": {} |
|
|
} |
|
|
|
|
|
|
|
|
all_features = [] |
|
|
for interaction in interactions: |
|
|
if "features_used" in interaction.content: |
|
|
all_features.extend(interaction.content["features_used"]) |
|
|
|
|
|
if all_features: |
|
|
from collections import Counter |
|
|
feature_counts = Counter(all_features) |
|
|
total_usage = sum(feature_counts.values()) |
|
|
|
|
|
for feature, count in feature_counts.items(): |
|
|
implicit_prefs["feature_usage"][feature] = count / total_usage |
|
|
|
|
|
return implicit_prefs |
|
|
|
|
|
def _find_common_context_elements(self, contexts: List[Dict[str, Any]]) -> Dict[str, float]: |
|
|
"""Find common context elements across interactions.""" |
|
|
|
|
|
if not contexts: |
|
|
return {} |
|
|
|
|
|
|
|
|
all_keys = set() |
|
|
for context in contexts: |
|
|
all_keys.update(context.keys()) |
|
|
|
|
|
|
|
|
key_counts = defaultdict(int) |
|
|
for context in contexts: |
|
|
for key in context.keys(): |
|
|
key_counts[key] += 1 |
|
|
|
|
|
|
|
|
common_elements = {} |
|
|
for key in all_keys: |
|
|
frequency = key_counts[key] / len(contexts) |
|
|
if frequency > 0.3: |
|
|
common_elements[key] = frequency |
|
|
|
|
|
return common_elements |
|
|
|
|
|
def _calculate_overall_context_sensitivity(self, interactions: List[UserInteraction]) -> float: |
|
|
"""Calculate overall context sensitivity.""" |
|
|
|
|
|
if not interactions: |
|
|
return 0.0 |
|
|
|
|
|
sensitivities = [] |
|
|
for interaction in interactions: |
|
|
sensitivity = self._calculate_context_sensitivity(interaction) |
|
|
sensitivities.append(sensitivity) |
|
|
|
|
|
return np.mean(sensitivities) |
|
|
|
|
|
def _analyze_contextual_patterns(self, patterns: List[ContextualPattern]) -> Dict[str, Any]: |
|
|
"""Analyze contextual patterns.""" |
|
|
|
|
|
pattern_analysis = { |
|
|
"pattern_count": len(patterns), |
|
|
"pattern_types": {}, |
|
|
"high_frequency_patterns": [], |
|
|
"recent_patterns": [] |
|
|
} |
|
|
|
|
|
|
|
|
type_counts = defaultdict(int) |
|
|
for pattern in patterns: |
|
|
type_counts[pattern.pattern_type] += 1 |
|
|
|
|
|
pattern_analysis["pattern_types"] = dict(type_counts) |
|
|
|
|
|
|
|
|
high_freq_patterns = [p for p in patterns if p.frequency > 0.5] |
|
|
pattern_analysis["high_frequency_patterns"] = [ |
|
|
{ |
|
|
"type": p.pattern_type, |
|
|
"frequency": p.frequency, |
|
|
"confidence": p.confidence |
|
|
} |
|
|
for p in high_freq_patterns |
|
|
] |
|
|
|
|
|
|
|
|
recent_patterns = [ |
|
|
p for p in patterns |
|
|
if (datetime.utcnow() - p.last_observed).days < 7 |
|
|
] |
|
|
pattern_analysis["recent_patterns"] = [ |
|
|
{ |
|
|
"type": p.pattern_type, |
|
|
"last_observed": p.last_observed.isoformat() |
|
|
} |
|
|
for p in recent_patterns |
|
|
] |
|
|
|
|
|
return pattern_analysis |
|
|
|
|
|
|
|
|
|
|
|
def _calculate_profile_completeness(self, data: Dict[str, Any]) -> float: |
|
|
"""Calculate completeness score of profile data.""" |
|
|
|
|
|
if not data: |
|
|
return 0.0 |
|
|
|
|
|
|
|
|
filled_fields = 0 |
|
|
total_fields = 0 |
|
|
|
|
|
def count_fields(obj, path=""): |
|
|
nonlocal filled_fields, total_fields |
|
|
|
|
|
if isinstance(obj, dict): |
|
|
for key, value in obj.items(): |
|
|
new_path = f"{path}.{key}" if path else key |
|
|
count_fields(value, new_path) |
|
|
elif isinstance(obj, list): |
|
|
if obj: |
|
|
count_fields(obj[0], f"{path}[0]") |
|
|
else: |
|
|
total_fields += 1 |
|
|
else: |
|
|
total_fields += 1 |
|
|
if obj is not None and obj != "": |
|
|
filled_fields += 1 |
|
|
|
|
|
count_fields(data) |
|
|
|
|
|
return filled_fields / max(total_fields, 1) |
|
|
|
|
|
def _calculate_behavioral_confidence(self, data: Dict[str, Any]) -> float: |
|
|
"""Calculate confidence score for behavioral profile.""" |
|
|
|
|
|
|
|
|
confidence_factors = [] |
|
|
|
|
|
if "interaction_patterns" in data and data["interaction_patterns"]: |
|
|
confidence_factors.append(0.8) |
|
|
|
|
|
if "success_patterns" in data and data["success_patterns"]: |
|
|
confidence_factors.append(0.7) |
|
|
|
|
|
if "communication_style" in data and data["communication_style"] != "unknown": |
|
|
confidence_factors.append(0.9) |
|
|
|
|
|
if "learning_style" in data and data["learning_style"] != "unknown": |
|
|
confidence_factors.append(0.8) |
|
|
|
|
|
return np.mean(confidence_factors) if confidence_factors else 0.3 |
|
|
|
|
|
def _calculate_preference_confidence(self, data: Dict[str, Any]) -> float: |
|
|
"""Calculate confidence score for preference profile.""" |
|
|
|
|
|
confidence_factors = [] |
|
|
|
|
|
if "explicit_preferences" in data and data["explicit_preferences"]: |
|
|
|
|
|
num_explicit = sum(len(category) for category in data["explicit_preferences"].values()) |
|
|
confidence_factors.append(min(1.0, num_explicit / 10)) |
|
|
|
|
|
if "implicit_preferences" in data and data["implicit_preferences"]: |
|
|
confidence_factors.append(0.6) |
|
|
|
|
|
if "preference_confidence" in data: |
|
|
avg_confidence = data["preference_confidence"].get("average", 0) |
|
|
confidence_factors.append(avg_confidence) |
|
|
|
|
|
return np.mean(confidence_factors) if confidence_factors else 0.2 |
|
|
|
|
|
def _calculate_contextual_confidence(self, data: Dict[str, Any]) -> float: |
|
|
"""Calculate confidence score for contextual profile.""" |
|
|
|
|
|
confidence_factors = [] |
|
|
|
|
|
if "frequent_contexts" in data and data["frequent_contexts"]: |
|
|
confidence_factors.append(0.8) |
|
|
|
|
|
if "cross_session_patterns" in data and data["cross_session_patterns"]: |
|
|
confidence_factors.append(0.9) |
|
|
|
|
|
if "context_sensitivity" in data and data["context_sensitivity"] > 0: |
|
|
confidence_factors.append(data["context_sensitivity"]) |
|
|
|
|
|
return np.mean(confidence_factors) if confidence_factors else 0.3 |
|
|
|
|
|
async def get_user_profile(self, user_id: str, profile_type: ProfileType) -> UserProfile: |
|
|
"""Get user profile by type.""" |
|
|
|
|
|
if user_id not in self.user_profiles: |
|
|
return await self._create_empty_profile(user_id, profile_type) |
|
|
|
|
|
user_profiles = self.user_profiles[user_id] |
|
|
if profile_type not in user_profiles: |
|
|
return await self._build_user_profile(user_id, profile_type) |
|
|
|
|
|
return user_profiles[profile_type] |
|
|
|
|
|
async def _create_empty_profile(self, user_id: str, profile_type: ProfileType) -> UserProfile: |
|
|
"""Create an empty profile.""" |
|
|
|
|
|
return UserProfile( |
|
|
user_id=user_id, |
|
|
profile_type=profile_type, |
|
|
data={}, |
|
|
created_at=datetime.utcnow(), |
|
|
updated_at=datetime.utcnow(), |
|
|
version=1, |
|
|
completeness_score=0.0, |
|
|
confidence_score=0.0 |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _update_profiles_from_interaction(self, interaction: UserInteraction, insights: Dict[str, Any]) -> Dict[str, str]: |
|
|
"""Update profiles based on interaction.""" |
|
|
|
|
|
return {"status": "updated_profiles"} |
|
|
|
|
|
async def _identify_contextual_patterns(self, interaction: UserInteraction, insights: Dict[str, Any]) -> List[ContextualPattern]: |
|
|
"""Identify new contextual patterns.""" |
|
|
|
|
|
return [] |
|
|
|
|
|
async def _update_preferences(self, interaction: UserInteraction, insights: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Update user preferences.""" |
|
|
|
|
|
return {"status": "updated_preferences"} |
|
|
|
|
|
async def _generate_adaptation_recommendations(self, interaction: UserInteraction, profiles: Dict[str, Any], insights: Dict[str, Any]) -> List[Dict[str, Any]]: |
|
|
"""Generate adaptation recommendations.""" |
|
|
|
|
|
return [] |
|
|
|
|
|
async def _build_interaction_profile(self, user_id: str, interactions: List[UserInteraction]) -> UserProfile: |
|
|
"""Build interaction profile.""" |
|
|
return await self._create_empty_profile(user_id, ProfileType.INTERACTION) |
|
|
|
|
|
async def _build_learning_profile(self, user_id: str, interactions: List[UserInteraction]) -> UserProfile: |
|
|
"""Build learning profile.""" |
|
|
return await self._create_empty_profile(user_id, ProfileType.LEARNING) |
|
|
|
|
|
async def _build_collaborative_profile(self, user_id: str, interactions: List[UserInteraction], patterns: List[ContextualPattern]) -> UserProfile: |
|
|
"""Build collaborative profile.""" |
|
|
return await self._create_empty_profile(user_id, ProfileType.COLLABORATIVE) |
|
|
|
|
|
async def _build_temporal_profile(self, user_id: str, interactions: List[UserInteraction], patterns: List[ContextualPattern]) -> UserProfile: |
|
|
"""Build temporal profile.""" |
|
|
return await self._create_empty_profile(user_id, ProfileType.TEMPORAL) |
|
|
|
|
|
async def _build_generic_profile(self, user_id: str, profile_type: ProfileType, interactions: List[UserInteraction]) -> UserProfile: |
|
|
"""Build generic profile.""" |
|
|
return await self._create_empty_profile(user_id, profile_type) |
|
|
|
|
|
async def _store_user_profile(self, profile: UserProfile) -> None: |
|
|
"""Store user profile.""" |
|
|
if profile.user_id not in self.user_profiles: |
|
|
self.user_profiles[profile.user_id] = {} |
|
|
self.user_profiles[profile.user_id][profile.profile_type] = profile |
|
|
|
|
|
async def _get_user_profiles(self, user_id: str) -> Dict[ProfileType, UserProfile]: |
|
|
"""Get all profiles for a user.""" |
|
|
return self.user_profiles.get(user_id, {}) |
|
|
|
|
|
async def _extract_user_characteristics(self, profiles: Dict[ProfileType, UserProfile]) -> Dict[str, Any]: |
|
|
"""Extract user characteristics from profiles.""" |
|
|
characteristics = {} |
|
|
|
|
|
for profile_type, profile in profiles.items(): |
|
|
weight = self.profile_weights.get(profile_type, 0.1) |
|
|
characteristics[profile_type.value] = { |
|
|
"data": profile.data, |
|
|
"confidence": profile.confidence_score, |
|
|
"weight": weight |
|
|
} |
|
|
|
|
|
return characteristics |
|
|
|
|
|
async def _analyze_current_context(self, context: Dict[str, Any], characteristics: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Analyze current context in relation to user characteristics.""" |
|
|
|
|
|
return { |
|
|
"context_relevance": 0.8, |
|
|
"adaptation_need": 0.5, |
|
|
"personalization_opportunities": ["style", "preferences"] |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async def _gradual_adaptation(self, user_id: str, context_analysis: Dict[str, Any], characteristics: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Gradual adaptation strategy.""" |
|
|
return { |
|
|
"strategy": "gradual", |
|
|
"adaptation_rate": 0.1, |
|
|
"target_aspects": ["communication_style", "interaction_pace"], |
|
|
"timeline": "multiple_sessions" |
|
|
} |
|
|
|
|
|
async def _immediate_adaptation(self, user_id: str, context_analysis: Dict[str, Any], characteristics: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Immediate adaptation strategy.""" |
|
|
return { |
|
|
"strategy": "immediate", |
|
|
"adaptation_rate": 0.8, |
|
|
"target_aspects": ["user_preferences", "interface_layout"], |
|
|
"timeline": "current_session" |
|
|
} |
|
|
|
|
|
async def _predictive_adaptation(self, user_id: str, context_analysis: Dict[str, Any], characteristics: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Predictive adaptation strategy.""" |
|
|
return { |
|
|
"strategy": "predictive", |
|
|
"adaptation_rate": 0.3, |
|
|
"target_aspects": ["upcoming_needs", "anticipated_preferences"], |
|
|
"timeline": "future_sessions" |
|
|
} |
|
|
|
|
|
async def _validate_adaptation(self, adaptation: Dict[str, Any], characteristics: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Validate adaptation strategy.""" |
|
|
|
|
|
validated_adaptation = adaptation.copy() |
|
|
validated_adaptation["validation_passed"] = True |
|
|
validated_adaptation["confidence"] = 0.8 |
|
|
return validated_adaptation |
|
|
|
|
|
|
|
|
|
|
|
def _classify_session_type(self, context: Dict[str, Any]) -> str: |
|
|
"""Classify the type of session based on context.""" |
|
|
|
|
|
if "task_complexity" in context: |
|
|
if context["task_complexity"] > 0.7: |
|
|
return "complex_task" |
|
|
else: |
|
|
return "simple_task" |
|
|
return "general_session" |
|
|
|
|
|
async def _update_persistent_context(self, current_persistent: Dict[str, Any], session_context: Dict[str, Any]) -> Dict[str, Any]: |
|
|
"""Update persistent context with session information.""" |
|
|
|
|
|
updated_persistent = current_persistent.copy() |
|
|
updated_persistent["last_session"] = session_context |
|
|
return updated_persistent |
|
|
|
|
|
async def _identify_cross_session_patterns(self, user_id: str, persistent: Dict[str, Any], session: Dict[str, Any]) -> List[Dict[str, Any]]: |
|
|
"""Identify patterns across sessions.""" |
|
|
|
|
|
return [ |
|
|
{ |
|
|
"pattern_type": "session_continuity", |
|
|
"strength": 0.7, |
|
|
"context": "persistent_preferences" |
|
|
} |
|
|
] |
|
|
|
|
|
async def _generate_continuity_recommendations(self, user_id: str, persistent: Dict[str, Any], patterns: List[Dict[str, Any]]) -> List[Dict[str, Any]]: |
|
|
"""Generate recommendations for maintaining continuity.""" |
|
|
|
|
|
return [ |
|
|
{ |
|
|
"recommendation": "maintain_preferred_style", |
|
|
"priority": "high", |
|
|
"context": "user_communication_preferences" |
|
|
} |
|
|
] |
|
|
|
|
|
def _calculate_continuity_strength(self, patterns: List[Dict[str, Any]]) -> float: |
|
|
"""Calculate strength of continuity patterns.""" |
|
|
if not patterns: |
|
|
return 0.0 |
|
|
return np.mean([pattern.get("strength", 0.5) for pattern in patterns]) |
|
|
|
|
|
|
|
|
|
|
|
async def _incremental_learning(self, interaction: UserInteraction) -> Dict[str, Any]: |
|
|
"""Incremental learning from interaction.""" |
|
|
return {"learning_type": "incremental", "progress": 0.1} |
|
|
|
|
|
async def _batch_learning(self, interactions: List[UserInteraction]) -> Dict[str, Any]: |
|
|
"""Batch learning from multiple interactions.""" |
|
|
return {"learning_type": "batch", "progress": 0.3} |
|
|
|
|
|
async def _reinforcement_learning(self, interaction: UserInteraction) -> Dict[str, Any]: |
|
|
"""Reinforcement learning from interaction outcome.""" |
|
|
return {"learning_type": "reinforcement", "reward": interaction.success} |
|
|
|
|
|
async def _association_learning(self, interaction: UserInteraction) -> Dict[str, Any]: |
|
|
"""Association learning between context and outcomes.""" |
|
|
return {"learning_type": "association", "connections": 2} |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
print("Contextual Personalization & User Profiling System Initialized") |
|
|
print("=" * 70) |
|
|
engine = ContextualPersonalizationEngine() |
|
|
print("Ready for advanced user profiling and personalization!") |