studfaceval / app5_selectbox /evaluation_analysis_g4f.py
MENG21's picture
9d38733
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)
# # ================================================