sanjaystarc's picture
Update app.py
a85d717 verified
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()