PraneshJs's picture
added server name and port
f833cab verified
import io
import json
from typing import Optional
import gradio as gr
import PyPDF2
from resume_ai import score, improve
def extract_text_from_pdf(file_obj: io.IOBase) -> str:
"""Extract text from a PDF file-like object."""
try:
reader = PyPDF2.PdfReader(file_obj)
text_chunks = []
for page in reader.pages:
page_text = page.extract_text() or ""
text_chunks.append(page_text)
text = "\n".join(text_chunks).strip()
if not text:
raise ValueError("No extractable text found in PDF.")
return text
except Exception as e:
raise ValueError(f"Error reading PDF: {e}")
def read_resume_to_text(resume_file_path) -> str:
"""
Accepts a file path and returns text content.
Supports PDF and plain text files.
"""
if resume_file_path is None:
raise ValueError("Please upload a resume file.")
filename = str(resume_file_path).lower()
if filename.endswith(".pdf"):
with open(resume_file_path, "rb") as f:
return extract_text_from_pdf(f)
else:
with open(resume_file_path, "rb") as f:
data = f.read()
if not data:
raise ValueError("Uploaded file is empty.")
try:
return data.decode("utf-8").strip()
except UnicodeDecodeError:
return data.decode("latin-1").strip()
def score_fn(resume_file_path, job_desc: str) -> str:
try:
if not job_desc or not job_desc.strip():
raise ValueError("Please paste a job description.")
resume_text = read_resume_to_text(resume_file_path)
result = score(resume_text, job_desc)
return json.dumps(result, indent=2, ensure_ascii=False)
except Exception as e:
return f"Error: {e}"
def improve_fn(resume_file_path, job_desc: Optional[str]) -> str:
try:
resume_text = read_resume_to_text(resume_file_path)
jd_text = job_desc if job_desc and job_desc.strip() else None
suggestions = improve(resume_text, jd_text)
if isinstance(suggestions, (list, tuple)):
bullets = "\n".join(f"- {s}" for s in suggestions)
return f"### Suggestions\n{bullets}"
elif isinstance(suggestions, dict):
return "```json\n" + json.dumps(suggestions, indent=2, ensure_ascii=False) + "\n```"
else:
return str(suggestions)
except Exception as e:
return f"Error: {e}"
def format_score_display(result_json) -> str:
"""
Takes the result JSON (as dict or str), parses it, and returns a Markdown string for display.
"""
if isinstance(result_json, str):
try:
result = json.loads(result_json)
except Exception:
return f"```\n{result_json}\n```"
else:
result = result_json
md = f"## πŸ† ATS Compatibility Score: **{result.get('overall_score', 0)}%**\n\n"
md += "### Category Scores\n"
md += "| Skills | Experience | Education |\n"
md += "|--------|------------|-----------|\n"
cs = result.get("category_scores", {})
md += f"| {cs.get('skills',0)}% | {cs.get('experience',0)}% | {cs.get('education',0)}% |\n\n"
gaps = result.get("top_skill_gaps", [])
if gaps:
md += "### 🚩 Top Skill Gaps\n"
for gap in gaps:
md += f"- {gap}\n"
return md
# ...existing code...
with gr.Blocks(title="Resume AI (Score & Improve)") as demo:
gr.Markdown(
"""
# πŸ“„ Resume AI β€” Score & Improve
Upload your resume (PDF or TXT), paste a Job Description, and get:
- **Score**: A formatted breakdown of your resume's ATS compatibility
- **Improve**: A healthy set of suggestions to enhance your resume
"""
)
with gr.Row():
resume = gr.File(label="Upload Resume (PDF or TXT)", file_types=[".pdf", ".txt"], type="filepath")
jd = gr.Textbox(label="Job Description (paste here)", lines=10, placeholder="Paste JD text...")
with gr.Row():
score_btn = gr.Button("βš–οΈ Score Resume", variant="primary")
improve_btn = gr.Button("✨ Improve Resume")
score_out = gr.Markdown(label="Score (Formatted)")
improve_out = gr.Markdown(label="Improvement Suggestions")
def score_fn_display(resume_file_path, job_desc: str) -> str:
try:
if not job_desc or not job_desc.strip():
raise ValueError("Please paste a job description.")
resume_text = read_resume_to_text(resume_file_path)
result = score(resume_text, job_desc)
return format_score_display(result)
except Exception as e:
return f"Error: {e}"
score_btn.click(fn=score_fn_display, inputs=[resume, jd], outputs=score_out)
improve_btn.click(fn=improve_fn, inputs=[resume, jd], outputs=improve_out)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0",server_port=7860, pwa=True)