Spaces:
Build error
Build error
| 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() |