Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -35,15 +35,77 @@ def extract_text_from_pdf(pdf_file):
|
|
| 35 |
finally:
|
| 36 |
gc.collect()
|
| 37 |
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
"""Smart ATS relying fully on AI for analysis"""
|
| 40 |
try:
|
| 41 |
resume_text = extract_text_from_pdf(pdf_file)
|
| 42 |
except Exception as e:
|
| 43 |
return f"Extraction failed: {str(e)}", {"error": str(e)}
|
| 44 |
|
| 45 |
-
# Fallback if no inference function
|
| 46 |
if not inference_fn:
|
|
|
|
| 47 |
basic_analysis = {
|
| 48 |
"score": {"total": 10, "breakdown": {"competency": 10}},
|
| 49 |
"analysis": {
|
|
@@ -57,7 +119,7 @@ def analyze_resume(pdf_file, job_desc=None, role_type="general", inference_fn=No
|
|
| 57 |
return resume_text[:5000], basic_analysis
|
| 58 |
|
| 59 |
# AI-driven analysis
|
| 60 |
-
prompt = f"""[Return valid JSON]: You are a smart ATS designed to evaluate resumes without rejecting worthy candidates. Analyze this resume: '{resume_text[:2000]}' against job description: '{job_desc or "None"}'
|
| 61 |
Provide:
|
| 62 |
- "score": {{total: X (0-100), breakdown: {{competency: X (technical/non-technical skills), experience: X (duration and depth), impact: X (achievements), potential: X (learning ability), leadership: X (influence), adaptability: X (fit to role or general)}}}}
|
| 63 |
- "analysis": {{"strengths": [2-3 items, e.g., "Strong React skills"], "improvements": [2-3 items, e.g., "Add teamwork examples"], "missing_skills": [0-3 items, only if job_desc provided], "flags": [0-2 items, e.g., "High potential candidate"]}}
|
|
@@ -71,7 +133,9 @@ def analyze_resume(pdf_file, job_desc=None, role_type="general", inference_fn=No
|
|
| 71 |
Return valid JSON only."""
|
| 72 |
|
| 73 |
try:
|
|
|
|
| 74 |
result = inference_fn(prompt)
|
|
|
|
| 75 |
if result and result.strip():
|
| 76 |
analysis = json.loads(result)
|
| 77 |
analysis["raw_text_sample"] = resume_text[:200]
|
|
@@ -82,7 +146,7 @@ def analyze_resume(pdf_file, job_desc=None, role_type="general", inference_fn=No
|
|
| 82 |
print(f"AI analysis error: {str(e)}")
|
| 83 |
return resume_text[:5000], {
|
| 84 |
"score": {"total": 10, "breakdown": {"competency": 10}},
|
| 85 |
-
"analysis": {"strengths": ["Text processed"], "improvements": ["Analysis failed
|
| 86 |
"raw_text_sample": resume_text[:200]
|
| 87 |
}
|
| 88 |
|
|
@@ -92,7 +156,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 92 |
with gr.Column(scale=1):
|
| 93 |
pdf_input = gr.File(label="PDF Resume", type="binary")
|
| 94 |
job_desc_input = gr.Textbox(label="Job Description (Optional)", lines=3)
|
| 95 |
-
role_type_input = gr.Dropdown(label="Role Type", choices=["General", "Frontend", "Backend", "Non-Technical"], value="General")
|
| 96 |
submit_btn = gr.Button("Analyze")
|
| 97 |
with gr.Column(scale=2):
|
| 98 |
extracted_text = gr.Textbox(label="Extracted Text", lines=10, interactive=False)
|
|
@@ -100,7 +163,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 100 |
|
| 101 |
submit_btn.click(
|
| 102 |
fn=analyze_resume,
|
| 103 |
-
inputs=[pdf_input, job_desc_input
|
| 104 |
outputs=[extracted_text, analysis_output]
|
| 105 |
)
|
| 106 |
|
|
|
|
| 35 |
finally:
|
| 36 |
gc.collect()
|
| 37 |
|
| 38 |
+
# Placeholder inference function to match your example output
|
| 39 |
+
def dummy_inference_fn(prompt):
|
| 40 |
+
"""Temporary inference function - replace with your actual AI model"""
|
| 41 |
+
# Simulate response based on your resume and job description in prompt
|
| 42 |
+
resume_text = prompt.split("Analyze this resume: '")[1].split("' against job description")[0]
|
| 43 |
+
job_desc = prompt.split("against job description: '")[1].split("'")[0]
|
| 44 |
+
|
| 45 |
+
# Default response mimicking your example
|
| 46 |
+
response = {
|
| 47 |
+
"score": {
|
| 48 |
+
"total": 85,
|
| 49 |
+
"breakdown": {
|
| 50 |
+
"competency": 25,
|
| 51 |
+
"experience": 15,
|
| 52 |
+
"impact": 20,
|
| 53 |
+
"potential": 5,
|
| 54 |
+
"leadership": 0,
|
| 55 |
+
"adaptability": 20
|
| 56 |
+
}
|
| 57 |
+
},
|
| 58 |
+
"analysis": {
|
| 59 |
+
"strengths": [
|
| 60 |
+
"Strong frontend skills (React.js, JavaScript, UI components)",
|
| 61 |
+
"Proven performance impact (e.g., 30% code redundancy reduction, 20% efficiency boost)",
|
| 62 |
+
"Matches experience requirement (3+ years with relevant projects)"
|
| 63 |
+
],
|
| 64 |
+
"improvements": [
|
| 65 |
+
"Emphasize UI/UX contributions in projects",
|
| 66 |
+
"Add leadership or teamwork examples for well-roundedness"
|
| 67 |
+
],
|
| 68 |
+
"missing_skills": [],
|
| 69 |
+
"flags": []
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
# Adjust slightly if no job description
|
| 74 |
+
if job_desc == "None":
|
| 75 |
+
response["score"]["adaptability"] = 10
|
| 76 |
+
response["score"]["total"] = 75
|
| 77 |
+
response["analysis"]["strengths"] = [
|
| 78 |
+
"Strong technical skills (MERN stack, blockchain)",
|
| 79 |
+
"Proven project impact (e.g., 25% session time increase)",
|
| 80 |
+
"Solid experience (3+ years)"
|
| 81 |
+
]
|
| 82 |
+
response["analysis"]["improvements"] = [
|
| 83 |
+
"Add leadership or teamwork examples",
|
| 84 |
+
"Highlight learning initiatives"
|
| 85 |
+
]
|
| 86 |
+
|
| 87 |
+
return json.dumps(response) # Return as JSON string
|
| 88 |
+
|
| 89 |
+
# Real inference function example (uncomment and configure if you have a model)
|
| 90 |
+
"""
|
| 91 |
+
from transformers import pipeline
|
| 92 |
+
def inference_fn(prompt):
|
| 93 |
+
model = pipeline("text-generation", model="gpt2", token=os.getenv("HF_TOKEN")) # Replace with your model
|
| 94 |
+
response = model(prompt, max_length=2000, num_return_sequences=1)[0]["generated_text"]
|
| 95 |
+
start = response.find("[Return valid JSON]:") + len("[Return valid JSON]:")
|
| 96 |
+
return response[start:].strip()
|
| 97 |
+
"""
|
| 98 |
+
|
| 99 |
+
def analyze_resume(pdf_file, job_desc=None, inference_fn=dummy_inference_fn):
|
| 100 |
"""Smart ATS relying fully on AI for analysis"""
|
| 101 |
try:
|
| 102 |
resume_text = extract_text_from_pdf(pdf_file)
|
| 103 |
except Exception as e:
|
| 104 |
return f"Extraction failed: {str(e)}", {"error": str(e)}
|
| 105 |
|
| 106 |
+
# Fallback if no inference function
|
| 107 |
if not inference_fn:
|
| 108 |
+
print("No inference function provided - using fallback")
|
| 109 |
basic_analysis = {
|
| 110 |
"score": {"total": 10, "breakdown": {"competency": 10}},
|
| 111 |
"analysis": {
|
|
|
|
| 119 |
return resume_text[:5000], basic_analysis
|
| 120 |
|
| 121 |
# AI-driven analysis
|
| 122 |
+
prompt = f"""[Return valid JSON]: You are a smart ATS designed to evaluate resumes without rejecting worthy candidates. Analyze this resume: '{resume_text[:2000]}' against job description: '{job_desc or "None"}'.
|
| 123 |
Provide:
|
| 124 |
- "score": {{total: X (0-100), breakdown: {{competency: X (technical/non-technical skills), experience: X (duration and depth), impact: X (achievements), potential: X (learning ability), leadership: X (influence), adaptability: X (fit to role or general)}}}}
|
| 125 |
- "analysis": {{"strengths": [2-3 items, e.g., "Strong React skills"], "improvements": [2-3 items, e.g., "Add teamwork examples"], "missing_skills": [0-3 items, only if job_desc provided], "flags": [0-2 items, e.g., "High potential candidate"]}}
|
|
|
|
| 133 |
Return valid JSON only."""
|
| 134 |
|
| 135 |
try:
|
| 136 |
+
print("Calling inference_fn with prompt:", prompt[:200]) # Debug
|
| 137 |
result = inference_fn(prompt)
|
| 138 |
+
print("Inference result:", result) # Debug
|
| 139 |
if result and result.strip():
|
| 140 |
analysis = json.loads(result)
|
| 141 |
analysis["raw_text_sample"] = resume_text[:200]
|
|
|
|
| 146 |
print(f"AI analysis error: {str(e)}")
|
| 147 |
return resume_text[:5000], {
|
| 148 |
"score": {"total": 10, "breakdown": {"competency": 10}},
|
| 149 |
+
"analysis": {"strengths": ["Text processed"], "improvements": [f"Analysis failed: {str(e)}"], "missing_skills": [], "flags": []},
|
| 150 |
"raw_text_sample": resume_text[:200]
|
| 151 |
}
|
| 152 |
|
|
|
|
| 156 |
with gr.Column(scale=1):
|
| 157 |
pdf_input = gr.File(label="PDF Resume", type="binary")
|
| 158 |
job_desc_input = gr.Textbox(label="Job Description (Optional)", lines=3)
|
|
|
|
| 159 |
submit_btn = gr.Button("Analyze")
|
| 160 |
with gr.Column(scale=2):
|
| 161 |
extracted_text = gr.Textbox(label="Extracted Text", lines=10, interactive=False)
|
|
|
|
| 163 |
|
| 164 |
submit_btn.click(
|
| 165 |
fn=analyze_resume,
|
| 166 |
+
inputs=[pdf_input, job_desc_input],
|
| 167 |
outputs=[extracted_text, analysis_output]
|
| 168 |
)
|
| 169 |
|