joey1101 commited on
Commit
05be7ae
ยท
verified ยท
1 Parent(s): 69c8028

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -79
app.py CHANGED
@@ -1,7 +1,7 @@
1
  ##########################################
2
  # Step 0: Import required libraries
3
  ##########################################
4
- import streamlit as st # Web app framework
5
  from transformers import (
6
  pipeline,
7
  SpeechT5Processor,
@@ -9,17 +9,17 @@ from transformers import (
9
  SpeechT5HifiGan,
10
  AutoModelForCausalLM,
11
  AutoTokenizer
12
- ) # NLP and TTS models
13
- from datasets import load_dataset # Speaker embeddings
14
- import torch # Tensor operations
15
- import soundfile as sf # Audio file handling
16
- import sentencepiece # Tokenization dependency
17
 
18
  ##########################################
19
  # Initial configuration (MUST be first)
20
  ##########################################
21
  st.set_page_config(
22
- page_title="๐Ÿš€ Just Comment",
23
  page_icon="๐Ÿ’ฌ",
24
  layout="centered",
25
  initial_sidebar_state="collapsed"
@@ -32,22 +32,15 @@ st.set_page_config(
32
  def load_models():
33
  """Load and cache all ML models"""
34
  return {
35
- # Emotion classifier
36
  'emotion': pipeline(
37
  "text-classification",
38
  model="Thea231/jhartmann_emotion_finetuning"
39
  ),
40
-
41
- # Text generation models
42
  'textgen_tokenizer': AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B"),
43
  'textgen_model': AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B"),
44
-
45
- # TTS components
46
  'tts_processor': SpeechT5Processor.from_pretrained("microsoft/speecht5_tts"),
47
  'tts_model': SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts"),
48
  'tts_vocoder': SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan"),
49
-
50
- # Speaker embeddings
51
  'speaker_embeddings': torch.tensor(
52
  load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")[7306]["xvector"]
53
  ).unsqueeze(0)
@@ -57,13 +50,13 @@ def load_models():
57
  # UI Components
58
  ##########################################
59
  def render_interface():
60
- """Create user interface elements"""
61
- st.title("๐Ÿš€ I'm listening to you, my friend๏ฝž")
62
- st.caption("Analyzes feedback and tell tailored responses")
63
 
64
  return st.text_area(
65
- "๐Ÿ“ Paste customer feedback here:",
66
- placeholder="The product arrived damaged...",
67
  height=150,
68
  key="user_input"
69
  )
@@ -72,88 +65,80 @@ def render_interface():
72
  # Core Logic Components
73
  ##########################################
74
  def analyze_emotion(text, classifier):
75
- """Determine dominant emotion with confidence threshold"""
76
  results = classifier(text, return_all_scores=True)[0]
77
- top_emotion = max(results, key=lambda x: x['score'])
78
- return top_emotion if top_emotion['score'] > 0.6 else {'label': 'neutral', 'score': 1.0}
 
79
 
80
  def generate_prompt(text, emotion):
81
- """Create structured prompts for different emotions"""
82
  prompt_templates = {
83
- "anger": (
84
- "Customer complaint: {input}\n"
85
- "Respond with:\n"
86
- "1. Apology\n2. Solution steps\n3. Compensation offer\n"
87
- "Response:"
88
  ),
89
  "joy": (
90
  "Positive feedback: {input}\n"
91
- "Respond with:\n"
92
- "1. Appreciation\n2. Highlight strengths\n3. Loyalty benefits\n"
93
- "Response:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  ),
95
- "neutral": (
96
- "Customer comment: {input}\n"
97
- "Respond with:\n"
98
- "1. Acknowledge feedback\n2. Offer assistance\n3. Next steps\n"
99
- "Response:"
100
  )
101
  }
102
- return prompt_templates.get(emotion.lower(), prompt_templates['neutral']).format(input=text)
103
 
104
  def process_response(output_text):
105
- """Ensure response quality and proper formatting"""
106
- # Remove incomplete sentences
107
- if '.' in output_text:
108
- output_text = output_text.rsplit('.', 1)[0] + '.'
109
-
110
- # Length constraints
111
- output_text = output_text[:300].strip() # Hard limit at 300 characters
112
-
113
- # Fallback for short responses
114
- if len(output_text) < 50:
115
- return "Thank you for your feedback. We'll review this and contact you shortly."
116
-
117
- return output_text
118
 
119
  def generate_text_response(user_input, models):
120
- """Generate and validate text response"""
121
- # Emotion analysis
122
  emotion = analyze_emotion(user_input, models['emotion'])
123
-
124
- # Prompt engineering
125
  prompt = generate_prompt(user_input, emotion['label'])
126
 
127
- # Text generation
128
  inputs = models['textgen_tokenizer'](prompt, return_tensors="pt")
129
  outputs = models['textgen_model'].generate(
130
  inputs.input_ids,
131
- max_new_tokens=100,
132
  temperature=0.7,
133
  do_sample=True,
134
  top_p=0.9
135
  )
136
 
137
- # Decode and process
138
- full_response = models['textgen_tokenizer'].decode(outputs[0], skip_special_tokens=True)
139
- return process_response(full_response.split("Response:")[-1].strip())
140
 
141
  def generate_audio_response(text, models):
142
- """Convert text to speech"""
143
- # Process text input
144
  inputs = models['tts_processor'](text=text, return_tensors="pt")
145
-
146
- # Generate spectrogram
147
  spectrogram = models['tts_model'].generate_speech(
148
  inputs["input_ids"],
149
  models['speaker_embeddings']
150
  )
151
-
152
- # Generate waveform
153
  with torch.no_grad():
154
  waveform = models['tts_vocoder'](spectrogram)
155
-
156
- # Save and return audio
157
  sf.write("response.wav", waveform.numpy(), samplerate=16000)
158
  return "response.wav"
159
 
@@ -161,25 +146,20 @@ def generate_audio_response(text, models):
161
  # Main Application Flow
162
  ##########################################
163
  def main():
164
- # Load models once
165
  ml_models = load_models()
166
-
167
- # Render UI
168
  user_input = render_interface()
169
 
170
- # Process input
171
  if user_input:
172
- # Text generation
173
- with st.status("๐Ÿ” Analyzing feedback...", expanded=True) as status:
174
  text_response = generate_text_response(user_input, ml_models)
175
- status.update(label="โœ… Analysis Complete", state="complete")
176
 
177
- # Display text response
178
- st.subheader("๐Ÿ“ Generated Response")
179
- st.markdown(f"```\n{text_response}\n```")
180
 
181
- # Audio generation
182
- with st.spinner("๐Ÿ”Š Generating voice response..."):
183
  audio_file = generate_audio_response(text_response, ml_models)
184
  st.audio(audio_file, format="audio/wav")
185
 
 
1
  ##########################################
2
  # Step 0: Import required libraries
3
  ##########################################
4
+ import streamlit as st
5
  from transformers import (
6
  pipeline,
7
  SpeechT5Processor,
 
9
  SpeechT5HifiGan,
10
  AutoModelForCausalLM,
11
  AutoTokenizer
12
+ )
13
+ from datasets import load_dataset
14
+ import torch
15
+ import soundfile as sf
16
+ import sentencepiece
17
 
18
  ##########################################
19
  # Initial configuration (MUST be first)
20
  ##########################################
21
  st.set_page_config(
22
+ page_title="Just Comment",
23
  page_icon="๐Ÿ’ฌ",
24
  layout="centered",
25
  initial_sidebar_state="collapsed"
 
32
  def load_models():
33
  """Load and cache all ML models"""
34
  return {
 
35
  'emotion': pipeline(
36
  "text-classification",
37
  model="Thea231/jhartmann_emotion_finetuning"
38
  ),
 
 
39
  'textgen_tokenizer': AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B"),
40
  'textgen_model': AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B"),
 
 
41
  'tts_processor': SpeechT5Processor.from_pretrained("microsoft/speecht5_tts"),
42
  'tts_model': SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts"),
43
  'tts_vocoder': SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan"),
 
 
44
  'speaker_embeddings': torch.tensor(
45
  load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")[7306]["xvector"]
46
  ).unsqueeze(0)
 
50
  # UI Components
51
  ##########################################
52
  def render_interface():
53
+ """Create user interface"""
54
+ st.title("Just Comment")
55
+ st.markdown("### I'm listening to you, my friend๏ฝž")
56
 
57
  return st.text_area(
58
+ "๐Ÿ“ Enter your comment:",
59
+ placeholder="Share your thoughts...",
60
  height=150,
61
  key="user_input"
62
  )
 
65
  # Core Logic Components
66
  ##########################################
67
  def analyze_emotion(text, classifier):
68
+ """Determine emotion with quick analysis"""
69
  results = classifier(text, return_all_scores=True)[0]
70
+ valid_emotions = ['sadness', 'joy', 'love', 'anger', 'fear', 'surprise']
71
+ filtered = [e for e in results if e['label'].lower() in valid_emotions]
72
+ return max(filtered, key=lambda x: x['score'])
73
 
74
  def generate_prompt(text, emotion):
75
+ """Complete prompt templates for all 6 emotions"""
76
  prompt_templates = {
77
+ "sadness": (
78
+ "Customer expressed sadness: {input}\n"
79
+ "Respond with:\n1. Empathetic acknowledgment\n"
80
+ "2. Supportive statement\n3. Concrete help offer\nResponse:"
 
81
  ),
82
  "joy": (
83
  "Positive feedback: {input}\n"
84
+ "Respond with:\n1. Enthusiastic thanks\n"
85
+ "2. Specific compliment\n3. Future engagement\nResponse:"
86
+ ),
87
+ "love": (
88
+ "Customer showed affection: {input}\n"
89
+ "Respond with:\n1. Warm appreciation\n"
90
+ "2. Community building\n3. Exclusive offer\nResponse:"
91
+ ),
92
+ "anger": (
93
+ "Angry complaint: {input}\n"
94
+ "Respond with:\n1. Sincere apology\n"
95
+ "2. Solution steps\n3. Compensation\nResponse:"
96
+ ),
97
+ "fear": (
98
+ "Customer expressed concerns: {input}\n"
99
+ "Respond with:\n1. Reassurance\n"
100
+ "2. Safety measures\n3. Support channels\nResponse:"
101
  ),
102
+ "surprise": (
103
+ "Unexpected feedback: {input}\n"
104
+ "Respond with:\n1. Acknowledge uniqueness\n"
105
+ "2. Creative solution\n3. Follow-up plan\nResponse:"
 
106
  )
107
  }
108
+ return prompt_templates.get(emotion.lower(), "").format(input=text)
109
 
110
  def process_response(output_text):
111
+ """Optimized response processing"""
112
+ output_text = output_text.split("Response:")[-1].strip()
113
+ return output_text[:200] # Strict length control
 
 
 
 
 
 
 
 
 
 
114
 
115
  def generate_text_response(user_input, models):
116
+ """Efficient text generation"""
 
117
  emotion = analyze_emotion(user_input, models['emotion'])
 
 
118
  prompt = generate_prompt(user_input, emotion['label'])
119
 
 
120
  inputs = models['textgen_tokenizer'](prompt, return_tensors="pt")
121
  outputs = models['textgen_model'].generate(
122
  inputs.input_ids,
123
+ max_new_tokens=150, # Reduced for speed
124
  temperature=0.7,
125
  do_sample=True,
126
  top_p=0.9
127
  )
128
 
129
+ return process_response(
130
+ models['textgen_tokenizer'].decode(outputs[0], skip_special_tokens=True)
131
+ )
132
 
133
  def generate_audio_response(text, models):
134
+ """Optimized TTS conversion"""
 
135
  inputs = models['tts_processor'](text=text, return_tensors="pt")
 
 
136
  spectrogram = models['tts_model'].generate_speech(
137
  inputs["input_ids"],
138
  models['speaker_embeddings']
139
  )
 
 
140
  with torch.no_grad():
141
  waveform = models['tts_vocoder'](spectrogram)
 
 
142
  sf.write("response.wav", waveform.numpy(), samplerate=16000)
143
  return "response.wav"
144
 
 
146
  # Main Application Flow
147
  ##########################################
148
  def main():
 
149
  ml_models = load_models()
 
 
150
  user_input = render_interface()
151
 
 
152
  if user_input:
153
+ # Text Generation
154
+ with st.spinner("๐Ÿ” Analyzing emotions..."):
155
  text_response = generate_text_response(user_input, ml_models)
 
156
 
157
+ # Display Results
158
+ st.subheader("๐Ÿ“„ Generated Response")
159
+ st.success(text_response)
160
 
161
+ # Audio Generation
162
+ with st.spinner("๐Ÿ”Š Generating voice..."):
163
  audio_file = generate_audio_response(text_response, ml_models)
164
  st.audio(audio_file, format="audio/wav")
165