Spaces:
Sleeping
Sleeping
| import warnings | |
| import numpy as np | |
| import pandas as pd | |
| import os | |
| import json | |
| import random | |
| import gradio as gr | |
| import torch | |
| from sklearn.preprocessing import OneHotEncoder | |
| from transformers import AutoModelForSequenceClassification, AutoTokenizer, AutoModelForCausalLM, pipeline | |
| from deap import base, creator, tools, algorithms | |
| import nltk | |
| from nltk.sentiment import SentimentIntensityAnalyzer | |
| from nltk.tokenize import word_tokenize | |
| from nltk.tag import pos_tag | |
| from nltk.chunk import ne_chunk | |
| from textblob import TextBlob | |
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| from accelerate import init_empty_weights, load_checkpoint_and_dispatch | |
| warnings.filterwarnings('ignore', category=FutureWarning, module='huggingface_hub.file_download') | |
| # Download necessary NLTK data | |
| nltk.download('vader_lexicon', quiet=True) | |
| nltk.download('punkt', quiet=True) | |
| nltk.download('averaged_perceptron_tagger', quiet=True) | |
| nltk.download('maxent_ne_chunker', quiet=True) | |
| nltk.download('words', quiet=True) | |
| # Initialize Example Dataset (For Emotion Prediction) | |
| data = { | |
| 'context': [ | |
| 'I am happy', 'I am sad', 'I am angry', 'I am excited', 'I am calm', | |
| 'I am feeling joyful', 'I am grieving', 'I am feeling peaceful', 'I am frustrated', | |
| 'I am determined', 'I feel resentment', 'I am feeling glorious', 'I am motivated', | |
| 'I am surprised', 'I am fearful', 'I am trusting', 'I feel disgust', 'I am optimistic', | |
| 'I am pessimistic', 'I feel bored', 'I am envious' | |
| ], | |
| 'emotion': [ | |
| 'joy', 'sadness', 'anger', 'joy', 'calmness', 'joy', 'grief', 'calmness', 'anger', | |
| 'determination', 'resentment', 'glory', 'motivation', 'surprise', 'fear', 'trust', | |
| 'disgust', 'optimism', 'pessimism', 'boredom', 'envy' | |
| ] | |
| } | |
| df = pd.DataFrame(data) | |
| # Encoding the contexts using One-Hot Encoding (memory-efficient) | |
| try: | |
| encoder = OneHotEncoder(handle_unknown='ignore', sparse_output=True) | |
| except TypeError: | |
| encoder = OneHotEncoder(handle_unknown='ignore', sparse=True) | |
| contexts_encoded = encoder.fit_transform(df[['context']]) | |
| # Encoding emotions | |
| emotions_target = pd.Categorical(df['emotion']).codes | |
| emotion_classes = pd.Categorical(df['emotion']).categories | |
| # Load pre-trained BERT model for emotion prediction | |
| emotion_prediction_model = AutoModelForSequenceClassification.from_pretrained("bhadresh-savani/distilbert-base-uncased-emotion") | |
| emotion_prediction_tokenizer = AutoTokenizer.from_pretrained("bhadresh-savani/distilbert-base-uncased-emotion") | |
| # Load pre-trained large language model and tokenizer for response generation with increased context window | |
| response_model_name = "gpt2-xl" | |
| response_tokenizer = AutoTokenizer.from_pretrained(response_model_name) | |
| with init_empty_weights(): | |
| response_model = AutoModelForCausalLM.from_pretrained(response_model_name, device_map="auto", torch_dtype=torch.float16) | |
| # Set the pad token | |
| response_tokenizer.pad_token = response_tokenizer.eos_token | |
| # Enhanced Emotional States | |
| emotions = { | |
| 'joy': {'percentage': 10, 'motivation': 'positive', 'intensity': 0}, | |
| 'sadness': {'percentage': 10, 'motivation': 'negative', 'intensity': 0}, | |
| 'anger': {'percentage': 10, 'motivation': 'traumatic or strong', 'intensity': 0}, | |
| 'fear': {'percentage': 10, 'motivation': 'defensive', 'intensity': 0}, | |
| 'love': {'percentage': 10, 'motivation': 'affectionate', 'intensity': 0}, | |
| 'surprise': {'percentage': 10, 'motivation': 'unexpected', 'intensity': 0}, | |
| 'neutral': {'percentage': 40, 'motivation': 'balanced', 'intensity': 0}, | |
| } | |
| total_percentage = 100 | |
| emotion_history_file = 'emotion_history.json' | |
| global conversation_history | |
| conversation_history = [] | |
| max_history_length = 1000 # Increase the maximum history length | |
| def load_historical_data(file_path=emotion_history_file): | |
| if os.path.exists(file_path): | |
| with open(file_path, 'r') as file: | |
| return json.load(file) | |
| return [] | |
| def save_historical_data(historical_data, file_path=emotion_history_file): | |
| with open(file_path, 'w') as file: | |
| json.dump(historical_data, file) | |
| emotion_history = load_historical_data() | |
| def update_emotion(emotion, percentage, intensity): | |
| emotions[emotion]['percentage'] += percentage | |
| emotions[emotion]['intensity'] = intensity | |
| # Normalize percentages | |
| total = sum(e['percentage'] for e in emotions.values()) | |
| for e in emotions: | |
| emotions[e]['percentage'] = (emotions[e]['percentage'] / total) * 100 | |
| def normalize_context(context): | |
| return context.lower().strip() | |
| # Create FitnessMulti and Individual outside of evolve_emotions | |
| creator.create("FitnessMulti", base.Fitness, weights=(-1.0, -0.5, -0.2)) | |
| creator.create("Individual", list, fitness=creator.FitnessMulti) | |
| def evaluate(individual): | |
| emotion_values = individual[:len(emotions)] | |
| intensities = individual[len(emotions):] | |
| total_diff = abs(100 - sum(emotion_values)) | |
| intensity_range = max(intensities) - min(intensities) | |
| emotion_balance = max(emotion_values) - min(emotion_values) | |
| return total_diff, intensity_range, emotion_balance | |
| def evolve_emotions(): | |
| toolbox = base.Toolbox() | |
| toolbox.register("attr_float", random.uniform, 0, 100) | |
| toolbox.register("attr_intensity", random.uniform, 0, 10) | |
| toolbox.register("individual", tools.initCycle, creator.Individual, | |
| (toolbox.attr_float,) * len(emotions) + | |
| (toolbox.attr_intensity,) * len(emotions), n=1) | |
| toolbox.register("population", tools.initRepeat, list, toolbox.individual) | |
| toolbox.register("mate", tools.cxTwoPoint) | |
| toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.2) | |
| toolbox.register("select", tools.selNSGA2) | |
| toolbox.register("evaluate", evaluate) | |
| population = toolbox.population(n=100) | |
| algorithms.eaMuPlusLambda(population, toolbox, mu=50, lambda_=100, cxpb=0.7, mutpb=0.2, ngen=50, | |
| stats=None, halloffame=None, verbose=False) | |
| best_individual = tools.selBest(population, k=1)[0] | |
| emotion_values = best_individual[:len(emotions)] | |
| intensities = best_individual[len(emotions):] | |
| for i, (emotion, data) in enumerate(emotions.items()): | |
| data['percentage'] = emotion_values[i] | |
| data['intensity'] = intensities[i] | |
| # Normalize percentages | |
| total = sum(e['percentage'] for e in emotions.values()) | |
| for e in emotions: | |
| emotions[e]['percentage'] = (emotions[e]['percentage'] /total) * 100 | |
| def update_emotion_history(emotion, percentage, intensity, context): | |
| entry = { | |
| 'emotion': emotion, | |
| 'percentage': percentage, | |
| 'intensity': intensity, | |
| 'context': context, | |
| 'timestamp': pd.Timestamp.now().isoformat() | |
| } | |
| emotion_history.append(entry) | |
| save_historical_data(emotion_history) | |
| # Adding 443 features | |
| additional_features = {} | |
| for i in range(443): | |
| additional_features[f'feature_{i+1}'] = 0 | |
| def feature_transformations(): | |
| global additional_features | |
| for feature in additional_features: | |
| additional_features[feature] += random.uniform(-1, 1) | |
| def generate_response(input_text, ai_emotion, conversation_history): | |
| # Prepare a prompt based on the current emotion and input | |
| prompt = f"You are an AI assistant created by Sephiroth Baptiste, and you are currently feeling {ai_emotion}. Your response should reflect this emotion. Human: {input_text}\nAI:" | |
| # Add conversation history to the prompt | |
| for entry in conversation_history[-100:]: # Use last 100 entries for context | |
| prompt = f"Human: {entry['user']}\nAI: {entry['response']}\n" + prompt | |
| inputs = response_tokenizer(prompt, return_tensors="pt", padding=True, truncation=True, max_length=8192) | |
| # Adjust generation parameters based on emotion | |
| temperature = 0.7 | |
| if ai_emotion == 'anger': | |
| temperature = 0.9 # More randomness for angry responses | |
| elif ai_emotion == 'joy': | |
| temperature = 0.5 # More focused responses for joyful state | |
| with torch.no_grad(), torch.cuda.amp.autocast(): | |
| response_ids = response_model.generate( | |
| inputs.input_ids, | |
| attention_mask=inputs.attention_mask, | |
| max_length=8192, | |
| num_return_sequences=1, | |
| no_repeat_ngram_size=2, | |
| do_sample=True, | |
| top_k=50, | |
| top_p=0.95, | |
| temperature=temperature, | |
| pad_token_id=response_tokenizer.eos_token_id | |
| ) | |
| response = response_tokenizer.decode(response_ids[0], skip_special_tokens=True) | |
| # Extract only the AI's response | |
| response = response.split("AI:")[-1].strip() | |
| return response | |
| def predict_emotion(context): | |
| inputs = emotion_prediction_tokenizer(context, return_tensors="pt", truncation=True, max_length=512) | |
| with torch.no_grad(): | |
| outputs = emotion_prediction_model(**inputs) | |
| probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1) | |
| predicted_class = torch.argmax(probabilities, dim=-1).item() | |
| emotion_labels = ["sadness", "joy", "love", "anger", "fear", "surprise"] | |
| return emotion_labels[predicted_class] | |
| def sentiment_analysis(text): | |
| sia = SentimentIntensityAnalyzer() | |
| sentiment_scores = sia.polarity_scores(text) | |
| return sentiment_scores | |
| def extract_entities(text): | |
| chunked = ne_chunk(pos_tag(word_tokenize(text))) | |
| entities = [] | |
| for chunk in chunked: | |
| if hasattr(chunk, 'label'): | |
| entities.append(((' '.join(c[0] for c in chunk)), chunk.label())) | |
| return entities | |
| def analyze_text_complexity(text): | |
| blob = TextBlob(text) | |
| return { | |
| 'word_count': len(blob.words), | |
| 'sentence_count': len(blob.sentences), | |
| 'average_sentence_length': len(blob.words) / len(blob.sentences) if len(blob.sentences) > 0 else 0, | |
| 'polarity': blob.sentiment.polarity, | |
| 'subjectivity': blob.sentiment.subjectivity | |
| } | |
| def visualize_emotions(): | |
| emotions_df = pd.DataFrame([(e, d['percentage'], d['intensity']) for e, d in emotions.items()], | |
| columns=['Emotion', 'Percentage', 'Intensity']) | |
| plt.figure(figsize=(12, 6)) | |
| sns.barplot(x='Emotion', y='Percentage', data=emotions_df) | |
| plt.title('Current Emotional State') | |
| plt.xticks(rotation=45, ha='right') | |
| plt.tight_layout() | |
| plt.savefig('emotional_state.png') | |
| plt.close() | |
| return 'emotional_state.png' | |
| def interactive_interface(input_text): | |
| global conversation_history | |
| try: | |
| evolve_emotions() | |
| predicted_emotion = predict_emotion(input_text) | |
| sentiment_scores = sentiment_analysis(input_text) | |
| entities = extract_entities(input_text) | |
| text_complexity = analyze_text_complexity(input_text) | |
| # Update AI's emotional state based on input | |
| update_emotion(predicted_emotion, random.uniform(5, 15), random.uniform(0, 10)) | |
| # Determine AI's current dominant emotion | |
| ai_emotion = max(emotions, key=lambda e: emotions[e]['percentage']) | |
| # Generate response based on AI's emotion | |
| response = generate_response(input_text, ai_emotion, conversation_history) | |
| # Update conversation history | |
| conversation_history.append({ | |
| 'user': input_text, | |
| 'response': response | |
| }) | |
| # Trim conversation history if it exceeds the maximum length | |
| if len(conversation_history) > max_history_length: | |
| conversation_history = conversation_history[-max_history_length:] | |
| update_emotion_history(ai_emotion, emotions[ai_emotion]['percentage'], emotions[ai_emotion]['intensity'], input_text) | |
| feature_transformations() | |
| emotion_visualization = visualize_emotions() | |
| analysis_result = { | |
| 'predicted_user_emotion': predicted_emotion, | |
| 'ai_emotion': ai_emotion, | |
| 'sentiment_scores': sentiment_scores, | |
| 'entities': entities, | |
| 'text_complexity': text_complexity, | |
| 'response': response, | |
| 'emotion_visualization': emotion_visualization | |
| } | |
| return analysis_result | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| return { | |
| 'predicted_user_emotion': 'unknown', | |
| 'ai_emotion': 'neutral', | |
| 'sentiment_scores': {'compound': 0, 'neg': 0, 'neu': 1, 'pos': 0}, | |
| 'entities': [], | |
| 'text_complexity': {'word_count': 0, 'sentence_count': 0, 'average_sentence_length': 0, 'polarity': 0, 'subjectivity': 0}, | |
| 'response': "I'm sorry, but I encountered an error and was unable to generate a response.", | |
| 'emotion_visualization': 'emotional_state.png' | |
| } | |
| # Create a Gradio interface | |
| gr.Interface( | |
| fn=interactive_interface, | |
| inputs=gr.Textbox(label="Your Message"), | |
| outputs=[ | |
| gr.Textbox(label="Predicted User Emotion"), | |
| gr.Textbox(label="AI Emotion"), | |
| gr.Textbox(label="Sentiment Scores"), | |
| gr.Textbox(label="Extracted Entities"), | |
| gr.Textbox(label="Text Complexity"), | |
| gr.Textbox(label="AI Response"), | |
| gr.Image(label="Emotional State Visualization") | |
| ], | |
| title="Emotion-Aware AI Assistant by Sephfox", | |
| description="Interact with an AI assistant created by Sephfox that responds based on its emotional state.", | |
| ).launch() |