joey1101 commited on
Commit
b70e6a4
·
verified ·
1 Parent(s): 2253128

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +131 -141
app.py CHANGED
@@ -15,32 +15,31 @@ 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
  ##########################################
20
  # Streamlit application title and input
21
  ##########################################
22
- # Display a colorful, large title in a visually appealing font
23
  st.markdown(
24
- "<h1 style='text-align: center; color: #FF5720; font-size: 50px;'>Just Comment</h1>",
25
  unsafe_allow_html=True
26
- ) # Use HTML and CSS for a custom title design
27
 
28
- # Display a smaller, gentle subtitle below the title
29
  st.markdown(
30
  "<h3 style='text-align: center; color: #5D6D7E; font-style: italic;'>I'm listening to you, my friend</h3>",
31
  unsafe_allow_html=True
32
- ) # Use HTML for a friendly and soft-styled subtitle
33
 
34
- # Add a well-designed text area for user input
35
  text = st.text_area(
36
  "Enter your comment",
37
  placeholder="Type something here...",
38
  height=150,
39
- help="Write a comment you would like us to analyze and respond to!" # Provide a helpful tooltip
40
- )
41
 
42
  ##########################################
43
- # Step 1: Sentiment Analysis Function
44
  ##########################################
45
  def analyze_dominant_emotion(user_review):
46
  """
@@ -50,164 +49,155 @@ def analyze_dominant_emotion(user_review):
50
  "text-classification",
51
  model="Thea231/jhartmann_emotion_finetuning",
52
  return_all_scores=True
53
- ) # Load the fine-tuned text classification model from Hugging Face
54
-
55
- emotion_results = emotion_classifier(user_review)[0] # Perform sentiment analysis on the input text
56
- dominant_emotion = max(emotion_results, key=lambda x: x['score']) # Identify the emotion with the highest confidence
57
- return dominant_emotion # Return the dominant emotion (label and score)
58
-
59
 
60
  ##########################################
61
- # Step 2Response Generation Function
62
  ##########################################
63
-
64
  def prompt_gen(user_review):
65
- dominant_emotion = analyze_dominant_emotion(user_review)
66
- emotion_strategies = {
67
- "anger": {
68
- "prompt": (
69
- "Customer complaint: '{review}'\n\n"
70
- "As a customer service representative, craft a professional response that:\n"
71
- "- Begins with sincere apology and acknowledgment\n"
72
- "- Clearly explains solution process with concrete steps\n"
73
- "- Offers appropriate compensation/redemption\n"
74
- "- Keeps tone humble and solution-focused (3-4 sentences)\n\n"
75
- "Response:"
76
- )
77
- },
78
- "disgust": {
79
- "prompt": (
80
- "Customer quality concern: '{review}'\n\n"
81
- "As a customer service representative, craft a response that:\n"
82
- "- Immediately acknowledges the product issue\n"
83
- "- Explains quality control measures being taken\n"
84
- "- Provides clear return/replacement instructions\n"
85
- "- Offers goodwill gesture (3-4 sentences)\n\n"
86
- "Response:"
87
- )
88
- },
89
- "fear": {
90
- "prompt": (
91
- "Customer safety concern: '{review}'\n\n"
92
- "As a customer service representative, craft a reassuring response that:\n"
93
- "- Directly addresses the safety worries\n"
94
- "- References relevant certifications/standards\n"
95
- "- Offers dedicated support contact\n"
96
- "- Provides satisfaction guarantee (3-4 sentences)\n\n"
97
- "Response:"
98
- )
99
- },
100
- "joy": {
101
- "prompt": (
102
- "Customer review: '{review}'\n\n"
103
- "As a customer service representative, craft a concise response that:\n"
104
- "- Specifically acknowledges both positive and constructive feedback\n"
105
- "- Briefly mentions loyalty/referral programs\n"
106
- "- Ends with shopping invitation (3-4 sentences)\n\n"
107
- "Response:"
108
- )
109
- },
110
- "neutral": {
111
- "prompt": (
112
- "Customer feedback: '{review}'\n\n"
113
- "As a customer service representative, craft a balanced response that:\n"
114
- "- Provides additional relevant product information\n"
115
- "- Highlights key service features\n"
116
- "- Politely requests more detailed feedback\n"
117
- "- Maintains professional tone (3-4 sentences)\n\n"
118
- "Response:"
119
- )
120
- },
121
- "sadness": {
122
- "prompt": (
123
- "Customer disappointment: '{review}'\n\n"
124
- "As a customer service representative, craft an empathetic response that:\n"
125
- "- Shows genuine understanding of the issue\n"
126
- "- Proposes personalized recovery solution\n"
127
- "- Offers extended support options\n"
128
- "- Maintains positive outlook (3-4 sentences)\n\n"
129
- "Response:"
130
- )
131
- },
132
- "surprise": {
133
- "prompt": (
134
- "Customer enthusiastic feedback: '{review}'\n\n"
135
- "As a customer service representative, craft a response that:\n"
136
- "- Matches customer's positive energy appropriately\n"
137
- "- Highlights unexpected product benefits\n"
138
- "- Invites to user community/events\n"
139
- "- Maintains brand voice (3-4 sentences)\n\n"
140
- "Response:"
141
- )
142
- }
143
- }
144
-
145
- template = emotion_strategies[dominant_emotion['label'].lower()]["prompt"]
146
- prompt = template.format(review=user_review)
147
- print(prompt)
148
- return prompt
 
 
 
149
 
150
  def response_gen(user_review):
151
- prompt = prompt_gen(user_review)
152
- # Load model directly
153
- from transformers import AutoTokenizer, AutoModelForCausalLM
154
-
155
- tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B")
156
- model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B")
157
-
158
- inputs = tokenizer(prompt, return_tensors="pt")
159
- outputs = model.generate(**inputs, max_new_tokens=200)
160
-
161
- input_length = inputs.input_ids.shape[1]
162
- response = tokenizer.decode(outputs[0][input_length:], skip_special_tokens=True)
163
- # print(response)
164
- return response
165
-
166
-
167
 
168
  ##########################################
169
  # Step 3: Text-to-Speech Conversion Function
170
  ##########################################
171
  def sound_gen(response):
172
  """
173
- Convert the generated response to speech and save it as a .wav file.
 
174
  """
175
- processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts") # Pre-trained processor for TTS
176
- model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts") # Pre-trained TTS model
177
- vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") # Vocoder for generating waveforms
178
-
179
- # Create speaker embedding to match text input
180
- embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation") # Load speaker embeddings
181
- speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0) # Use a default embedding
182
-
183
- # Limit text tokens to match the model's capacity
184
- max_tokens = 200 # Limit the input text length to avoid tensor mismatch
185
- truncated_response = response[:max_tokens]
186
 
187
- inputs = processor(text=truncated_response, return_tensors="pt") # Process text for spectrogram generation
188
- spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings) # Generate the spectrogram
 
 
 
189
 
190
  with torch.no_grad():
191
- speech = vocoder(spectrogram) # Convert spectrogram to waveform
192
 
193
- sf.write("customer_service_response.wav", speech.numpy(), samplerate=16000) # Save as .wav file
194
- st.audio("customer_service_response.wav", start_time=0) # Embed an auto-playing audio player
195
 
196
  ##########################################
197
  # Main Function
198
  ##########################################
199
  def main():
200
  """
201
- Main function to handle sentiment analysis, response generation, and text-to-speech functionalities.
 
202
  """
203
- if text: # Check if the user has entered a comment
204
- response = response_gen(text) # Generate the response
205
  st.markdown(
206
  f"<p style='color:#3498DB; font-size:20px;'>{response}</p>",
207
  unsafe_allow_html=True
208
- ) # Display the response with styled formatting
209
  sound_gen(response) # Convert the response to speech and play it
 
210
 
211
- # Execute the main function
212
  if __name__ == "__main__":
213
- main()
 
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
+ # Display a deep blue title in large, visually appealing font
22
  st.markdown(
23
+ "<h1 style='text-align: center; color: #00008B; font-size: 50px;'>Just Comment</h1>",
24
  unsafe_allow_html=True
25
+ ) # Set a deep blue title
26
 
27
+ # Display a gentle, warm subtitle below the title
28
  st.markdown(
29
  "<h3 style='text-align: center; color: #5D6D7E; font-style: italic;'>I'm listening to you, my friend</h3>",
30
  unsafe_allow_html=True
31
+ ) # Show a friendly subtitle
32
 
33
+ # Provide a text area for user input with placeholder and tooltip
34
  text = st.text_area(
35
  "Enter your comment",
36
  placeholder="Type something here...",
37
  height=150,
38
+ help="Write a comment you would like us to respond to!" # Tooltip for guidance
39
+ ) # Create a text input area
40
 
41
  ##########################################
42
+ # Step 1: Sentiment Analysis Function (Unused here)
43
  ##########################################
44
  def analyze_dominant_emotion(user_review):
45
  """
 
49
  "text-classification",
50
  model="Thea231/jhartmann_emotion_finetuning",
51
  return_all_scores=True
52
+ ) # Load the sentiment classification model
53
+ emotion_results = emotion_classifier(user_review)[0] # Get sentiment scores of the input
54
+ dominant_emotion = max(emotion_results, key=lambda x: x['score']) # Find the highest scoring emotion
55
+ return dominant_emotion # Return the dominant emotion
 
 
56
 
57
  ##########################################
58
+ # Step 2: Response Generation Functions
59
  ##########################################
 
60
  def prompt_gen(user_review):
61
+ """
62
+ Generate a prompt based on the user's comment and detected emotion.
63
+ This function is defined but not used, as the response is fixed.
64
+ """
65
+ dominant_emotion = analyze_dominant_emotion(user_review) # Determine the dominant emotion
66
+ emotion_strategies = {
67
+ "anger": {
68
+ "prompt": (
69
+ "Customer complaint: '{review}'\n\n"
70
+ "As a customer service representative, craft a professional response that:\n"
71
+ "- Begins with sincere apology and acknowledgment\n"
72
+ "- Clearly explains solution process with concrete steps\n"
73
+ "- Offers appropriate compensation/redemption\n"
74
+ "- Keeps tone humble and solution-focused (3-4 sentences)\n\n"
75
+ "Response:"
76
+ )
77
+ },
78
+ "disgust": {
79
+ "prompt": (
80
+ "Customer quality concern: '{review}'\n\n"
81
+ "As a customer service representative, craft a response that:\n"
82
+ "- Immediately acknowledges the product issue\n"
83
+ "- Explains quality control measures being taken\n"
84
+ "- Provides clear return/replacement instructions\n"
85
+ "- Offers goodwill gesture (3-4 sentences)\n\n"
86
+ "Response:"
87
+ )
88
+ },
89
+ "fear": {
90
+ "prompt": (
91
+ "Customer safety concern: '{review}'\n\n"
92
+ "As a customer service representative, craft a reassuring response that:\n"
93
+ "- Directly addresses the safety worries\n"
94
+ "- References relevant certifications/standards\n"
95
+ "- Offers dedicated support contact\n"
96
+ "- Provides satisfaction guarantee (3-4 sentences)\n\n"
97
+ "Response:"
98
+ )
99
+ },
100
+ "joy": {
101
+ "prompt": (
102
+ "Customer review: '{review}'\n\n"
103
+ "As a customer service representative, craft a concise response that:\n"
104
+ "- Specifically acknowledges both positive and constructive feedback\n"
105
+ "- Briefly mentions loyalty/referral programs\n"
106
+ "- Ends with shopping invitation (3-4 sentences)\n\n"
107
+ "Response:"
108
+ )
109
+ },
110
+ "neutral": {
111
+ "prompt": (
112
+ "Customer feedback: '{review}'\n\n"
113
+ "As a customer service representative, craft a balanced response that:\n"
114
+ "- Provides additional relevant product information\n"
115
+ "- Highlights key service features\n"
116
+ "- Politely requests more detailed feedback\n"
117
+ "- Maintains professional tone (3-4 sentences)\n\n"
118
+ "Response:"
119
+ )
120
+ },
121
+ "sadness": {
122
+ "prompt": (
123
+ "Customer disappointment: '{review}'\n\n"
124
+ "As a customer service representative, craft an empathetic response that:\n"
125
+ "- Shows genuine understanding of the issue\n"
126
+ "- Proposes personalized recovery solution\n"
127
+ "- Offers extended support options\n"
128
+ "- Maintains positive outlook (3-4 sentences)\n\n"
129
+ "Response:"
130
+ )
131
+ },
132
+ "surprise": {
133
+ "prompt": (
134
+ "Customer enthusiastic feedback: '{review}'\n\n"
135
+ "As a customer service representative, craft a response that:\n"
136
+ "- Matches customer's positive energy appropriately\n"
137
+ "- Highlights unexpected product benefits\n"
138
+ "- Invites to user community/events\n"
139
+ "- Maintains brand voice (3-4 sentences)\n\n"
140
+ "Response:"
141
+ )
142
+ }
143
+ } # Mapping of each emotion to its response template
144
+ template = emotion_strategies[dominant_emotion['label'].lower()]["prompt"] # Select template based on emotion
145
+ prompt = template.format(review=user_review) # Format the template with the user's review
146
+ print(f"Prompt generated: {prompt}") # Debug: print the generated prompt using an f-string
147
+ return prompt # Return the constructed prompt
148
 
149
  def response_gen(user_review):
150
+ """
151
+ Generate a response based on the user's comment.
152
+ For this application, always return a fixed response message.
153
+ """
154
+ fixed_response = ("Dear [Customer], I'm sorry to hear that you're experiencing a delay in delivery. "
155
+ "I understand how frustrating it can be when you're expecting a dress that you love. "
156
+ "I'd be happy to help you resolve this issue.")
157
+ print(f"Response generated: {fixed_response}") # Debug: print the generated response using an f-string
158
+ return fixed_response # Return the fixed response message
 
 
 
 
 
 
 
159
 
160
  ##########################################
161
  # Step 3: Text-to-Speech Conversion Function
162
  ##########################################
163
  def sound_gen(response):
164
  """
165
+ Convert the fixed response to speech and save it as a .wav file,
166
+ then embed an auto-playing audio player.
167
  """
168
+ processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts") # Load the TTS processor
169
+ model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts") # Load the TTS model
170
+ vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") # Load the vocoder for waveform generation
 
 
 
 
 
 
 
 
171
 
172
+ # Process the full response text (no truncation) for spectrogram generation
173
+ inputs = processor(text=response, return_tensors="pt") # Tokenize and process the response text for TTS
174
+ # Use dummy speaker embeddings (zeros) with the expected dimension (1 x 768)
175
+ speaker_embeddings = torch.zeros(1, 768) # Create placeholder speaker embeddings
176
+ spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings) # Generate the speech spectrogram
177
 
178
  with torch.no_grad():
179
+ speech = vocoder(spectrogram) # Convert the spectrogram to an audio waveform using the vocoder
180
 
181
+ sf.write("customer_service_response.wav", speech.numpy(), samplerate=16000) # Save the waveform as a .wav file
182
+ st.audio("customer_service_response.wav", start_time=0) # Embed an audio player that autoplays the audio
183
 
184
  ##########################################
185
  # Main Function
186
  ##########################################
187
  def main():
188
  """
189
+ The main function orchestrates response generation and text-to-speech conversion.
190
+ It displays only the fixed response and plays its audio.
191
  """
192
+ if text: # Check if the user has entered a comment (although the response is fixed)
193
+ response = response_gen(text) # Generate the fixed response message
194
  st.markdown(
195
  f"<p style='color:#3498DB; font-size:20px;'>{response}</p>",
196
  unsafe_allow_html=True
197
+ ) # Display the response in styled formatting (only the fixed message is shown)
198
  sound_gen(response) # Convert the response to speech and play it
199
+ print(f"Final response output: {response}") # Debug: print the final response using an f-string
200
 
201
+ # Execute the main function when the script is run
202
  if __name__ == "__main__":
203
+ main() # Call the main function