Gemma / app.py
ShubhamD95's picture
Update app.py
fc823d8 verified
raw
history blame
4.11 kB
import gradio as gr
from transformers import pipeline
import re
import os
from huggingface_hub import login
# βœ… Authenticate using HF token stored in secret
login(token=os.environ.get("HUGGINGFACEHUB_API_TOKEN"))
# βœ… Use a lightweight instruction-tuned model compatible with CPU
summarizer = pipeline("text2text-generation", model="declare-lab/flan-alpaca-base")
# βœ… Highlight matching and find missing keywords
from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
def compare_keywords(resume_text, job_desc):
resume_words = set(re.findall(r"\b\w{3,}\b", resume_text.lower())) - ENGLISH_STOP_WORDS
job_words = set(re.findall(r"\b\w{3,}\b", job_desc.lower())) - ENGLISH_STOP_WORDS
matched = resume_words & job_words
missing = job_words - resume_words
return matched, missing
def highlight_keywords(resume_text, matched):
highlighted = resume_text
for word in sorted(matched, key=len, reverse=True):
highlighted = re.sub(rf"\b({re.escape(word)})\b", r"**\1**", highlighted, flags=re.IGNORECASE)
return highlighted
# πŸ” Use LLM to extract missing keywords contextually from JD
def extract_missing_keywords_with_llm(job_desc, resume_text):
prompt = f"""
Given the following job description and resume, list the important skills, tools, and concepts from the job description that are missing or weakly represented in the resume.
Job Description:
{job_desc}
Resume:
{resume_text}
Only list the missing keywords as bullet points.
"""
result = summarizer(prompt, max_new_tokens=300, do_sample=True)[0]['generated_text']
return result.strip()
# πŸ” Prompt for dynamic section classification and feedback
def build_dynamic_prompt(job_desc, resume_text, analyze_with_jd):
prompt = f"""
Analyze the resume below and organize it into meaningful categories (e.g., Skills, Education, Work Experience, etc.).
If a job description is provided, compare it against the resume and suggest improvements section by section.
Job Description:
{job_desc if analyze_with_jd else '[None provided]'}
Resume:
{resume_text}
Return structured Markdown with headers for each section and improvement suggestions.
"""
return prompt
# 🧠 Function to call Hugging Face model and get structured resume feedback
def analyze_resume(job_desc, resume_text, analyze_with_jd):
if not resume_text.strip():
return "⚠️ Please paste your resume text."
user_prompt = build_dynamic_prompt(job_desc, resume_text, analyze_with_jd)
try:
response = summarizer(user_prompt, max_new_tokens=512, do_sample=True)[0]['generated_text']
if analyze_with_jd and job_desc:
matched, _ = compare_keywords(resume_text, job_desc)
highlighted_resume = highlight_keywords(resume_text, matched)
llm_missing_keywords = extract_missing_keywords_with_llm(job_desc, resume_text)
return f"### πŸ” Resume with Highlighted Matches\n\n{highlighted_resume}\n\n---\n**βœ… Matched Keywords:** {', '.join(sorted(matched)) or 'None'}\n\n**❌ LLM-Inferred Missing Keywords:**\n{llm_missing_keywords}\n\n---\n{response.strip()}"
return response.strip()
except Exception as e:
return f"❌ Error: {str(e)}"
# πŸŽ›οΈ Gradio UI
def create_ui():
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
analyze_checkbox = gr.Checkbox(label="Analyze with Job Description", value=True)
job_desc = gr.Textbox(label="Job Description", lines=6, placeholder="Paste job description here...")
resume_text = gr.Textbox(label="Resume Text", lines=16, placeholder="Paste resume content here...")
with gr.Column():
output_analysis = gr.Markdown(label="Resume Analysis and Suggestions")
resume_text.change(fn=analyze_resume, inputs=[job_desc, resume_text, analyze_checkbox], outputs=output_analysis)
job_desc.change(fn=analyze_resume, inputs=[job_desc, resume_text, analyze_checkbox], outputs=output_analysis)
return demo
if __name__ == '__main__':
create_ui().launch()