Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,6 +7,14 @@ import scipy.io.wavfile as wavfile # For writing WAV data to in-memory file
|
|
| 7 |
import numpy as np # To handle the audio array
|
| 8 |
import datetime # For logging timestamps if needed (not directly used in this version, but good practice)
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
system_prompt = """
|
| 11 |
You are a sophisticated AI voice bot representing Krishnavamshi Thumma. Your persona should be that of a highly skilled, professional, and engaging Generative AI and Data Engineering enthusiast. When responding to questions, embody the following detailed professional identity:
|
| 12 |
|
|
@@ -21,13 +29,13 @@ system_prompt = """
|
|
| 21 |
|
| 22 |
**Technical Skills:**
|
| 23 |
Your robust technical skill set includes:
|
| 24 |
-
* **Languages:** Python, SQL, JavaScript (Node.js)
|
| 25 |
-
* **GenAI/ML:** OpenAI GPT-4o, LangChain, Transformers Architecture, LLMs, RAG
|
| 26 |
-
* **Vector Databases:** FAISS, MongoDB Vector Search
|
| 27 |
-
* **Data Engineering Tools:** Apache Airflow, AWS Lambda, REST APIs, Pandas, PyPDF2, BeautifulSoup, FastAPI, Streamlit
|
| 28 |
-
* **Cloud & Infrastructure:** AWS S3, GCP, Docker, Terraform
|
| 29 |
-
* **Version Control:** Git, GitHub
|
| 30 |
-
* **Other Relevant Skills:** Data Structures & Algorithms (DSA), Content-Based Retrieval, Prompt Engineering
|
| 31 |
|
| 32 |
**Key Projects & Expertise Areas:**
|
| 33 |
|
|
@@ -46,24 +54,23 @@ system_prompt = """
|
|
| 46 |
r = sr.Recognizer()
|
| 47 |
|
| 48 |
# Modified function to accept audio as a numpy array and samplerate
|
| 49 |
-
def transcribe_audio_and_chat(audio_tuple, history
|
| 50 |
-
#
|
| 51 |
-
if not
|
| 52 |
-
raise gr.Error("❌ Please
|
| 53 |
-
|
| 54 |
-
if audio_tuple is None:
|
| 55 |
-
# If no audio is received, add an assistant message to history and reset audio input
|
| 56 |
-
return history, history, None
|
| 57 |
|
| 58 |
-
#
|
| 59 |
if history is None:
|
| 60 |
history = []
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
samplerate, audio_np_array = audio_tuple
|
| 63 |
|
| 64 |
try:
|
| 65 |
# Convert the NumPy array to a format speech_recognition can handle (in-memory WAV)
|
| 66 |
-
# Ensure the array is int16 as it's a common format for audio samples and expected by scipy.io.wavfile
|
| 67 |
if audio_np_array.dtype != np.int16:
|
| 68 |
audio_np_array = audio_np_array.astype(np.int16)
|
| 69 |
|
|
@@ -88,16 +95,16 @@ def transcribe_audio_and_chat(audio_tuple, history, api_key):
|
|
| 88 |
return history, history, None # Reset audio input after error
|
| 89 |
|
| 90 |
# --- Proceed with OpenAI chat ---
|
| 91 |
-
|
|
|
|
| 92 |
|
| 93 |
# Create the full messages list for OpenAI, starting with the system prompt
|
| 94 |
-
# and then appending the current chat history, followed by the new user input.
|
| 95 |
messages_for_openai = [{"role": "system", "content": system_prompt}] + history
|
| 96 |
messages_for_openai.append({"role": "user", "content": user_input})
|
| 97 |
|
| 98 |
-
# Get response from OpenAI
|
| 99 |
response = client.chat.completions.create(
|
| 100 |
-
model=
|
| 101 |
messages=messages_for_openai, # Pass the correctly formatted messages
|
| 102 |
temperature=0.7
|
| 103 |
)
|
|
@@ -105,7 +112,6 @@ def transcribe_audio_and_chat(audio_tuple, history, api_key):
|
|
| 105 |
bot_reply = response.choices[0].message.content
|
| 106 |
|
| 107 |
# Append both the user input and bot reply to the *Gradio* history (state)
|
| 108 |
-
# in the 'messages' format that Gradio's chatbot expects.
|
| 109 |
history.append({"role": "user", "content": user_input})
|
| 110 |
history.append({"role": "assistant", "content": bot_reply})
|
| 111 |
|
|
@@ -116,7 +122,6 @@ def transcribe_audio_and_chat(audio_tuple, history, api_key):
|
|
| 116 |
|
| 117 |
except Exception as e:
|
| 118 |
print(f"An unexpected error occurred: {e}") # Log the error for debugging
|
| 119 |
-
# If an unexpected error occurs, still try to reset the audio input
|
| 120 |
raise gr.Error(f"❌ An unexpected error occurred: {str(e)}")
|
| 121 |
|
| 122 |
|
|
@@ -149,7 +154,7 @@ with gr.Blocks(title="Voice Bot: Krishnavamshi Thumma") as demo:
|
|
| 149 |
#audioInputComponent {
|
| 150 |
margin-top: 20px;
|
| 151 |
}
|
| 152 |
-
.key-status {
|
| 153 |
padding: 5px;
|
| 154 |
margin-top: 5px;
|
| 155 |
border-radius: 4px;
|
|
@@ -165,13 +170,9 @@ with gr.Blocks(title="Voice Bot: Krishnavamshi Thumma") as demo:
|
|
| 165 |
</style>
|
| 166 |
""")
|
| 167 |
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
type="password",
|
| 172 |
-
elem_id="apiKeyInput"
|
| 173 |
-
)
|
| 174 |
-
key_status = gr.HTML("<div id='keyStatus'></div>")
|
| 175 |
|
| 176 |
# Chatbot component to display messages
|
| 177 |
chatbot = gr.Chatbot(elem_id="chatBox", type="messages", height=400)
|
|
@@ -192,27 +193,16 @@ with gr.Blocks(title="Voice Bot: Krishnavamshi Thumma") as demo:
|
|
| 192 |
# Event handler: When audio input is recorded and submitted (by stopping recording)
|
| 193 |
audio_input.change(
|
| 194 |
fn=transcribe_audio_and_chat,
|
| 195 |
-
inputs=[audio_input, state, api_key
|
| 196 |
# Outputs: 1. chatbot display, 2. state (updated history), 3. audio_input (to clear it)
|
| 197 |
outputs=[chatbot, state, audio_input]
|
| 198 |
)
|
| 199 |
|
| 200 |
-
# JavaScript
|
| 201 |
gr.HTML("""
|
| 202 |
<script>
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
const keyStatus = document.getElementById("keyStatus");
|
| 206 |
-
|
| 207 |
-
if (apiKey) {
|
| 208 |
-
keyStatus.innerHTML = '<div class="key-status success">API Key saved successfully!</div>';
|
| 209 |
-
} else {
|
| 210 |
-
keyStatus.innerHTML = '<div class="key-status error">Please enter a valid API key</div>';
|
| 211 |
-
}
|
| 212 |
-
});
|
| 213 |
-
|
| 214 |
-
// Focus on API key input on page load for convenience
|
| 215 |
-
document.querySelector("#apiKeyInput input").focus();
|
| 216 |
</script>
|
| 217 |
""")
|
| 218 |
|
|
|
|
| 7 |
import numpy as np # To handle the audio array
|
| 8 |
import datetime # For logging timestamps if needed (not directly used in this version, but good practice)
|
| 9 |
|
| 10 |
+
# --- Fetch API Key from Environment Variable ---
|
| 11 |
+
# This is the SECURE way to handle API keys in Hugging Face Spaces.
|
| 12 |
+
# You MUST set an environment variable named OPENAI_API_KEY in your Space's settings.
|
| 13 |
+
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
|
| 14 |
+
|
| 15 |
+
# --- Define the OpenAI Model to use ---
|
| 16 |
+
OPENAI_MODEL = "gpt-3.5-turbo" # Changed from gpt-4o to gpt-3.5-turbo
|
| 17 |
+
|
| 18 |
system_prompt = """
|
| 19 |
You are a sophisticated AI voice bot representing Krishnavamshi Thumma. Your persona should be that of a highly skilled, professional, and engaging Generative AI and Data Engineering enthusiast. When responding to questions, embody the following detailed professional identity:
|
| 20 |
|
|
|
|
| 29 |
|
| 30 |
**Technical Skills:**
|
| 31 |
Your robust technical skill set includes:
|
| 32 |
+
* **Languages:** Python, SQL, JavaScript (Node.js)
|
| 33 |
+
* **GenAI/ML:** OpenAI GPT-4o, LangChain, Transformers Architecture, LLMs, RAG
|
| 34 |
+
* **Vector Databases:** FAISS, MongoDB Vector Search
|
| 35 |
+
* **Data Engineering Tools:** Apache Airflow, AWS Lambda, REST APIs, Pandas, PyPDF2, BeautifulSoup, FastAPI, Streamlit
|
| 36 |
+
* **Cloud & Infrastructure:** AWS S3, GCP, Docker, Terraform
|
| 37 |
+
* **Version Control:** Git, GitHub
|
| 38 |
+
* **Other Relevant Skills:** Data Structures & Algorithms (DSA), Content-Based Retrieval, Prompt Engineering
|
| 39 |
|
| 40 |
**Key Projects & Expertise Areas:**
|
| 41 |
|
|
|
|
| 54 |
r = sr.Recognizer()
|
| 55 |
|
| 56 |
# Modified function to accept audio as a numpy array and samplerate
|
| 57 |
+
def transcribe_audio_and_chat(audio_tuple, history): # Removed api_key from function arguments
|
| 58 |
+
# Check if API key is available in environment
|
| 59 |
+
if not OPENAI_API_KEY:
|
| 60 |
+
raise gr.Error("❌ OpenAI API key not found. Please set OPENAI_API_KEY as a Space Secret.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
+
# Handle cases where history might be None (defensive programming)
|
| 63 |
if history is None:
|
| 64 |
history = []
|
| 65 |
|
| 66 |
+
if audio_tuple is None:
|
| 67 |
+
# If no audio, raise a Gradio Error directly instead of adding to chat history
|
| 68 |
+
raise gr.Error("No audio received. Please speak into the microphone.")
|
| 69 |
+
|
| 70 |
samplerate, audio_np_array = audio_tuple
|
| 71 |
|
| 72 |
try:
|
| 73 |
# Convert the NumPy array to a format speech_recognition can handle (in-memory WAV)
|
|
|
|
| 74 |
if audio_np_array.dtype != np.int16:
|
| 75 |
audio_np_array = audio_np_array.astype(np.int16)
|
| 76 |
|
|
|
|
| 95 |
return history, history, None # Reset audio input after error
|
| 96 |
|
| 97 |
# --- Proceed with OpenAI chat ---
|
| 98 |
+
# Use the global OPENAI_API_KEY
|
| 99 |
+
client = OpenAI(api_key=OPENAI_API_KEY)
|
| 100 |
|
| 101 |
# Create the full messages list for OpenAI, starting with the system prompt
|
|
|
|
| 102 |
messages_for_openai = [{"role": "system", "content": system_prompt}] + history
|
| 103 |
messages_for_openai.append({"role": "user", "content": user_input})
|
| 104 |
|
| 105 |
+
# Get response from OpenAI using the specified model
|
| 106 |
response = client.chat.completions.create(
|
| 107 |
+
model=OPENAI_MODEL, # Use the global OPENAI_MODEL
|
| 108 |
messages=messages_for_openai, # Pass the correctly formatted messages
|
| 109 |
temperature=0.7
|
| 110 |
)
|
|
|
|
| 112 |
bot_reply = response.choices[0].message.content
|
| 113 |
|
| 114 |
# Append both the user input and bot reply to the *Gradio* history (state)
|
|
|
|
| 115 |
history.append({"role": "user", "content": user_input})
|
| 116 |
history.append({"role": "assistant", "content": bot_reply})
|
| 117 |
|
|
|
|
| 122 |
|
| 123 |
except Exception as e:
|
| 124 |
print(f"An unexpected error occurred: {e}") # Log the error for debugging
|
|
|
|
| 125 |
raise gr.Error(f"❌ An unexpected error occurred: {str(e)}")
|
| 126 |
|
| 127 |
|
|
|
|
| 154 |
#audioInputComponent {
|
| 155 |
margin-top: 20px;
|
| 156 |
}
|
| 157 |
+
.key-status { /* No longer strictly needed but keeping for style consistency if other status messages arise */
|
| 158 |
padding: 5px;
|
| 159 |
margin-top: 5px;
|
| 160 |
border-radius: 4px;
|
|
|
|
| 170 |
</style>
|
| 171 |
""")
|
| 172 |
|
| 173 |
+
# Removed the API key textbox and its status display as it's now handled by Space Secrets
|
| 174 |
+
# api_key = gr.Textbox(...)
|
| 175 |
+
# key_status = gr.HTML(...)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
# Chatbot component to display messages
|
| 178 |
chatbot = gr.Chatbot(elem_id="chatBox", type="messages", height=400)
|
|
|
|
| 193 |
# Event handler: When audio input is recorded and submitted (by stopping recording)
|
| 194 |
audio_input.change(
|
| 195 |
fn=transcribe_audio_and_chat,
|
| 196 |
+
inputs=[audio_input, state], # Removed api_key from inputs as it's global
|
| 197 |
# Outputs: 1. chatbot display, 2. state (updated history), 3. audio_input (to clear it)
|
| 198 |
outputs=[chatbot, state, audio_input]
|
| 199 |
)
|
| 200 |
|
| 201 |
+
# Removed JavaScript related to API key input
|
| 202 |
gr.HTML("""
|
| 203 |
<script>
|
| 204 |
+
// No specific API key JS needed anymore as it's handled by secrets
|
| 205 |
+
// You can add other useful JS here if needed in the future
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
</script>
|
| 207 |
""")
|
| 208 |
|