ats / app.py
muhyousf's picture
Create app.py
7019d1c verified
Raw
History Blame Contribute Delete
14 kB
import gradio as gr
import os
import requests
import json
import time
from typing import List, Dict, Tuple
# Mistral API configuration
MISTRAL_API_URL = "https://api.mistral.ai/v1/chat/completions"
# Function to get API key from Hugging Face secrets or user input
def get_mistral_api_key(user_key: str = None) -> str:
"""Get API key from HF secrets or user input"""
# First try Hugging Face secrets
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
# Function to call Mistral API
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-based system prompts
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."""
}
# Generate AI interview question
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"])
# Format conversation history for Mistral
messages = [{"role": "system", "content": system_prompt}]
for speaker, text in conversation_history[-4:]: # Last 4 exchanges
if speaker == "AI Interviewer":
messages.append({"role": "assistant", "content": text})
else:
messages.append({"role": "user", "content": text})
# Add prompt for next question
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})
# Call Mistral API
response = call_mistral_api(messages, api_key)
return response
# Main interview function
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:
# Add user's response to history
history.append(("Candidate", user_message))
# Generate AI response using Mistral
ai_response = generate_ai_question(role, history, api_key)
# Add AI response to history
history.append(("AI Interviewer", ai_response))
return "", history, ai_response
# Start new interview
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", [], ""
# Start with AI greeting
initial_history = []
ai_response = generate_ai_question(role, initial_history, api_key)
initial_history.append(("AI Interviewer", ai_response))
return ai_response, initial_history, ""
# Analyze voice using Mistral
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", "", {}, ""
# Simulate processing time
time.sleep(2)
# Use Mistral to analyze communication skills based on transcript
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)
# Generate scores based on analysis (simulated for demo)
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 for display
summary = "Voice analysis completed using AI. Check detailed feedback below."
return summary, analysis, scores, "βœ… Analysis ready! View results below."
# Gradio Interface
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
""")
# Store API key in session state
api_key_state = gr.State("")
with gr.Tabs():
# Tab 1: Settings
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
# Tab 2: AI Interview
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)
# Response display
ai_response_display = gr.Textbox(
label="Current AI Question",
interactive=False,
lines=3
)
# Event handlers
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]
)
# Tab 3: Voice Interview
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]
)
# Tab 4: How to Use
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
""")
# Launch app
if __name__ == "__main__":
demo.launch(
debug=True,
share=False,
server_name="0.0.0.0",
server_port=7860
)