joey1101 commited on
Commit
f26186a
·
verified ·
1 Parent(s): d090d86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -80
app.py CHANGED
@@ -2,15 +2,15 @@
2
  # Step 0: Import required libraries
3
  ##########################################
4
  import streamlit as st # For building the web application interface
5
- from transformers import (
6
  pipeline,
7
  SpeechT5Processor,
8
  SpeechT5ForTextToSpeech,
9
  SpeechT5HifiGan,
10
  AutoModelForCausalLM,
11
  AutoTokenizer
12
- ) # For sentiment 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
@@ -18,28 +18,28 @@ import sentencepiece # Required by SpeechT5Processor for tokenization
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=100,
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
  """
@@ -50,28 +50,29 @@ def analyze_dominant_emotion(user_review):
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 (1-3 sentences)\n\n"
75
  "Response:"
76
  )
77
  },
@@ -79,10 +80,10 @@ def prompt_gen(user_review):
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 (1-3 sentences)\n\n"
86
  "Response:"
87
  )
88
  },
@@ -90,10 +91,10 @@ def prompt_gen(user_review):
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 (1-3 sentences)\n\n"
97
  "Response:"
98
  )
99
  },
@@ -101,9 +102,9 @@ def prompt_gen(user_review):
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 (1-3 sentences)\n\n"
107
  "Response:"
108
  )
109
  },
@@ -111,10 +112,10 @@ def prompt_gen(user_review):
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 (1-3 sentences)\n\n"
118
  "Response:"
119
  )
120
  },
@@ -122,10 +123,10 @@ def prompt_gen(user_review):
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 (1-3 sentences)\n\n"
129
  "Response:"
130
  )
131
  },
@@ -133,70 +134,79 @@ def prompt_gen(user_review):
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 (1-3 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__":
 
2
  # Step 0: Import required libraries
3
  ##########################################
4
  import streamlit as st # For building the web application interface
5
+ from transformers import ( # For text classification, text-to-speech, and text generation
6
  pipeline,
7
  SpeechT5Processor,
8
  SpeechT5ForTextToSpeech,
9
  SpeechT5HifiGan,
10
  AutoModelForCausalLM,
11
  AutoTokenizer
12
+ )
13
+ from datasets import load_dataset # To load speaker embeddings dataset
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
 
18
  ##########################################
19
  # Streamlit application title and input
20
  ##########################################
21
+ # Display a deep blue title in a 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 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
+ ) # Set a friendly subtitle
32
 
33
+ # Add 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=100,
38
+ help="Write a comment you would like us to respond to!" # Provide tooltip
39
+ ) # Create text input field
40
 
41
  ##########################################
42
+ # Step 1: Sentiment Analysis Function
43
  ##########################################
44
  def analyze_dominant_emotion(user_review):
45
  """
 
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 for the input text
54
+ dominant_emotion = max(emotion_results, key=lambda x: x['score']) # Identify the emotion with highest score
55
+ return dominant_emotion # Return the dominant emotion (as a dict with label and score)
56
 
57
  ##########################################
58
  # Step 2: Response Generation Functions
59
  ##########################################
60
  def prompt_gen(user_review):
61
  """
62
+ Generate the text generation prompt based on the user's comment and detected emotion.
 
63
  """
64
+ # Get dominant emotion for the input
65
+ dominant_emotion = analyze_dominant_emotion(user_review) # Analyze user's comment
66
+ # Define response templates for 7 emotions
67
  emotion_strategies = {
68
  "anger": {
69
  "prompt": (
70
  "Customer complaint: '{review}'\n\n"
71
  "As a customer service representative, craft a professional response that:\n"
72
+ "- Begins with a sincere apology and acknowledgment.\n"
73
+ "- Clearly explains a solution process with concrete steps.\n"
74
+ "- Offers appropriate compensation or redemption.\n"
75
+ "- Keeps a humble and solution-focused tone (1-3 sentences).\n\n"
76
  "Response:"
77
  )
78
  },
 
80
  "prompt": (
81
  "Customer quality concern: '{review}'\n\n"
82
  "As a customer service representative, craft a response that:\n"
83
+ "- Immediately acknowledges the product issue.\n"
84
+ "- Explains measures taken in quality control.\n"
85
+ "- Provides clear return/replacement instructions.\n"
86
+ "- Offers a goodwill gesture (1-3 sentences).\n\n"
87
  "Response:"
88
  )
89
  },
 
91
  "prompt": (
92
  "Customer safety concern: '{review}'\n\n"
93
  "As a customer service representative, craft a reassuring response that:\n"
94
+ "- Directly addresses the safety worries.\n"
95
+ "- References relevant certifications or standards.\n"
96
+ "- Offers a dedicated support contact.\n"
97
+ "- Provides a satisfaction guarantee (1-3 sentences).\n\n"
98
  "Response:"
99
  )
100
  },
 
102
  "prompt": (
103
  "Customer review: '{review}'\n\n"
104
  "As a customer service representative, craft a concise response that:\n"
105
+ "- Thanks the customer for their feedback.\n"
106
+ "- Acknowledges both positive and constructive points.\n"
107
+ "- Invites them to explore loyalty or referral programs (1-3 sentences).\n\n"
108
  "Response:"
109
  )
110
  },
 
112
  "prompt": (
113
  "Customer feedback: '{review}'\n\n"
114
  "As a customer service representative, craft a balanced response that:\n"
115
+ "- Provides additional relevant product information.\n"
116
+ "- Highlights key service features.\n"
117
+ "- Politely requests more detailed feedback.\n"
118
+ "- Maintains a professional tone (1-3 sentences).\n\n"
119
  "Response:"
120
  )
121
  },
 
123
  "prompt": (
124
  "Customer disappointment: '{review}'\n\n"
125
  "As a customer service representative, craft an empathetic response that:\n"
126
+ "- Shows genuine understanding of the issue.\n"
127
+ "- Proposes a personalized recovery solution.\n"
128
+ "- Offers extended support options.\n"
129
+ "- Maintains a positive outlook (1-3 sentences).\n\n"
130
  "Response:"
131
  )
132
  },
 
134
  "prompt": (
135
  "Customer enthusiastic feedback: '{review}'\n\n"
136
  "As a customer service representative, craft a response that:\n"
137
+ "- Matches the customer's positive energy.\n"
138
+ "- Highlights unexpected product benefits.\n"
139
+ "- Invites the customer to join community events or programs.\n"
140
+ "- Maintains the brand's voice (1-3 sentences).\n\n"
141
  "Response:"
142
  )
143
  }
144
+ } # Dictionary mapping each emotion to a prompt template
145
+ # Get the template for the detected emotion, default to 'neutral' if not found
146
+ template = emotion_strategies.get(dominant_emotion["label"].lower(), emotion_strategies["neutral"])["prompt"]
147
+ prompt = template.format(review=user_review) # Insert the user review into the template
148
+ print(f"Generated prompt: {prompt}") # Debug print using f-string
149
+ return prompt # Return the generated prompt
150
 
151
  def response_gen(user_review):
152
  """
153
+ Generate a response using text generation based on the user's comment.
 
154
  """
155
+ prompt = prompt_gen(user_review) # Get the generated prompt using the detected emotion template
156
+ # Load the tokenizer and language model for text generation
157
+ tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B") # Load tokenizer for text generation
158
+ model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B") # Load causal language model for generation
159
+ inputs = tokenizer(prompt, return_tensors="pt") # Tokenize the prompt
160
+ outputs = model.generate(
161
+ **inputs,
162
+ max_new_tokens=100, # Allow up to 100 new tokens for the answer
163
+ min_length=30, # Ensure a minimum length for the generated response
164
+ no_repeat_ngram_size=2, # Avoid repeated phrases
165
+ temperature=0.7 # Use a moderate temperature for creativity
166
+ ) # Generate response from the model
167
+ input_length = inputs.input_ids.shape[1] # Determine length of the input prompt
168
+ response = tokenizer.decode(outputs[0][input_length:], skip_special_tokens=True) # Extract only generated answer text
169
+ print(f"Generated response: {response}") # Debug print using f-string
170
+ return response # Return the generated response
171
 
172
  ##########################################
173
  # Step 3: Text-to-Speech Conversion Function
174
  ##########################################
175
  def sound_gen(response):
176
  """
177
+ Convert the generated response to speech and embed an auto-playing audio player.
 
178
  """
179
+ # Load SpeechT5 processor, TTS model, and vocoder
180
+ processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts") # Load TTS processor
181
+ model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts") # Load TTS model
182
+ vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") # Load vocoder
183
+ # Process the full generated response text for TTS
184
+ inputs = processor(text=response, return_tensors="pt") # Convert text to model input tensors
185
+ # Use dummy speaker embeddings with shape (1,768) to avoid dimension mismatch
186
+ speaker_embeddings = torch.zeros(1, 768, dtype=torch.float32) # Create dummy speaker embedding
187
+ spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings) # Generate speech spectrogram
 
188
  with torch.no_grad():
189
+ speech = vocoder(spectrogram) # Convert spectrogram to waveform
190
+ # Save the audio as a .wav file with 16kHz sampling rate
191
+ sf.write("customer_service_response.wav", speech.numpy(), samplerate=16000) # Write the waveform to file
192
+ st.audio("customer_service_response.wav", start_time=0) # Embed an auto-playing audio widget
193
 
194
  ##########################################
195
  # Main Function
196
  ##########################################
197
  def main():
198
  """
199
+ Main function to orchestrate text generation and text-to-speech conversion.
200
+ It displays only the generated response and plays its audio.
201
  """
202
+ if text: # Check if the user has entered a comment
203
+ response = response_gen(text) # Generate a response using text generation based on emotion
204
  st.markdown(
205
  f"<p style='color:#3498DB; font-size:20px;'>{response}</p>",
206
  unsafe_allow_html=True
207
+ ) # Display the generated response in styled format
208
+ sound_gen(response) # Convert the generated response to speech and embed the audio player
209
+ print(f"Final generated response: {response}") # Debug print using f-string
210
 
211
  # Execute the main function when the script is run
212
  if __name__ == "__main__":