Krishnavamshithumma commited on
Commit
734ecc1
Β·
verified Β·
1 Parent(s): 99d36a1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -125
app.py CHANGED
@@ -11,191 +11,124 @@ Answer questions about your background professionally but engagingly (2-3 senten
11
 
12
  def chat_with_openai(user_input, history, api_key):
13
  if not api_key:
14
- # Instead of returning history and an error string,
15
- # Gradio handles errors better when raised as exceptions
16
  raise gr.Error("❌ Please enter your OpenAI API key.")
17
-
18
  try:
19
  client = OpenAI(api_key=api_key)
20
-
21
- # Build messages from history
22
  messages = [{"role": "system", "content": system_prompt}]
23
  for entry in history:
24
  messages.append({"role": "user", "content": entry[0]})
25
  messages.append({"role": "assistant", "content": entry[1]})
26
  messages.append({"role": "user", "content": user_input})
27
-
28
- # Get response from OpenAI
29
  response = client.chat.completions.create(
30
  model="gpt-4o",
31
  messages=messages,
32
  temperature=0.7
33
  )
34
-
35
  bot_reply = response.choices[0].message.content
36
  history.append((user_input, bot_reply))
37
- return history, "" # Clear the input text box after processing
38
  except Exception as e:
39
  raise gr.Error(f"❌ Error: {str(e)}")
40
 
41
  with gr.Blocks(title="Voice Bot: Krishnavamshi Thumma") as demo:
42
  gr.Markdown("## πŸŽ™οΈ Krishnavamshi Thumma - Voice Assistant")
43
 
44
- # Add custom CSS
45
  gr.HTML("""
46
  <style>
47
- #chatBox {
48
- height: 60vh;
49
- overflow-y: auto;
50
- padding: 20px;
51
- border-radius: 10px;
52
- background: #f9f9f9;
53
- margin-bottom: 20px;
54
- }
55
- .message {
56
- margin: 10px 0;
57
- padding: 12px;
58
- border-radius: 8px;
59
- }
60
- .user {
61
- background: #e3f2fd;
62
- text-align: right;
63
- }
64
- .bot {
65
- background: #f5f5f5;
66
- }
67
- #micButton {
68
- width: 100%;
69
- padding: 12px;
70
- font-size: 1.2em;
71
- background: #007bff;
72
- color: white;
73
- border: none;
74
- border-radius: 5px;
75
- cursor: pointer;
76
- }
77
- #micButton:disabled {
78
- background: #cccccc;
79
- cursor: not-allowed;
80
- }
81
- .key-status {
82
- padding: 5px;
83
- margin-top: 5px;
84
- border-radius: 4px;
85
- }
86
- .success {
87
- background: #d4edda;
88
- color: #155724;
89
- }
90
- .error {
91
- background: #f8d7da;
92
- color: #721c24;
93
- }
94
  </style>
95
  """)
96
 
97
  api_key = gr.Textbox(label="πŸ” OpenAI API Key", type="password", elem_id="apiKeyInput")
98
  key_status = gr.HTML("<div id='keyStatus'></div>")
99
- chatbot = gr.Chatbot(elem_id="chatBox", type="messages", height=400) # Added height for better display
100
  state = gr.State([])
101
 
102
- # This textbox will be the one that takes the speech-to-text output
103
- # and directly triggers the chat_with_openai function.
104
- # It will remain hidden from the user.
105
- text_input_for_voice = gr.Textbox(label="Voice Input Text", visible=False)
106
-
107
  mic_btn = gr.Button("🎀 Click & Speak", elem_id="micButton")
108
-
109
  clear_btn = gr.Button("πŸ—‘οΈ Clear Chat")
110
 
111
- # Event handlers
112
- # The chat_with_openai function will now be triggered by the text_input_for_voice.submit()
113
- # or by its change event, which will be manually triggered by the JavaScript.
114
  text_input_for_voice.submit(
115
  chat_with_openai,
116
  [text_input_for_voice, state, api_key],
117
- [chatbot, state, text_input_for_voice] # Also clear the voice input textbox after submission
118
  )
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- # JavaScript functions
122
- # Using Gradio's _js to integrate JavaScript with Python components directly
123
- mic_btn.click(
124
- None,
125
- inputs=[api_key],
126
- outputs=[mic_btn],
127
- _js="""
128
- (api_key) => {
129
- if (!api_key) {
 
 
 
 
 
 
130
  alert("Please enter your OpenAI API key first!");
131
- return [gr.Button.update(interactive=true)]; // Keep button enabled if no key
132
  }
 
133
  const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
134
  recognition.continuous = false;
135
  recognition.lang = "en-US";
136
- const micButton = document.getElementById("micButton");
137
 
138
  micButton.textContent = "πŸ”΄ Listening...";
139
- micButton.disabled = true; // Disable while listening
140
 
141
- recognition.onresult = function(event) {
142
  const transcript = event.results[0][0].transcript;
143
- // Directly set the value of the hidden text_input_for_voice and trigger its submit event
144
- // Gradio's internal JS will handle the connection to the Python backend function
145
- const voiceInputTextbox = document.querySelector('#voice_input_for_voice input'); // Correctly select the hidden input field
146
- if (voiceInputTextbox) {
147
- voiceInputTextbox.value = transcript;
148
- // Trigger the 'input' event which Gradio uses for its change/submit events
149
- voiceInputTextbox.dispatchEvent(new Event('input', { bubbles: true }));
150
  }
151
  };
152
 
153
- recognition.onend = function() {
 
 
154
  micButton.textContent = "🎀 Click & Speak";
155
- micButton.disabled = false; // Re-enable after listening ends
156
  };
157
 
158
- recognition.onerror = function(event) {
159
- console.error("Speech recognition error", event.error);
160
  micButton.textContent = "🎀 Click & Speak";
161
- micButton.disabled = false; // Re-enable on error
162
- alert("Speech recognition error: " + event.error);
163
  };
164
 
165
  recognition.start();
166
- return [gr.Button.update(interactive=false)]; // Disable button visually when started
167
- }
168
- """
169
- )
170
-
171
-
172
- # JavaScript for API key input and status
173
- gr.HTML("""
174
- <script>
175
- document.getElementById("apiKeyInput").addEventListener("input", function() {
176
- const apiKey = this.value.trim();
177
- const keyStatus = document.getElementById("keyStatus");
178
- const micButton = document.getElementById("micButton");
179
-
180
- if (apiKey) {
181
- keyStatus.innerHTML = '<div class="key-status success">API Key saved successfully!</div>';
182
- micButton.disabled = false;
183
- } else {
184
- keyStatus.innerHTML = '<div class="key-status error">Please enter a valid API key</div>';
185
- micButton.disabled = true;
186
- }
187
  });
188
 
189
- // Auto-scroll chat - this should be triggered whenever chatbot updates
190
- // However, Gradio's Chatbot often handles auto-scrolling itself.
191
- // If not, you might need a more sophisticated way to observe changes.
192
-
193
- // Initial setup
194
- document.getElementById("micButton").disabled = true;
195
- document.querySelector("#apiKeyInput input").focus();
196
  </script>
197
  """)
198
 
199
- clear_btn.click(lambda: ([], []), None, [chatbot, state])
200
-
201
- demo.launch()
 
11
 
12
  def chat_with_openai(user_input, history, api_key):
13
  if not api_key:
 
 
14
  raise gr.Error("❌ Please enter your OpenAI API key.")
 
15
  try:
16
  client = OpenAI(api_key=api_key)
 
 
17
  messages = [{"role": "system", "content": system_prompt}]
18
  for entry in history:
19
  messages.append({"role": "user", "content": entry[0]})
20
  messages.append({"role": "assistant", "content": entry[1]})
21
  messages.append({"role": "user", "content": user_input})
 
 
22
  response = client.chat.completions.create(
23
  model="gpt-4o",
24
  messages=messages,
25
  temperature=0.7
26
  )
 
27
  bot_reply = response.choices[0].message.content
28
  history.append((user_input, bot_reply))
29
+ return history, ""
30
  except Exception as e:
31
  raise gr.Error(f"❌ Error: {str(e)}")
32
 
33
  with gr.Blocks(title="Voice Bot: Krishnavamshi Thumma") as demo:
34
  gr.Markdown("## πŸŽ™οΈ Krishnavamshi Thumma - Voice Assistant")
35
 
 
36
  gr.HTML("""
37
  <style>
38
+ #chatBox { height: 60vh; overflow-y: auto; padding: 20px; border-radius: 10px; background: #f9f9f9; margin-bottom: 20px; }
39
+ .message { margin: 10px 0; padding: 12px; border-radius: 8px; }
40
+ .user { background: #e3f2fd; text-align: right; }
41
+ .bot { background: #f5f5f5; }
42
+ #micButton { width: 100%; padding: 12px; font-size: 1.2em; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; }
43
+ #micButton:disabled { background: #cccccc; cursor: not-allowed; }
44
+ .key-status { padding: 5px; margin-top: 5px; border-radius: 4px; }
45
+ .success { background: #d4edda; color: #155724; }
46
+ .error { background: #f8d7da; color: #721c24; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  </style>
48
  """)
49
 
50
  api_key = gr.Textbox(label="πŸ” OpenAI API Key", type="password", elem_id="apiKeyInput")
51
  key_status = gr.HTML("<div id='keyStatus'></div>")
52
+ chatbot = gr.Chatbot(elem_id="chatBox", type="messages", height=400)
53
  state = gr.State([])
54
 
55
+ text_input_for_voice = gr.Textbox(label="Voice Input Text", visible=False, elem_id="voice_input_for_voice")
 
 
 
 
56
  mic_btn = gr.Button("🎀 Click & Speak", elem_id="micButton")
 
57
  clear_btn = gr.Button("πŸ—‘οΈ Clear Chat")
58
 
59
+ # Backend trigger
 
 
60
  text_input_for_voice.submit(
61
  chat_with_openai,
62
  [text_input_for_voice, state, api_key],
63
+ [chatbot, state, text_input_for_voice]
64
  )
65
 
66
+ # Clear chat
67
+ clear_btn.click(lambda: ([], []), None, [chatbot, state])
68
+
69
+ # JavaScript: mic + api key handling
70
+ gr.HTML("""
71
+ <script>
72
+ const micButton = document.getElementById("micButton");
73
+ const apiInput = document.querySelector("#apiKeyInput input");
74
+ const voiceInput = document.querySelector("#voice_input_for_voice input");
75
+ const keyStatus = document.getElementById("keyStatus");
76
+
77
+ // Disable mic button initially
78
+ micButton.disabled = true;
79
 
80
+ // Enable mic if API key is valid
81
+ apiInput.addEventListener("input", () => {
82
+ const apiKey = apiInput.value.trim();
83
+ if (apiKey) {
84
+ keyStatus.innerHTML = '<div class="key-status success">API Key saved successfully!</div>';
85
+ micButton.disabled = false;
86
+ } else {
87
+ keyStatus.innerHTML = '<div class="key-status error">Please enter a valid API key</div>';
88
+ micButton.disabled = true;
89
+ }
90
+ });
91
+
92
+ micButton.addEventListener("click", () => {
93
+ const apiKey = apiInput.value.trim();
94
+ if (!apiKey) {
95
  alert("Please enter your OpenAI API key first!");
96
+ return;
97
  }
98
+
99
  const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
100
  recognition.continuous = false;
101
  recognition.lang = "en-US";
 
102
 
103
  micButton.textContent = "πŸ”΄ Listening...";
104
+ micButton.disabled = true;
105
 
106
+ recognition.onresult = (event) => {
107
  const transcript = event.results[0][0].transcript;
108
+ if (voiceInput) {
109
+ voiceInput.value = transcript;
110
+ voiceInput.dispatchEvent(new Event('input', { bubbles: true }));
 
 
 
 
111
  }
112
  };
113
 
114
+ recognition.onerror = (event) => {
115
+ console.error("Speech recognition error:", event.error);
116
+ alert("Speech recognition error: " + event.error);
117
  micButton.textContent = "🎀 Click & Speak";
118
+ micButton.disabled = false;
119
  };
120
 
121
+ recognition.onend = () => {
 
122
  micButton.textContent = "🎀 Click & Speak";
123
+ micButton.disabled = false;
 
124
  };
125
 
126
  recognition.start();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  });
128
 
129
+ // Auto-focus on API key input
130
+ apiInput.focus();
 
 
 
 
 
131
  </script>
132
  """)
133
 
134
+ demo.launch()