edouardlgp commited on
Commit
ec96017
·
verified ·
1 Parent(s): 2a04f37

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -23
app.py CHANGED
@@ -963,7 +963,7 @@ def generate_word_document(
963
  ) -> str:
964
  """
965
  Generate a comprehensive Word document from analysis results with multiple fallback mechanisms.
966
-
967
  Args:
968
  file_name: Original PDF filename
969
  responsibilities: Extracted responsibilities text
@@ -974,7 +974,7 @@ def generate_word_document(
974
  skills: List of required skills
975
  esco_levels: ESCO classification levels
976
  esco_skills: ESCO mapped skills
977
-
978
  Returns:
979
  Path to the generated Word document
980
  """
@@ -982,7 +982,7 @@ def generate_word_document(
982
  doc = Document()
983
  doc.core_properties.author = "IOM Talent Management System"
984
  doc.core_properties.title = "Position Description Analysis Report"
985
-
986
  # Default values for all fields
987
  default_values = {
988
  "file": "Unknown file",
@@ -1005,11 +1005,11 @@ def generate_word_document(
1005
  "skills": {"skills": skills} if skills and isinstance(skills, list) else default_values["skills"],
1006
  "skills_esco": esco_skills if esco_skills and isinstance(esco_skills, dict) else default_values["skills_esco"]
1007
  }
1008
-
1009
  # Add level information with validation
1010
  if ccoq_levels and isinstance(ccoq_levels, dict):
1011
  result.update({k: v for k, v in ccoq_levels.items() if v is not None})
1012
-
1013
  if esco_levels and isinstance(esco_levels, dict):
1014
  result.update({k: v for k, v in esco_levels.items() if v is not None})
1015
 
@@ -1017,22 +1017,20 @@ def generate_word_document(
1017
  log_debug(f"Error building result dictionary: {str(e)}")
1018
  result = default_values
1019
 
1020
-
1021
-
1022
  # ================= DOCUMENT CONTENT GENERATION =================
1023
  try:
1024
  # Document header
1025
  doc.add_heading('Job Description Analysis Report', level=0)
1026
  doc.add_paragraph(f"Generated on {time.strftime('%Y-%m-%d %H:%M:%S')}")
1027
  doc.add_paragraph("International Organization for Migration", style="Intense Quote")
1028
-
1029
  # Metadata table
1030
  table = doc.add_table(rows=1, cols=2)
1031
  table.style = 'Light Shading Accent 1'
1032
  hdr_cells = table.rows[0].cells
1033
  hdr_cells[0].text = 'Field'
1034
  hdr_cells[1].text = 'Value'
1035
-
1036
  def _add_table_row(table, field, value):
1037
  row = table.add_row().cells
1038
  row[0].text = field
@@ -1040,14 +1038,14 @@ def generate_word_document(
1040
 
1041
  _add_table_row(table, "File Name", result["file"])
1042
  _add_table_row(table, "Job Family", result["classified_job_family"])
1043
-
1044
  # Section generator with error handling
1045
  def _add_section(heading, content, level=2):
1046
  doc.add_heading(heading, level=level)
1047
  if not content:
1048
  doc.add_paragraph("No information available", style='Subtle Emphasis')
1049
  return
1050
-
1051
  if isinstance(content, (list, tuple)):
1052
  for item in content:
1053
  if item and str(item).strip():
@@ -1062,14 +1060,14 @@ def generate_word_document(
1062
  # Core sections
1063
  _add_section("1. Responsibilities", result["responsibilities"])
1064
  _add_section("2. Qualifications", result["qualification"])
1065
-
1066
  # Skills sections with robust handling
1067
  def _add_skills_section(heading, skills_data):
1068
  doc.add_heading(heading, level=2)
1069
  if not skills_data or not skills_data.get("skills"):
1070
  doc.add_paragraph("No skills information available", style='Subtle Emphasis')
1071
  return
1072
-
1073
  try:
1074
  skills_table = doc.add_table(rows=1, cols=4)
1075
  skills_table.style = 'Medium List 2 Accent 1'
@@ -1078,11 +1076,11 @@ def generate_word_document(
1078
  hdr[1].text = 'Description'
1079
  hdr[2].text = 'Proficiency'
1080
  hdr[3].text = 'Assessment'
1081
-
1082
  for skill in skills_data["skills"]:
1083
  if not isinstance(skill, dict):
1084
  continue
1085
-
1086
  row = skills_table.add_row().cells
1087
  row[0].text = str(skill.get("skill_name", "Unnamed skill"))
1088
  row[1].text = str(skill.get("skill_description", ""))[:100] + ("..." if len(str(skill.get("skill_description", ""))) > 100 else "")
@@ -1093,7 +1091,7 @@ def generate_word_document(
1093
 
1094
  _add_skills_section("3. Required Skills", result["skills"])
1095
  _add_skills_section("4. ESCO Mapped Skills", result["skills_esco"])
1096
-
1097
  # Classification sections
1098
  def _add_classification_section(heading, prefix, levels=4):
1099
  doc.add_heading(heading, level=2)
@@ -1102,7 +1100,7 @@ def generate_word_document(
1102
  code = result.get(f"{prefix}_{i}_code")
1103
  name = result.get(f"{prefix}_{i}_name")
1104
  desc = result.get(f"{prefix}_{i}_desc")
1105
-
1106
  if any([code, name, desc]):
1107
  found = True
1108
  doc.add_heading(f"Level {i}", level=3)
@@ -1112,13 +1110,13 @@ def generate_word_document(
1112
  doc.add_paragraph(f"Name: {name}")
1113
  if desc:
1114
  doc.add_paragraph(f"Description: {desc}")
1115
-
1116
  if not found:
1117
  doc.add_paragraph("No classification information available", style='Subtle Emphasis')
1118
 
1119
  _add_classification_section("5. CCOG Classification", "Level_CCOG")
1120
  _add_classification_section("6. ESCO Classification", "Level_ESCO", levels=5)
1121
-
1122
  # Interview questions
1123
  doc.add_heading("7. Suggested Interview Questions", level=2)
1124
  if result["interview"] and any(q.strip() for q in result["interview"]):
@@ -1127,7 +1125,7 @@ def generate_word_document(
1127
  doc.add_paragraph(f"{i}. {question}", style='List Number')
1128
  else:
1129
  doc.add_paragraph("No interview questions generated", style='Subtle Emphasis')
1130
-
1131
  # Footer
1132
  doc.add_paragraph()
1133
  doc.add_paragraph("Generated by IOM Talent Management AI Tool", style='Footer')
@@ -1148,7 +1146,7 @@ def generate_word_document(
1148
  output_filename = f"{clean_name}_analysis_{time.strftime('%Y%m%d')}.docx"
1149
  else:
1150
  output_filename = f"job_analysis_{time.strftime('%Y%m%d_%H%M%S')}.docx"
1151
-
1152
  # Try saving to reports directory first
1153
  output_dir = "generated_reports"
1154
  try:
@@ -1162,7 +1160,7 @@ def generate_word_document(
1162
  temp_path = os.path.join(temp_dir, output_filename)
1163
  doc.save(temp_path)
1164
  return temp_path
1165
-
1166
  except Exception as e:
1167
  # Ultimate fallback with error document
1168
  error_doc = Document()
@@ -1172,7 +1170,6 @@ def generate_word_document(
1172
  error_doc.save(fallback_path)
1173
  return fallback_path
1174
 
1175
-
1176
  # ================= GRADIO INTERFACE =================
1177
  with gr.Blocks(
1178
  title="AI-powered tool to review Job Position Description",
 
963
  ) -> str:
964
  """
965
  Generate a comprehensive Word document from analysis results with multiple fallback mechanisms.
966
+
967
  Args:
968
  file_name: Original PDF filename
969
  responsibilities: Extracted responsibilities text
 
974
  skills: List of required skills
975
  esco_levels: ESCO classification levels
976
  esco_skills: ESCO mapped skills
977
+
978
  Returns:
979
  Path to the generated Word document
980
  """
 
982
  doc = Document()
983
  doc.core_properties.author = "IOM Talent Management System"
984
  doc.core_properties.title = "Position Description Analysis Report"
985
+
986
  # Default values for all fields
987
  default_values = {
988
  "file": "Unknown file",
 
1005
  "skills": {"skills": skills} if skills and isinstance(skills, list) else default_values["skills"],
1006
  "skills_esco": esco_skills if esco_skills and isinstance(esco_skills, dict) else default_values["skills_esco"]
1007
  }
1008
+
1009
  # Add level information with validation
1010
  if ccoq_levels and isinstance(ccoq_levels, dict):
1011
  result.update({k: v for k, v in ccoq_levels.items() if v is not None})
1012
+
1013
  if esco_levels and isinstance(esco_levels, dict):
1014
  result.update({k: v for k, v in esco_levels.items() if v is not None})
1015
 
 
1017
  log_debug(f"Error building result dictionary: {str(e)}")
1018
  result = default_values
1019
 
 
 
1020
  # ================= DOCUMENT CONTENT GENERATION =================
1021
  try:
1022
  # Document header
1023
  doc.add_heading('Job Description Analysis Report', level=0)
1024
  doc.add_paragraph(f"Generated on {time.strftime('%Y-%m-%d %H:%M:%S')}")
1025
  doc.add_paragraph("International Organization for Migration", style="Intense Quote")
1026
+
1027
  # Metadata table
1028
  table = doc.add_table(rows=1, cols=2)
1029
  table.style = 'Light Shading Accent 1'
1030
  hdr_cells = table.rows[0].cells
1031
  hdr_cells[0].text = 'Field'
1032
  hdr_cells[1].text = 'Value'
1033
+
1034
  def _add_table_row(table, field, value):
1035
  row = table.add_row().cells
1036
  row[0].text = field
 
1038
 
1039
  _add_table_row(table, "File Name", result["file"])
1040
  _add_table_row(table, "Job Family", result["classified_job_family"])
1041
+
1042
  # Section generator with error handling
1043
  def _add_section(heading, content, level=2):
1044
  doc.add_heading(heading, level=level)
1045
  if not content:
1046
  doc.add_paragraph("No information available", style='Subtle Emphasis')
1047
  return
1048
+
1049
  if isinstance(content, (list, tuple)):
1050
  for item in content:
1051
  if item and str(item).strip():
 
1060
  # Core sections
1061
  _add_section("1. Responsibilities", result["responsibilities"])
1062
  _add_section("2. Qualifications", result["qualification"])
1063
+
1064
  # Skills sections with robust handling
1065
  def _add_skills_section(heading, skills_data):
1066
  doc.add_heading(heading, level=2)
1067
  if not skills_data or not skills_data.get("skills"):
1068
  doc.add_paragraph("No skills information available", style='Subtle Emphasis')
1069
  return
1070
+
1071
  try:
1072
  skills_table = doc.add_table(rows=1, cols=4)
1073
  skills_table.style = 'Medium List 2 Accent 1'
 
1076
  hdr[1].text = 'Description'
1077
  hdr[2].text = 'Proficiency'
1078
  hdr[3].text = 'Assessment'
1079
+
1080
  for skill in skills_data["skills"]:
1081
  if not isinstance(skill, dict):
1082
  continue
1083
+
1084
  row = skills_table.add_row().cells
1085
  row[0].text = str(skill.get("skill_name", "Unnamed skill"))
1086
  row[1].text = str(skill.get("skill_description", ""))[:100] + ("..." if len(str(skill.get("skill_description", ""))) > 100 else "")
 
1091
 
1092
  _add_skills_section("3. Required Skills", result["skills"])
1093
  _add_skills_section("4. ESCO Mapped Skills", result["skills_esco"])
1094
+
1095
  # Classification sections
1096
  def _add_classification_section(heading, prefix, levels=4):
1097
  doc.add_heading(heading, level=2)
 
1100
  code = result.get(f"{prefix}_{i}_code")
1101
  name = result.get(f"{prefix}_{i}_name")
1102
  desc = result.get(f"{prefix}_{i}_desc")
1103
+
1104
  if any([code, name, desc]):
1105
  found = True
1106
  doc.add_heading(f"Level {i}", level=3)
 
1110
  doc.add_paragraph(f"Name: {name}")
1111
  if desc:
1112
  doc.add_paragraph(f"Description: {desc}")
1113
+
1114
  if not found:
1115
  doc.add_paragraph("No classification information available", style='Subtle Emphasis')
1116
 
1117
  _add_classification_section("5. CCOG Classification", "Level_CCOG")
1118
  _add_classification_section("6. ESCO Classification", "Level_ESCO", levels=5)
1119
+
1120
  # Interview questions
1121
  doc.add_heading("7. Suggested Interview Questions", level=2)
1122
  if result["interview"] and any(q.strip() for q in result["interview"]):
 
1125
  doc.add_paragraph(f"{i}. {question}", style='List Number')
1126
  else:
1127
  doc.add_paragraph("No interview questions generated", style='Subtle Emphasis')
1128
+
1129
  # Footer
1130
  doc.add_paragraph()
1131
  doc.add_paragraph("Generated by IOM Talent Management AI Tool", style='Footer')
 
1146
  output_filename = f"{clean_name}_analysis_{time.strftime('%Y%m%d')}.docx"
1147
  else:
1148
  output_filename = f"job_analysis_{time.strftime('%Y%m%d_%H%M%S')}.docx"
1149
+
1150
  # Try saving to reports directory first
1151
  output_dir = "generated_reports"
1152
  try:
 
1160
  temp_path = os.path.join(temp_dir, output_filename)
1161
  doc.save(temp_path)
1162
  return temp_path
1163
+
1164
  except Exception as e:
1165
  # Ultimate fallback with error document
1166
  error_doc = Document()
 
1170
  error_doc.save(fallback_path)
1171
  return fallback_path
1172
 
 
1173
  # ================= GRADIO INTERFACE =================
1174
  with gr.Blocks(
1175
  title="AI-powered tool to review Job Position Description",