norhan12 commited on
Commit
52fdc1d
·
verified ·
1 Parent(s): 4260dbb

Update process_interview.py

Browse files
Files changed (1) hide show
  1. process_interview.py +119 -119
process_interview.py CHANGED
@@ -788,81 +788,81 @@ def create_company_pdf_report(analysis_data: Dict, output_path: str, gemini_repo
788
  canvas.drawRightString(doc.width + doc.leftMargin, doc.height + 0.95*inch, time.strftime('%B %d, %Y'))
789
  canvas.restoreState()
790
 
791
- # Title Page
792
- story.append(Paragraph("Candidate Interview Analysis", h1))
793
- story.append(Paragraph(f"Generated {time.strftime('%B %d, %Y')}", ParagraphStyle(name='Date', alignment=1, fontSize=8, textColor=colors.HexColor('#666666'), fontName='Helvetica')))
794
- story.append(Spacer(1, 0.3*inch))
795
- acceptance_prob = analysis_data.get('acceptance_probability', 50.0)
796
- story.append(Paragraph("Hiring Suitability Snapshot", h2))
797
- prob_color = colors.HexColor('#2E7D32') if acceptance_prob >= 80 else colors.HexColor('#F57C00') if acceptance_prob >= 60 else colors.HexColor('#D32F2F')
798
- story.append(Paragraph(f"Suitability Score: <font size=14 color='{prob_color.hexval()}'><b>{acceptance_prob:.2f}%</b></font>",
799
- ParagraphStyle(name='Prob', fontSize=10, spaceAfter=8, alignment=1, fontName='Helvetica-Bold')))
800
- if acceptance_prob >= 80:
801
- story.append(Paragraph("<b>HR Verdict:</b> Outstanding candidate, recommended for immediate advancement.", body_text))
802
- elif acceptance_prob >= 60:
803
- story.append(Paragraph("<b>HR Verdict:</b> Strong candidate, suitable for further evaluation.", body_text))
804
- elif acceptance_prob >= 40:
805
- story.append(Paragraph("<b>HR Verdict:</b> Moderate potential, needs additional assessment.", body_text))
806
- else:
807
- story.append(Paragraph("<b>HR Verdict:</b> Limited fit, significant improvement required.", body_text))
808
- story.append(Spacer(1, 0.2*inch))
809
- participants = sorted([p for u in set(u['speaker'] for u in analysis_data['transcript'] if u['speaker'] != ['Unknown'])
810
- participants_str = ', '.join(participants)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  table_data = [
812
- ['Metric', 'Value'],
813
- ['Interview Duration', f"{analysis_data['text_analysis']['total_duration']:.2f} seconds"],
814
- ['Speaker Turns', f"{analysis_data['text_analysis']['speaker_turns']}"],
815
- ['Participants', participants_str],
 
 
816
  ]
817
- table = Table(table_data, colWidths=[2.0*inch, 4.0*inch])
818
  table.setStyle(TableStyle([
819
- ('Background', (0,0), (-1,0), colors.HexColor('#0050BC')),
820
  ('TEXTCOLOR', (0,0), (-1,0), colors.white),
821
  ('ALIGN', (0,0), (-1,-1), 'LEFT'),
822
  ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
823
  ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
824
  ('FONTSIZE', (0,0), (-1,-1), 8),
825
- ('BOTTOMPADING', (0,0), (-1,0), 6),
826
- ('TOPPADING', (0,0), (-1,0), 6),
827
- ('Background', (0,1), (-1,-1), colors.HexColor('#F5F6FA')),
828
  ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#DDE4EB')),
829
- ('LEFTPAD', (1,3), (1,3), 10),
830
- ('WORDWRAP', (1,3), (1,3), 'CJK'),
831
  ]))
832
  story.append(table)
833
- story.append(Spacer(1, 0.3*inch))
834
- story.append(Paragraph("Prepared by EvalBot - AI-Powered HR Analysis", body_text))
835
- story.append(PageBreak())
836
-
837
- # Detailed Analysis
838
- story.append(Paragraph("Detailed Candidate Evaluation", h1))
839
-
840
- # Communication and Vocal Dynamics
841
- story.append(Paragraph("1. Communication & Vocal Dynamics", h2))
842
- voice_analysis = analysis_data.get('voice_analysis', {})
843
- if voice_analysis and 'error' not in voice_analysis:
844
- table_data = [
845
- ['Metric', 'Value', 'HR Insight'],
846
- ['Speaking Rate', f"{voice_analysis.get('speaking_rate', 0):.2f} words/sec", 'Benchmark: 2.0-3.0 wps; impacts clarity'],
847
- ['Filler Words', f"{voice_analysis.get('filler_ratio', 0) * 100:.1f}%", 'High usage reduces credibility'],
848
- ['Anxiety', voice_analysis.get('interpretation', {}).get('anxiety_level', 'N/A'), f"Score: {voice_analysis.get('composite_scores'), {}).get('anxiety', 0):.3f}"],
849
- ['Confidence', voice_analysis.get('('interpretation', {}).get('confidence_level'), 'N/A'), f"Score: {voice_analysis.get('('composite_scores', {}).get('confidence', 0):.3f}"],
850
- ['Fluency', voice_analysis.get('interpretation', {}).get('fluency_level', 'N/A'), 'Drives engagement'),
851
- ]
852
- table = Table(table_data, colWidths=[1.5*inch, 1.3*inch, 3.2*inch])
853
- table.setStyle(TableStyle([
854
- ('Background', (0,0), (-1,0), colors.HexColor('#0050BC')),
855
- ('TEXTCOLOR', (0,0), (-1,0), colors.white),
856
- ('ALIGN', (0,0), (-1,-1), 'LEFT'),
857
- ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
858
- ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
859
- ('FONTSIZE', (0,0), (-1,-1), 8),
860
- ('BOTTOMPADING', (0,0), (-1,0), 6),
861
- ('TOPPADING', (0,0), (-1,0), 6),
862
- ('Background', (0,1), (-1,-1), colors.HexColor('#F5F6FA')),
863
- ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#DDE4EB')),
864
- ]))
865
- story.append(table)
866
  story.append(Spacer(1, 0.15*inch))
867
  chart_buffer = io.BytesIO()
868
  generate_anxiety_confidence_chart(voice_analysis.get('composite_scores', {}), chart_buffer)
@@ -898,7 +898,7 @@ def create_company_pdf_report(analysis_data: Dict, output_path: str, gemini_repo
898
  if 'Executive Summary' in section_title:
899
  current_section = 'Executive Summary'
900
  current_subsection = None
901
- elif section_title == 'Communication and Vocal Dynamics':
902
  current_section = 'Communication'
903
  current_subsection = None
904
  elif 'Competency' in section_title:
@@ -907,7 +907,7 @@ def create_company_pdf_report(analysis_data: Dict, output_path: str, gemini_repo
907
  elif 'Role Fit' in section_title:
908
  current_section = 'Role Fit'
909
  current_subsection = None
910
- elif section_title == 'Recommendations':
911
  current_section = 'Recommendations'
912
  current_subsection = None
913
  logger.debug(f"Set section: {current_section}")
@@ -916,14 +916,14 @@ def create_company_pdf_report(analysis_data: Dict, output_path: str, gemini_repo
916
  if not clean_line:
917
  continue
918
  clean_line = re.sub(r'[^\w\s.,;:-]', '', clean_line)
919
- logger.debug(f"Processing bullet: {clean_line}, section: {current_section}, {subsection: current_subsection}")
920
  if current_section in ['Competency', 'Recommendations']:
921
  if current_subsection is None:
922
  if current_section == 'Competency':
923
  current_subsection = 'Strengths'
924
  elif current_section == 'Recommendations':
925
  current_subsection = 'Development'
926
- logger.debug(f"Default subsetion set to: {current_subsection}")
927
  if current_subsection:
928
  sections[current_section][current_subsection].append(clean_line)
929
  else:
@@ -939,63 +939,63 @@ def create_company_pdf_report(analysis_data: Dict, output_path: str, gemini_repo
939
  else:
940
  current_subsection = 'Strengths' if current_section == 'Competency' else 'Development'
941
  sections[current_section][current_subsection].append(clean_line)
942
- logger.debug(f"Default subsetion for non-bullet set to: {current_subsection}")
943
  else:
944
  sections[current_section].append(clean_line)
945
 
946
- # Executive Summary
947
- story.append(Paragraph("2. Executive Summary", h2))
948
- if sections['Executive Summary']:
949
- for line in sections['Executive Summary']:
950
- story.append(Paragraph(line, bullet_style))
951
- else:
952
- story.append(Paragraph("Candidate showed moderate engagement; further assessment needed.", bullet_style))
953
- story.append(Paragraph(f"Interview lasted {analysis_data['text_analysis']['total_duration']:.2f} seconds with {analysis_data['text_analysis']['speaker_turns']} turns.", bullet_style))
954
- story.append(Spacer(1, 0.15*inch))
955
 
956
- # Competency and Content
957
- story.append(Paragraph("3. Competency & Content", h2))
958
- story.append(Paragraph("Strengths", h3))
959
- if sections['Competency']['Strengths']:
960
- for line in sections['Competency']['Strengths']:
961
- story.append(Paragraph(line, bullet_style))
962
- else:
963
- story.append(Paragraph("Strengths not fully assessed; candidate demonstrated consistent communication.", bullet_style))
964
- story.append(Spacer(1, 0.1*inch))
965
- story.append(Paragraph("Growth Areas", h3))
966
- if sections['Competency']['Growth Areas']:
967
- for line in sections['Competency']['Growth Areas']:
968
- story.append(Paragraph(line, bullet_style))
969
- else:
970
- story.append(Paragraph("Consider enhancing specificity in responses to highlight expertise.", bullet_style))
971
- story.append(Spacer(1, 0.15*inch))
972
 
973
- # Role Fit
974
- story.append(Paragraph("4. Role Fit & Potential", h2))
975
- if sections['Role Fit']:
976
- for line in sections['Role Fit']:
977
- story.append(Paragraph(line, bullet_style))
978
- else:
979
- story.append(Paragraph("Potential for role fit exists; further evaluation needed to confirm alignment.", bullet_style))
980
- story.append(Spacer(1, 0.15*inch))
981
 
982
- # Recommendations
983
- story.append(Paragraph("5. Recommendations", h2))
984
- story.append(Paragraph("Development Priorities", h3))
985
- if sections['Recommendations']['Development']:
986
- for line in sections['Recommendations']['Development']:
987
- story.append(Paragraph(line, bullet_style))
988
- else:
989
- story.append(Paragraph("Enrollment in communication training to reduce filler words.", bullet_style))
990
- story.append(Spacer(1, 0.1*inch))
991
- story.append(Paragraph("Next Steps for Hiring Managers", h3))
992
- if sections['Recommendations']['Next Steps']:
993
- for line in sections['Recommendations']['Next Steps']:
994
- story.append(Paragraph(line, bullet_style))
995
- else:
996
- story.append(Paragraph("Schedule a technical assessment to evaluate role-specific skills.", bullet_style))
997
- story.append(Spacer(1, 0.15*inch))
998
- story.append(Paragraph("This report provides actionable insights to support hiring decisions.", body_text))
999
 
1000
  doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer)
1001
  logger.info(f"Company PDF report successfully generated at {output_path}")
 
788
  canvas.drawRightString(doc.width + doc.leftMargin, doc.height + 0.95*inch, time.strftime('%B %d, %Y'))
789
  canvas.restoreState()
790
 
791
+ # Title Page
792
+ story.append(Paragraph("Candidate Interview Analysis", h1))
793
+ story.append(Paragraph(f"Generated {time.strftime('%B %d, %Y')}", ParagraphStyle(name='Date', alignment=1, fontSize=8, textColor=colors.HexColor('#666666'), fontName='Helvetica')))
794
+ story.append(Spacer(1, 0.3*inch))
795
+ acceptance_prob = analysis_data.get('acceptance_probability', 50.0)
796
+ story.append(Paragraph("Hiring Suitability Snapshot", h2))
797
+ prob_color = colors.HexColor('#2E7D32') if acceptance_prob >= 80 else colors.HexColor('#F57C00') if acceptance_prob >= 60 else colors.HexColor('#D32F2F')
798
+ story.append(Paragraph(f"Suitability Score: <font size=14 color='{prob_color.hexval()}'><b>{acceptance_prob:.2f}%</b></font>",
799
+ ParagraphStyle(name='Prob', fontSize=10, spaceAfter=8, alignment=1, fontName='Helvetica-Bold')))
800
+ if acceptance_prob >= 80:
801
+ story.append(Paragraph("<b>HR Verdict:</b> Outstanding candidate, recommended for immediate advancement.", body_text))
802
+ elif acceptance_prob >= 60:
803
+ story.append(Paragraph("<b>HR Verdict:</b> Strong candidate, suitable for further evaluation.", body_text))
804
+ elif acceptance_prob >= 40:
805
+ story.append(Paragraph("<b>HR Verdict:</b> Moderate potential, needs additional assessment.", body_text))
806
+ else:
807
+ story.append(Paragraph("<b>HR Verdict:</b> Limited fit, significant improvement required.", body_text))
808
+ story.append(Spacer(1, 0.2*inch))
809
+ participants = sorted(set(u['speaker'] for u in analysis_data['transcript'] if u['speaker'] != 'Unknown'))
810
+ participants_str = ', '.join(participants)
811
+ table_data = [
812
+ ['Metric', 'Value'],
813
+ ['Interview Duration', f"{analysis_data['text_analysis']['total_duration']:.2f} seconds"],
814
+ ['Speaker Turns', f"{analysis_data['text_analysis']['speaker_turns']}"],
815
+ ['Participants', participants_str],
816
+ ]
817
+ table = Table(table_data, colWidths=[2.0*inch, 4.0*inch])
818
+ table.setStyle(TableStyle([
819
+ ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#0050BC')),
820
+ ('TEXTCOLOR', (0,0), (-1,0), colors.white),
821
+ ('ALIGN', (0,0), (-1,-1), 'LEFT'),
822
+ ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
823
+ ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
824
+ ('FONTSIZE', (0,0), (-1,-1), 8),
825
+ ('BOTTOMPADDING', (0,0), (-1,0), 6),
826
+ ('TOPPADDING', (0,0), (-1,0), 6),
827
+ ('BACKGROUND', (0,1), (-1,-1), colors.HexColor('#F5F6FA')),
828
+ ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#DDE4EB')),
829
+ ('LEFTPADDING', (1,3), (1,3), 10),
830
+ ('WORDWRAP', (1,3), (1,3), 'CJK'),
831
+ ]))
832
+ story.append(table)
833
+ story.append(Spacer(1, 0.3*inch))
834
+ story.append(Paragraph("Prepared by EvalBot - AI-Powered HR Analysis", body_text))
835
+ story.append(PageBreak())
836
+
837
+ # Detailed Analysis
838
+ story.append(Paragraph("Detailed Candidate Evaluation", h1))
839
+
840
+ # Communication and Vocal Dynamics
841
+ story.append(Paragraph("1. Communication & Vocal Dynamics", h2))
842
+ voice_analysis = analysis_data.get('voice_analysis', {})
843
+ if voice_analysis and 'error' not in voice_analysis:
844
  table_data = [
845
+ ['Metric', 'Value', 'HR Insight'],
846
+ ['Speaking Rate', f"{voice_analysis.get('speaking_rate', 0):.2f} words/sec", 'Benchmark: 2.0-3.0 wps; impacts clarity'],
847
+ ['Filler Words', f"{voice_analysis.get('filler_ratio', 0) * 100:.1f}%", 'High usage reduces credibility'],
848
+ ['Anxiety', voice_analysis.get('interpretation', {}).get('anxiety_level', 'N/A'), f"Score: {voice_analysis.get('composite_scores', {}).get('anxiety', 0):.3f}"],
849
+ ['Confidence', voice_analysis.get('interpretation', {}).get('confidence_level', 'N/A'), f"Score: {voice_analysis.get('composite_scores', {}).get('confidence', 0):.3f}"],
850
+ ['Fluency', voice_analysis.get('interpretation', {}).get('fluency_level', 'N/A'), 'Drives engagement'],
851
  ]
852
+ table = Table(table_data, colWidths=[1.5*inch, 1.3*inch, 3.2*inch])
853
  table.setStyle(TableStyle([
854
+ ('BACKGROUND', (0,0), (-1,0), colors.HexColor('#0050BC')),
855
  ('TEXTCOLOR', (0,0), (-1,0), colors.white),
856
  ('ALIGN', (0,0), (-1,-1), 'LEFT'),
857
  ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
858
  ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
859
  ('FONTSIZE', (0,0), (-1,-1), 8),
860
+ ('BOTTOMPADDING', (0,0), (-1,0), 6),
861
+ ('TOPPADDING', (0,0), (-1,0), 6),
862
+ ('BACKGROUND', (0,1), (-1,-1), colors.HexColor('#F5F6FA')),
863
  ('GRID', (0,0), (-1,-1), 0.4, colors.HexColor('#DDE4EB')),
 
 
864
  ]))
865
  story.append(table)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
866
  story.append(Spacer(1, 0.15*inch))
867
  chart_buffer = io.BytesIO()
868
  generate_anxiety_confidence_chart(voice_analysis.get('composite_scores', {}), chart_buffer)
 
898
  if 'Executive Summary' in section_title:
899
  current_section = 'Executive Summary'
900
  current_subsection = None
901
+ elif 'Communication' in section_title:
902
  current_section = 'Communication'
903
  current_subsection = None
904
  elif 'Competency' in section_title:
 
907
  elif 'Role Fit' in section_title:
908
  current_section = 'Role Fit'
909
  current_subsection = None
910
+ elif 'Recommendations' in section_title:
911
  current_section = 'Recommendations'
912
  current_subsection = None
913
  logger.debug(f"Set section: {current_section}")
 
916
  if not clean_line:
917
  continue
918
  clean_line = re.sub(r'[^\w\s.,;:-]', '', clean_line)
919
+ logger.debug(f"Processing bullet: {clean_line}, section: {current_section}, subsection: {current_subsection}")
920
  if current_section in ['Competency', 'Recommendations']:
921
  if current_subsection is None:
922
  if current_section == 'Competency':
923
  current_subsection = 'Strengths'
924
  elif current_section == 'Recommendations':
925
  current_subsection = 'Development'
926
+ logger.debug(f"Default subsection set to: {current_subsection}")
927
  if current_subsection:
928
  sections[current_section][current_subsection].append(clean_line)
929
  else:
 
939
  else:
940
  current_subsection = 'Strengths' if current_section == 'Competency' else 'Development'
941
  sections[current_section][current_subsection].append(clean_line)
942
+ logger.debug(f"Default subsection for non-bullet set to: {current_subsection}")
943
  else:
944
  sections[current_section].append(clean_line)
945
 
946
+ # Executive Summary
947
+ story.append(Paragraph("2. Executive Summary", h2))
948
+ if sections['Executive Summary']:
949
+ for line in sections['Executive Summary']:
950
+ story.append(Paragraph(line, bullet_style))
951
+ else:
952
+ story.append(Paragraph("Candidate showed moderate engagement; further assessment needed.", bullet_style))
953
+ story.append(Paragraph(f"Interview lasted {analysis_data['text_analysis']['total_duration']:.2f} seconds with {analysis_data['text_analysis']['speaker_turns']} turns.", bullet_style))
954
+ story.append(Spacer(1, 0.15*inch))
955
 
956
+ # Competency and Content
957
+ story.append(Paragraph("3. Competency & Content", h2))
958
+ story.append(Paragraph("Strengths", h3))
959
+ if sections['Competency']['Strengths']:
960
+ for line in sections['Competency']['Strengths']:
961
+ story.append(Paragraph(line, bullet_style))
962
+ else:
963
+ story.append(Paragraph("Strengths not fully assessed; candidate demonstrated consistent communication.", bullet_style))
964
+ story.append(Spacer(1, 0.1*inch))
965
+ story.append(Paragraph("Growth Areas", h3))
966
+ if sections['Competency']['Growth Areas']:
967
+ for line in sections['Competency']['Growth Areas']:
968
+ story.append(Paragraph(line, bullet_style))
969
+ else:
970
+ story.append(Paragraph("Consider enhancing specificity in responses to highlight expertise.", bullet_style))
971
+ story.append(Spacer(1, 0.15*inch))
972
 
973
+ # Role Fit
974
+ story.append(Paragraph("4. Role Fit & Potential", h2))
975
+ if sections['Role Fit']:
976
+ for line in sections['Role Fit']:
977
+ story.append(Paragraph(line, bullet_style))
978
+ else:
979
+ story.append(Paragraph("Potential for role fit exists; further evaluation needed to confirm alignment.", bullet_style))
980
+ story.append(Spacer(1, 0.15*inch))
981
 
982
+ # Recommendations
983
+ story.append(Paragraph("5. Recommendations", h2))
984
+ story.append(Paragraph("Development Priorities", h3))
985
+ if sections['Recommendations']['Development']:
986
+ for line in sections['Recommendations']['Development']:
987
+ story.append(Paragraph(line, bullet_style))
988
+ else:
989
+ story.append(Paragraph("Enrollment in communication training to reduce filler words.", bullet_style))
990
+ story.append(Spacer(1, 0.1*inch))
991
+ story.append(Paragraph("Next Steps for Hiring Managers", h3))
992
+ if sections['Recommendations']['Next Steps']:
993
+ for line in sections['Recommendations']['Next Steps']:
994
+ story.append(Paragraph(line, bullet_style))
995
+ else:
996
+ story.append(Paragraph("Schedule a technical assessment to evaluate role-specific skills.", bullet_style))
997
+ story.append(Spacer(1, 0.15*inch))
998
+ story.append(Paragraph("This report provides actionable insights to support hiring decisions.", body_text))
999
 
1000
  doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer)
1001
  logger.info(f"Company PDF report successfully generated at {output_path}")