DreamStream-1 commited on
Commit
4c3199c
·
verified ·
1 Parent(s): 5f224c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -97
app.py CHANGED
@@ -5,10 +5,7 @@ from PyPDF2 import PdfReader
5
  import docx
6
  import re
7
  import google.generativeai as genai
8
- from sklearn.feature_extraction.text import TfidfVectorizer
9
- from sklearn.metrics.pairwise import cosine_similarity
10
  import pandas as pd
11
- import json
12
 
13
  # Load pre-trained embedding model for basic analysis
14
  sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
@@ -37,19 +34,6 @@ def extract_text_from_file(file_path):
37
  else:
38
  return ""
39
 
40
- def calculate_similarity(resume_text, job_desc):
41
- resume_emb = sentence_model.encode(resume_text, convert_to_tensor=True)
42
- job_emb = sentence_model.encode(job_desc, convert_to_tensor=True)
43
- similarity = util.pytorch_cos_sim(resume_emb, job_emb)[0][0].item()
44
- return round(similarity * 100, 2)
45
-
46
- def calculate_match_percentage(resume_text, job_desc):
47
- docs = [resume_text, job_desc]
48
- vectorizer = TfidfVectorizer(stop_words="english")
49
- tfidf_matrix = vectorizer.fit_transform(docs)
50
- cosine_sim = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])
51
- return round(cosine_sim[0][0] * 100, 2)
52
-
53
  def analyze_with_gemini(resume_text, job_desc):
54
  prompt = f"""
55
  Analyze the resume with respect to the job description.
@@ -57,37 +41,53 @@ def analyze_with_gemini(resume_text, job_desc):
57
  Job Description: {job_desc}
58
  Extract:
59
  1. Candidate Name
60
- 2. Relevant Skills
61
- 3. Educational Background
62
- 4. Team Leadership Experience (years)
63
- 5. Management Experience (years)
64
- 6. Management Skills (leadership + management)
65
- Provide a summary of qualifications in 5 bullet points in JSON format.
 
 
 
66
  """
67
  response = genai.GenerativeModel('gemini-1.5-flash').generate_content(prompt)
68
- try:
69
- # Parse the JSON output
70
- analysis = json.loads(response.text.strip())
71
- return {
72
- "Candidate Name": analysis.get("Candidate Name", "Unknown"),
73
- "Relevant Skills": analysis.get("Relevant Skills", "Not Extracted"),
74
- "Educational Background": analysis.get("Educational Background", "Not Extracted"),
75
- "Leadership Experience (years)": analysis.get("Team Leadership Experience (years)", "Not Extracted"),
76
- "Management Experience (years)": analysis.get("Management Experience (years)", "Not Extracted"),
77
- "Management Skills": analysis.get("Management Skills (leadership + management)", "Not Extracted"),
78
- "Summary": analysis.get("Summary", "Not Extracted")
79
- }
80
- except json.JSONDecodeError:
81
- # Handle parsing errors
82
- return {
83
- "Candidate Name": "Unknown",
84
- "Relevant Skills": "Failed",
85
- "Educational Background": "Failed",
86
- "Leadership Experience (years)": "Failed",
87
- "Management Experience (years)": "Failed",
88
- "Management Skills": "Failed",
89
- "Summary": response.text.strip()
90
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  def process_resumes(job_desc_file, resumes):
93
  if not job_desc_file or not resumes:
@@ -99,6 +99,9 @@ def process_resumes(job_desc_file, resumes):
99
  # Load job description text
100
  job_desc = extract_text_from_file(job_desc_file)
101
 
 
 
 
102
  results = []
103
  for resume in resumes:
104
  resume_text = extract_text_from_file(resume.name)
@@ -106,83 +109,57 @@ def process_resumes(job_desc_file, resumes):
106
  if not resume_text.strip():
107
  results.append({
108
  "Resume": resume.name,
109
- "Similarity (Embed)": 0.0,
110
- "Match Percentage (TF-IDF)": 0.0,
 
 
111
  "Gemini Analysis": "Failed to extract text from resume."
112
  })
113
  continue
114
 
115
- # Calculate similarity using embeddings
116
- embed_similarity = calculate_similarity(resume_text, job_desc)
117
-
118
- # Calculate match percentage using TF-IDF
119
- tfidf_match = calculate_match_percentage(resume_text, job_desc)
120
-
121
  # Detailed analysis with Gemini API
122
  try:
123
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
 
 
 
 
 
 
124
  except Exception as e:
125
- gemini_analysis = {
126
- "Candidate Name": "Unknown",
127
- "Relevant Skills": "Failed",
128
- "Educational Background": "Failed",
129
- "Leadership Experience (years)": "Failed",
130
- "Management Experience (years)": "Failed",
131
- "Management Skills": "Failed",
132
- "Summary": f"Gemini analysis failed: {str(e)}"
133
- }
134
-
135
- # Assign weights to Leadership, Management, and Management Skills
136
- try:
137
- leadership_years = float(gemini_analysis.get("Leadership Experience (years)", 0))
138
- management_years = float(gemini_analysis.get("Management Experience (years)", 0))
139
- management_skills = float(gemini_analysis.get("Management Skills", 0))
140
- except ValueError:
141
- leadership_years = 0.0
142
- management_years = 0.0
143
- management_skills = 0.0
144
-
145
- # Define weights for each metric
146
- overall_score = (
147
- 0.3 * embed_similarity + # 30% weight to embedding similarity
148
- 0.3 * tfidf_match + # 30% weight to TF-IDF match
149
- 0.2 * leadership_years + # 20% weight to leadership experience (years)
150
- 0.1 * management_years + # 10% weight to management experience (years)
151
- 0.1 * management_skills # 10% weight to management skills (combined leadership + management)
152
- )
153
 
154
  results.append({
155
  "Resume": resume.name,
156
- "Overall Score": round(overall_score, 2),
157
- "Similarity (Embed)": embed_similarity,
158
- "Match Percentage (TF-IDF)": tfidf_match,
159
- "Leadership Experience (years)": leadership_years,
160
- "Management Experience (years)": management_years,
161
- "Management Skills": management_skills,
162
- "Gemini Analysis": gemini_analysis["Summary"]
163
  })
164
 
165
- # Convert results to pandas DataFrame
166
  df = pd.DataFrame(results)
167
 
168
- # Save DataFrame to CSV
169
- csv_file = "/tmp/analysis_results.csv"
170
- df.to_csv(csv_file, index=False)
171
 
172
- return csv_file
173
 
174
  # Gradio Interface
175
  job_desc_input = gr.File(label="Upload Job Description (TXT, PDF, DOCX)", type="filepath")
176
  resumes_input = gr.Files(label="Upload Resumes (TXT, PDF, DOCX)", type="filepath")
177
-
178
- results_output = gr.File(label="Download Analysis Results (CSV)")
179
 
180
  interface = gr.Interface(
181
  fn=process_resumes,
182
  inputs=[job_desc_input, resumes_input],
183
- outputs=[results_output],
184
  title="Resume Analysis with Gemini API",
185
- description="Upload a job description and resumes to evaluate candidates' match."
186
  )
187
 
188
  interface.launch()
 
5
  import docx
6
  import re
7
  import google.generativeai as genai
 
 
8
  import pandas as pd
 
9
 
10
  # Load pre-trained embedding model for basic analysis
11
  sentence_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
 
34
  else:
35
  return ""
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  def analyze_with_gemini(resume_text, job_desc):
38
  prompt = f"""
39
  Analyze the resume with respect to the job description.
 
41
  Job Description: {job_desc}
42
  Extract:
43
  1. Candidate Name
44
+ 2. Email Address
45
+ 3. Contact Number
46
+ 4. Relevant Skills
47
+ 5. Educational Background
48
+ 6. Team Leadership Experience (years)
49
+ 7. Management Experience (years)
50
+ 8. Management Skills (e.g. strategic planning, team management, project management, etc.)
51
+ 9. Match Percentage (leadership and management focus)
52
+ Provide a summary of qualifications in 5 bullet points.
53
  """
54
  response = genai.GenerativeModel('gemini-1.5-flash').generate_content(prompt)
55
+ return response.text.strip()
56
+
57
+ def extract_management_details(gemini_response):
58
+ # Regular expressions for extracting leadership and management details
59
+ leadership_exp_pattern = r"Team Leadership Experience \(years\):\s*(\d+)"
60
+ management_exp_pattern = r"Management Experience \(years\):\s*(\d+)"
61
+ management_skills_pattern = r"Management Skills\s*[:\-]?\s*(.*?)(?=\n|$)"
62
+
63
+ leadership_match = re.search(leadership_exp_pattern, gemini_response)
64
+ management_match = re.search(management_exp_pattern, gemini_response)
65
+ skills_match = re.search(management_skills_pattern, gemini_response)
66
+
67
+ leadership_years = int(leadership_match.group(1)) if leadership_match else 0
68
+ management_years = int(management_match.group(1)) if management_match else 0
69
+ skills = skills_match.group(1) if skills_match else ""
70
+
71
+ return leadership_years, management_years, skills
72
+
73
+ def calculate_overall_match(leadership_years, management_years, skills, required_skills, max_leadership_exp=10, max_management_exp=10):
74
+ # Assign weight to leadership, management, and relevant skills
75
+ leadership_weight = 0.4 # 40% weight to leadership
76
+ management_weight = 0.4 # 40% weight to management
77
+ skills_weight = 0.2 # 20% weight to skills
78
+
79
+ # Normalize years of experience to 100% scale (if maximum years of experience is 10 years)
80
+ leadership_score = min(leadership_years / max_leadership_exp, 1.0) * 100
81
+ management_score = min(management_years / max_management_exp, 1.0) * 100
82
+
83
+ # Calculate skill match (based on whether any required skills are present in the resume)
84
+ skill_match = any(skill.lower() in skills.lower() for skill in required_skills)
85
+
86
+ skill_score = 100 if skill_match else 0
87
+
88
+ # Calculate the overall match score
89
+ overall_match = (leadership_score * leadership_weight) + (management_score * management_weight) + (skill_score * skills_weight)
90
+ return round(overall_match, 2)
91
 
92
  def process_resumes(job_desc_file, resumes):
93
  if not job_desc_file or not resumes:
 
99
  # Load job description text
100
  job_desc = extract_text_from_file(job_desc_file)
101
 
102
+ # Define the key leadership and management skills you're looking for
103
+ required_skills = ["strategic planning", "team management", "project management", "decision making", "communication"]
104
+
105
  results = []
106
  for resume in resumes:
107
  resume_text = extract_text_from_file(resume.name)
 
109
  if not resume_text.strip():
110
  results.append({
111
  "Resume": resume.name,
112
+ "Candidate Name": "N/A",
113
+ "Email": "N/A",
114
+ "Contact": "N/A",
115
+ "Overall Match Percentage": 0.0,
116
  "Gemini Analysis": "Failed to extract text from resume."
117
  })
118
  continue
119
 
 
 
 
 
 
 
120
  # Detailed analysis with Gemini API
121
  try:
122
  gemini_analysis = analyze_with_gemini(resume_text, job_desc)
123
+ # Extract leadership and management details
124
+ leadership_years, management_years, skills = extract_management_details(gemini_analysis)
125
+ # Calculate overall match percentage
126
+ overall_match = calculate_overall_match(leadership_years, management_years, skills, required_skills)
127
+ # Extract candidate details
128
+ name, email, contact = extract_candidate_details(gemini_analysis)
129
  except Exception as e:
130
+ gemini_analysis = f"Gemini analysis failed: {str(e)}"
131
+ name, email, contact = "N/A", "N/A", "N/A"
132
+ overall_match = 0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  results.append({
135
  "Resume": resume.name,
136
+ "Candidate Name": name,
137
+ "Email": email,
138
+ "Contact": contact,
139
+ "Overall Match Percentage": overall_match,
140
+ "Gemini Analysis": gemini_analysis
 
 
141
  })
142
 
143
+ # Create a pandas DataFrame for better formatting and downloadable output
144
  df = pd.DataFrame(results)
145
 
146
+ # Output the DataFrame as a CSV file for download
147
+ output_file = "/tmp/analysis_results.csv"
148
+ df.to_csv(output_file, index=False)
149
 
150
+ return df, output_file
151
 
152
  # Gradio Interface
153
  job_desc_input = gr.File(label="Upload Job Description (TXT, PDF, DOCX)", type="filepath")
154
  resumes_input = gr.Files(label="Upload Resumes (TXT, PDF, DOCX)", type="filepath")
155
+ results_output = gr.Dataframe(label="Analysis Results", headers=["Resume", "Candidate Name", "Email", "Contact", "Overall Match Percentage", "Gemini Analysis"], show_label=False)
 
156
 
157
  interface = gr.Interface(
158
  fn=process_resumes,
159
  inputs=[job_desc_input, resumes_input],
160
+ outputs=[results_output, gr.File(label="Download CSV Results")],
161
  title="Resume Analysis with Gemini API",
162
+ description="Upload a job description and resumes to evaluate candidates' match focusing on leadership and management."
163
  )
164
 
165
  interface.launch()