File size: 4,244 Bytes
5e6df1f bfc8ca4 866b9c1 bfc8ca4 5e6df1f bfc8ca4 e546e82 bfc8ca4 e546e82 5e6df1f bfc8ca4 866b9c1 bfc8ca4 866b9c1 5e6df1f bfc8ca4 866b9c1 bfc8ca4 866b9c1 5e6df1f bfc8ca4 5e6df1f 866b9c1 bfc8ca4 866b9c1 bfc8ca4 5e6df1f bfc8ca4 866b9c1 bfc8ca4 866b9c1 bfc8ca4 5e6df1f bfc8ca4 5e6df1f bfc8ca4 5e6df1f 866b9c1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import gradio as gr
import os
import docx2txt
import PyPDF2
import json
from openai import OpenAI
# Replace this with your actual API key
client = OpenAI(
base_url="https://api.aimlapi.com/v1",
api_key=os.getenv("AIML_API_KEY")
)
# -------- Resume Parsing --------
def extract_text_from_pdf(file):
try:
reader = PyPDF2.PdfReader(file)
return "\n".join([page.extract_text() or "" for page in reader.pages])
except Exception:
return ""
def extract_text_from_docx(file):
try:
return docx2txt.process(file)
except Exception:
return ""
def parse_resume(file):
ext = os.path.splitext(file.name)[1].lower()
if ext == ".pdf":
return extract_text_from_pdf(file)
elif ext == ".docx":
return extract_text_from_docx(file)
else:
return None
# -------- AI Screening --------
def call_ai_screening_agent(resume_texts, job_description, min_experience):
prompt = f"""
You are an AI resume screening assistant. Compare each candidate's resume to the job description below.
Only include candidates who meet the minimum required years of experience: {min_experience}.
For each candidate, return:
- name (from filename or parsed text)
- strengths (2–5 key strengths)
- risks (0–3 potential risks)
- score (from 1 to 10)
Job Description:
\"\"\"{job_description}\"\"\"
Resumes:
{resume_texts}
Return a JSON list of candidates as described.
"""
try:
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=0.2
)
return json.loads(response.choices[0].message.content)
except Exception as e:
return {"error": str(e)}
# -------- Main App Logic --------
def process_resumes(files, job_description, min_experience):
if not files:
return "⚠️ Please upload at least one resume.", None
if not job_description.strip():
return "⚠️ Job description cannot be empty.", None
parsed_resumes = []
for file in files:
content = parse_resume(file)
if not content or len(content.strip()) == 0:
continue
parsed_resumes.append({"name": os.path.basename(file.name), "text": content})
if not parsed_resumes:
return "⚠️ Could not parse any valid resumes.", None
resume_texts = "\n\n".join([f"{r['name']}:\n{r['text']}" for r in parsed_resumes])
results = call_ai_screening_agent(resume_texts, job_description, min_experience)
if isinstance(results, dict) and "error" in results:
return f"⚠️ API Error: {results['error']}", None
# Display top 3 candidates
top_candidates = sorted(results, key=lambda x: x["score"], reverse=True)[:3]
display_md = ""
for candidate in top_candidates:
display_md += f"### {candidate['name']} \n"
display_md += f"⭐ **Score**: {candidate['score']} \n"
display_md += "✅ **Strengths**:\n"
for s in candidate['strengths']:
display_md += f"- ✅ {s}\n"
if candidate['risks']:
display_md += "⚠️ **Risks**:\n"
for r in candidate['risks']:
display_md += f"- ⚠️ {r}\n"
display_md += "\n---\n"
return None, display_md
# -------- Gradio UI --------
with gr.Blocks(title="SmartHire - AI Job Screening Assistant") as demo:
gr.Markdown("# 🤖 SmartHire — AI Job Screening Assistant")
gr.Markdown("Upload resumes and paste a job description to find the best candidates automatically!")
with gr.Row():
resume_input = gr.File(file_types=[".pdf", ".docx"], file_count="multiple", label="Upload Resumes")
experience_input = gr.Number(label="Minimum Years of Experience", value=0)
job_desc_input = gr.Textbox(lines=8, placeholder="Paste the job description here...", label="Job Description")
process_button = gr.Button("Run Screening")
error_output = gr.Textbox(label="Warnings / Errors", visible=False)
output_md = gr.Markdown()
process_button.click(
fn=process_resumes,
inputs=[resume_input, job_desc_input, experience_input],
outputs=[error_output, output_md]
)
demo.launch()
|