Spaces:
Sleeping
Sleeping
| 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: <number> | |
| """ | |
| 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() | |