import gspread import pandas as pd from oauth2client.service_account import ServiceAccountCredentials from transformers import BertForSequenceClassification, BertTokenizer import torch import streamlit as st from matplotlib import pyplot as plt import numpy as np from wordcloud import WordCloud # from PIL import ImageFont # from app5_selectbox.langchain_llama_gpu import llm_chain from app5_selectbox.g4f_prompt import g4f_prompt from app5_selectbox.df4_sentiment_analysis import sentiment_func # # Load the model and tokenizer # model = BertForSequenceClassification.from_pretrained("./sentiment_model") # tokenizer = BertTokenizer.from_pretrained("./sentiment_model") def eval_analysis(Instructor, Instructor_comment, criteria_results): # # Authenticate with Google Sheets API # scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"] # creds = ServiceAccountCredentials.from_json_keyfile_name('dataset-401003-7325e98039a4.json', scope) # client = gspread.authorize(creds) # # Open the spreadsheet by its title # spreadsheet = client.open('survey (Responses)') # # Select a specific worksheet # worksheet = spreadsheet.worksheet('Form Responses 1') # # Read data from the worksheet # data = worksheet.get_all_values() # # Create a Pandas DataFrame from the data # df = pd.DataFrame(data[1:], columns=data[0]) # Assuming the first row contains column headers # df = df.iloc[:, [1, 2]] # Filter columns # # # instructor_list = df.iloc[:, 0].unique() # instructor_list = sorted(instructor_list) # # print(instructor_list) # # Create a dropdown widget in the sidebar # option = st.sidebar.selectbox("Select an option", instructor_list) # # Filter rows containing "Instructor 1" # Instructor = df[df['Instructor'] == option] # Instructor_comment = Instructor['comment'].tolist() # ##################################################### BERT MODEL # def perform_sentiment_analysis(text): # inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True) # with torch.no_grad(): # outputs = model(**inputs) # logits = outputs.logits # predicted_class = torch.argmax(logits, dim=1).item() # sentiment_labels = ["negative", "neutral", "positive"] # sentiment = sentiment_labels[predicted_class] # return sentiment # from transformers import BertForSequenceClassification, BertTokenizer # # Load the model and tokenizer # model = BertForSequenceClassification.from_pretrained("./sentiment_model") # tokenizer = BertTokenizer.from_pretrained("./sentiment_model") # # sample_texts_tfidf = vectorizer.transform(sample_texts) # # sample_predictions = classifier.predict(sample_texts_tfidf) # sample_predictions = [] # # Initialize counters for sentiment classes # negative_count = 0 # neutral_count = 0 # positive_count = 0 # for text in Instructor_comment: # predicted_class = perform_sentiment_analysis(text) # print(f"Text: {text}") # print(f"Predicted Sentiment: {predicted_class}") # sample_predictions.append(predicted_class) # if predicted_class == "negative": # negative_count += 1 # elif predicted_class == "neutral": # neutral_count += 1 # else: # positive_count += 1 # print(f'negative_count {negative_count}') # print(f'neutral_count {neutral_count}') # print(f'positive_count {positive_count}') ################################################### scikit learn model # import joblib # # Load the model and vectorizer for predictions # loaded_model, loaded_vectorizer = joblib.load("MultinomialNB_Sentiment.pkl") # # Transform the new text data using the loaded vectorizer # new_text_features = loaded_vectorizer.transform(Instructor_comment) # # Make predictions using the loaded model # predicted_class = loaded_model.predict(new_text_features) # # print(f"Predicted class: {predicted_class}") # sample_predictions = [] # # Initialize counters for sentiment classes # negative_count = 0 # neutral_count = 0 # positive_count = 0 # for text, prediction in zip(Instructor_comment, predicted_class): # print(f"Text: {text}") # print(f"Predicted Sentiment: {prediction}") # sample_predictions.append(prediction) # if prediction == "negative": # negative_count += 1 # elif prediction == "neutral": # neutral_count += 1 # else: # positive_count += 1 # print(f'negative_count {negative_count}') # print(f'neutral_count {neutral_count}') # print(f'positive_count {positive_count}') ################################################### bert2 model import torch from transformers import BertTokenizer, BertForSequenceClassification import numpy as np # Load the saved model loaded_model = BertForSequenceClassification.from_pretrained('sentiment_model') tokenizerr = BertTokenizer.from_pretrained('bert-base-uncased', do_lower_case=True) # Encode the sample comments sample_encodings = tokenizerr(list(Instructor_comment), truncation=True, padding=True, max_length=128, return_tensors='pt') # Make predictions on the sample comments sample_input_ids = sample_encodings['input_ids'] sample_attention_mask = sample_encodings['attention_mask'] with torch.no_grad(): sample_outputs = loaded_model(sample_input_ids, attention_mask=sample_attention_mask) # Get predicted labels sample_logits = sample_outputs.logits sample_predictions = np.argmax(sample_logits, axis=1) # Map predicted labels back to sentiment labels sentiment_labels = ['negative', 'positive'] # predicted_sentiments = [sentiment_labels[label] for label in sample_predictions] predicted_sentiments = sentiment_func(Instructor_comment) print(predicted_sentiments) # # Print the comments and predicted sentiments # for comment, sentiment in zip(Instructor_comment, predicted_sentiments): # print(f"Comment: {comment}") # print(f"Predicted Sentiment: {sentiment}") # print() sample_predictions = [] # Initialize counters for sentiment classes negative_count = 0 neutral_count = 0 positive_count = 0 # print(predicted_sentiments) # print(Instructor_comment) for text, prediction in zip(Instructor_comment, predicted_sentiments): print(f"Text: {text}") print(f"Predicted Sentiment: {prediction}") sample_predictions.append(prediction) if prediction == "negative": negative_count += 1 elif prediction == "neutral": neutral_count += 1 else: positive_count += 1 print(f'negative_count {negative_count}') # print(f'neutral_count {neutral_count}') print(f'positive_count {positive_count}') ################################################### # Create a Streamlit app st.title("Sentiment Analysis Dashboard") st.sidebar.header("Settings") link_text = "Instructor Survey" link_url = "https://forms.gle/64n9CXMDRP2NYgZYA" st.sidebar.markdown(f"[{link_text}]({link_url})") # Display sentiment counts st.write("### Sentiment Counts") st.write(f"Negative: {negative_count}") # st.write(f"Neutral: {neutral_count}") st.write(f"Positive: {positive_count}") # Plot sentiment distribution sentiment_counts = pd.Series(np.array(sample_predictions)).value_counts() desired_order = ['positive', # 'neutral', 'negative'] sentiment_counts = sentiment_counts.reindex(desired_order, fill_value=0) percentage_distribution = sentiment_counts / len(sample_predictions) * 100 st.write("### Sentiment Distribution") fig, ax = plt.subplots(figsize=(8, 6)) bars = plt.bar(percentage_distribution.index, sentiment_counts.values, color=['green', 'orange', 'red']) plt.xlabel('Sentiment') plt.ylabel('Count') plt.title('Sentiment Distribution in Sample Predictions') plt.xticks(rotation=45) for bar, percentage, des_order in zip(bars, percentage_distribution, desired_order): height = bar.get_height() ax.text(bar.get_x() + bar.get_width() / 2, height, f'{percentage:.2f}% {des_order.upper()}', ha='center', va='bottom') st.pyplot(fig) st.set_option('deprecation.showPyplotGlobalUse', False) # Generate word clouds based on sentiment categories sentiment_texts = { 'positive': [], # 'neutral': [], 'negative': [] } for text, sentiment in zip(Instructor_comment, sample_predictions): sentiment_texts[sentiment].append(text) text_for_llama = "" for sentiment, texts in sentiment_texts.items(): combined_texts = ' '.join(texts) combined_texts = combined_texts.split() filtered_words = [word for word in combined_texts if len(word) > 2] combined_texts = ' '.join(filtered_words) if combined_texts =="": continue # Load your custom TrueType font using PIL font_path = "QuartzoBold-W9lv.ttf" # Replace with the path to your TTF font file # custom_font = ImageFont.truetyp e(font_path) # Adjust the font size as needed # Set the font family to use the TrueType font # font = ImageFont.truetype(font_path) wordcloud = WordCloud(font_path=font_path,width=800, height=600, background_color='white', max_words=15).generate(combined_texts) st.write(f"### Word Cloud for {sentiment} Sentiment") plt.figure(figsize=(10, 6)) plt.imshow(wordcloud, interpolation='bilinear') plt.axis('off') st.pyplot() if sentiment == "negative": # Extract the text from the word cloud object generated_text = wordcloud.words_ # Print the generated text for word, frequency in generated_text.items(): # print(f"{word}: {frequency}") text_for_llama += str(word)+" " # Generate a word cloud from all the text data all_text = ' '.join(Instructor_comment) all_text = all_text.split() filtered_words = [word for word in all_text if len(word) > 3] all_text = ' '.join(filtered_words) st.write("### Word Cloud for All Sentiments") wordcloud = WordCloud(font_path=font_path, width=800, height=800, background_color='white', max_words=200).generate(all_text) plt.figure(figsize=(8, 8), facecolor=None) plt.imshow(wordcloud) plt.axis("off") st.pyplot() neg_comments = [] pos_comments = [] # Print the comments and predicted sentiments for comment, sentiment in zip(Instructor_comment, predicted_sentiments): if sentiment == "positive": pos_comments.append(comment) else: neg_comments.append(comment) if text_for_llama == "": st.title("Expressing Gratitude and Dedication") text_for_llama = f""" There's no negative feedback/comments to the instructor, give him/her short email to say. [Your Name] = The Management [Instructor's Name] = {Instructor} """ else: st.title('Recommendation:') text_for_llama = text_for_llama.split() text_for_llama = ", ".join(text_for_llama) text_for_llama = f""" Based from these students' feedback: {str(text_for_llama)}. \n Please generate a short email to teh instructor having 10 recommendation in bullet format to the instructor. Make it in sentence type and in English language only. define the best email subject based from the recomendation [Your Name] = The Management [Instructor's Name] = {Instructor} """ # text_for_llama = f""" # Based from these students' feedback: {str(text_for_llama)}. \n # Please generate a short 10 recommendation in bullet format to the instructor. Make it in sentence type and in English language only. # """ # text_for_llama = f""" # Based from these students' feedback: {str(text_for_llama)}. \n # and Overall score per criteria results: {str(criteria_results)}. \n # Please generate a short 10 recommendation in bullet format to the instructor. Make it in sentence type and in English language only. # """ # Then give insights about the evaluation report based from different criteria. # Here is the results: {criteria_results} # Your response format- # Recommendation to Instructor: # Insights on Evaluation Report: prompt = text_for_llama # # ================================================ replicate.com # CUDA_LAUNCH_BLOCKING=1 # import replicate # replicate = replicate.Client(api_token='r8_M9Dx8VYKkuTcw1o39d4Yw0HtpWFt4k239ebvW') # output = replicate.run( # # "meta/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1", # "meta/llama-2-70b-chat:02e509c789964a7ea8736978a43525956ef40397be9033abf9fd2badfe68c9e3", # input={"prompt": prompt} # ) # st.write(output) # # The meta/llama-2-70b-chat model can stream output as it's running. # # The predict method returns an iterator, and you can iterate over that output. # # ================================================ # # st.title('Recommendation:') # # llama_output = "" # # with st.spinner("Generating Recommendation"): # # loading_text = st.empty() # # for item in reponse(prompt): # # llama_output +=item # # loading_text.write(llama_output) # # st.success("Generation Complete!") # # ================================================ local llama llm_chain while True: try: with st.spinner("Generating...."): # st.write(llm_chain.run(prompt)) # st.write(g4f_prompt(prompt)) ################# st.success("Generation Complete!") break except Exception as e: # Handle the error (e.g., log it or take appropriate action) # Sleep for a moment before retrying # st.write("Error occurred.. Retrying") pass # time.sleep(0.4) # # ================================================