PrepGrid / app.py
HARISARAVANANM's picture
Update app.py
453708d verified
Raw
History Blame Contribute Delete
9.17 kB
import gradio as gr
import json
import os
import random
INTERVIEW_QUESTIONS = {
"Software Engineer": [
"Tell me about your most challenging project and how you solved it.",
"Describe your experience with system design. Walk me through your approach.",
"How do you handle debugging in production? Give a real example.",
"Tell me about a time you had to learn a new technology quickly.",
"Describe your experience with code reviews.",
"What's your approach to writing maintainable code?"
],
"Data Scientist": [
"Walk me through a machine learning project you built from scratch.",
"How do you handle imbalanced datasets?",
"Describe your approach to feature engineering.",
"How do you explain complex models to non-technical stakeholders?",
"How do you evaluate model performance?",
"Describe your data preprocessing experience."
],
"Product Manager": [
"Tell me about a product you'd build and your strategy.",
"How do you prioritize features?",
"Tell me about a time you said no to stakeholder requests.",
"How do you measure product success?",
"Describe your cross-functional collaboration.",
"Tell me about a product decision you'd redo."
],
"DevOps Engineer": [
"Tell me about your containerization experience.",
"How do you approach infrastructure as code?",
"Tell me about a critical production incident.",
"How do you ensure system reliability?",
"Describe your CI/CD experience.",
"How do you optimize cloud infrastructure costs?"
],
"Frontend Developer": [
"Tell me about a complex UI you built.",
"How do you optimize performance?",
"Describe your state management experience.",
"Tell me about working with legacy code.",
"How do you ensure accessibility?",
"Tell me about responsive design."
],
"Data Engineer": [
"Walk me through a data pipeline design.",
"How do you handle data quality?",
"Tell me about big data technologies.",
"Describe optimizing slow processes.",
"How do you approach data modeling?",
"Tell me about ETL/ELT experience."
]
}
def calculate_score(c, r, d, s, cf):
total = c + r + d + s + cf
percentage = (total / 50) * 100
if percentage >= 90:
return int(percentage), "Excellent"
elif percentage >= 75:
return int(percentage), "Good"
elif percentage >= 60:
return int(percentage), "Average"
elif percentage >= 40:
return int(percentage), "Needs Improvement"
else:
return int(percentage), "Needs Work"
def get_color(score):
if score >= 90:
return "#10b981"
elif score >= 75:
return "#22c55e"
elif score >= 60:
return "#eab308"
elif score >= 40:
return "#f97316"
else:
return "#ef4444"
css = """
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body, .gradio-container { font-family: 'Inter', sans-serif !important; background: linear-gradient(135deg, #0f172a 0%, #1e1b4b 100%) !important; }
.card { background: linear-gradient(145deg, #1e293b 0%, #0f172a 100%) !important; border-radius: 16px !important; padding: 24px !important; border: 1px solid rgba(99, 102, 241, 0.2) !important; }
.title { font-size: 2.5em !important; font-weight: 700 !important; background: linear-gradient(135deg, #818cf8, #c084fc) !important; -webkit-background-clip: text !important; -webkit-text-fill-color: transparent !important; }
.question-box { background: rgba(99, 102, 241, 0.1); border-radius: 12px; padding: 20px; border-left: 4px solid #6366f1; color: #e2e8f0; }
.stat-card { background: rgba(30, 41, 59, 0.8) !important; border-radius: 12px !important; padding: 20px !important; text-align: center !important; }
.stat-value { font-size: 2.2em !important; font-weight: 700 !important; }
"""
with gr.Blocks(title="PrepGrid", theme=gr.themes.Soft(), css=css) as demo:
gr.Markdown("# 🎀 PrepGrid - Interview Tracker", elem_classes="title")
session_state = gr.State({
"questions": [],
"responses": [],
"scores": [],
"current_q": 0,
"started": False
})
with gr.Group(elem_classes="card"):
gr.Markdown("### πŸ“„ Step 1: Upload Resume & Select Role")
resume_file = gr.File(label="Upload Resume (PDF/TXT/DOC)", file_count="single")
role_dropdown = gr.Dropdown(
choices=list(INTERVIEW_QUESTIONS.keys()),
label="Select Role",
value="Software Engineer"
)
experience_dropdown = gr.Dropdown(
choices=["0-1 years", "1-3 years", "3-5 years", "5-7 years", "7+ years"],
label="Experience Level",
value="3-5 years"
)
start_btn = gr.Button("Start Interview", variant="primary", size="lg")
resume_preview = gr.Textbox(label="Resume Preview", lines=4, interactive=False)
with gr.Group(elem_classes="card"):
gr.Markdown("### 🎯 Step 2: Answer Questions")
question_display = gr.Markdown("Upload resume and click Start", elem_classes="question-box")
question_counter = gr.Markdown("Question 0 of 6")
response_text = gr.Textbox(
label="Your Response",
placeholder="Type your answer...",
lines=8,
interactive=False
)
with gr.Group(elem_classes="card"):
gr.Markdown("### πŸ“Š Step 3: Score Your Response")
with gr.Row():
comm = gr.Slider(0, 10, 7, step=1, label="Communication", interactive=False)
rel = gr.Slider(0, 10, 7, step=1, label="Relevance", interactive=False)
with gr.Row():
depth = gr.Slider(0, 10, 7, step=1, label="Depth", interactive=False)
struct = gr.Slider(0, 10, 7, step=1, label="Structure", interactive=False)
conf = gr.Slider(0, 10, 7, step=1, label="Confidence", interactive=False)
with gr.Row():
calc_btn = gr.Button("Calculate Score", variant="primary", interactive=False)
next_btn = gr.Button("Next Question β†’", interactive=False)
score_display = gr.Markdown("")
with gr.Group(elem_classes="card"):
gr.Markdown("### πŸ“ˆ Interview Summary")
summary_display = gr.Markdown("Complete the interview to see your summary")
def start_interview(resume, role, exp):
if not resume:
return None, "Upload resume first", "Q 0/6", False, False, False, False, False, False, False, None
try:
with open(resume.name, 'r', encoding='utf-8', errors='ignore') as f:
resume_text = f.read()[:400]
except:
resume_text = "[Resume uploaded]"
questions = random.sample(INTERVIEW_QUESTIONS[role], 6)
state = {"questions": questions, "responses": [], "scores": [], "current_q": 0, "started": True}
return (
state, resume_text, f"## Q1: {questions[0]}", "Question 1 of 6",
True, True, True, True, True, True, True, state
)
start_btn.click(
start_interview,
inputs=[resume_file, role_dropdown, experience_dropdown],
outputs=[session_state, resume_preview, question_display, question_counter,
response_text, comm, rel, depth, struct, conf, calc_btn, session_state]
)
def calc_score_fn(c, r, d, s, cf):
score, grade = calculate_score(c, r, d, s, cf)
color = get_color(score)
return f'<div class="stat-card"><div class="stat-value" style="color: {color};">{score}%</div><div style="color: #94a3b8;">{grade}</div></div>'
calc_btn.click(calc_score_fn, inputs=[comm, rel, depth, struct, conf], outputs=[score_display])
def next_question(state, response, c, r, d, s, cf):
if not state.get("started"):
return state, "", "", "Q 0/6", False, False
score, _ = calculate_score(c, r, d, s, cf)
state["responses"].append(response)
state["scores"].append(score)
state["current_q"] += 1
if state["current_q"] >= len(state["questions"]):
avg = sum(state["scores"]) / len(state["scores"]) if state["scores"] else 0
summary = f"## πŸŽ‰ Complete!\n\n**Score:** {int(avg)}%\n\n"
for i, s in enumerate(state["scores"], 1):
summary += f"Q{i}: {s}%\n"
return state, summary, "Done", "Done", False, False
return (
state, "", f"## Q{state['current_q']+1}: {state['questions'][state['current_q']]}",
f"Question {state['current_q']+1} of 6", True, True
)
next_btn.click(
next_question,
inputs=[session_state, response_text, comm, rel, depth, struct, conf],
outputs=[session_state, summary_display, question_display, question_counter, response_text, next_btn]
)
if __name__ == "__main__":
demo.launch()