Spaces:
Sleeping
Sleeping
bsiddhharth
commited on
Commit
·
d914592
1
Parent(s):
387ea50
changed the implementation of cv_short by adding form so the issue with min_exp is resolved
Browse files- cv_short.py +169 -198
cv_short.py
CHANGED
@@ -85,137 +85,121 @@ class CVAnalyzer:
|
|
85 |
return score_components
|
86 |
|
87 |
|
|
|
|
|
88 |
|
89 |
-
#
|
90 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
-
#
|
93 |
-
|
94 |
-
# # Reset analysis state when starting new analysis
|
95 |
-
# if 'analysis_started' not in st.session_state:
|
96 |
-
# st.session_state.analysis_started = False
|
97 |
|
98 |
-
#
|
99 |
-
#
|
100 |
-
#
|
101 |
-
#
|
|
|
102 |
|
103 |
-
#
|
104 |
-
#
|
|
|
|
|
|
|
|
|
105 |
|
106 |
-
#
|
107 |
-
#
|
108 |
-
# min_years = st.number_input("Minimum years of experience",
|
109 |
-
# min_value=0,
|
110 |
-
# value=st.session_state.min_years if 'min_years' in st.session_state else 3)
|
111 |
|
112 |
-
#
|
113 |
-
# value=','.join(st.session_state.required_skills_list) if 'required_skills_list' in st.session_state else "")
|
114 |
|
115 |
-
#
|
116 |
-
|
117 |
-
#
|
118 |
-
# st.session_state.
|
119 |
-
# st.session_state.min_years = min_years
|
120 |
|
121 |
-
#
|
122 |
-
#
|
123 |
-
#
|
124 |
-
#
|
125 |
-
#
|
126 |
-
#
|
127 |
|
128 |
-
#
|
129 |
-
#
|
130 |
-
# st.session_state.analysis_started = True
|
131 |
|
132 |
-
#
|
133 |
-
#
|
134 |
-
#
|
135 |
-
#
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
146 |
|
147 |
-
|
148 |
-
|
149 |
-
# cv_text = extr.process_file(uploaded_file)
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
|
|
|
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
# st.error(f"Error processing CV: {str(e)}")
|
185 |
-
|
186 |
-
# # Mark analysis as complete
|
187 |
-
# st.session_state.analysis_complete = True
|
188 |
-
|
189 |
-
# # Display results
|
190 |
-
# if st.session_state.results:
|
191 |
-
# df = pd.DataFrame(st.session_state.results)
|
192 |
-
# df = df.sort_values("Overall Score", ascending=False)
|
193 |
-
# st.dataframe(df)
|
194 |
-
|
195 |
-
# # Save top candidates
|
196 |
-
# st.session_state.top_candidates = df.head()
|
197 |
-
# else:
|
198 |
-
# logger.warning("No valid candidates found")
|
199 |
-
# st.warning("No valid candidates found in the uploaded CVs")
|
200 |
-
|
201 |
-
# except Exception as e:
|
202 |
-
# logger.error(f"Analysis error: {str(e)}")
|
203 |
-
# st.error(f"An error occurred during analysis: {str(e)}")
|
204 |
-
# st.session_state.analysis_complete = False
|
205 |
-
|
206 |
-
# # Display analysis status
|
207 |
-
# if st.session_state.get('analysis_complete', False):
|
208 |
-
# st.success("CV analysis complete! You can now proceed to generate interview questions.")
|
209 |
-
|
210 |
|
211 |
-
def create_cv_shortlisting_page():
|
212 |
-
# logger.info("Starting CV shortlisting system")
|
213 |
|
214 |
-
|
215 |
if 'jd_text' not in st.session_state:
|
216 |
-
st.session_state.jd_text =
|
217 |
if 'min_years' not in st.session_state:
|
218 |
-
st.session_state.min_years =
|
219 |
if 'required_skills_list' not in st.session_state:
|
220 |
st.session_state.required_skills_list = []
|
221 |
if 'uploaded_files' not in st.session_state:
|
@@ -225,94 +209,81 @@ def create_cv_shortlisting_page():
|
|
225 |
if 'analysis_complete' not in st.session_state:
|
226 |
st.session_state.analysis_complete = False
|
227 |
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
st.session_state.jd_text = jd_text
|
235 |
-
|
236 |
-
# Job Requirements Input
|
237 |
-
st.header("Job Requirements")
|
238 |
-
min_years = st.number_input("Minimum years of experience",
|
239 |
-
min_value=0,
|
240 |
-
value=st.session_state.min_years,
|
241 |
-
)
|
242 |
-
|
243 |
-
required_skills = st.text_input("Required skills (comma-separated)",
|
244 |
-
value=','.join(st.session_state.required_skills_list) if st.session_state.required_skills_list else "")
|
245 |
-
|
246 |
-
required_skills_list = [skill.strip() for skill in required_skills.split(",") if skill.strip()]
|
247 |
-
|
248 |
-
if required_skills_list:
|
249 |
-
st.session_state.required_skills_list = required_skills_list
|
250 |
-
if min_years:
|
251 |
st.session_state.min_years = min_years
|
252 |
-
|
253 |
-
# CV Upload
|
254 |
-
st.header("Upload CVs")
|
255 |
-
uploaded_files = st.file_uploader("Choose CV files",
|
256 |
-
accept_multiple_files=True,
|
257 |
-
type=['pdf', 'txt'],
|
258 |
-
key="unique_cv_upload")
|
259 |
-
|
260 |
-
if uploaded_files:
|
261 |
st.session_state.uploaded_files = uploaded_files
|
262 |
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
}
|
273 |
-
|
274 |
-
results = []
|
275 |
-
st.session_state.results = [] # Reset results for new analysis
|
276 |
-
|
277 |
-
# Process each CV
|
278 |
-
for uploaded_file in uploaded_files:
|
279 |
-
cv_text = extr.process_file(uploaded_file)
|
280 |
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
283 |
|
284 |
-
|
285 |
-
|
286 |
-
candidate.__dict__,
|
287 |
-
job_requirements
|
288 |
-
)
|
289 |
-
|
290 |
-
result = {
|
291 |
-
"Name": candidate.name or "Unknown",
|
292 |
-
"Experience (Years)": candidate.years_of_exp or 0,
|
293 |
-
"Skills": ", ".join(candidate.skills) if candidate.skills else "None",
|
294 |
-
"Certifications": ", ".join(candidate.certifications) if candidate.certifications else "None",
|
295 |
-
"Skills Match": f"{match_scores['skills_match']:.2%}",
|
296 |
-
"Experience Match": f"{match_scores['experience_match']:.2%}",
|
297 |
-
"Overall Score": f"{match_scores['overall_score']:.2%}"
|
298 |
-
}
|
299 |
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
return score_components
|
86 |
|
87 |
|
88 |
+
def create_cv_shortlisting_page():
|
89 |
+
# logger.info("Starting CV shortlisting system")
|
90 |
|
91 |
+
# Initialize session state if not already initialized
|
92 |
+
# if 'jd_text' not in st.session_state:
|
93 |
+
# st.session_state.jd_text = ""
|
94 |
+
# if 'min_years' not in st.session_state:
|
95 |
+
# st.session_state.min_years = 3
|
96 |
+
# if 'required_skills_list' not in st.session_state:
|
97 |
+
# st.session_state.required_skills_list = []
|
98 |
+
# if 'uploaded_files' not in st.session_state:
|
99 |
+
# st.session_state.uploaded_files = None
|
100 |
+
# if 'results' not in st.session_state:
|
101 |
+
# st.session_state.results = []
|
102 |
+
# if 'analysis_complete' not in st.session_state:
|
103 |
+
# st.session_state.analysis_complete = False
|
104 |
|
105 |
+
# st.title("CV Shortlisting System")
|
|
|
|
|
|
|
|
|
106 |
|
107 |
+
# # Job Description Input
|
108 |
+
# st.header("Job Description")
|
109 |
+
# jd_text = st.text_area("Enter the job description", value=st.session_state.jd_text)
|
110 |
+
# if jd_text:
|
111 |
+
# st.session_state.jd_text = jd_text
|
112 |
|
113 |
+
# # Job Requirements Input
|
114 |
+
# st.header("Job Requirements")
|
115 |
+
# min_years = st.number_input("Minimum years of experience",
|
116 |
+
# min_value=0,
|
117 |
+
# value=st.session_state.min_years,
|
118 |
+
# )
|
119 |
|
120 |
+
# required_skills = st.text_input("Required skills (comma-separated)",
|
121 |
+
# value=','.join(st.session_state.required_skills_list) if st.session_state.required_skills_list else "")
|
|
|
|
|
|
|
122 |
|
123 |
+
# required_skills_list = [skill.strip() for skill in required_skills.split(",") if skill.strip()]
|
|
|
124 |
|
125 |
+
# if required_skills_list:
|
126 |
+
# st.session_state.required_skills_list = required_skills_list
|
127 |
+
# if min_years:
|
128 |
+
# st.session_state.min_years = min_years
|
|
|
129 |
|
130 |
+
# # CV Upload
|
131 |
+
# st.header("Upload CVs")
|
132 |
+
# uploaded_files = st.file_uploader("Choose CV files",
|
133 |
+
# accept_multiple_files=True,
|
134 |
+
# type=['pdf', 'txt'],
|
135 |
+
# key="unique_cv_upload")
|
136 |
|
137 |
+
# if uploaded_files:
|
138 |
+
# st.session_state.uploaded_files = uploaded_files
|
|
|
139 |
|
140 |
+
# if st.button("Analyze CVs") and uploaded_files and jd_text:
|
141 |
+
# # logger.info("Analyzing uploaded CVs")
|
142 |
+
# with st.spinner('Analyzing CVs...'):
|
143 |
+
# analyzer = CVAnalyzer()
|
144 |
+
|
145 |
+
# # Prepare job requirements
|
146 |
+
# job_requirements = {
|
147 |
+
# "min_years_experience": st.session_state.min_years,
|
148 |
+
# "required_skills": st.session_state.required_skills_list
|
149 |
+
# }
|
150 |
+
|
151 |
+
# results = []
|
152 |
+
# st.session_state.results = [] # Reset results for new analysis
|
153 |
+
|
154 |
+
# # Process each CV
|
155 |
+
# for uploaded_file in uploaded_files:
|
156 |
+
# cv_text = extr.process_file(uploaded_file)
|
157 |
|
158 |
+
# try:
|
159 |
+
# candidates = analyzer.extract_cv_info(cv_text)
|
|
|
160 |
|
161 |
+
# for candidate in candidates:
|
162 |
+
# match_scores = analyzer.calculate_match_score(
|
163 |
+
# candidate.__dict__,
|
164 |
+
# job_requirements
|
165 |
+
# )
|
166 |
|
167 |
+
# result = {
|
168 |
+
# "Name": candidate.name or "Unknown",
|
169 |
+
# "Experience (Years)": candidate.years_of_exp or 0,
|
170 |
+
# "Skills": ", ".join(candidate.skills) if candidate.skills else "None",
|
171 |
+
# "Certifications": ", ".join(candidate.certifications) if candidate.certifications else "None",
|
172 |
+
# "Skills Match": f"{match_scores['skills_match']:.2%}",
|
173 |
+
# "Experience Match": f"{match_scores['experience_match']:.2%}",
|
174 |
+
# "Overall Score": f"{match_scores['overall_score']:.2%}"
|
175 |
+
# }
|
176 |
+
|
177 |
+
# results.append(result)
|
178 |
+
# st.session_state.results.append(result)
|
179 |
+
|
180 |
+
# except Exception as e:
|
181 |
+
# st.error(f"Error processing CV: {str(e)}")
|
182 |
+
# # logger.error(f"Error processing CV: {str(e)}")
|
183 |
+
|
184 |
+
# # Display results
|
185 |
+
# # logger.info(f"Displaying analyzed results for {len(results)} candidate(s)")
|
186 |
+
|
187 |
+
# if st.session_state.results:
|
188 |
+
# df = pd.DataFrame(st.session_state.results)
|
189 |
+
# df = df.sort_values("Overall Score", ascending=False)
|
190 |
+
# st.dataframe(df)
|
191 |
+
# st.session_state.analysis_complete = True
|
192 |
+
# else:
|
193 |
+
# # logger.warning("No valid candidates found in uploaded CVs")
|
194 |
+
# st.error("No valid results found from CV analysis")
|
195 |
+
# st.session_state.analysis_complete = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
|
|
|
|
|
197 |
|
198 |
+
# Initialize session state variables if they don't exist
|
199 |
if 'jd_text' not in st.session_state:
|
200 |
+
st.session_state.jd_text = ''
|
201 |
if 'min_years' not in st.session_state:
|
202 |
+
st.session_state.min_years = 0
|
203 |
if 'required_skills_list' not in st.session_state:
|
204 |
st.session_state.required_skills_list = []
|
205 |
if 'uploaded_files' not in st.session_state:
|
|
|
209 |
if 'analysis_complete' not in st.session_state:
|
210 |
st.session_state.analysis_complete = False
|
211 |
|
212 |
+
# Form for input
|
213 |
+
with st.form("job_description_form"):
|
214 |
+
# Job Description Input
|
215 |
+
st.header("Job Description")
|
216 |
+
jd_text = st.text_area("Enter the job description", value=st.session_state.jd_text)
|
217 |
+
|
218 |
+
# Job Requirements Input
|
219 |
+
st.header("Job Requirements")
|
220 |
+
min_years = st.number_input("Minimum years of experience", min_value=0, value=st.session_state.min_years)
|
221 |
+
|
222 |
+
required_skills = st.text_input("Required skills (comma-separated)",
|
223 |
+
value=','.join(st.session_state.required_skills_list) if st.session_state.required_skills_list else "")
|
224 |
+
|
225 |
+
# CV Upload
|
226 |
+
st.header("Upload CVs")
|
227 |
+
uploaded_files = st.file_uploader("Choose CV files", accept_multiple_files=True, type=['pdf', 'txt'], key="unique_cv_upload")
|
228 |
+
|
229 |
+
# Submit Button
|
230 |
+
submit_button = st.form_submit_button(label="Analyze CVs")
|
231 |
+
|
232 |
+
# Update session state after form submission
|
233 |
+
if submit_button:
|
234 |
st.session_state.jd_text = jd_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
235 |
st.session_state.min_years = min_years
|
236 |
+
st.session_state.required_skills_list = [skill.strip() for skill in required_skills.split(",") if skill.strip()]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
st.session_state.uploaded_files = uploaded_files
|
238 |
|
239 |
+
if st.session_state.uploaded_files and st.session_state.jd_text:
|
240 |
+
with st.spinner('Analyzing CVs...'):
|
241 |
+
analyzer = CVAnalyzer()
|
242 |
+
|
243 |
+
# Prepare job requirements
|
244 |
+
job_requirements = {
|
245 |
+
"min_years_experience": st.session_state.min_years,
|
246 |
+
"required_skills": st.session_state.required_skills_list
|
247 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
|
249 |
+
results = []
|
250 |
+
st.session_state.results = [] # Reset results for new analysis
|
251 |
+
|
252 |
+
# Process each CV
|
253 |
+
for uploaded_file in st.session_state.uploaded_files:
|
254 |
+
cv_text = extr.process_file(uploaded_file)
|
255 |
|
256 |
+
try:
|
257 |
+
candidates = analyzer.extract_cv_info(cv_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
|
259 |
+
for candidate in candidates:
|
260 |
+
match_scores = analyzer.calculate_match_score(
|
261 |
+
candidate.__dict__,
|
262 |
+
job_requirements
|
263 |
+
)
|
264 |
+
|
265 |
+
result = {
|
266 |
+
"Name": candidate.name or "Unknown",
|
267 |
+
"Experience (Years)": candidate.years_of_exp or 0,
|
268 |
+
"Skills": ", ".join(candidate.skills) if candidate.skills else "None",
|
269 |
+
"Certifications": ", ".join(candidate.certifications) if candidate.certifications else "None",
|
270 |
+
"Skills Match": f"{match_scores['skills_match']:.2%}",
|
271 |
+
"Experience Match": f"{match_scores['experience_match']:.2%}",
|
272 |
+
"Overall Score": f"{match_scores['overall_score']:.2%}"
|
273 |
+
}
|
274 |
+
|
275 |
+
results.append(result)
|
276 |
+
st.session_state.results.append(result)
|
277 |
+
|
278 |
+
except Exception as e:
|
279 |
+
st.error(f"Error processing CV: {str(e)}")
|
280 |
+
|
281 |
+
# Display results
|
282 |
+
if st.session_state.results:
|
283 |
+
df = pd.DataFrame(st.session_state.results)
|
284 |
+
df = df.sort_values("Overall Score", ascending=False)
|
285 |
+
st.dataframe(df)
|
286 |
+
st.session_state.analysis_complete = True
|
287 |
+
else:
|
288 |
+
st.error("No valid results found from CV analysis")
|
289 |
+
st.session_state.analysis_complete = False
|