joey1101 commited on
Commit
40fdf9a
·
verified ·
1 Parent(s): d49b90d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -119
app.py CHANGED
@@ -2,171 +2,97 @@
2
  # Step 0: Import required libraries
3
  ##########################################
4
  import streamlit as st # For building the web application
5
- from transformers import (
6
- pipeline,
7
- SpeechT5Processor,
8
- SpeechT5ForTextToSpeech,
9
- SpeechT5HifiGan,
10
- AutoModelForCausalLM,
11
- AutoTokenizer
12
  ) # For emotion analysis, text-to-speech, and text generation
13
  from datasets import load_dataset # For loading datasets (e.g., speaker embeddings)
14
  import torch # For tensor operations
15
  import soundfile as sf # For saving audio as .wav files
16
- import sentencepiece # Required by SpeechT5Processor for tokenization
17
 
18
  ##########################################
19
  # Streamlit application title and input
20
  ##########################################
21
-
22
  st.title("🚀 Just Comment") # Application title displayed to users
23
  st.write("I'm listening to you, my friend~") # Application description for users
24
  text = st.text_area("Enter your comment", "") # Text area for user input of comments
25
 
26
-
27
  ##########################################
28
  # Step 1: Sentiment Analysis Function
29
  ##########################################
30
  def analyze_dominant_emotion(user_review):
31
- """
32
- Analyze the dominant emotion in the user's review using a text classification model.
33
- """
34
- emotion_classifier = pipeline(
35
- "text-classification",
36
- model="Thea231/jhartmann_emotion_finetuning",
37
- return_all_scores=True
38
- ) # Load our fine-tuned emotion classification model
39
-
40
  emotion_results = emotion_classifier(user_review)[0] # Get emotion scores for the review
41
  dominant_emotion = max(emotion_results, key=lambda x: x['score']) # Find the emotion with the highest confidence
42
- return dominant_emotion # Return the dominant emotion (as a dict with label and score)
43
 
44
  ##########################################
45
  # Step 2: Response Generation Function
46
  ##########################################
47
  def response_gen(user_review):
48
- """
49
- Generate a response based on the sentiment of the user's review.
50
- """
51
- # Get dominant emotion for the input
52
- dominant_emotion = analyze_dominant_emotion(user_review) # Get the dominant emotion
53
  emotion_label = dominant_emotion['label'].lower() # Extract emotion label
54
-
55
- # Define response templates for each emotion
56
  emotion_prompts = {
57
- "anger": (
58
- "Customer complaint: '{review}'\n\n"
59
- "As a customer service representative, write a response that:\n"
60
- "- Sincerely apologizes for the issue\n"
61
- "- Explains how the issue will be resolved\n"
62
- "- Offers compensation where appropriate\n\n"
63
- "Response:"
64
- ),
65
- "joy": (
66
- "Customer review: '{review}'\n\n"
67
- "As a customer service representative, write a positive response that:\n"
68
- "- Thanks the customer for their feedback\n"
69
- "- Acknowledges both positive and constructive comments\n"
70
- "- Invites them to explore loyalty programs\n\n"
71
- "Response:"
72
- ),
73
- "disgust": (
74
- "Customer quality concern: '{review}'\n\n"
75
- "As a customer service representative, craft a response that:\n"
76
- "- Immediately acknowledges the product issue.\n"
77
- "- Explains measures taken in quality control.\n"
78
- "- Provides clear return/replacement instructions.\n"
79
- "- Offers a goodwill gesture (1-3 sentences).\n\n"
80
- "Response:"
81
- ),
82
- "fear": (
83
- "Customer safety concern: '{review}'\n\n"
84
- "As a customer service representative, craft a reassuring response that:\n"
85
- "- Directly addresses the safety worries.\n"
86
- "- References relevant certifications or standards.\n"
87
- "- Offers a dedicated support contact.\n"
88
- "- Provides a satisfaction guarantee (1-3 sentences).\n\n"
89
- "Response:"
90
- ),
91
- "neutral": (
92
- "Customer feedback: '{review}'\n\n"
93
- "As a customer service representative, craft a balanced response that:\n"
94
- "- Provides additional relevant product information.\n"
95
- "- Highlights key service features.\n"
96
- "- Politely requests more detailed feedback.\n"
97
- "- Maintains a professional tone (1-3 sentences).\n\n"
98
- "Response:"
99
- ),
100
- "sadness": (
101
- "Customer disappointment: '{review}'\n\n"
102
- "As a customer service representative, craft an empathetic response that:\n"
103
- "- Shows genuine understanding of the issue.\n"
104
- "- Proposes a personalized recovery solution.\n"
105
- "- Offers extended support options.\n"
106
- "- Maintains a positive outlook (1-3 sentences).\n\n"
107
- "Response:"
108
- ),
109
- "surprise": (
110
- "Customer enthusiastic feedback: '{review}'\n\n"
111
- "As a customer service representative, craft a response that:\n"
112
- "- Matches the customer's positive energy.\n"
113
- "- Highlights unexpected product benefits.\n"
114
- "- Invites the customer to join community events or programs.\n"
115
- "- Maintains the brand's voice (1-3 sentences).\n\n"
116
- "Response:"
117
- ),
118
-
119
-
120
  }
121
-
122
  # Format the prompt with the user's review
123
  prompt = emotion_prompts.get(emotion_label, "Neutral").format(review=user_review)
124
-
125
- # Load a pre-trained text generation model (replace 'meta-llama/Llama-3.2-1B' with an available model)
126
- tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B")
127
- model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B")
128
  inputs = tokenizer(prompt, return_tensors="pt") # Tokenize the prompt
 
129
  outputs = model.generate(**inputs, max_new_tokens=100) # Generate a response
130
-
131
- input_length = inputs.input_ids.shape[1] # Length of the input text
132
- response = tokenizer.decode(outputs[0][input_length:], skip_special_tokens=True) # Decode the generated text
133
- return response
134
 
135
  ##########################################
136
  # Step 3: Text-to-Speech Conversion Function
137
  ##########################################
138
  def sound_gen(response):
139
- """
140
- Convert the generated response to speech and save as a .wav file.
141
- """
142
  # Load the pre-trained TTS models
143
- processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
144
- model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
145
- vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
146
-
147
  # Load speaker embeddings (e.g., neutral female voice)
148
- embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")
149
- speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)
150
-
151
  # Process the input text and generate a spectrogram
152
- inputs = processor(text=response, return_tensors="pt")
153
- spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)
154
-
155
  # Use the vocoder to generate a waveform
156
  with torch.no_grad():
157
- speech = vocoder(spectrogram)
158
-
159
  # Save the generated speech as a .wav file
160
- sf.write("customer_service_response.wav", speech.numpy(), samplerate=16000)
161
  st.audio("customer_service_response.wav") # Play the audio in Streamlit
162
 
163
  ##########################################
164
  # Main Function
165
  ##########################################
166
  def main():
167
- """
168
- Main function to orchestrate the workflow of sentiment analysis, response generation, and text-to-speech.
169
- """
170
  if text: # Check if the user entered a comment
171
  response = response_gen(text) # Generate a response
172
  st.write(f"Generated response: {response}") # Display the generated response
@@ -174,4 +100,4 @@ def main():
174
 
175
  # Run the main function
176
  if __name__ == "__main__":
177
- main()
 
2
  # Step 0: Import required libraries
3
  ##########################################
4
  import streamlit as st # For building the web application
5
+ from transformers import (
6
+ pipeline,
7
+ SpeechT5Processor,
8
+ SpeechT5ForTextToSpeech,
9
+ SpeechT5HifiGan,
10
+ AutoModelForCausalLM,
11
+ AutoTokenizer
12
  ) # For emotion analysis, text-to-speech, and text generation
13
  from datasets import load_dataset # For loading datasets (e.g., speaker embeddings)
14
  import torch # For tensor operations
15
  import soundfile as sf # For saving audio as .wav files
 
16
 
17
  ##########################################
18
  # Streamlit application title and input
19
  ##########################################
 
20
  st.title("🚀 Just Comment") # Application title displayed to users
21
  st.write("I'm listening to you, my friend~") # Application description for users
22
  text = st.text_area("Enter your comment", "") # Text area for user input of comments
23
 
 
24
  ##########################################
25
  # Step 1: Sentiment Analysis Function
26
  ##########################################
27
  def analyze_dominant_emotion(user_review):
28
+ """ Analyze the dominant emotion in the user's review using a text classification model. """
29
+ emotion_classifier = pipeline("text-classification", model="Thea231/jhartmann_emotion_finetuning", return_all_scores=True) # Load emotion classification model
 
 
 
 
 
 
 
30
  emotion_results = emotion_classifier(user_review)[0] # Get emotion scores for the review
31
  dominant_emotion = max(emotion_results, key=lambda x: x['score']) # Find the emotion with the highest confidence
32
+ return dominant_emotion # Return the dominant emotion (as a dict with label and score)
33
 
34
  ##########################################
35
  # Step 2: Response Generation Function
36
  ##########################################
37
  def response_gen(user_review):
38
+ """ Generate a response based on the sentiment of the user's review. """
39
+ dominant_emotion = analyze_dominant_emotion(user_review) # Get dominant emotion for the input
 
 
 
40
  emotion_label = dominant_emotion['label'].lower() # Extract emotion label
41
+
42
+ # Define response templates for each emotion
43
  emotion_prompts = {
44
+ "anger": "I appreciate your feedback and apologize for the inconvenience caused by '{review}'. We're committed to resolving this issue promptly and will ensure it doesn't happen again. Thank you for your patience.",
45
+ "joy": "Thank you for your positive feedback on '{review}'! We're thrilled to hear you had a great experience and hope to serve you again soon.",
46
+ "disgust": "We regret that your experience with '{review}' did not meet our standards. We will take immediate steps to address this issue and appreciate your understanding.",
47
+ "fear": "Your safety is our priority. Regarding your concern about '{review}', we ensure that all our products meet strict safety standards. Please feel free to reach out for further assistance.",
48
+ "neutral": "Thank you for your feedback on '{review}'. We value your input and would love to hear more about your experience to improve our services.",
49
+ "sadness": "I'm sorry to hear that you were disappointed with '{review}'. We're here to help and would like to offer you a solution tailored to your needs.",
50
+ "surprise": "We're glad to hear that '{review}' exceeded your expectations! Thank you for sharing your excitement with us."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
+
53
  # Format the prompt with the user's review
54
  prompt = emotion_prompts.get(emotion_label, "Neutral").format(review=user_review)
55
+
56
+ # Load a pre-trained text generation model
57
+ tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B") # Load tokenizer
58
+ model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B") # Load model
59
  inputs = tokenizer(prompt, return_tensors="pt") # Tokenize the prompt
60
+
61
  outputs = model.generate(**inputs, max_new_tokens=100) # Generate a response
62
+ response = tokenizer.decode(outputs[0], skip_special_tokens=True) # Decode the generated text
63
+ return response.strip()[:200] # Return a response trimmed to 200 characters
 
 
64
 
65
  ##########################################
66
  # Step 3: Text-to-Speech Conversion Function
67
  ##########################################
68
  def sound_gen(response):
69
+ """ Convert the generated response to speech and save as a .wav file. """
 
 
70
  # Load the pre-trained TTS models
71
+ processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts") # Load processor
72
+ model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts") # Load TTS model
73
+ vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") # Load vocoder
74
+
75
  # Load speaker embeddings (e.g., neutral female voice)
76
+ embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation") # Load dataset
77
+ speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0) # Get speaker embeddings
78
+
79
  # Process the input text and generate a spectrogram
80
+ inputs = processor(text=response, return_tensors="pt") # Process the text
81
+ spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings) # Generate spectrogram
82
+
83
  # Use the vocoder to generate a waveform
84
  with torch.no_grad():
85
+ speech = vocoder(spectrogram) # Generate speech waveform
86
+
87
  # Save the generated speech as a .wav file
88
+ sf.write("customer_service_response.wav", speech.numpy(), samplerate=16000) # Save audio
89
  st.audio("customer_service_response.wav") # Play the audio in Streamlit
90
 
91
  ##########################################
92
  # Main Function
93
  ##########################################
94
  def main():
95
+ """ Main function to orchestrate the workflow of sentiment analysis, response generation, and text-to-speech. """
 
 
96
  if text: # Check if the user entered a comment
97
  response = response_gen(text) # Generate a response
98
  st.write(f"Generated response: {response}") # Display the generated response
 
100
 
101
  # Run the main function
102
  if __name__ == "__main__":
103
+ main() # Execute the main function