mbosse99 commited on
Commit
0fae1d4
·
1 Parent(s): 2b5ebc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -108
app.py CHANGED
@@ -58,7 +58,7 @@ def upload_blob(pdf_name, json_data, pdf_data_jobdescription,pdf_data_cvs, pre_g
58
 
59
  cv_nr_for_id = i+1
60
  cv_session_state_string = "cv-"+str(cv_nr_for_id)
61
- session_state_name = st.session_state["final_candidates"][i].metadata["name"]
62
  names.append(session_state_name)
63
  cv_id = pdf_name + "-cv-nr-" + str(cv_nr_for_id)+str(calendar.timegm(time.gmtime()))
64
  upload_db_item(session_state_name, json.loads(json_data), pdf_name, cv_id)
@@ -171,26 +171,68 @@ st.markdown(
171
 
172
  with open("sys_prompt_frontend.txt") as f:
173
  sys_prompt = f.read()
 
 
174
 
175
  def adjust_numbering(lst):
176
  return [f"{i + 1}. {item.split('. ', 1)[1]}" for i, item in enumerate(lst)]
177
 
178
  def generate_candidate_mail(candidate, chat_link)-> str:
179
- prompt = "You are a professional recruiter who has selected a suitable candidate based on a job description. Your task is to write two to three sentences about the candidate and why we think they are suitable for the job. The text will then be used in an email to the candidate, so address the candidate."
180
- res = openai.ChatCompletion.create(
181
- engine="gpt-4",
182
- temperature=0.2,
183
- messages=[
184
- {
185
- "role": "system",
186
- "content": prompt,
187
- },
188
- {"role": "system", "content": "Job description: "+st.session_state["job_string"]+"; Resume: "+candidate.page_content}
189
- ],
190
- )
191
- # print(res.choices[0]["message"]["content"])
192
- output_string = f"""{res.choices[0]["message"]["content"]}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  We have added the job description to the mail attachment.
195
  If you are interested in the position, please click on the following link, answer a few questions from our chatbot for about 10-15 minutes and we will get back to you.
196
 
@@ -204,21 +246,24 @@ WorkGenius
204
 
205
  def generate_job_bullets(job)->str:
206
  prompt = "You are a professional recruiter whose task is to summarize the provided job description in the most important 5 key points. The key points should have a maximum of 8 words. The only thing you should return are the bullet points."
207
- res = openai.ChatCompletion.create(
208
- engine="gpt-4",
209
- temperature=0.2,
210
- messages=[
211
- {
212
- "role": "system",
213
- "content": prompt,
214
- },
215
- {"role": "system", "content": "Job description: "+st.session_state["job_string"]}
216
- ],
217
- )
218
- # print(res.choices[0]["message"]["content"])
219
- output_string = f"""{res.choices[0]["message"]["content"]}"""
220
- # print(output_string)
221
- return output_string
 
 
 
222
 
223
  def check_keywords_in_content(database_path, table_name, input_id, keywords):
224
  # Verbindung zur Datenbank herstellen
@@ -248,6 +293,100 @@ def check_keywords_in_content(database_path, table_name, input_id, keywords):
248
 
249
  return contains_keywords
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  if "similarity_search_string" not in st.session_state:
252
  st.session_state["similarity_search_string"] = None
253
  if "job_string" not in st.session_state:
@@ -260,6 +399,12 @@ if "final_question_string" not in st.session_state:
260
  st.session_state["final_question_string"] = []
261
  if "ai_questions" not in st.session_state:
262
  st.session_state["ai_questions"] = None
 
 
 
 
 
 
263
  if "db" not in st.session_state:
264
  embedder = OpenAIEmbeddings(deployment="text-embedding-ada-002", chunk_size=1)
265
  embedding_function = embedder.embed_query
@@ -288,6 +433,43 @@ with col_clear:
288
  if st.button("Clear", use_container_width=True):
289
  streamlit_js_eval(js_expressions="parent.window.location.reload()")
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  st.write("Switch from a similarity search (default) to a hybrid search (activated)")
292
  st.toggle("Switch Search", key="search_type")
293
 
@@ -304,74 +486,23 @@ text_area_params = st.text_area(label="Add additional search parameters, which a
304
 
305
  submit = st.button("Search candidates",disabled= True if st.session_state["final_candidates"] else False)
306
 
307
- def load_candidates():
308
- with st.spinner("Load the candidates, this may take a moment..."):
309
- filter_string = ""
310
- query_string = "The following keywords must be included: " + text_area_params + " " + st.session_state["job_string"]
311
- checked_candidates = []
312
- db_path = 'cvdb.db'
313
- table_name = 'files'
314
- candidates_per_search = 100
315
- target_candidates_count = 10
316
- current_offset = 0
317
-
318
- if st.session_state["screened"]:
319
- filter_string = "amount_screenings gt 0 "
320
- if st.session_state["handed"]:
321
- if len(filter_string) > 0:
322
- filter_string += "and amount_handoffs gt 0 "
323
- else:
324
- filter_string += "amount_handoffs gt 0 "
325
- if st.session_state["placed"]:
326
- if len(filter_string) > 0:
327
- filter_string += "and amount_placed gt 0"
328
- else:
329
- filter_string += "amount_placed gt 0"
330
- print(filter_string)
331
- while len(checked_candidates) < target_candidates_count:
332
- # Führe eine similarity search durch und erhalte 100 Kandidaten
333
- if st.session_state["search_type"]:
334
- print("hybrid")
335
- raw_candidates = st.session_state["db"].hybrid_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
336
- else:
337
- print("similarity")
338
- raw_candidates = st.session_state["db"].similarity_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
339
-
340
- for candidate in raw_candidates[current_offset:]:
341
- candidates_id = candidate.metadata["source"].split("/")[-1]
342
- keyword_bool = check_keywords_in_content(db_path, table_name, candidates_id, text_area_params.split(','))
343
-
344
- if keyword_bool:
345
- checked_candidates.append(candidate)
346
-
347
- # Überprüfe, ob die Zielanzahl erreicht wurde und breche die Schleife ab, wenn ja
348
- if len(checked_candidates) >= target_candidates_count:
349
- break
350
-
351
- current_offset += candidates_per_search
352
- if current_offset == 600:
353
- break
354
- # Setze die Ergebnisse in der Session State Variable
355
- st.session_state["docs_res"] = checked_candidates
356
- if len(checked_candidates) == 0:
357
- st.error("No candidates can be found with these keywords. Please adjust the keywords and try again.", icon="🚨")
358
 
359
  if not st.session_state["job"] and submit:
360
  st.error("Please upload a job description to search for candidates")
361
  if st.session_state["docs_res"] and submit:
362
- load_candidates()
363
- if (st.session_state["job"] and submit) or st.session_state["docs_res"]:
364
- if not st.session_state["job_string"]:
365
- pdf_data_jobdescription = st.session_state["job"].read()
366
- pdf_data_jobdescription_string = ""
367
- pdf_reader_job = PdfReader(io.BytesIO(pdf_data_jobdescription))
368
- for page_num in range(len(pdf_reader_job.pages)):
369
- page = pdf_reader_job.pages[page_num]
370
- pdf_data_jobdescription_string += page.extract_text()
371
- # st.session_state["pdf_data_jobdescription"] = pdf_data_jobdescription activate and add sessio state if data is needed
372
- st.session_state["job_string"] = pdf_data_jobdescription_string
373
  if not st.session_state["docs_res"]:
374
- load_candidates()
375
  if not st.session_state["final_candidates"]:
376
  for i,doc in enumerate(st.session_state["docs_res"]):
377
  # print(doc)
@@ -383,21 +514,34 @@ if (st.session_state["job"] and submit) or st.session_state["docs_res"]:
383
  st.rerun()
384
  with cols_final[0]:
385
  # st.subheader(doc.metadata["source"])
386
- with st.expander(doc.metadata["name"]):
387
- st.write(doc.page_content)
388
- if st.button("Accept candidates", key="accept_candidates_btn"):
389
- print("hello")
390
- st.session_state["final_candidates"] = st.session_state["docs_res"].copy()
391
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  else:
393
  print("Now Questions")
394
  st.subheader("Your Candidates:")
395
- st.write(", ".join(candidate.metadata["name"] for candidate in st.session_state["final_candidates"]))
396
  # for i,candidate in enumerate(st.session_state["final_candidates"]):
397
  # st.write(candidate.metadata["source"])
398
- cv_strings = "; Next CV: ".join(candidate.page_content for candidate in st.session_state["final_candidates"])
399
  # print(len(cv_strings))
400
- system = sys_prompt.format(job=st.session_state["job_string"], resume=st.session_state["final_candidates"][0], n=15)
401
  if not st.session_state["ai_questions"]:
402
  try:
403
  # st.write("The questions are generated. This may take a short moment...")
@@ -517,7 +661,7 @@ Your Candidate-Search-Tool
517
  for candidate in st.session_state["final_candidates"]:
518
  styles = getSampleStyleSheet()
519
  pdf = SimpleDocTemplate(temp_pdf_file)
520
- flowables = [Paragraph(candidate.page_content, styles['Normal'])]
521
  pdf.build(flowables)
522
  with open(temp_pdf_file, 'rb') as pdf_file:
523
  bytes_data = pdf_file.read()
@@ -527,9 +671,9 @@ Your Candidate-Search-Tool
527
  mail_txt_string = ""
528
  for i, candidate in enumerate(st.session_state["final_candidates"]):
529
  if i > 0:
530
- mail_txt_string += "\n\nMail to the "+str(i+1)+". candidate: "+candidate.metadata["name"]+" "+candidate.metadata["candidateId"]+" \n\n"
531
  else:
532
- mail_txt_string += "Mail to the "+str(i+1)+". candidate: "+candidate.metadata["name"]+" "+candidate.metadata["candidateId"]+" \n\n"
533
  mail_txt_string += generate_candidate_mail(candidate,candidate_links[i])
534
  # Summary in eine TXT Datei schreiben
535
  mail_txt_path = "mailattachment.txt"
@@ -565,6 +709,4 @@ Your Candidate-Search-Tool
565
  st.success('The dispatch and the upload of the data was successful')
566
  except Exception as e:
567
  st.error("Unfortunately the SMS dispatch did not work. Please reload the page and try again or contact the administrator. ", icon="🚨")
568
- print("Fehler beim Senden der SMS:", str(e))
569
-
570
-
 
58
 
59
  cv_nr_for_id = i+1
60
  cv_session_state_string = "cv-"+str(cv_nr_for_id)
61
+ session_state_name = st.session_state["final_candidates"][i][0].metadata["name"]
62
  names.append(session_state_name)
63
  cv_id = pdf_name + "-cv-nr-" + str(cv_nr_for_id)+str(calendar.timegm(time.gmtime()))
64
  upload_db_item(session_state_name, json.loads(json_data), pdf_name, cv_id)
 
171
 
172
  with open("sys_prompt_frontend.txt") as f:
173
  sys_prompt = f.read()
174
+ with open("sys_prompt_job_optimization.txt") as j:
175
+ sys_prompt_optimization = j.read()
176
 
177
  def adjust_numbering(lst):
178
  return [f"{i + 1}. {item.split('. ', 1)[1]}" for i, item in enumerate(lst)]
179
 
180
  def generate_candidate_mail(candidate, chat_link)-> str:
181
+ candidate_first_name = candidate[0].metadata["name"].split(" ")[0]
182
+ prompt = f"You are a professional recruiter who has selected a suitable candidate on the basis of a job description. Your task is to write two to three sentences about the applicant and explain why we think they are suitable for the job. The text will then be used in an e-mail to the applicant, so please address it to them. Please start the e-mail with 'Dear {candidate_first_name}'. I'll write the end of the mail myself."
183
+ try:
184
+ res = openai.ChatCompletion.create(
185
+ engine="gpt-4",
186
+ temperature=0.2,
187
+ messages=[
188
+ {
189
+ "role": "system",
190
+ "content": prompt,
191
+ },
192
+ {"role": "system", "content": "Job description: "+st.session_state["job_string"]+"; Resume: "+candidate[0].page_content}
193
+ ],
194
+ )
195
+ # print(res.choices[0]["message"]["content"])
196
+ except Exception as e:
197
+ # Iterativ die Anfrage wiederholen und 200 Chars von hinten vom Resume weglassen
198
+ max_retries = 5
199
+ retries = 0
200
+ while retries < max_retries:
201
+ try:
202
+ # Reduziere die Länge des Resume um 200 Chars von hinten
203
+ candidate[0].page_content = candidate[0].page_content[:-200]
204
+
205
+ # Neue Anfrage senden
206
+ res = openai.ChatCompletion.create(
207
+ engine="gpt-4",
208
+ temperature=0.2,
209
+ messages=[
210
+ {
211
+ "role": "system",
212
+ "content": prompt,
213
+ },
214
+ {"role": "system", "content": "Job description: " + st.session_state["job_string"] + "; Resume: " + candidate[0].page_content}
215
+ ],
216
+ )
217
+ # print(res.choices[0]["message"]["content"])
218
+
219
+ # Wenn die Anfrage erfolgreich ist, den Schleifen-Iterator beenden
220
+ break
221
 
222
+ except Exception as e:
223
+ # Bei erneuter Ausnahme die Schleife fortsetzen
224
+ retries += 1
225
+ if retries == max_retries:
226
+ # Falls die maximale Anzahl von Wiederholungen erreicht ist, handle die Ausnahme entsprechend
227
+ print("Max retries reached. Unable to get a valid response.")
228
+ return "The CV was too long to generate a Mail"
229
+ # Hier kannst du zusätzlichen Code für den Fall implementieren, dass die maximale Anzahl von Wiederholungen erreicht wurde.
230
+
231
+ # Optional: Füge eine Wartezeit zwischen den Anfragen hinzu, um API-Beschränkungen zu respektieren
232
+ time.sleep(1)
233
+
234
+ output_string = f"""{res.choices[0]["message"]["content"]}
235
+
236
  We have added the job description to the mail attachment.
237
  If you are interested in the position, please click on the following link, answer a few questions from our chatbot for about 10-15 minutes and we will get back to you.
238
 
 
246
 
247
  def generate_job_bullets(job)->str:
248
  prompt = "You are a professional recruiter whose task is to summarize the provided job description in the most important 5 key points. The key points should have a maximum of 8 words. The only thing you should return are the bullet points."
249
+ try:
250
+ res = openai.ChatCompletion.create(
251
+ engine="gpt-4",
252
+ temperature=0.2,
253
+ messages=[
254
+ {
255
+ "role": "system",
256
+ "content": prompt,
257
+ },
258
+ {"role": "system", "content": "Job description: "+job}
259
+ ],
260
+ )
261
+ # print(res.choices[0]["message"]["content"])
262
+ output_string = f"""{res.choices[0]["message"]["content"]}"""
263
+ # print(output_string)
264
+ return output_string
265
+ except Exception as e:
266
+ print(f"Fehler beim generieren der Bullets: {str(e)}")
267
 
268
  def check_keywords_in_content(database_path, table_name, input_id, keywords):
269
  # Verbindung zur Datenbank herstellen
 
293
 
294
  return contains_keywords
295
 
296
+ def load_candidates(fillup):
297
+ with st.spinner("Load the candidates, this may take a moment..."):
298
+ # print(st.session_state["job_string"])
299
+ filter_string = ""
300
+ query_string = "The following keywords must be included: " + text_area_params + " " + st.session_state["job_string"]
301
+ checked_candidates = []
302
+ db_path = 'cvdb.db'
303
+ table_name = 'files'
304
+ candidates_per_search = 100
305
+ target_candidates_count = 10
306
+ current_offset = 0
307
+
308
+ if st.session_state["screened"]:
309
+ filter_string = "amount_screenings gt 0 "
310
+ if st.session_state["handed"]:
311
+ if len(filter_string) > 0:
312
+ filter_string += "and amount_handoffs gt 0 "
313
+ else:
314
+ filter_string += "amount_handoffs gt 0 "
315
+ if st.session_state["placed"]:
316
+ if len(filter_string) > 0:
317
+ filter_string += "and amount_placed gt 0"
318
+ else:
319
+ filter_string += "amount_placed gt 0"
320
+ # print(filter_string)
321
+ if not fillup:
322
+ while len(checked_candidates) < target_candidates_count:
323
+ # Führe eine similarity search durch und erhalte 100 Kandidaten
324
+ if st.session_state["search_type"]:
325
+ print("hybrid")
326
+ # raw_candidates = st.session_state["db"].hybrid_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
327
+ raw_candidates = st.session_state["db"].hybrid_search_with_score(query_string, k=candidates_per_search+current_offset, filters=filter_string)
328
+ else:
329
+ print("similarity")
330
+ # raw_candidates = st.session_state["db"].similarity_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
331
+ raw_candidates = st.session_state["db"].similarity_search_with_relevance_scores(query_string, k=candidates_per_search+current_offset, filters=filter_string)
332
+
333
+ for candidate in raw_candidates[current_offset:]:
334
+ candidates_id = candidate[0].metadata["source"].split("/")[-1]
335
+ keyword_bool = check_keywords_in_content(db_path, table_name, candidates_id, text_area_params.split(','))
336
+
337
+ if keyword_bool:
338
+ checked_candidates.append(candidate)
339
+
340
+ # Überprüfe, ob die Zielanzahl erreicht wurde und breche die Schleife ab, wenn ja
341
+ if len(checked_candidates) >= target_candidates_count:
342
+ break
343
+
344
+ current_offset += candidates_per_search
345
+ if current_offset == 600:
346
+ break
347
+ # Setze die Ergebnisse in der Session State Variable
348
+ st.session_state["docs_res"] = checked_candidates
349
+ st.session_state["candidate_offset"] = current_offset
350
+ if len(checked_candidates) == 0:
351
+ st.error("No candidates can be found with these keywords. Please adjust the keywords and try again.", icon="🚨")
352
+ else:
353
+ # Setze die Zielanzahl auf 10
354
+ target_candidates_count = 10
355
+
356
+ current_offset = st.session_state["candidate_offset"]
357
+
358
+ # Solange die Anzahl der überprüften Kandidaten kleiner als die Zielanzahl ist
359
+ while len(st.session_state["docs_res"]) < target_candidates_count:
360
+ # Führe eine similarity search durch und erhalte 100 Kandidaten
361
+ if st.session_state["search_type"]:
362
+ print("hybrid")
363
+ # raw_candidates = st.session_state["db"].hybrid_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
364
+ raw_candidates = st.session_state["db"].hybrid_search_with_score(query_string, k=candidates_per_search+current_offset, filters=filter_string)
365
+ else:
366
+ print("similarity")
367
+ # raw_candidates = st.session_state["db"].similarity_search(query_string, k=candidates_per_search+current_offset, filters=filter_string)
368
+ raw_candidates = st.session_state["db"].similarity_search_with_relevance_scores(query_string, k=candidates_per_search+current_offset, filters=filter_string)
369
+ temp_offset_add = 0
370
+ for candidate in raw_candidates[current_offset:]:
371
+ candidates_id = candidate[0].metadata["source"].split("/")[-1]
372
+ keyword_bool = check_keywords_in_content(db_path, table_name, candidates_id, text_area_params.split(','))
373
+
374
+ if keyword_bool:
375
+ st.session_state["docs_res"].append(candidate)
376
+ temp_offset_add += 1
377
+ # Überprüfe, ob die Zielanzahl erreicht wurde und breche die Schleife ab, wenn ja
378
+ if len(st.session_state["docs_res"]) >= target_candidates_count:
379
+ st.session_state["candidate_offset"] = current_offset+temp_offset_add
380
+ break
381
+
382
+ current_offset += candidates_per_search
383
+ if current_offset == 900:
384
+ break
385
+
386
+ # Wenn die Liste immer noch leer ist, zeige eine Fehlermeldung an
387
+ if len(st.session_state["docs_res"]) == 0:
388
+ st.warning("No more candidates can be found.", icon="🔥")
389
+
390
  if "similarity_search_string" not in st.session_state:
391
  st.session_state["similarity_search_string"] = None
392
  if "job_string" not in st.session_state:
 
399
  st.session_state["final_question_string"] = []
400
  if "ai_questions" not in st.session_state:
401
  st.session_state["ai_questions"] = None
402
+ if "raw_job" not in st.session_state:
403
+ st.session_state["raw_job"] = None
404
+ if "optimized_job" not in st.session_state:
405
+ st.session_state["optimized_job"] = None
406
+ if "candidate_offset" not in st.session_state:
407
+ st.session_state["candidate_offset"] = 0
408
  if "db" not in st.session_state:
409
  embedder = OpenAIEmbeddings(deployment="text-embedding-ada-002", chunk_size=1)
410
  embedding_function = embedder.embed_query
 
433
  if st.button("Clear", use_container_width=True):
434
  streamlit_js_eval(js_expressions="parent.window.location.reload()")
435
 
436
+ if st.session_state["job"]:
437
+ if not st.session_state["job_string"]:
438
+ if not st.session_state["optimized_job"]:
439
+ with st.spinner("Optimizing the job description. This may take a moment..."):
440
+ pdf_data_jobdescription = st.session_state["job"].read()
441
+ pdf_data_jobdescription_string = ""
442
+ pdf_reader_job = PdfReader(io.BytesIO(pdf_data_jobdescription))
443
+ for page_num in range(len(pdf_reader_job.pages)):
444
+ page = pdf_reader_job.pages[page_num]
445
+ pdf_data_jobdescription_string += page.extract_text()
446
+ # st.session_state["pdf_data_jobdescription"] = pdf_data_jobdescription activate and add sessio state if data is needed
447
+ system_prompt_job = sys_prompt_optimization.format(job=pdf_data_jobdescription_string)
448
+ try:
449
+ res = openai.ChatCompletion.create(
450
+ engine="gpt-4",
451
+ temperature=0.2,
452
+ messages=[
453
+ {
454
+ "role": "system",
455
+ "content": system_prompt_job,
456
+ },
457
+ ],
458
+ )
459
+ # print(res.choices[0]["message"]["content"])
460
+ output_string = f"""{res.choices[0]["message"]["content"]}"""
461
+ st.session_state["optimized_job"] = output_string
462
+ st.rerun()
463
+ except Exception as e:
464
+ print(f"Fehler beim generieren der optimierten JD: {str(e)}")
465
+ st.error("An error has occurred. Please reload the page or contact the admin.", icon="🚨")
466
+ # st.session_state["job_string"] = pdf_data_jobdescription_string
467
+ # print(output_string)
468
+ st.text_area("This is the AI-generated optimized job description. If necessary, change something to your liking:", value=st.session_state["optimized_job"], height=700, key="optimized_job_edited")
469
+ if st.button("Accept the job description"):
470
+ st.session_state["job_string"] = st.session_state["optimized_job_edited"]
471
+ st.rerun()
472
+
473
  st.write("Switch from a similarity search (default) to a hybrid search (activated)")
474
  st.toggle("Switch Search", key="search_type")
475
 
 
486
 
487
  submit = st.button("Search candidates",disabled= True if st.session_state["final_candidates"] else False)
488
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
 
490
  if not st.session_state["job"] and submit:
491
  st.error("Please upload a job description to search for candidates")
492
  if st.session_state["docs_res"] and submit:
493
+ load_candidates(False)
494
+ if (st.session_state["job_string"] and submit) or st.session_state["docs_res"]:
495
+ # if not st.session_state["job_string"]:
496
+ # pdf_data_jobdescription = st.session_state["job"].read()
497
+ # pdf_data_jobdescription_string = ""
498
+ # pdf_reader_job = PdfReader(io.BytesIO(pdf_data_jobdescription))
499
+ # for page_num in range(len(pdf_reader_job.pages)):
500
+ # page = pdf_reader_job.pages[page_num]
501
+ # pdf_data_jobdescription_string += page.extract_text()
502
+ # # st.session_state["pdf_data_jobdescription"] = pdf_data_jobdescription activate and add sessio state if data is needed
503
+ # st.session_state["job_string"] = pdf_data_jobdescription_string
504
  if not st.session_state["docs_res"]:
505
+ load_candidates(False)
506
  if not st.session_state["final_candidates"]:
507
  for i,doc in enumerate(st.session_state["docs_res"]):
508
  # print(doc)
 
514
  st.rerun()
515
  with cols_final[0]:
516
  # st.subheader(doc.metadata["source"])
517
+ with st.expander(doc[0].metadata["name"]+" with a search score of: "+str(round(doc[1] * 100, 3))+"%"):
518
+ st.write(doc[0].page_content)
519
+ if len(st.session_state["docs_res"])>=10:
520
+ if st.button("Accept candidates", key="accept_candidates_btn"):
521
+ print("hello")
522
+ st.session_state["final_candidates"] = st.session_state["docs_res"].copy()
523
+ st.rerun()
524
+ else:
525
+ col_accept, col_empty ,col_load_new = st.columns([2, 3, 2])
526
+ with col_accept:
527
+ if st.button("Accept candidates", key="accept_candidates_btn"):
528
+ print("hello")
529
+ st.session_state["final_candidates"] = st.session_state["docs_res"].copy()
530
+ st.rerun()
531
+ with col_load_new:
532
+ if st.button("Load new candidates", key="load_new_candidates"):
533
+ print("loading new candidates")
534
+ load_candidates(True)
535
+ st.rerun()
536
  else:
537
  print("Now Questions")
538
  st.subheader("Your Candidates:")
539
+ st.write(", ".join(candidate[0].metadata["name"] for candidate in st.session_state["final_candidates"]))
540
  # for i,candidate in enumerate(st.session_state["final_candidates"]):
541
  # st.write(candidate.metadata["source"])
542
+ cv_strings = "; Next CV: ".join(candidate[0].page_content for candidate in st.session_state["final_candidates"])
543
  # print(len(cv_strings))
544
+ system = sys_prompt.format(job=st.session_state["job_string"], resume=st.session_state["final_candidates"][0][0].page_content, n=15)
545
  if not st.session_state["ai_questions"]:
546
  try:
547
  # st.write("The questions are generated. This may take a short moment...")
 
661
  for candidate in st.session_state["final_candidates"]:
662
  styles = getSampleStyleSheet()
663
  pdf = SimpleDocTemplate(temp_pdf_file)
664
+ flowables = [Paragraph(candidate[0].page_content, styles['Normal'])]
665
  pdf.build(flowables)
666
  with open(temp_pdf_file, 'rb') as pdf_file:
667
  bytes_data = pdf_file.read()
 
671
  mail_txt_string = ""
672
  for i, candidate in enumerate(st.session_state["final_candidates"]):
673
  if i > 0:
674
+ mail_txt_string += "\n\nMail to the "+str(i+1)+". candidate: "+candidate[0].metadata["name"]+" "+candidate[0].metadata["candidateId"]+" \n\n"
675
  else:
676
+ mail_txt_string += "Mail to the "+str(i+1)+". candidate: "+candidate[0].metadata["name"]+" "+candidate[0].metadata["candidateId"]+" \n\n"
677
  mail_txt_string += generate_candidate_mail(candidate,candidate_links[i])
678
  # Summary in eine TXT Datei schreiben
679
  mail_txt_path = "mailattachment.txt"
 
709
  st.success('The dispatch and the upload of the data was successful')
710
  except Exception as e:
711
  st.error("Unfortunately the SMS dispatch did not work. Please reload the page and try again or contact the administrator. ", icon="🚨")
712
+ print("Fehler beim Senden der SMS:", str(e))