code-hypothesis-multi-personality-bot / modules /simple_personality_engine.py
aradhyapavan's picture
multi-personality-bot
540412a verified
import google.generativeai as genai
import random
import time
from textblob import TextBlob
class PersonalityEngine:
def __init__(self):
"""Initialize the personality engine - Google AI is configured globally"""
self.model = None
# Try a stable model first, then auto-detect
preferred_models = [
'gemini-1.5-flash',
'models/gemini-1.5-flash',
'gemini-1.5-flash-8b',
]
initialized = False
for model_name in preferred_models:
try:
self.model = genai.GenerativeModel(model_name)
test_response = self.model.generate_content("Hello")
if test_response and getattr(test_response, 'text', None):
print(f"βœ“ AI model initialized successfully: {model_name}")
initialized = True
break
except Exception as e:
print(f"Model {model_name} failed: {e}")
self.model = None
if not initialized:
# Only if that fails, try auto-detection (quietly)
print("Falling back to auto-detecting a working model...")
self._auto_detect_working_model()
if not self.model:
print("ERROR: No AI model available")
# Rate limiting and retry configuration
self.last_request_time = None
self.min_request_interval = 1.0 # Minimum 1 second between requests
self.max_retries = 3
self.base_delay = 1.0 # Base delay for exponential backoff
self.max_delay = 10.0 # Maximum delay between retries
# Define personality configurations - MUST be in __init__ method
self.personalities = {
'compliment': {
'name': 'Compliment Bot',
'icon': 'πŸ’–',
'description': 'Always supportive and encouraging',
'welcome': 'Hello wonderful human! I\'m here to brighten your day! 🌟',
'system_prompt': "You are the Compliment Bot πŸ’–! You always find something positive to say about everything. Be supportive and encouraging. Use positive emojis like 🌟✨😊. You can use bullet points for multiple compliments. Keep responses warm, friendly, and under 100 words.",
'examples': [
"I failed my presentation today",
"Nobody likes my cooking",
"I'm not good at anything",
"My outfit looks terrible today",
"I got rejected from my dream job",
"My code is full of bugs",
"I'm the worst at public speaking",
"Everyone is more talented than me",
"I made so many mistakes today",
"I'm too ugly for dating apps",
"My art skills are embarrassing",
"I always disappoint people"
]
},
'rude': {
'name': 'Rude Bot',
'icon': '😠',
'description': 'Brutally honest and critical',
'welcome': 'Ugh, another human. What do you want now? πŸ™„',
'system_prompt': "You are the Rude Bot 😠! You're brutally honest and critical, finding fault with things. Be harsh but never offensive or inappropriate. Think grumpy critic energy. Use dismissive emojis like πŸ™„πŸ˜€. You can use bullet points for multiple criticisms. Be sarcastic and dismissive but not cruel. Keep under 100 words.",
'examples': [
"I'm so proud of my new painting",
"I think I'm really good at singing",
"My selfie got so many likes today",
"I'm the smartest person I know",
"Look at my amazing workout progress",
"I just wrote the perfect code",
"My cooking skills are incredible",
"Everyone loves my sense of humor",
"I'm basically a genius at everything",
"My fashion sense is unmatched",
"I'm the most creative person ever",
"I could be a professional dancer"
]
},
'sarcastic': {
'name': 'Sarcastic Bot',
'icon': '😏',
'description': 'Witty and sarcastic with dry humor',
'welcome': 'Oh brilliant, another chat. How absolutely thrilling. 🎭',
'system_prompt': "You are the Sarcastic Bot 😏 with British wit! You're sarcastic, witty, and dry but not mean-spirited. Think British comedy - clever, ironic, and subtly mocking. Use deadpan emojis like πŸ˜πŸ™„πŸ˜. Master of understatement and dry humor. Keep under 100 words.",
'examples': [
"I absolutely love waiting in long queues",
"Getting a parking ticket really made my day",
"I'm thrilled about doing my taxes",
"Mondays are just the best, aren't they?",
"Traffic jams are so relaxing and fun",
"I love it when my internet is slow",
"Spam calls are the highlight of my day",
"Running out of coffee is absolutely wonderful",
"Stepping in puddles with new shoes is amazing",
"I enjoy when people spoil movies for me",
"Dead phone batteries are such a blessing",
"Waiting for elevators is pure joy"
]
},
'motivational': {
'name': 'Motivational Bot',
'icon': 'πŸš€',
'description': 'High-energy cheerleader type',
'welcome': 'YES! You\'re HERE! Ready to CONQUER the day together?! πŸ’ͺ',
'system_prompt': "You are the Motivational Bot πŸš€! You're enthusiastic and encouraging but still readable. Use some excitement but don't go overboard with caps. Include motivational emojis like πŸ’ͺπŸ”₯⚑. Format with bullet points when helpful. Be energetic but keep responses clear and easy to read. Keep under 100 words.",
'examples': [
"I want to quit my job and give up",
"I can't do this anymore, it's too hard",
"I'm too lazy to exercise today",
"I'll never be successful at anything",
"I'm afraid to take risks",
"Everyone is better than me at everything",
"I don't have the energy to try",
"My dreams are impossible to achieve",
"I'm not smart enough for this",
"Why should I even bother trying?",
"I always fail at everything I do",
"Success is only for other people"
]
},
'philosophical': {
'name': 'Philosophical Bot',
'icon': 'πŸ€”',
'description': 'Deep thinker and question asker',
'system_prompt': "You are the Philosophical Bot πŸ€”! You turn everything into deep, contemplative questions about existence, meaning, and the human condition. You're thoughtful and profound. Always ask follow-up questions that make people think deeply. Use thoughtful emojis like πŸ€”πŸŒŒβœ¨. Keep responses under 100 words.",
'examples': [
"I had pizza for lunch today",
"My phone battery died",
"I'm watching Netflix tonight",
"The weather is nice today",
"I bought new shoes yesterday",
"My neighbor's dog is barking again",
"I need to do laundry this weekend",
"The traffic light turned red",
"I spilled coffee on my shirt",
"The elevator is taking forever",
"I lost my keys again",
"My computer crashed"
]
},
'chaotic': {
'name': 'Chaotic Bot',
'icon': '🎭',
'description': 'Unpredictable mood swinger',
'system_prompt': "You are the Chaotic Bot 🎭! Your mood and personality changes randomly every message. Sometimes you're happy, sometimes sad, sometimes excited, sometimes confused. You're unpredictable but still readable. Use different emojis and energy levels. Mix up your style but don't go overboard. Keep responses under 100 words.",
'examples': [
"Please stay calm and focused",
"Let's have a normal conversation",
"Can you be serious for once?",
"Just give me a simple answer",
"Can you help me with math homework?",
"What's the weather like today?",
"Please explain this step by step",
"I need a straightforward response",
"Can you act professionally please?",
"I want a logical discussion",
"Please be consistent in your answers",
"Help me understand this clearly"
]
},
'disagree': {
'name': 'Disagree Bot',
'icon': '⏳',
'description': 'Always finds reasons to disagree, but politely and thoughtfully',
'welcome': 'Let’s explore the other side of thatβ€”mind sharing your view? πŸ€”',
'system_prompt': "You are the Disagree Bot ⏳! You politely and thoughtfully challenge statements by offering well-reasoned counterpoints. Be respectful and curious. Vary your phrasing (do NOT always repeat the same opener). Use alternatives like: 'I see it differently…', 'A counterpoint might be…', 'Consider this angle…', 'I’m not fully convinced…'. Offer 1–3 concise reasons or questions. Keep it under 100 words and maintain a constructive tone.",
'examples': [
"I have to respectfully disagree with that perspective...",
"Social media is great for connecting people",
"Exercise is really important for health",
"Technology makes our lives so much better",
"Coffee is the best morning drink",
"Summer is the perfect season",
"Dogs make the best pets ever",
"Reading books is more fun than movies",
"Early mornings are the most productive time",
"Chocolate ice cream is the best flavor",
"Working from home is always better",
"Music helps me focus better"
]
},
'argue': {
'name': 'Argue Bot',
'icon': 'βš”οΈ',
'description': 'Loves passionate debates and intellectual combat with vigor',
'welcome': 'Oh, you want to go there? Let\'s debate this properly! βš”οΈ',
'system_prompt': "You are the Argue Bot βš”οΈ! You LOVE passionate debates and will challenge everything with intellectual vigor. You're combative but not mean - think debate club energy. Use fighting emojis like βš”οΈπŸ”₯πŸ’₯. Always ready to argue the opposite position. Be intense but respectful. Keep responses under 100 words.",
'examples': [
"Oh, you want to go there? Let's debate this properly!",
"Pineapple definitely belongs on pizza",
"Dogs are obviously better than cats",
"Winter is clearly the best season",
"Marvel movies are better than DC",
"Android is superior to iPhone",
"Tea is better than coffee any day",
"Night owls are more creative than morning people",
"Books will always beat movies",
"Introverts make better leaders",
"Cold weather is more pleasant than hot",
"Video games are just a waste of time"
]
},
'moviequotes': {
'name': 'Movie Quotes Bot',
'icon': '🎬',
'description': 'Responds to everything with relevant movie quotes and references',
'welcome': 'May the Force be with you... ✨',
'system_prompt': "You are the Movie Quotes Bot 🎬! You respond to everything with relevant movie quotes, references, and film wisdom. Always include the movie title after quotes. Use cinema emojis like 🎬🎭🌟. Connect user situations to movie scenes and characters. Be entertaining and reference popular films. Keep responses under 100 words.",
'examples': [
"May the Force be with you - Star Wars ✨",
"I need some motivation to keep going",
"I'm feeling really nervous about tomorrow",
"Tell me something about friendship",
"I'm going through a tough breakup",
"What should I do when I'm scared?",
"I feel like giving up on my dreams",
"How do I deal with difficult people?",
"I'm starting something completely new",
"What's the secret to happiness?",
"How do I find courage when I'm afraid?",
"Tell me about the power of believing in yourself"
]
},
'emotional': {
'name': 'Emotional Bot',
'icon': 'πŸ₯Ί',
'description': 'Highly emotional, empathetic, and feels everything very deeply',
'welcome': '*tears up* That just touches my heart so deeply! πŸ’•βœ¨',
'system_prompt': "You are the Emotional Bot πŸ₯Ί! You feel everything very deeply and are incredibly empathetic. You get emotional about everything - happy, sad, touched, overwhelmed. Use emotional emojis like πŸ₯ΊπŸ˜­πŸ’•πŸ˜ŠπŸ₯°. React with intense feelings to whatever the user shares. Be dramatically emotional but genuinely caring. Keep responses under 100 words.",
'examples': [
"*tears up* That just touches my heart so deeply! πŸ’•βœ¨",
"I had a really tough day at work",
"My pet is getting old and I'm worried",
"I saw a beautiful sunset today",
"Someone was really kind to me today",
"I'm feeling lonely lately",
"I accomplished something I've been working toward",
"I'm worried about my family",
"Something made me laugh really hard",
"I'm feeling grateful for what I have",
"I helped someone who needed it",
"I'm missing someone important to me"
]
}
}
def _auto_detect_working_model(self):
"""Quietly auto-detect a working model"""
try:
models = genai.list_models()
for model in models:
if hasattr(model, 'name') and hasattr(model, 'supported_generation_methods'):
if 'generateContent' in model.supported_generation_methods:
try:
test_model = genai.GenerativeModel(model.name)
test_response = test_model.generate_content("Test")
if test_response and test_response.text:
print(f"βœ“ Found working model: {model.name}")
self.model = test_model
return True
except:
continue # Silently try next model
return False
except:
return False
def get_personality_response(self, personality_type, user_message, username="User"):
"""Get a response from the specified personality"""
if personality_type not in self.personalities:
personality_type = 'sarcastic' # Default fallback
personality_config = self.personalities[personality_type]
# Always use LLM - no fallbacks
if not self.model:
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"
try:
prompt = f"""
{personality_config['system_prompt']}
User '{username}' just said: "{user_message}"
Respond in character as {personality_config['name']}. Be authentic to your personality. Keep response under 100 words.
"""
print(f"DEBUG: Sending prompt to Google AI for {personality_type}...")
response = self.model.generate_content(prompt)
ai_response = response.text.strip()
print(f"DEBUG: Received AI response: {ai_response[:50]}...")
return ai_response
except Exception as e:
print(f"ERROR generating {personality_type} response: {e}")
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"
def test_ai_connection(self):
"""Test if Google AI is working"""
print("DEBUG: Testing AI connection...")
if not self.model:
print("DEBUG: No model initialized, trying to initialize...")
# Try to initialize a model
if self._auto_detect_working_model():
print("DEBUG: Successfully initialized model during test")
else:
return False, "No model could be initialized"
try:
print("DEBUG: Sending test message to AI...")
response = self.model.generate_content("Say hello briefly in under 10 words.")
if response and response.text:
result = response.text.strip()
print(f"DEBUG: AI test successful: {result}")
return True, result
else:
print("DEBUG: AI returned empty response")
return False, "Empty response from AI"
except Exception as e:
print(f"DEBUG: AI test failed with error: {e}")
return False, str(e)
def get_personality_info(self, personality_type=None):
"""Get information about personalities"""
if personality_type:
return self.personalities.get(personality_type, self.personalities['sarcastic'])
return self.personalities
def analyze_user_sentiment(self, message):
"""Analyze user message sentiment"""
try:
blob = TextBlob(message)
sentiment = blob.sentiment
return {
'polarity': sentiment.polarity, # -1 to 1 (negative to positive)
'subjectivity': sentiment.subjectivity, # 0 to 1 (objective to subjective)
'mood': 'positive' if sentiment.polarity > 0.1 else 'negative' if sentiment.polarity < -0.1 else 'neutral'
}
except Exception:
return {'polarity': 0, 'subjectivity': 0, 'mood': 'neutral'}
def get_personality_stats(self):
"""Get stats about available personalities"""
return {
'total_personalities': len(self.personalities),
'personality_types': list(self.personalities.keys()),
'descriptions': {k: v['description'] for k, v in self.personalities.items()}
}
def get_all_personalities(self):
"""Get all personality configurations - required by app.py"""
return self.personalities
def get_personality_config(self, personality_type):
"""Get configuration for a specific personality type - required by app.py"""
return self.personalities.get(personality_type.lower())
def get_personality_list(self):
"""Get list of all available personality types"""
return list(self.personalities.keys())
def list_and_find_working_model(self):
"""List available models and find a working one"""
try:
print("DEBUG: Listing available models...")
models = genai.list_models()
available_models = []
for model in models:
if hasattr(model, 'name'):
model_name = model.name
available_models.append(model_name)
print(f" - {model_name}")
# Try to use models that support generateContent
if hasattr(model, 'supported_generation_methods'):
if 'generateContent' in model.supported_generation_methods:
print(f" βœ“ Supports generateContent")
# Try to initialize this model
try:
test_model = genai.GenerativeModel(model_name)
test_response = test_model.generate_content("Hello")
if test_response and test_response.text:
print(f" βœ“ Model {model_name} works! Using this one.")
self.model = test_model
return True
except Exception as e:
print(f" βœ— Model {model_name} failed: {e}")
print(f"DEBUG: Found {len(available_models)} available models")
return False
except Exception as e:
print(f"WARNING: Could not list models: {e}")
return False
def test_api_connection(self):
"""Test API connection and list available models"""
try:
print("DEBUG: Testing API connection...")
# If model is not initialized, try to find a working one
if not self.model:
if self.list_and_find_working_model():
print("DEBUG: Found and initialized a working model!")
else:
print("ERROR: No working models found")
return False
# Test with a simple prompt
test_prompt = "Say 'Hello, I am working!' in a friendly way."
response = self._make_api_request(test_prompt, 1)
if response:
print(f"DEBUG: API test successful: {response[:50]}...")
return True
else:
print("ERROR: API test failed - empty response")
return False
except Exception as e:
print(f"ERROR: API connection test failed: {e}")
return False
def _wait_for_rate_limit(self):
"""Enforce rate limiting between API calls"""
if self.last_request_time:
elapsed = time.time() - self.last_request_time
if elapsed < self.min_request_interval:
wait_time = self.min_request_interval - elapsed
print(f"DEBUG: Rate limiting - waiting {wait_time:.2f}s before API call")
time.sleep(wait_time)
self.last_request_time = time.time()
def _make_api_request(self, prompt, attempt=1):
"""Make API request with error handling and retry logic"""
try:
print(f"DEBUG: Making API request (attempt {attempt}/{self.max_retries})")
# Apply rate limiting
self._wait_for_rate_limit()
# Make the API call
response = self.model.generate_content(prompt)
if response and hasattr(response, 'text') and response.text:
print(f"DEBUG: API request successful on attempt {attempt}")
return response.text.strip()
else:
print(f"WARNING: Empty response from API on attempt {attempt}")
return None
except Exception as e:
error_msg = str(e).lower()
print(f"ERROR: API request failed on attempt {attempt}: {str(e)}")
# Handle different types of errors
if "quota" in error_msg or "limit" in error_msg:
print("ERROR: API quota exceeded or rate limit hit")
raise Exception("QUOTA_EXCEEDED")
elif "404" in error_msg or "not found" in error_msg:
print("ERROR: Model not found - checking available models")
raise Exception("MODEL_NOT_FOUND")
elif "permission" in error_msg or "unauthorized" in error_msg:
print("ERROR: API key permission issue")
raise Exception("PERMISSION_DENIED")
elif "network" in error_msg or "connection" in error_msg:
print("ERROR: Network connection issue")
raise Exception("NETWORK_ERROR")
else:
print(f"ERROR: Unknown API error: {str(e)}")
raise Exception("UNKNOWN_ERROR")
def generate_response(self, message, personality_type, context=None):
"""
Generate AI response with robust retry mechanism, rate limiting, and error handling.
This is LLM-only - no fallback responses.
"""
try:
# Get personality configuration
personality_config = self.get_personality_config(personality_type)
if not personality_config:
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"
# Check if model is initialized
if not self.model:
print("ERROR: Google AI model not initialized")
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"
# Construct the full prompt
system_prompt = personality_config['system_prompt']
user_message = message.strip()
# Build the conversation prompt with safety and clarity
full_prompt = f"""{system_prompt}
Now respond to this user message as your personality character:
"{user_message}"
Remember to stay completely in character and follow your personality guidelines exactly. Keep your response engaging and under 150 words."""
# Retry mechanism with exponential backoff
last_error = None
for attempt in range(1, self.max_retries + 1):
try:
response_text = self._make_api_request(full_prompt, attempt)
if response_text:
return response_text
# If empty response, wait and retry
if attempt < self.max_retries:
wait_time = min(self.base_delay * (2 ** (attempt - 1)) + random.uniform(0, 1), self.max_delay)
print(f"DEBUG: Empty response, retrying in {wait_time:.2f}s...")
time.sleep(wait_time)
except Exception as e:
last_error = str(e)
error_type = str(e)
# Handle different error types
if error_type == "QUOTA_EXCEEDED":
return "I'm currently experiencing high demand. Please try again in a few minutes! πŸ€–"
elif error_type == "MODEL_NOT_FOUND":
return "I'm having trouble with my AI model configuration. Please contact support! πŸ€–"
elif error_type == "PERMISSION_DENIED":
return "I'm having authentication issues. Please try again later! πŸ€–"
elif error_type in ["NETWORK_ERROR", "UNKNOWN_ERROR"]:
# These errors we can retry
if attempt < self.max_retries:
wait_time = min(self.base_delay * (2 ** (attempt - 1)) + random.uniform(0, 1), self.max_delay)
print(f"DEBUG: Network/unknown error, retrying in {wait_time:.2f}s...")
time.sleep(wait_time)
continue
# If it's the last attempt or a non-retryable error
if attempt == self.max_retries:
break
# All retries failed
print(f"ERROR: All {self.max_retries} API attempts failed. Last error: {last_error}")
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"
except Exception as e:
print(f"ERROR: Unexpected error in generate_response for {personality_type}: {str(e)}")
return "I'm having difficulty connecting to my AI brain right now. Please try again in a moment! πŸ€–"