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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -37
app.py CHANGED
@@ -5,24 +5,22 @@ 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(
21
- token.text for token in doc
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,46 +28,45 @@ def compare_keywords(resume_text, 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]'}
@@ -77,29 +74,27 @@ Job Description:
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
 
@@ -116,14 +111,12 @@ def analyze_resume(job_desc, resume_text, analyze_with_jd):
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():
@@ -141,3 +134,4 @@ def create_ui():
141
 
142
  if __name__ == '__main__':
143
  create_ui().launch()
 
 
5
  from huggingface_hub import login
6
  import spacy
7
 
8
+ # Authenticate with Hugging Face token
9
  login(token=os.environ.get("HUGGINGFACEHUB_API_TOKEN"))
10
 
11
+ # Load models
12
  summarizer = pipeline("text2text-generation", model="declare-lab/flan-alpaca-base")
 
 
13
  nlp = spacy.load("en_core_web_sm")
14
 
15
+ # Extract contextually relevant keywords using spaCy
16
  def extract_relevant_keywords(text):
17
  doc = nlp(text.lower())
18
  return set(
19
+ token.lemma_ for token in doc
20
  if token.pos_ in {"NOUN", "PROPN"} and not token.is_stop and len(token.text) > 2
21
  )
22
 
23
+ # Compare resume and JD for keyword matches
24
  def compare_keywords(resume_text, job_desc):
25
  resume_words = extract_relevant_keywords(resume_text)
26
  job_words = extract_relevant_keywords(job_desc)
 
28
  missing = job_words - resume_words
29
  return matched, missing
30
 
31
+ # Highlight matched words in resume text
32
  def highlight_keywords(resume_text, matched):
33
  highlighted = resume_text
34
  for word in sorted(matched, key=len, reverse=True):
35
  highlighted = re.sub(rf"\b({re.escape(word)})\b", r"**\1**", highlighted, flags=re.IGNORECASE)
36
  return highlighted
37
 
38
+ # LLM-based keyword extraction from JD
39
  def extract_missing_keywords_with_llm(job_desc, resume_text):
40
  prompt = f"""
41
  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.
42
+ Only list the missing keywords as bullet points.
43
 
44
  Job Description:
45
  {job_desc}
46
 
47
  Resume:
48
  {resume_text}
 
 
49
  """
50
+ result = summarizer(prompt, max_new_tokens=300, do_sample=False)[0]
51
+ raw_text = result.get('generated_text', result.get('summary_text', str(result))).strip()
52
+
53
+ # Clean and deduplicate
54
+ lines = re.findall(r"-\s*(.+)", raw_text)
55
+ cleaned = list({kw.strip().lower() for kw in lines if len(kw.strip()) > 2})
56
+ return ', '.join(sorted(cleaned)) or "None"
57
 
58
+ # Prompt builder for structured LLM resume analysis
59
  def build_dynamic_prompt(job_desc, resume_text, analyze_with_jd):
60
  prompt = f"""
61
+ Act as a resume evaluator. Break the following resume into meaningful sections such as:
 
 
 
 
62
  - Technical Skills
63
  - Soft Skills
64
+ - Education
65
+ - Experience
66
  - Certifications
67
+ - Projects (if present)
 
 
 
68
 
69
+ Then, if a job description is provided, highlight what improvements are needed in each section to better align with the job role.
70
 
71
  Job Description:
72
  {job_desc if analyze_with_jd else '[None provided]'}
 
74
  Resume:
75
  {resume_text}
76
 
77
+ Output your response in markdown format with section headings.
78
  """
79
  return prompt
80
 
81
+ # Core analysis function
82
  def analyze_resume(job_desc, resume_text, analyze_with_jd):
83
  if not resume_text.strip():
84
  return "⚠️ Please paste your resume text."
85
 
86
+ user_prompt = build_dynamic_prompt(job_desc, resume_text, analyze_with_jd)
87
 
88
  try:
89
+ result = summarizer(user_prompt, max_new_tokens=512, do_sample=False)[0]
90
+ response_text = result.get('generated_text', result.get('summary_text', str(result))).strip()
91
 
 
92
  if analyze_with_jd and job_desc:
93
  matched, missing = compare_keywords(resume_text, job_desc)
94
  highlighted_resume = highlight_keywords(resume_text, matched)
95
  llm_missing_keywords = extract_missing_keywords_with_llm(job_desc, resume_text)
96
 
97
+ return f"""### πŸ” Resume with Highlighted Matches
 
98
 
99
  {highlighted_resume}
100
 
 
111
 
112
  ---
113
 
114
+ {response_text}"""
115
+ return response_text
 
 
116
  except Exception as e:
117
  return f"❌ Error: {str(e)}"
118
 
119
+ # Gradio interface
120
  def create_ui():
121
  with gr.Blocks() as demo:
122
  with gr.Row():
 
134
 
135
  if __name__ == '__main__':
136
  create_ui().launch()
137
+