rca123456 commited on
Commit
fb1840b
Β·
verified Β·
1 Parent(s): 7b3efda

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -56
app.py CHANGED
@@ -7,12 +7,10 @@ from langchain_core.output_parsers import StrOutputParser
7
  from sklearn.metrics.pairwise import cosine_similarity
8
  from dotenv import load_dotenv
9
  from fpdf import FPDF
10
- from wordcloud import WordCloud
11
- import matplotlib.pyplot as plt
12
  import numpy as np
13
  import tempfile
14
  import os
15
- import io
16
 
17
  load_dotenv()
18
  groq_api_key = os.getenv("GROQ_API_KEY")
@@ -33,7 +31,7 @@ def extract_skills(text):
33
  def generate_learning_resources(missing_skills):
34
  suggestions = []
35
  for skill in missing_skills:
36
- suggestions.append(f"For {skill}: Search for '{skill} tutorial' on YouTube or Coursera.")
37
  return "\n".join(suggestions)
38
 
39
  def generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent):
@@ -60,75 +58,62 @@ def generate_skill_gap_report(user_skills, job_skills, missing_skills, match_per
60
 
61
  return report
62
 
63
- def create_pdf(report_text):
64
  pdf = FPDF()
65
  pdf.add_page()
66
  pdf.set_font("Arial", size=12)
67
- pdf.multi_cell(0, 10, report_text)
68
- output_path = "skill_gap_report.pdf"
69
  pdf.output(output_path)
70
  return output_path
71
 
72
- from PIL import Image
73
-
74
- def generate_wordcloud(missing_skills):
75
- if not missing_skills:
76
- return None
77
- text = " ".join(missing_skills)
78
- wordcloud = WordCloud(width=600, height=400, background_color='black', colormap='Set3').generate(text)
79
- buffer = io.BytesIO()
80
- plt.figure(figsize=(6, 4))
81
- plt.imshow(wordcloud, interpolation='bilinear')
82
- plt.axis('off')
83
- plt.tight_layout()
84
- plt.savefig(buffer, format='png')
85
- plt.close()
86
- buffer.seek(0)
87
- return Image.open(buffer)
88
-
89
-
90
  def process_skill_gap(resume_pdf, jd_pdfs):
91
  if resume_pdf is None or jd_pdfs is None:
92
- return 0, "❌ Please upload Resume and at least one Job Description PDF.", "", "", "", None, None, ""
93
 
94
  resume_text = extract_text_from_pdf(resume_pdf)
95
  user_skills = extract_skills(resume_text)
96
 
97
- best_match_percent = 0
98
- best_missing_skills = []
99
- best_job_skills = []
100
- best_similarity = 0
101
- best_report = ""
102
 
103
- for jd_pdf in jd_pdfs:
104
  jd_text = extract_text_from_pdf(jd_pdf)
105
  job_skills = extract_skills(jd_text)
106
 
107
  common = set(user_skills) & set(job_skills)
108
  match_percent = (len(common) / len(job_skills)) * 100 if job_skills else 0
109
  missing_skills = list(set(job_skills) - set(user_skills))
 
110
 
111
  embed_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
112
  vectors = embed_model.embed_documents([resume_text, jd_text])
113
  similarity_score = cosine_similarity([vectors[0]], [vectors[1]])[0][0]
114
  similarity_percent = round(similarity_score * 100, 2)
115
 
116
- if match_percent > best_match_percent:
117
- best_match_percent = match_percent
118
- best_missing_skills = missing_skills
119
- best_job_skills = job_skills
120
- best_similarity = similarity_percent
121
- best_report = generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent)
 
 
 
 
 
122
 
123
- resources = generate_learning_resources(best_missing_skills)
124
- pdf_path = create_pdf(best_report)
125
- wordcloud_img = generate_wordcloud(best_missing_skills) if best_missing_skills else None
 
126
 
127
- skill_text = f"βœ… Skill Match: {best_match_percent}%"
128
- missing_text = f"❌ Missing Skills: {', '.join(best_missing_skills) if best_missing_skills else 'None'}"
129
- similarity_text = f"πŸ”Ž Best JD Similarity Score: {best_similarity}%"
 
130
 
131
- return best_match_percent, skill_text, missing_text, similarity_text, best_report, pdf_path, wordcloud_img, resources
132
 
133
  with gr.Blocks() as demo:
134
  gr.HTML("""
@@ -144,28 +129,31 @@ with gr.Blocks() as demo:
144
  </style>
145
  """)
146
 
147
- gr.Markdown("# 🧠 AI Skill Gap Checker - Advanced Version")
148
- gr.Markdown("Upload your **Resume PDF** and **Multiple Job Description PDFs**. The AI will compare and suggest learning resources.")
149
 
150
  with gr.Row():
151
  resume_file = gr.File(label="πŸ“„ Upload Resume (PDF)", type="binary")
152
- jd_files = gr.File(label="πŸ“„ Upload Job Description PDFs (Multiple Allowed)", type="binary", file_types=[".pdf"], file_count="multiple")
153
 
154
  submit_btn = gr.Button("πŸš€ Analyze Skill Gap")
155
 
156
- match_slider = gr.Slider(minimum=0, maximum=100, step=1, label="Job Match Percentage (%)", interactive=False)
157
- skill_match_text = gr.Textbox(label="Skill Match Details", interactive=False)
158
- missing_skills_text = gr.Textbox(label="Missing Skills", interactive=False)
159
- similarity_text = gr.Textbox(label="Best JD Similarity Score", interactive=False)
160
- report_output = gr.Textbox(label="AI-Generated Skill Gap Report", lines=12, interactive=False)
161
- download_pdf = gr.File(label="πŸ“₯ Download Skill Gap Report (PDF)")
162
- wordcloud_output = gr.Image(label="πŸ“Š Missing Skills Word Cloud")
163
  learning_resources = gr.Textbox(label="πŸ“š AI Learning Resource Recommendations", interactive=False)
164
 
165
  submit_btn.click(
166
  fn=process_skill_gap,
167
  inputs=[resume_file, jd_files],
168
- outputs=[match_slider, skill_match_text, missing_skills_text, similarity_text, report_output, download_pdf, wordcloud_output, learning_resources]
 
 
 
169
  )
170
 
171
  demo.launch()
 
7
  from sklearn.metrics.pairwise import cosine_similarity
8
  from dotenv import load_dotenv
9
  from fpdf import FPDF
10
+ from collections import Counter
 
11
  import numpy as np
12
  import tempfile
13
  import os
 
14
 
15
  load_dotenv()
16
  groq_api_key = os.getenv("GROQ_API_KEY")
 
31
  def generate_learning_resources(missing_skills):
32
  suggestions = []
33
  for skill in missing_skills:
34
+ suggestions.append(f"For {skill}: Search for '{skill} tutorial' on YouTube, Coursera, or Udemy.")
35
  return "\n".join(suggestions)
36
 
37
  def generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent):
 
58
 
59
  return report
60
 
61
+ def create_pdf(full_report_text):
62
  pdf = FPDF()
63
  pdf.add_page()
64
  pdf.set_font("Arial", size=12)
65
+ pdf.multi_cell(0, 10, full_report_text)
66
+ output_path = "multi_jd_skill_gap_report.pdf"
67
  pdf.output(output_path)
68
  return output_path
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  def process_skill_gap(resume_pdf, jd_pdfs):
71
  if resume_pdf is None or jd_pdfs is None:
72
+ return 0, "❌ Please upload Resume and Job Descriptions.", "", "", "", None, "", ""
73
 
74
  resume_text = extract_text_from_pdf(resume_pdf)
75
  user_skills = extract_skills(resume_text)
76
 
77
+ all_missing_skills = []
78
+ full_report = ""
 
 
 
79
 
80
+ for idx, jd_pdf in enumerate(jd_pdfs, start=1):
81
  jd_text = extract_text_from_pdf(jd_pdf)
82
  job_skills = extract_skills(jd_text)
83
 
84
  common = set(user_skills) & set(job_skills)
85
  match_percent = (len(common) / len(job_skills)) * 100 if job_skills else 0
86
  missing_skills = list(set(job_skills) - set(user_skills))
87
+ all_missing_skills.extend(missing_skills)
88
 
89
  embed_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
90
  vectors = embed_model.embed_documents([resume_text, jd_text])
91
  similarity_score = cosine_similarity([vectors[0]], [vectors[1]])[0][0]
92
  similarity_percent = round(similarity_score * 100, 2)
93
 
94
+ ai_report = generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent)
95
+
96
+ full_report += f"\nπŸ”Ž JD {idx}:\n"
97
+ full_report += f"βœ… Skill Match: {match_percent}%\n"
98
+ full_report += f"❌ Missing Skills: {', '.join(missing_skills) if missing_skills else 'None'}\n"
99
+ full_report += f"πŸ”— Similarity Score: {similarity_percent}%\n"
100
+ full_report += f"πŸ“‹ AI Report:\n{ai_report}\n"
101
+ full_report += "-------------------------\n"
102
+
103
+ resources = generate_learning_resources(list(set(all_missing_skills)))
104
+ pdf_path = create_pdf(full_report)
105
 
106
+ most_common_skills = Counter(all_missing_skills).most_common(3)
107
+ top_missing_skills_text = "Top Missing Skills Across JDs: " + ", ".join(
108
+ [f"{skill} ({count} times)" for skill, count in most_common_skills]
109
+ ) if most_common_skills else "No missing skills detected."
110
 
111
+ overall_match = round(
112
+ (sum([len(set(user_skills) & set(extract_skills(extract_text_from_pdf(jd)))) for jd in jd_pdfs]) / (len(user_skills) * len(jd_pdfs))) * 100,
113
+ 2
114
+ ) if user_skills else 0
115
 
116
+ return overall_match, "βœ… Analysis done across all JDs", ", ".join(set(all_missing_skills)), "Multi-JD Comparison Completed", full_report, pdf_path, top_missing_skills_text, resources
117
 
118
  with gr.Blocks() as demo:
119
  gr.HTML("""
 
129
  </style>
130
  """)
131
 
132
+ gr.Markdown("# 🧠 AI Skill Gap Checker - Multi-JD Comparison (No Word Cloud)")
133
+ gr.Markdown("Upload your **Resume PDF** and **Multiple Job Descriptions (PDFs)**. AI will compare and generate detailed reports with skill gap and recommendations.")
134
 
135
  with gr.Row():
136
  resume_file = gr.File(label="πŸ“„ Upload Resume (PDF)", type="binary")
137
+ jd_files = gr.File(label="πŸ“„ Upload Multiple Job Descriptions (PDFs)", type="binary", file_types=[".pdf"], file_count="multiple")
138
 
139
  submit_btn = gr.Button("πŸš€ Analyze Skill Gap")
140
 
141
+ match_slider = gr.Slider(minimum=0, maximum=100, step=1, label="Overall Skill Match (%)", interactive=False)
142
+ skill_match_text = gr.Textbox(label="Status", interactive=False)
143
+ missing_skills_text = gr.Textbox(label="All Missing Skills", interactive=False)
144
+ similarity_text = gr.Textbox(label="Status Message", interactive=False)
145
+ report_output = gr.Textbox(label="AI-Generated Multi-JD Skill Gap Report", lines=20, interactive=False)
146
+ download_pdf = gr.File(label="πŸ“₯ Download Full Report as PDF")
147
+ top_skills_output = gr.Textbox(label="Top Missing Skills Across JDs", interactive=False)
148
  learning_resources = gr.Textbox(label="πŸ“š AI Learning Resource Recommendations", interactive=False)
149
 
150
  submit_btn.click(
151
  fn=process_skill_gap,
152
  inputs=[resume_file, jd_files],
153
+ outputs=[
154
+ match_slider, skill_match_text, missing_skills_text, similarity_text,
155
+ report_output, download_pdf, top_skills_output, learning_resources
156
+ ]
157
  )
158
 
159
  demo.launch()