rca123456 commited on
Commit
fc99598
Β·
verified Β·
1 Parent(s): 2e541d1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -54
app.py CHANGED
@@ -1,16 +1,18 @@
1
  import gradio as gr
2
  from langchain_community.document_loaders.pdf import PyPDFLoader
3
  from langchain_community.embeddings import HuggingFaceEmbeddings
4
- from langchain_community.vectorstores.faiss import FAISS
5
  from langchain_core.prompts import PromptTemplate
6
  from langchain_core.output_parsers import StrOutputParser
7
- from langchain_groq import ChatGroq
8
  from sklearn.metrics.pairwise import cosine_similarity
9
  from dotenv import load_dotenv
10
  from fpdf import FPDF
 
 
11
  import numpy as np
12
  import tempfile
13
  import os
 
14
 
15
  load_dotenv()
16
  groq_api_key = os.getenv("GROQ_API_KEY")
@@ -28,11 +30,11 @@ def extract_skills(text):
28
  skills_list = ["Python", "SQL", "Machine Learning", "Deep Learning", "NLP", "Data Visualization", "Cloud", "TensorFlow", "PyTorch", "Statistics", "Java", "C++", "HTML", "CSS", "JavaScript"]
29
  return [skill for skill in skills_list if skill.lower() in text.lower()]
30
 
31
- def calculate_match(user_skills, job_skills):
32
- common = set(user_skills) & set(job_skills)
33
- match_percent = (len(common) / len(job_skills)) * 100 if job_skills else 0
34
- missing_skills = list(set(job_skills) - set(user_skills))
35
- return round(match_percent, 2), missing_skills
36
 
37
  def generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent):
38
  llm = ChatGroq(model="llama3-8b-8192", temperature=0.2)
@@ -67,79 +69,98 @@ def create_pdf(report_text):
67
  pdf.output(output_path)
68
  return output_path
69
 
70
- def process_skill_gap(resume_pdf, jd_pdf):
71
- if resume_pdf is None or jd_pdf is None:
72
- return 0, "❌ Please upload both Resume and Job Description PDFs.", "", "", "", None
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  resume_text = extract_text_from_pdf(resume_pdf)
75
- jd_text = extract_text_from_pdf(jd_pdf)
76
-
77
  user_skills = extract_skills(resume_text)
78
- job_skills = extract_skills(jd_text)
79
 
80
- match_percent, missing_skills = calculate_match(user_skills, job_skills)
 
 
 
 
81
 
82
- embed_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
83
- vectors = embed_model.embed_documents([resume_text, jd_text])
84
- similarity_score = cosine_similarity([vectors[0]], [vectors[1]])[0][0]
85
- similarity_percent = round(similarity_score * 100, 2)
86
 
87
- report = generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent)
 
 
88
 
89
- pdf_path = create_pdf(report)
 
 
 
90
 
91
- skill_text = f"βœ… Skill Match: {match_percent}%"
92
- missing_text = f"❌ Missing Skills: {', '.join(missing_skills) if missing_skills else 'None'}"
93
- similarity_text = f"πŸ”Ž Resume vs JD Similarity Score: {similarity_percent}%"
 
 
 
94
 
95
- return match_percent, skill_text, missing_text, similarity_text, report, pdf_path
 
 
 
 
 
 
 
 
96
 
97
  with gr.Blocks() as demo:
98
  gr.HTML("""
99
- <style>
100
- body {
101
- background-color: #121212;
102
- color: #ffffff;
103
- }
104
- .gradio-container {
105
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
106
- color: #ffffff;
107
- }
108
- h1, h2, h3, h4, h5, h6, p, label, textarea, input, .gr-textbox, .gr-button {
109
- color: #ffffff !important;
110
- background-color: #1e1e1e !important;
111
- border-color: #333333 !important;
112
- }
113
- .gr-button {
114
- background-color: #4CAF50 !important;
115
- color: white !important;
116
- }
117
- </style>
118
- """)
119
-
120
-
121
- gr.Markdown("# 🧠 AI Skill Gap Checker")
122
- gr.Markdown("Upload your **Resume PDF** and **Job Description PDF** below. The AI will analyze your skill match and generate an improvement report. πŸ“„")
123
 
124
  with gr.Row():
125
  resume_file = gr.File(label="πŸ“„ Upload Resume (PDF)", type="binary")
126
- jd_file = gr.File(label="πŸ“„ Upload Job Description (PDF)", type="binary")
127
 
128
  submit_btn = gr.Button("πŸš€ Analyze Skill Gap")
129
 
130
- gr.Markdown("## 🎯 Match Percentage")
131
  match_slider = gr.Slider(minimum=0, maximum=100, step=1, label="Job Match Percentage (%)", interactive=False)
132
-
133
  skill_match_text = gr.Textbox(label="Skill Match Details", interactive=False)
134
  missing_skills_text = gr.Textbox(label="Missing Skills", interactive=False)
135
- similarity_text = gr.Textbox(label="Resume-JD Similarity Score", interactive=False)
136
  report_output = gr.Textbox(label="AI-Generated Skill Gap Report", lines=12, interactive=False)
137
  download_pdf = gr.File(label="πŸ“₯ Download Skill Gap Report (PDF)")
 
 
138
 
139
  submit_btn.click(
140
  fn=process_skill_gap,
141
- inputs=[resume_file, jd_file],
142
- outputs=[match_slider, skill_match_text, missing_skills_text, similarity_text, report_output, download_pdf]
143
  )
144
 
145
  demo.launch()
 
1
  import gradio as gr
2
  from langchain_community.document_loaders.pdf import PyPDFLoader
3
  from langchain_community.embeddings import HuggingFaceEmbeddings
4
+ from langchain_groq import ChatGroq
5
  from langchain_core.prompts import PromptTemplate
6
  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")
 
30
  skills_list = ["Python", "SQL", "Machine Learning", "Deep Learning", "NLP", "Data Visualization", "Cloud", "TensorFlow", "PyTorch", "Statistics", "Java", "C++", "HTML", "CSS", "JavaScript"]
31
  return [skill for skill in skills_list if skill.lower() in text.lower()]
32
 
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):
40
  llm = ChatGroq(model="llama3-8b-8192", temperature=0.2)
 
69
  pdf.output(output_path)
70
  return output_path
71
 
72
+ def generate_wordcloud(missing_skills):
73
+ text = " ".join(missing_skills)
74
+ wordcloud = WordCloud(width=600, height=400, background_color='black', colormap='Set3').generate(text)
75
+ buffer = io.BytesIO()
76
+ plt.figure(figsize=(6,4))
77
+ plt.imshow(wordcloud, interpolation='bilinear')
78
+ plt.axis('off')
79
+ plt.tight_layout()
80
+ plt.savefig(buffer, format='png')
81
+ plt.close()
82
+ buffer.seek(0)
83
+ return buffer
84
+
85
+ def process_skill_gap(resume_pdf, jd_pdfs):
86
+ if resume_pdf is None or jd_pdfs is None:
87
+ return 0, "❌ Please upload Resume and at least one Job Description PDF.", "", "", "", None, None, ""
88
 
89
  resume_text = extract_text_from_pdf(resume_pdf)
 
 
90
  user_skills = extract_skills(resume_text)
 
91
 
92
+ best_match_percent = 0
93
+ best_missing_skills = []
94
+ best_job_skills = []
95
+ best_similarity = 0
96
+ best_report = ""
97
 
98
+ for jd_pdf in jd_pdfs:
99
+ jd_text = extract_text_from_pdf(jd_pdf)
100
+ job_skills = extract_skills(jd_text)
 
101
 
102
+ common = set(user_skills) & set(job_skills)
103
+ match_percent = (len(common) / len(job_skills)) * 100 if job_skills else 0
104
+ missing_skills = list(set(job_skills) - set(user_skills))
105
 
106
+ embed_model = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
107
+ vectors = embed_model.embed_documents([resume_text, jd_text])
108
+ similarity_score = cosine_similarity([vectors[0]], [vectors[1]])[0][0]
109
+ similarity_percent = round(similarity_score * 100, 2)
110
 
111
+ if match_percent > best_match_percent:
112
+ best_match_percent = match_percent
113
+ best_missing_skills = missing_skills
114
+ best_job_skills = job_skills
115
+ best_similarity = similarity_percent
116
+ best_report = generate_skill_gap_report(user_skills, job_skills, missing_skills, match_percent)
117
 
118
+ resources = generate_learning_resources(best_missing_skills)
119
+ pdf_path = create_pdf(best_report)
120
+ wordcloud_img = generate_wordcloud(best_missing_skills) if best_missing_skills else None
121
+
122
+ skill_text = f"βœ… Skill Match: {best_match_percent}%"
123
+ missing_text = f"❌ Missing Skills: {', '.join(best_missing_skills) if best_missing_skills else 'None'}"
124
+ similarity_text = f"πŸ”Ž Best JD Similarity Score: {best_similarity}%"
125
+
126
+ return best_match_percent, skill_text, missing_text, similarity_text, best_report, pdf_path, wordcloud_img, resources
127
 
128
  with gr.Blocks() as demo:
129
  gr.HTML("""
130
+ <style>
131
+ body { background-color: #121212; color: #ffffff; }
132
+ .gradio-container { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #ffffff; }
133
+ h1, h2, h3, p, label, textarea, input, .gr-textbox, .gr-button {
134
+ color: #ffffff !important;
135
+ background-color: #1e1e1e !important;
136
+ border-color: #333333 !important;
137
+ }
138
+ .gr-button { background-color: #4CAF50 !important; color: white !important; }
139
+ </style>
140
+ """)
141
+
142
+ gr.Markdown("# 🧠 AI Skill Gap Checker - Advanced Version")
143
+ gr.Markdown("Upload your **Resume PDF** and **Multiple Job Description PDFs**. The AI will compare and suggest learning resources.")
 
 
 
 
 
 
 
 
 
 
144
 
145
  with gr.Row():
146
  resume_file = gr.File(label="πŸ“„ Upload Resume (PDF)", type="binary")
147
+ jd_files = gr.File(label="πŸ“„ Upload Job Description PDFs (Multiple Allowed)", type="binary", file_types=[".pdf"], file_count="multiple")
148
 
149
  submit_btn = gr.Button("πŸš€ Analyze Skill Gap")
150
 
 
151
  match_slider = gr.Slider(minimum=0, maximum=100, step=1, label="Job Match Percentage (%)", interactive=False)
 
152
  skill_match_text = gr.Textbox(label="Skill Match Details", interactive=False)
153
  missing_skills_text = gr.Textbox(label="Missing Skills", interactive=False)
154
+ similarity_text = gr.Textbox(label="Best JD Similarity Score", interactive=False)
155
  report_output = gr.Textbox(label="AI-Generated Skill Gap Report", lines=12, interactive=False)
156
  download_pdf = gr.File(label="πŸ“₯ Download Skill Gap Report (PDF)")
157
+ wordcloud_output = gr.Image(label="πŸ“Š Missing Skills Word Cloud")
158
+ learning_resources = gr.Textbox(label="πŸ“š AI Learning Resource Recommendations", interactive=False)
159
 
160
  submit_btn.click(
161
  fn=process_skill_gap,
162
+ inputs=[resume_file, jd_files],
163
+ outputs=[match_slider, skill_match_text, missing_skills_text, similarity_text, report_output, download_pdf, wordcloud_output, learning_resources]
164
  )
165
 
166
  demo.launch()