ShubhamD95 commited on
Commit
286e0a1
Β·
verified Β·
1 Parent(s): fc27649

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -24
app.py CHANGED
@@ -4,18 +4,17 @@ import re
4
  import os
5
  from huggingface_hub import login
6
  import spacy
7
- from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS
8
 
9
- # Authenticate with Hugging Face
10
  login(token=os.environ.get("HUGGINGFACEHUB_API_TOKEN"))
11
 
12
- # Load summarization model
13
  summarizer = pipeline("text2text-generation", model="declare-lab/flan-alpaca-base")
14
 
15
- # Load SpaCy English model
16
  nlp = spacy.load("en_core_web_sm")
17
 
18
- # πŸ” Use SpaCy to extract nouns and proper nouns (contextually relevant keywords)
19
  def extract_relevant_keywords(text):
20
  doc = nlp(text.lower())
21
  return set(
@@ -23,7 +22,7 @@ def extract_relevant_keywords(text):
23
  if token.pos_ in {"NOUN", "PROPN"} and not token.is_stop and len(token.text) > 2
24
  )
25
 
26
- # Compare keywords with semantic filtering
27
  def compare_keywords(resume_text, job_desc):
28
  resume_words = extract_relevant_keywords(resume_text)
29
  job_words = extract_relevant_keywords(job_desc)
@@ -31,78 +30,100 @@ def compare_keywords(resume_text, job_desc):
31
  missing = job_words - resume_words
32
  return matched, missing
33
 
34
- # Highlight matched keywords in the resume
35
  def highlight_keywords(resume_text, matched):
36
  highlighted = resume_text
37
  for word in sorted(matched, key=len, reverse=True):
38
  highlighted = re.sub(rf"\b({re.escape(word)})\b", r"**\1**", highlighted, flags=re.IGNORECASE)
39
  return highlighted
40
 
41
- # LLM-based missing keyword extraction
42
  def extract_missing_keywords_with_llm(job_desc, resume_text):
43
  prompt = f"""
44
  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.
 
45
  Job Description:
46
  {job_desc}
 
47
  Resume:
48
  {resume_text}
 
49
  Only list the missing keywords as bullet points.
50
  """
51
  result = summarizer(prompt, max_new_tokens=300, do_sample=True)[0]
52
- return result.get('generated_text', result.get('summary_text', str(result))).strip()
53
 
54
- # Resume improvement prompt
55
  def build_dynamic_prompt(job_desc, resume_text, analyze_with_jd):
56
  prompt = f"""
57
- Analyze the resume below and organize it into meaningful categories (e.g., Skills, Education, Work Experience, etc.).
58
- If a job description is provided, compare it against the resume and suggest improvements section by section.
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  Job Description:
60
  {job_desc if analyze_with_jd else '[None provided]'}
 
61
  Resume:
62
  {resume_text}
63
- Return structured Markdown with headers for each section and improvement suggestions.
 
64
  """
65
  return prompt
66
 
67
- # Generate analysis result
68
  def analyze_resume(job_desc, resume_text, analyze_with_jd):
69
  if not resume_text.strip():
70
  return "⚠️ Please paste your resume text."
71
 
72
- user_prompt = build_dynamic_prompt(job_desc, resume_text, analyze_with_jd)
73
 
74
  try:
75
- result = summarizer(user_prompt, max_new_tokens=512, do_sample=True)[0]
76
- response_text = result.get('generated_text', result.get('summary_text', str(result))).strip()
77
 
 
78
  if analyze_with_jd and job_desc:
79
  matched, missing = compare_keywords(resume_text, job_desc)
80
  highlighted_resume = highlight_keywords(resume_text, matched)
81
  llm_missing_keywords = extract_missing_keywords_with_llm(job_desc, resume_text)
82
 
83
- return f"""### πŸ” Resume with Highlighted Matches
 
84
 
85
  {highlighted_resume}
86
 
87
  ---
88
 
89
- ** Matched Keywords (Semantic Comparison):**
90
  {', '.join(sorted(matched)) or 'None'}
91
 
92
- ** Missing Keywords (Semantic Comparison):**
93
  {', '.join(sorted(missing)) or 'None'}
94
 
95
- ** LLM-Inferred Missing Keywords:**
96
  {llm_missing_keywords}
97
 
98
  ---
99
 
100
- {response_text}"""
101
- return response_text
 
 
102
  except Exception as e:
103
  return f"❌ Error: {str(e)}"
104
 
105
- # Gradio Interface
106
  def create_ui():
107
  with gr.Blocks() as demo:
108
  with gr.Row():
 
4
  import os
5
  from huggingface_hub import login
6
  import spacy
 
7
 
8
+ # βœ… Authenticate using HF token stored in secret
9
  login(token=os.environ.get("HUGGINGFACEHUB_API_TOKEN"))
10
 
11
+ # βœ… Load summarization model (lightweight and CPU-friendly)
12
  summarizer = pipeline("text2text-generation", model="declare-lab/flan-alpaca-base")
13
 
14
+ # βœ… Load SpaCy English model for NLP keyword extraction
15
  nlp = spacy.load("en_core_web_sm")
16
 
17
+ # βœ… Extract keywords (nouns & proper nouns, excluding stopwords)
18
  def extract_relevant_keywords(text):
19
  doc = nlp(text.lower())
20
  return set(
 
22
  if token.pos_ in {"NOUN", "PROPN"} and not token.is_stop and len(token.text) > 2
23
  )
24
 
25
+ # βœ… Match resume keywords with job description
26
  def compare_keywords(resume_text, job_desc):
27
  resume_words = extract_relevant_keywords(resume_text)
28
  job_words = extract_relevant_keywords(job_desc)
 
30
  missing = job_words - resume_words
31
  return matched, missing
32
 
33
+ # βœ… Highlight matched keywords in resume text
34
  def highlight_keywords(resume_text, matched):
35
  highlighted = resume_text
36
  for word in sorted(matched, key=len, reverse=True):
37
  highlighted = re.sub(rf"\b({re.escape(word)})\b", r"**\1**", highlighted, flags=re.IGNORECASE)
38
  return highlighted
39
 
40
+ # βœ… Use LLM to extract contextually missing skills/tools
41
  def extract_missing_keywords_with_llm(job_desc, resume_text):
42
  prompt = f"""
43
  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.
44
+
45
  Job Description:
46
  {job_desc}
47
+
48
  Resume:
49
  {resume_text}
50
+
51
  Only list the missing keywords as bullet points.
52
  """
53
  result = summarizer(prompt, max_new_tokens=300, do_sample=True)[0]
54
+ return result.get('generated_text', str(result)).strip()
55
 
56
+ # βœ… Build LLM prompt to extract resume sections + insights
57
  def build_dynamic_prompt(job_desc, resume_text, analyze_with_jd):
58
  prompt = f"""
59
+ You are a professional resume analyst.
60
+
61
+ Classify the content of the resume below into logical sections such as:
62
+ - Education
63
+ - Work Experience
64
+ - Technical Skills
65
+ - Soft Skills
66
+ - Certifications
67
+ - Projects
68
+ - Achievements
69
+
70
+ Use markdown format with headers (###) for each section.
71
+
72
+ If a job description is also provided, add relevant suggestions under each section to improve alignment with the job.
73
+
74
  Job Description:
75
  {job_desc if analyze_with_jd else '[None provided]'}
76
+
77
  Resume:
78
  {resume_text}
79
+
80
+ Return your output in structured markdown format.
81
  """
82
  return prompt
83
 
84
+ # βœ… Generate structured LLM output + keyword analysis
85
  def analyze_resume(job_desc, resume_text, analyze_with_jd):
86
  if not resume_text.strip():
87
  return "⚠️ Please paste your resume text."
88
 
89
+ prompt = build_dynamic_prompt(job_desc, resume_text, analyze_with_jd)
90
 
91
  try:
92
+ llm_result = summarizer(prompt, max_new_tokens=512, do_sample=True)[0]
93
+ structured_response = llm_result.get('generated_text', str(llm_result)).strip()
94
 
95
+ # Perform keyword comparison and highlighting
96
  if analyze_with_jd and job_desc:
97
  matched, missing = compare_keywords(resume_text, job_desc)
98
  highlighted_resume = highlight_keywords(resume_text, matched)
99
  llm_missing_keywords = extract_missing_keywords_with_llm(job_desc, resume_text)
100
 
101
+ return f"""
102
+ ### πŸ” Resume with Highlighted Matches
103
 
104
  {highlighted_resume}
105
 
106
  ---
107
 
108
+ **βœ… Matched Keywords (Semantic Match):**
109
  {', '.join(sorted(matched)) or 'None'}
110
 
111
+ **❌ Missing Keywords (Semantic Match):**
112
  {', '.join(sorted(missing)) or 'None'}
113
 
114
+ **πŸ€– LLM-Inferred Missing Keywords:**
115
  {llm_missing_keywords}
116
 
117
  ---
118
 
119
+ {structured_response}
120
+ """
121
+ return structured_response
122
+
123
  except Exception as e:
124
  return f"❌ Error: {str(e)}"
125
 
126
+ # βœ… Gradio UI
127
  def create_ui():
128
  with gr.Blocks() as demo:
129
  with gr.Row():