Bur3hani commited on
Commit
86f4072
Β·
verified Β·
1 Parent(s): 6524043

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -27
app.py CHANGED
@@ -46,10 +46,8 @@ predefined_skills_list.update([
46
  "data engineer", "software engineer", "full stack", "frontend", "backend"
47
  ])
48
 
49
-
50
  # --- Text Extraction Functions (Adapted for file paths in Gradio's File component) ---
51
  # Gradio's gr.File component provides a file path to the temporary uploaded file.
52
-
53
  def extract_text_from_pdf(pdf_path):
54
  """
55
  Extracts text from a PDF file given its path.
@@ -259,7 +257,6 @@ def create_top_keywords_plot(cv_keywords, jd_keywords):
259
  plt.tight_layout()
260
  return fig
261
 
262
-
263
  # --- Main Gradio Interface Function ---
264
  def analyze_cv_match(cv_file_obj, cv_text_input, jd_text_input):
265
  """
@@ -272,17 +269,14 @@ def analyze_cv_match(cv_file_obj, cv_text_input, jd_text_input):
272
  cv_content = get_file_content(cv_file_obj)
273
  elif cv_text_input:
274
  cv_content = cv_text_input
275
-
276
  if not cv_content:
277
  return (f"<h4><p style='color:red;'>🚨 Error: Please upload a CV file or paste your CV text.</p></h4>",
278
  None, None, None, "Analysis Failed")
279
  if not jd_text_input:
280
  return (f"<h4><p style='color:red;'>🚨 Error: Please paste the Job Description text.</p></h4>",
281
  None, None, None, "Analysis Failed")
282
-
283
  try:
284
  analysis_results = perform_cv_job_analysis(cv_content, jd_text_input)
285
-
286
  # Generate HTML output for KPIs and detailed breakdown
287
  html_output = f"""
288
  <h2 style='text-align: center;'>πŸ’‘ Analysis Results Summary πŸ’‘</h2>
@@ -306,30 +300,24 @@ def analyze_cv_match(cv_file_obj, cv_text_input, jd_text_input):
306
  <p><strong>βœ… Matched Skills:</strong> {', '.join(analysis_results['matched_skills']) if analysis_results['matched_skills'] else 'None found matching job description.'}</p>
307
  <p><strong>❌ Missing Skills (from Job Description):</strong> {', '.join(analysis_results['missing_skills']) if analysis_results['missing_skills'] else 'πŸ₯³ None! Your CV has all specified skills.'}</p>
308
  <p><strong>πŸ’‘ Extra Skills in CV (not in Job Description):</strong> {', '.join(analysis_results['extra_skills_in_cv']) if analysis_results['extra_skills_in_cv'] else 'None. (This is often fine, showing broader capability.)'}</p>
309
-
310
  <h4>Keyword Relevance (Top TF-IDF Terms)</h4>
311
  <p><strong>🀝 Top Common Keywords:</strong> {', '.join(analysis_results['common_keywords']) if analysis_results['common_keywords'] else 'No significant common keywords beyond skills.'}</p>
312
  <p><strong>πŸ” Top Keywords in Your CV:**</strong> {', '.join(analysis_results['top_cv_keywords']) if analysis_results['top_cv_keywords'] else 'N/A'}</p>
313
  <p><strong>🎯 Top Keywords in Job Description:</strong> {', '.join(analysis_results['top_jd_keywords']) if analysis_results['top_jd_keywords'] else 'N/A'}</p>
314
-
315
  <h4>Experience & Education Comparison</h4>
316
  <p><strong>πŸ‘€ Your CV's Experience:</strong> <code>{analysis_results['cv_years_experience']}</code> years</p>
317
  <p><strong>πŸ’Ό Job's Required Experience:</strong> <code>{analysis_results['jd_years_experience']}</code> years</p>
318
  <p style='color:green;'><strong>Status:</strong> {analysis_results['experience_match_status']}</p>
319
-
320
  <p><strong>πŸŽ“ Your CV's Education:</strong> <code>{analysis_results['cv_education_level']}</code></p>
321
  <p><strong>πŸ“š Job's Required Education:</strong> <code>{analysis_results['jd_education_level']}</code></p>
322
  <p style='color:green;'><strong>Status:</strong> {analysis_results['education_match_status']}</p>
323
  """
324
-
325
  # Generate plots
326
  overall_plot = create_overall_match_plot(analysis_results['overall_match_score'])
327
  skill_plot = create_skill_match_plot(analysis_results['matched_skills'], analysis_results['missing_skills'])
328
  keywords_plot = create_top_keywords_plot(analysis_results['top_cv_keywords'], analysis_results['top_jd_keywords'])
329
-
330
  # Return all outputs in the correct order
331
  return html_output, overall_plot, skill_plot, keywords_plot, "Analysis Complete!"
332
-
333
  except Exception as e:
334
  import traceback
335
  error_traceback = traceback.format_exc()
@@ -338,9 +326,7 @@ def analyze_cv_match(cv_file_obj, cv_text_input, jd_text_input):
338
  f"<details><summary>Click for details</summary><pre>{error_traceback}</pre></details>",
339
  None, None, None, "Analysis Failed")
340
 
341
-
342
  # --- Gradio Interface Definition ---
343
-
344
  # Use gr.Blocks for more flexibility in layout
345
  with gr.Blocks(theme=gr.themes.Soft(), title="CV-Job Match Analyzer") as demo:
346
  gr.Markdown(
@@ -350,28 +336,22 @@ with gr.Blocks(theme=gr.themes.Soft(), title="CV-Job Match Analyzer") as demo:
350
  Upload a CV (PDF, DOCX, TXT) and paste the job description text to get an instant analysis.
351
  """
352
  )
353
-
354
  with gr.Row(): # Arrange inputs and outputs in two columns
355
  with gr.Column(scale=1, min_width=400): # Left column for inputs
356
  gr.Markdown("## **1. Your CV**") # Section title for CV input
357
  cv_file_obj = gr.File(label="Upload CV (PDF, DOCX, TXT)", file_types=[".pdf", ".docx", ".txt"])
358
  cv_text_input = gr.Textbox(label="Or paste CV text here (overrides file upload)", lines=10, placeholder="Paste your CV content here...")
359
-
360
  gr.Markdown("## **2. Job Description**") # Section title for JD input
361
  jd_text_input = gr.Textbox(label="Paste the Job Description text here", lines=10, placeholder="Paste the job description content here...")
362
-
363
  with gr.Row(): # Buttons in a row
364
  analyze_button = gr.Button("✨ Analyze CV Match ✨", variant="primary", scale=1)
365
  clear_button = gr.ClearButton([cv_file_obj, cv_text_input, jd_text_input], scale=1)
366
-
367
  with gr.Column(scale=2, min_width=600): # Right column for outputs (plots and HTML report)
368
  output_html = gr.HTML(label="Analysis Report") # This will show the text-based KPIs and detailed breakdown
369
  gr.Markdown("## **πŸ“Š Visual Insights**") # Title for the plots section
370
  output_overall_plot = gr.Plot(label="Overall Match Score") # Plots will appear here
371
  output_skill_plot = gr.Plot(label="Skill Match Breakdown")
372
  output_keywords_plot = gr.Plot(label="Top Keywords")
373
-
374
-
375
  # Define the action when the button is clicked
376
  analyze_button.click(
377
  fn=analyze_cv_match,
@@ -381,11 +361,4 @@ with gr.Blocks(theme=gr.themes.Soft(), title="CV-Job Match Analyzer") as demo:
381
  # Gradio uses the last return value for the status bar if it's a string, or you can explicitly link it.
382
  )
383
 
384
- # Optional: Clear button click event if you want it to trigger separately (already linked to ClearButton)
385
- # clear_button.click(
386
- # fn=lambda: [None, "", ""], # Returns empty values for inputs
387
- # outputs=[cv_file_obj, cv_text_input, jd_text_input]
388
- # )
389
-
390
-
391
  demo.launch()
 
46
  "data engineer", "software engineer", "full stack", "frontend", "backend"
47
  ])
48
 
 
49
  # --- Text Extraction Functions (Adapted for file paths in Gradio's File component) ---
50
  # Gradio's gr.File component provides a file path to the temporary uploaded file.
 
51
  def extract_text_from_pdf(pdf_path):
52
  """
53
  Extracts text from a PDF file given its path.
 
257
  plt.tight_layout()
258
  return fig
259
 
 
260
  # --- Main Gradio Interface Function ---
261
  def analyze_cv_match(cv_file_obj, cv_text_input, jd_text_input):
262
  """
 
269
  cv_content = get_file_content(cv_file_obj)
270
  elif cv_text_input:
271
  cv_content = cv_text_input
 
272
  if not cv_content:
273
  return (f"<h4><p style='color:red;'>🚨 Error: Please upload a CV file or paste your CV text.</p></h4>",
274
  None, None, None, "Analysis Failed")
275
  if not jd_text_input:
276
  return (f"<h4><p style='color:red;'>🚨 Error: Please paste the Job Description text.</p></h4>",
277
  None, None, None, "Analysis Failed")
 
278
  try:
279
  analysis_results = perform_cv_job_analysis(cv_content, jd_text_input)
 
280
  # Generate HTML output for KPIs and detailed breakdown
281
  html_output = f"""
282
  <h2 style='text-align: center;'>πŸ’‘ Analysis Results Summary πŸ’‘</h2>
 
300
  <p><strong>βœ… Matched Skills:</strong> {', '.join(analysis_results['matched_skills']) if analysis_results['matched_skills'] else 'None found matching job description.'}</p>
301
  <p><strong>❌ Missing Skills (from Job Description):</strong> {', '.join(analysis_results['missing_skills']) if analysis_results['missing_skills'] else 'πŸ₯³ None! Your CV has all specified skills.'}</p>
302
  <p><strong>πŸ’‘ Extra Skills in CV (not in Job Description):</strong> {', '.join(analysis_results['extra_skills_in_cv']) if analysis_results['extra_skills_in_cv'] else 'None. (This is often fine, showing broader capability.)'}</p>
 
303
  <h4>Keyword Relevance (Top TF-IDF Terms)</h4>
304
  <p><strong>🀝 Top Common Keywords:</strong> {', '.join(analysis_results['common_keywords']) if analysis_results['common_keywords'] else 'No significant common keywords beyond skills.'}</p>
305
  <p><strong>πŸ” Top Keywords in Your CV:**</strong> {', '.join(analysis_results['top_cv_keywords']) if analysis_results['top_cv_keywords'] else 'N/A'}</p>
306
  <p><strong>🎯 Top Keywords in Job Description:</strong> {', '.join(analysis_results['top_jd_keywords']) if analysis_results['top_jd_keywords'] else 'N/A'}</p>
 
307
  <h4>Experience & Education Comparison</h4>
308
  <p><strong>πŸ‘€ Your CV's Experience:</strong> <code>{analysis_results['cv_years_experience']}</code> years</p>
309
  <p><strong>πŸ’Ό Job's Required Experience:</strong> <code>{analysis_results['jd_years_experience']}</code> years</p>
310
  <p style='color:green;'><strong>Status:</strong> {analysis_results['experience_match_status']}</p>
 
311
  <p><strong>πŸŽ“ Your CV's Education:</strong> <code>{analysis_results['cv_education_level']}</code></p>
312
  <p><strong>πŸ“š Job's Required Education:</strong> <code>{analysis_results['jd_education_level']}</code></p>
313
  <p style='color:green;'><strong>Status:</strong> {analysis_results['education_match_status']}</p>
314
  """
 
315
  # Generate plots
316
  overall_plot = create_overall_match_plot(analysis_results['overall_match_score'])
317
  skill_plot = create_skill_match_plot(analysis_results['matched_skills'], analysis_results['missing_skills'])
318
  keywords_plot = create_top_keywords_plot(analysis_results['top_cv_keywords'], analysis_results['top_jd_keywords'])
 
319
  # Return all outputs in the correct order
320
  return html_output, overall_plot, skill_plot, keywords_plot, "Analysis Complete!"
 
321
  except Exception as e:
322
  import traceback
323
  error_traceback = traceback.format_exc()
 
326
  f"<details><summary>Click for details</summary><pre>{error_traceback}</pre></details>",
327
  None, None, None, "Analysis Failed")
328
 
 
329
  # --- Gradio Interface Definition ---
 
330
  # Use gr.Blocks for more flexibility in layout
331
  with gr.Blocks(theme=gr.themes.Soft(), title="CV-Job Match Analyzer") as demo:
332
  gr.Markdown(
 
336
  Upload a CV (PDF, DOCX, TXT) and paste the job description text to get an instant analysis.
337
  """
338
  )
 
339
  with gr.Row(): # Arrange inputs and outputs in two columns
340
  with gr.Column(scale=1, min_width=400): # Left column for inputs
341
  gr.Markdown("## **1. Your CV**") # Section title for CV input
342
  cv_file_obj = gr.File(label="Upload CV (PDF, DOCX, TXT)", file_types=[".pdf", ".docx", ".txt"])
343
  cv_text_input = gr.Textbox(label="Or paste CV text here (overrides file upload)", lines=10, placeholder="Paste your CV content here...")
 
344
  gr.Markdown("## **2. Job Description**") # Section title for JD input
345
  jd_text_input = gr.Textbox(label="Paste the Job Description text here", lines=10, placeholder="Paste the job description content here...")
 
346
  with gr.Row(): # Buttons in a row
347
  analyze_button = gr.Button("✨ Analyze CV Match ✨", variant="primary", scale=1)
348
  clear_button = gr.ClearButton([cv_file_obj, cv_text_input, jd_text_input], scale=1)
 
349
  with gr.Column(scale=2, min_width=600): # Right column for outputs (plots and HTML report)
350
  output_html = gr.HTML(label="Analysis Report") # This will show the text-based KPIs and detailed breakdown
351
  gr.Markdown("## **πŸ“Š Visual Insights**") # Title for the plots section
352
  output_overall_plot = gr.Plot(label="Overall Match Score") # Plots will appear here
353
  output_skill_plot = gr.Plot(label="Skill Match Breakdown")
354
  output_keywords_plot = gr.Plot(label="Top Keywords")
 
 
355
  # Define the action when the button is clicked
356
  analyze_button.click(
357
  fn=analyze_cv_match,
 
361
  # Gradio uses the last return value for the status bar if it's a string, or you can explicitly link it.
362
  )
363
 
 
 
 
 
 
 
 
364
  demo.launch()