Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| from openai import OpenAI | |
| import PyPDF2 | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import tempfile | |
| import json | |
| import re | |
| # Initialize OpenAI client | |
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) | |
| # --------------------------- | |
| # π§ Helper Functions | |
| # --------------------------- | |
| def extract_text_from_pdf(file_path): | |
| """Extract text safely from a PDF""" | |
| try: | |
| text = "" | |
| with open(file_path, "rb") as f: | |
| reader = PyPDF2.PdfReader(f) | |
| for page in reader.pages: | |
| page_text = page.extract_text() or "" | |
| text += page_text | |
| return text.strip() | |
| except Exception as e: | |
| return f"Error reading PDF: {e}" | |
| def analyze_resume(resume_text, job_desc): | |
| """Call GPT-4 model to analyze resume""" | |
| try: | |
| prompt = f""" | |
| You are an expert HR AI. | |
| Compare the following resume to the given job description. | |
| Rate how well the resume fits the job on a scale of 0β100. | |
| Then summarize the key strengths and weaknesses. | |
| Return output strictly in JSON format: | |
| {{ | |
| "score": <number>, | |
| "summary": "<text>" | |
| }} | |
| JOB DESCRIPTION: | |
| {job_desc} | |
| RESUME: | |
| {resume_text} | |
| """ | |
| response = client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.4, | |
| ) | |
| reply = response.choices[0].message.content | |
| match = re.search(r"\{.*\}", reply, re.S) | |
| if match: | |
| return json.loads(match.group()) | |
| else: | |
| return {"score": 50, "summary": reply.strip()} | |
| except Exception as e: | |
| return {"score": 0, "summary": f"Error: {e}"} | |
| def process_resumes(files, job_desc): | |
| """Main pipeline: extract text, analyze, chart results""" | |
| if not files or not job_desc: | |
| return "β οΈ Please upload resumes and enter a job description.", None, None | |
| results = [] | |
| for f in files: | |
| text = extract_text_from_pdf(f.name) | |
| result = analyze_resume(text, job_desc) | |
| results.append({ | |
| "Filename": os.path.basename(f.name), | |
| "Score": result.get("score", 0), | |
| "Summary": result.get("summary", "") | |
| }) | |
| df = pd.DataFrame(results) | |
| # Generate visualization | |
| fig, ax = plt.subplots(figsize=(6, 3)) | |
| ax.bar(df["Filename"], df["Score"], color="skyblue") | |
| ax.set_title("Resume Fit Scores") | |
| ax.set_ylabel("Score (0β100)") | |
| plt.xticks(rotation=15, ha="right") | |
| plt.tight_layout() | |
| tmp_chart = tempfile.NamedTemporaryFile(delete=False, suffix=".png") | |
| plt.savefig(tmp_chart.name) | |
| plt.close(fig) | |
| return df, tmp_chart.name, "β Analysis complete!" | |
| # --------------------------- | |
| # π¨ Gradio UI | |
| # --------------------------- | |
| with gr.Blocks(theme=gr.themes.Soft(), title="AI Resume Screener Pro") as app: | |
| gr.Markdown("## π€ AI Resume Screener Pro\nUpload resumes and compare them with a job description using GPT-4.") | |
| with gr.Row(): | |
| job_desc = gr.Textbox(label="Job Description", lines=6, placeholder="Enter the job description here...") | |
| files = gr.File(label="Upload Resumes", file_count="multiple", type="filepath") | |
| analyze_btn = gr.Button("π Analyze Resumes", variant="primary") | |
| output_table = gr.Dataframe(headers=["Filename", "Score", "Summary"], label="Results") | |
| output_plot = gr.Image(label="Visualization") | |
| output_status = gr.Textbox(label="Status", interactive=False) | |
| analyze_btn.click(fn=process_resumes, inputs=[files, job_desc], | |
| outputs=[output_table, output_plot, output_status]) | |
| gr.Markdown("---") | |
| gr.Markdown("Built with β€οΈ using OpenAI GPT-4 and Gradio.") | |
| app.launch() | |