import os import gradio as gr from llama_index.readers.file import PDFReader from llama_index.core import VectorStoreIndex from llama_index.llms.openai import OpenAI as LlamaOpenAI from openai import OpenAI # New SDK from gtts import gTTS import random import tempfile import speech_recognition as sr # šŸ” Set API key directly (use HF secret or hardcode for testing) OPENAI_API_KEY = os.environ.get('HF_OPENAI_API_KEY', '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') # Replace or use HF secret client = OpenAI(api_key=OPENAI_API_KEY) # Global state query_engine = None resume_summary = "" questions = [] asked_questions = [] # Step 1: Load and index resume def load_resume(file): global query_engine, resume_summary, questions, asked_questions reader = PDFReader() documents = reader.load_data(file=file.name) index = VectorStoreIndex.from_documents(documents) query_engine = index.as_query_engine() resume_summary = query_engine.query("Summarize this resume in detail.") prompt = f"Generate 5 personalized interview-style questions based on this resume:\n{resume_summary}" questions = [str(query_engine.query(prompt + f"\nQuestion {i+1}")) for i in range(5)] asked_questions = [] return f"āœ… Resume analyzed!\n\nšŸ“„ Summary:\n{resume_summary}" # Step 2: Ask next question (TTS with gTTS) def ask_next_question(): global questions, asked_questions if not questions: return "āŒ Resume not loaded yet.", None remaining = [q for q in questions if q not in asked_questions] if not remaining: return "āœ… All questions have been asked.", None next_q = random.choice(remaining) asked_questions.append(next_q) # Convert text to audio using gTTS tts = gTTS(next_q) temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") tts.save(temp_audio.name) return next_q, temp_audio.name # Step 3: Speech to Text def speech_to_text(audio_path): recognizer = sr.Recognizer() with sr.AudioFile(audio_path) as source: audio_data = recognizer.record(source) try: return recognizer.recognize_google(audio_data) except sr.UnknownValueError: return "āš ļø Could not understand the voice input." except sr.RequestError: return "āš ļø API error with speech recognition." # Step 4: Evaluate answer using OpenAI SDK v1.0+ def evaluate_answer(audio_path): if not audio_path: return "āš ļø Please record an answer.", "āŒ No score" transcript = speech_to_text(audio_path) if transcript.startswith("āš ļø"): return transcript, "āŒ" rating_prompt = f""" You are an interview evaluator. Rate the following candidate's answer from 1 to 5 based on: - Relevance - Clarity - Completeness Answer: "{transcript}" Only return: Score: """ try: response = client.chat.completions.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": rating_prompt}], max_tokens=10, temperature=0.2, ) score = response.choices[0].message.content.strip() return f"šŸ“ Transcript: {transcript}", f"šŸ”Ž {score}" except Exception as e: return "āŒ Evaluation failed", str(e) # Gradio Interface with gr.Blocks() as demo: gr.Markdown("# šŸŽ¤ Voice Resume Interview Bot\nUpload your resume → get questions in voice → answer via mic → get score.") with gr.Row(): resume_file = gr.File(label="šŸ“„ Upload Resume", file_types=[".pdf"]) resume_summary_box = gr.Textbox(label="Resume Summary", lines=6) gr.Button("Analyze Resume").click(fn=load_resume, inputs=resume_file, outputs=resume_summary_box) gr.Markdown("## šŸ”Š Ask a Resume-Based Question") question_text = gr.Textbox(label="Question", lines=2) question_audio = gr.Audio(label="Voice", type="filepath", autoplay=True) gr.Button("Ask Question").click(fn=ask_next_question, outputs=[question_text, question_audio]) gr.Markdown("## šŸŽ™ļø Speak Your Answer") user_audio = gr.Audio(label="Record Your Answer", type="filepath") transcript_output = gr.Textbox(label="Transcript") score_output = gr.Textbox(label="LLM Score") gr.Button("Submit Answer").click(fn=evaluate_answer, inputs=user_audio, outputs=[transcript_output, score_output]) demo.launch()