Thejas2001's picture
Update app.py
e510201 verified
# requirements.txt
# gradio
# openai>=1.0.0
# sentence-transformers
import gradio as gr
from openai import OpenAI, AuthenticationError
from sentence_transformers import SentenceTransformer, util
import os
import time
# --- Load Resume and Build Embedding Index ---
embedder = SentenceTransformer('all-MiniLM-L6-v2')
RESUME_PATH = "resume.txt"
def load_resume_chunks(path=RESUME_PATH):
with open(path, "r") as f:
content = f.read()
chunks = [chunk.strip() for chunk in content.split("\n\n") if chunk.strip()]
embeddings = embedder.encode(chunks, convert_to_tensor=True)
return chunks, embeddings
resume_chunks, resume_embeddings = load_resume_chunks()
def get_relevant_resume_chunks(query, top_k=3):
query_embedding = embedder.encode(query, convert_to_tensor=True)
scores = util.cos_sim(query_embedding, resume_embeddings)[0]
top_results = scores.argsort(descending=True)[:top_k]
return [resume_chunks[i] for i in top_results]
def extract_projects_section(path=RESUME_PATH):
with open(path, "r") as f:
content = f.read()
start = content.find("Project:")
end = content.find("Publication", start)
if start != -1 and end != -1:
return content[start:end].strip()
return ""
# --- Audio Bot Logic ---
def audio_bot(api_key, audio_filepath, chat_history):
if not api_key:
chat_history.append((None, "Error: OpenAI API key is missing."))
return chat_history, chat_history, None, None
try:
client = OpenAI(api_key=api_key)
except Exception as e:
chat_history.append((None, f"Error initializing OpenAI client: {e}"))
return chat_history, chat_history, None, None
if audio_filepath is None:
chat_history.append((None, "Error: No audio recorded."))
return chat_history, chat_history, None, None
messages = []
for user_msg, ai_msg in chat_history:
if user_msg:
messages.append({"role": "user", "content": user_msg})
if ai_msg:
messages.append({"role": "assistant", "content": ai_msg})
try:
with open(audio_filepath, "rb") as audio_file:
transcription = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file
)
user_text = transcription.text
print(f"User said: {user_text}")
# Check if the user is asking about projects
if "project" in user_text.lower():
projects_info = extract_projects_section()
system_prompt = f"""
You are Thejas Haridas — a Data Scientist, ML/AI Engineer, and Data Analyst.
Answer all questions in first person, as if you are Thejas Haridas himself.
Only use the following projects to answer questions about your work:
Always respond only in English.
{projects_info}
"""
else:
# Get relevant resume info and similarity scores
query_embedding = embedder.encode(user_text, convert_to_tensor=True)
scores = util.cos_sim(query_embedding, resume_embeddings)[0]
top_results = scores.argsort(descending=True)[:5] # Increase top_k to 5
relevant_info = "\n\n".join([resume_chunks[i] for i in top_results])
max_score = float(scores[top_results[0]])
system_prompt = f"""
You are Thejas Haridas — a Data Scientist, ML/AI Engineer, and Data Analyst.
Answer all questions in first person, as if you are Thejas Haridas himself.
Use the following relevant background info to answer questions:
Always respond only in English.
{relevant_info}
"""
messages.insert(0, {"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": user_text})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
ai_text = response.choices[0].message.content
print(f"AI responded: {ai_text}")
chat_history.append((user_text, ai_text))
# Convert response to speech
output_audio_filepath = f"ai_response_{int(time.time())}.mp3"
speech_response = client.audio.speech.create(
model="tts-1",
voice="nova",
input=ai_text
)
speech_response.stream_to_file(output_audio_filepath)
return chat_history, chat_history, output_audio_filepath, None
except AuthenticationError:
error_msg = "Error: Invalid OpenAI API key."
chat_history.append((user_text if 'user_text' in locals() else "Audio input", error_msg))
return chat_history, chat_history, None, None
except Exception as e:
error_msg = f"An error occurred: {e}"
print(error_msg)
chat_history.append((user_text if 'user_text' in locals() else "Audio input", error_msg))
return chat_history, chat_history, None, None
finally:
if audio_filepath and os.path.exists(audio_filepath):
os.remove(audio_filepath)
# --- Gradio UI ---
with gr.Blocks(theme=gr.themes.Soft(), title="Conversational Resume Bot") as demo:
gr.Markdown("# 🤖 Talk to Thejas Haridas (AI Resume Bot)")
gr.Markdown("Use your voice to ask questions about Thejas Haridas' background and experience.")
chat_history_state = gr.State([])
with gr.Row():
api_key_input = gr.Textbox(
label="OpenAI API Key",
placeholder="Enter your OpenAI API key here...",
type="password"
)
with gr.Row():
gr.Markdown("⚠️ **After recording, please click the ▶️ play button once before submitting, or the audio won't be saved.**")
with gr.Row():
audio_input = gr.Audio(
sources=["microphone"],
type="filepath",
label="Record your message",
streaming=False, # <-- Add this line to ensure file is saved on submit
interactive=True
)
with gr.Row():
submit_button = gr.Button("Submit Audio")
with gr.Column():
chatbot_output = gr.Chatbot(label="Conversation", height=400, avatar_images=("./user_avatar.png", "./bot_avatar.png"))
audio_output = gr.Audio(label="AI Response", autoplay=True, interactive=False, format="mp3")
submit_button.click(
fn=audio_bot,
inputs=[api_key_input, audio_input, chat_history_state],
outputs=[chatbot_output, chat_history_state, audio_output, audio_input] # Add audio_input here
)
gr.Markdown("---")
gr.Markdown("Made with ❤️ by Thejas Haridas using Gradio and OpenAI.")
if __name__ == "__main__":
if not os.path.exists("user_avatar.png"):
with open("user_avatar.png", "w"): pass
if not os.path.exists("bot_avatar.png"):
with open("bot_avatar.png", "w"): pass
demo.launch(debug=True, share=True)