| import gradio as gr |
| import os |
| import requests |
| import json |
| import time |
| from typing import List, Dict, Tuple |
|
|
| |
| MISTRAL_API_URL = "https://api.mistral.ai/v1/chat/completions" |
|
|
| |
| def get_mistral_api_key(user_key: str = None) -> str: |
| """Get API key from HF secrets or user input""" |
| |
| hf_key = os.environ.get("MISTRAL_API_KEY", "") |
| |
| if hf_key: |
| return hf_key |
| elif user_key and user_key.strip(): |
| return user_key.strip() |
| else: |
| return None |
|
|
| |
| def call_mistral_api( |
| messages: List[Dict[str, str]], |
| api_key: str, |
| model: str = "mistral-small-latest", |
| temperature: float = 0.7 |
| ) -> str: |
| """Call Mistral API for chat completion""" |
| if not api_key: |
| return "Error: API key not provided. Please enter your Mistral API key in the settings tab." |
| |
| headers = { |
| "Authorization": f"Bearer {api_key}", |
| "Content-Type": "application/json" |
| } |
| |
| payload = { |
| "model": model, |
| "messages": messages, |
| "temperature": temperature, |
| "max_tokens": 500 |
| } |
| |
| try: |
| response = requests.post( |
| MISTRAL_API_URL, |
| headers=headers, |
| data=json.dumps(payload), |
| timeout=30 |
| ) |
| |
| if response.status_code == 200: |
| result = response.json() |
| return result["choices"][0]["message"]["content"] |
| else: |
| return f"API Error {response.status_code}: {response.text}" |
| |
| except Exception as e: |
| return f"Connection error: {str(e)}" |
|
|
| |
| ROLE_PROMPTS = { |
| "Software Engineer": """You are an AI interviewer for a Software Engineer position. |
| Ask technical questions about programming, algorithms, system design, and problem-solving. |
| Be professional but conversational. Ask one question at a time and wait for the candidate's response. |
| If the candidate gives a short answer, ask follow-up questions to get more details. |
| Assess their technical depth and communication skills.""", |
| |
| "Marketing Manager": """You are an AI interviewer for a Marketing Manager position. |
| Ask questions about marketing strategies, campaign management, analytics, and team leadership. |
| Focus on their experience with digital marketing, ROI measurement, and creative thinking. |
| Ask one question at a time and evaluate their strategic approach.""", |
| |
| "Sales Executive": """You are an AI interviewer for a Sales Executive position. |
| Ask about sales techniques, client relationship management, target achievement, and negotiation skills. |
| Assess their persistence, communication style, and results-oriented mindset. |
| Ask one question at a time and provide constructive feedback.""" |
| } |
|
|
| |
| def generate_ai_question(role: str, conversation_history: List[Tuple[str, str]], api_key: str) -> str: |
| """Generate next interview question using Mistral API""" |
| |
| system_prompt = ROLE_PROMPTS.get(role, ROLE_PROMPTS["Software Engineer"]) |
| |
| |
| messages = [{"role": "system", "content": system_prompt}] |
| |
| for speaker, text in conversation_history[-4:]: |
| if speaker == "AI Interviewer": |
| messages.append({"role": "assistant", "content": text}) |
| else: |
| messages.append({"role": "user", "content": text}) |
| |
| |
| if not conversation_history: |
| prompt = "Start the interview with an opening greeting and first question." |
| else: |
| prompt = "Based on the conversation so far, ask the next appropriate interview question." |
| |
| messages.append({"role": "user", "content": prompt}) |
| |
| |
| response = call_mistral_api(messages, api_key) |
| return response |
|
|
| |
| def ai_interview(role, user_message, history, api_key_input): |
| if not role: |
| return "Please select a job role", history, "" |
| |
| api_key = get_mistral_api_key(api_key_input) |
| |
| if not api_key: |
| return "Please enter your Mistral API key in the Settings tab", history, "" |
| |
| if user_message: |
| |
| history.append(("Candidate", user_message)) |
| |
| |
| ai_response = generate_ai_question(role, history, api_key) |
| |
| |
| history.append(("AI Interviewer", ai_response)) |
| |
| return "", history, ai_response |
|
|
| |
| def start_interview(role, api_key_input): |
| if not role: |
| return "Please select a job role", [], "" |
| |
| api_key = get_mistral_api_key(api_key_input) |
| |
| if not api_key: |
| return "Please enter your Mistral API key", [], "" |
| |
| |
| initial_history = [] |
| ai_response = generate_ai_question(role, initial_history, api_key) |
| initial_history.append(("AI Interviewer", ai_response)) |
| |
| return ai_response, initial_history, "" |
|
|
| |
| def analyze_voice_with_ai(audio_path, api_key_input, transcript): |
| if not audio_path: |
| return "Please record your voice first", "", {}, "" |
| |
| api_key = get_mistral_api_key(api_key_input) |
| |
| if not api_key: |
| return "API key required for analysis", "", {}, "" |
| |
| |
| time.sleep(2) |
| |
| |
| system_prompt = """You are an expert speech analyst. Analyze the candidate's communication skills based on their interview response. |
| Provide assessment in these areas: |
| 1. Clarity and Pronunciation |
| 2. Confidence Level |
| 3. Communication Effectiveness |
| 4. Professional Tone |
| 5. Areas for Improvement |
| |
| Format your response with clear sections and be constructive.""" |
| |
| user_prompt = f"Analyze this interview response for communication skills:\n\n{transcript}" |
| |
| messages = [ |
| {"role": "system", "content": system_prompt}, |
| {"role": "user", "content": user_prompt} |
| ] |
| |
| analysis = call_mistral_api(messages, api_key) |
| |
| |
| scores = { |
| "Clarity": 75 + int(len(transcript) / 10) % 20, |
| "Confidence": 70 + int(len(transcript) / 15) % 25, |
| "Communication": 80 + int(len(transcript) / 20) % 15, |
| "Professionalism": 65 + int(len(transcript) / 12) % 30 |
| } |
| |
| |
| summary = "Voice analysis completed using AI. Check detailed feedback below." |
| |
| return summary, analysis, scores, "β
Analysis ready! View results below." |
|
|
| |
| with gr.Blocks(title="π€ AI-Powered ATS with Mistral", theme=gr.themes.Soft()) as demo: |
| gr.Markdown(""" |
| # π€ AI-Powered Applicant Tracking System |
| ### Real AI Interviews using Mistral API |
| |
| **Features:** |
| - Real AI-generated interview questions |
| - Voice recording and analysis |
| - Dynamic conversation with AI |
| """) |
| |
| |
| api_key_state = gr.State("") |
| |
| with gr.Tabs(): |
| |
| with gr.TabItem("βοΈ Settings"): |
| gr.Markdown("### Configure Your API Keys") |
| gr.Markdown(""" |
| **For Hugging Face Deployment:** |
| 1. Add `MISTRAL_API_KEY` in your Space's Secrets |
| 2. Go to Settings β Repository secrets |
| |
| **OR enter your key manually below:** |
| """) |
| |
| api_key_input = gr.Textbox( |
| label="Mistral API Key", |
| type="password", |
| placeholder="Enter your Mistral API key here...", |
| info="Get your key from: https://console.mistral.ai/api-keys/" |
| ) |
| |
| save_key_btn = gr.Button("Save API Key", variant="primary") |
| |
| @save_key_btn.click(inputs=[api_key_input], outputs=[api_key_state]) |
| def save_key(key): |
| return key |
| |
| |
| with gr.TabItem("π¬ AI Chat Interview"): |
| gr.Markdown("### AI-Powered Chat Interview") |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| role_selection = gr.Dropdown( |
| choices=list(ROLE_PROMPTS.keys()), |
| label="Select Job Role", |
| value="Software Engineer" |
| ) |
| |
| status = gr.Textbox(label="Status", interactive=False) |
| |
| with gr.Column(scale=2): |
| chatbot = gr.Chatbot( |
| label="Interview Conversation", |
| height=400, |
| avatar_images=( |
| "https://api.dicebear.com/7.x/avataaars/svg?seed=AI", |
| "https://api.dicebear.com/7.x/avataaars/svg?seed=User" |
| ) |
| ) |
| |
| with gr.Row(): |
| user_input = gr.Textbox( |
| label="Your Answer", |
| placeholder="Type your answer here...", |
| scale=4 |
| ) |
| |
| submit_btn = gr.Button("Submit", variant="primary", scale=1) |
| start_btn = gr.Button("Start New", scale=1) |
| |
| |
| ai_response_display = gr.Textbox( |
| label="Current AI Question", |
| interactive=False, |
| lines=3 |
| ) |
| |
| |
| submit_event = submit_btn.click( |
| ai_interview, |
| inputs=[role_selection, user_input, chatbot, api_key_state], |
| outputs=[user_input, chatbot, ai_response_display] |
| ) |
| |
| start_event = start_btn.click( |
| start_interview, |
| inputs=[role_selection, api_key_state], |
| outputs=[ai_response_display, chatbot, user_input] |
| ) |
| |
| user_input.submit( |
| ai_interview, |
| inputs=[role_selection, user_input, chatbot, api_key_state], |
| outputs=[user_input, chatbot, ai_response_display] |
| ) |
| |
| |
| with gr.TabItem("π€ Voice Assessment"): |
| gr.Markdown("### Voice Interview Recording") |
| gr.Markdown("Record your answer to assess communication skills") |
| |
| with gr.Row(): |
| with gr.Column(): |
| audio_input = gr.Audio( |
| sources=["microphone"], |
| type="filepath", |
| label="Record Your Answer (30-60 seconds)", |
| interactive=True |
| ) |
| |
| transcript_input = gr.Textbox( |
| label="What you said (or type manually)", |
| placeholder="Describe what you said in the recording...", |
| lines=3 |
| ) |
| |
| analyze_btn = gr.Button("Analyze with AI", variant="primary") |
| |
| with gr.Column(): |
| result_summary = gr.Textbox(label="Analysis Summary", interactive=False) |
| detailed_analysis = gr.Textbox( |
| label="Detailed AI Analysis", |
| interactive=False, |
| lines=8 |
| ) |
| |
| scores_display = gr.Label(label="Assessment Scores") |
| |
| status_indicator = gr.Textbox(label="Status", interactive=False) |
| |
| analyze_btn.click( |
| analyze_voice_with_ai, |
| inputs=[audio_input, api_key_state, transcript_input], |
| outputs=[result_summary, detailed_analysis, scores_display, status_indicator] |
| ) |
| |
| |
| with gr.TabItem("π How to Use"): |
| gr.Markdown(""" |
| ## Getting Started |
| |
| ### 1. **API Setup** |
| - Get Mistral API key from [Mistral Console](https://console.mistral.ai/api-keys/) |
| - **Option A (Recommended):** Add to Hugging Face Secrets |
| - Go to your Space β Settings β Repository secrets |
| - Add `MISTRAL_API_KEY` with your key |
| - **Option B:** Enter manually in Settings tab |
| |
| ### 2. **Conduct AI Interview** |
| 1. Go to "AI Chat Interview" tab |
| 2. Select job role |
| 3. Click "Start New" |
| 4. Respond to AI's questions |
| 5. AI will ask relevant follow-up questions |
| |
| ### 3. **Voice Assessment** |
| 1. Go to "Voice Assessment" tab |
| 2. Record your voice (30-60 seconds recommended) |
| 3. Describe what you said |
| 4. Click "Analyze with AI" |
| 5. Get detailed feedback on communication skills |
| |
| ### 4. **For Hugging Face Deployment** |
| ```yaml |
| # requirements.txt |
| gradio>=4.0 |
| requests |
| python-dotenv |
| ``` |
| |
| ### **Note:** |
| - First response may take 10-15 seconds |
| - Keep answers concise for best results |
| - Voice analysis uses transcript for AI assessment |
| """) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch( |
| debug=True, |
| share=False, |
| server_name="0.0.0.0", |
| server_port=7860 |
| ) |