Update app.py
Browse files
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, ""
|
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 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
}
|
55 |
-
.
|
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)
|
100 |
state = gr.State([])
|
101 |
|
102 |
-
|
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 |
-
#
|
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]
|
118 |
)
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
alert("Please enter your OpenAI API key first!");
|
131 |
-
return
|
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;
|
140 |
|
141 |
-
recognition.onresult =
|
142 |
const transcript = event.results[0][0].transcript;
|
143 |
-
|
144 |
-
|
145 |
-
|
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.
|
|
|
|
|
154 |
micButton.textContent = "π€ Click & Speak";
|
155 |
-
micButton.disabled = false;
|
156 |
};
|
157 |
|
158 |
-
recognition.
|
159 |
-
console.error("Speech recognition error", event.error);
|
160 |
micButton.textContent = "π€ Click & Speak";
|
161 |
-
micButton.disabled = false;
|
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-
|
190 |
-
|
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 |
-
|
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()
|
|
|
|