mbosse99 commited on
Commit
61125c4
·
1 Parent(s): bcb59e2

Update to POC Version

Browse files
Files changed (1) hide show
  1. app.py +197 -10
app.py CHANGED
@@ -1,13 +1,102 @@
1
  import openai
2
  import gradio as gr
3
  from PyPDF2 import PdfReader
4
- from dotenv import load_dotenv
 
 
 
 
 
 
 
 
5
 
6
  load_dotenv()
7
 
 
 
 
8
  with open("sys_prompt.txt") as f:
9
  sys_prompt = f.read()
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  def add_file(file, chat, job, resume):
13
  if file.name.endswith(".pdf"):
@@ -20,11 +109,13 @@ def add_file(file, chat, job, resume):
20
  text = f.read()
21
 
22
  if job:
 
23
  chat += [["📄 " + file.name.split("/")[-1], None]]
24
  resume = text
25
- else:
26
- chat += [["📄 " + file.name.split("/")[-1], "Thanks. Please upload the resume."]]
27
- job = text
 
28
 
29
  return chat, job, resume
30
 
@@ -33,12 +124,13 @@ def user(message, history):
33
  return "", history + [[message, None]]
34
 
35
 
36
- def bot(history, job, resume):
37
- if not resume:
 
38
  yield history
39
  return
40
 
41
- system = sys_prompt.format(job=job, resume=resume, n=8)
42
  messages = [{"role": "system", "content": system}]
43
  for user, assistant in history:
44
  if user:
@@ -58,27 +150,122 @@ def bot(history, job, resume):
58
  if len(chunk["choices"][0]["delta"]) != 0:
59
  history[-1][1] = history[-1][1] + chunk["choices"][0]["delta"]["content"]
60
  yield history
 
 
 
61
  return
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  css = "footer {visibility: hidden} #component-0{height: 90vh !important} #chatbot{height: 85vh !important}}"
65
 
66
  with gr.Blocks(css=css) as app:
 
67
  job = gr.State("")
68
  resume = gr.State("")
 
 
 
 
 
69
  chat = gr.Chatbot(
70
- [[None, "Please upload the job description."]], height=600, elem_id="chatbot"
71
  )
72
  with gr.Row():
73
  clr = gr.Button("Clear", scale=0)
74
  msg = gr.Textbox(lines=1, show_label=False, scale=1)
75
  file = gr.UploadButton("Browse", file_types=[".pdf", ".txt"], scale=0)
76
  msg.submit(user, [msg, chat], [msg, chat], queue=False).then(
77
- bot, [chat, job, resume], chat
78
  )
79
  file.upload(
80
  add_file, [file, chat, job, resume], [chat, job, resume], queue=False
81
- ).then(bot, [chat, job, resume], chat)
82
  clr.click(lambda: None, None, chat, queue=False)
83
 
84
  app.queue()
 
1
  import openai
2
  import gradio as gr
3
  from PyPDF2 import PdfReader
4
+ from azure.storage.blob import BlobServiceClient
5
+ import io
6
+ from PyPDF2 import PdfReader
7
+ import json
8
+ import smtplib
9
+ from email.mime.text import MIMEText
10
+ from email.mime.multipart import MIMEMultipart
11
+ from email.mime.application import MIMEApplication
12
+ import os
13
 
14
  load_dotenv()
15
 
16
+ os_connection_string = os.getenv("CONNECTION")
17
+ os_mail_password = os.getenv("MAIL_PASSWORD")
18
+
19
  with open("sys_prompt.txt") as f:
20
  sys_prompt = f.read()
21
 
22
+ get_window_url_params = """
23
+ function(job, job_params) {
24
+ console.log(job, job_params);
25
+ const params = new URLSearchParams(window.location.search);
26
+ job_params = Object.fromEntries(params);
27
+ return [job, job_params];
28
+ }
29
+ """
30
+
31
+ def download_and_parse_json_blob(storage_connection_string, container_name, blob_name, encoding='utf-8'):
32
+ try:
33
+ # Verbindung zum Blob-Dienst herstellen
34
+ blob_service_client = BlobServiceClient.from_connection_string(storage_connection_string)
35
+
36
+ # Container und Blob-Client erstellen
37
+ container_client = blob_service_client.get_container_client(container_name)
38
+ blob_client = container_client.get_blob_client(blob_name)
39
+
40
+ # Blob herunterladen
41
+ blob_data = blob_client.download_blob()
42
+ blob_bytes = blob_data.readall()
43
+
44
+ # JSON-Bytes in einen Python-Datenobjekt umwandeln
45
+ json_text = blob_bytes.decode(encoding)
46
+ json_data = json.loads(json_text)
47
+
48
+ # Parameter "title" und "email" aus dem JSON-Datenobjekt extrahieren und zurückgeben
49
+ title = json_data.get("title", "")
50
+ email = json_data.get("email", "")
51
+
52
+ return title, email
53
+ except Exception as e:
54
+ print(f"Fehler beim Herunterladen und Verarbeiten der JSON-Datei: {str(e)}")
55
+ return None, None
56
+
57
+ def download_pdf_blob_as_text(storage_connection_string, container_name, blob_name):
58
+ try:
59
+ # Verbindung zum Blob-Dienst herstellen
60
+ blob_service_client = BlobServiceClient.from_connection_string(storage_connection_string)
61
+
62
+ # Container und Blob-Client erstellen
63
+ container_client = blob_service_client.get_container_client(container_name)
64
+ blob_client = container_client.get_blob_client(blob_name)
65
+
66
+ # Blob herunterladen und als Binärdaten speichern
67
+ blob_data = blob_client.download_blob()
68
+ pdf_bytes = blob_data.readall()
69
+
70
+ # PDF-Text extrahieren
71
+ pdf_text = ""
72
+ pdf_reader = PdfReader(io.BytesIO(pdf_bytes))
73
+ for page_num in range(len(pdf_reader.pages)):
74
+ page = pdf_reader.pages[page_num]
75
+ pdf_text += page.extract_text()
76
+
77
+ return pdf_text
78
+ except Exception as e:
79
+ print(f"Fehler beim Herunterladen und Konvertieren der Datei: {str(e)}")
80
+ return None
81
+
82
+ def load_job_data(job, job_params):
83
+ if not job:
84
+ try:
85
+ print("Hello there")
86
+ print(job_params["job"])
87
+ pdf_filename = job_params["job"]+".pdf"
88
+ json_filename = job_params["job"]+"_jsondata.json"
89
+ storage_connection_string = os_connection_string
90
+ container_name = "jobdescriptions" # Der Name des Blob-Containers
91
+ job = download_pdf_blob_as_text(storage_connection_string, container_name, pdf_filename)
92
+ job_params = download_and_parse_json_blob(storage_connection_string,container_name,json_filename)
93
+ return job, job_params, gr.Label.update("Evaluation for the job: "+job_params[0])
94
+ except:
95
+ gr.Error("An error occurred, the job description could not be loaded. Please contact the recruiter.")
96
+ return job, job_params, gr.Label.update("An error occurred and the job description could not be loaded. Please contact the recruiter.", color="red")
97
+ # print(job)
98
+ # print(job_params)
99
+
100
 
101
  def add_file(file, chat, job, resume):
102
  if file.name.endswith(".pdf"):
 
109
  text = f.read()
110
 
111
  if job:
112
+ print("im cv")
113
  chat += [["📄 " + file.name.split("/")[-1], None]]
114
  resume = text
115
+ # else:
116
+ # print("im job")
117
+ # chat += [["📄 " + file.name.split("/")[-1], "Thanks. Please upload the resume."]]
118
+ # job = text
119
 
120
  return chat, job, resume
121
 
 
124
  return "", history + [[message, None]]
125
 
126
 
127
+ def bot(history, job, resume, job_params):
128
+
129
+ if not resume or not job:
130
  yield history
131
  return
132
 
133
+ system = sys_prompt.format(job=job, resume=resume, n=10)
134
  messages = [{"role": "system", "content": system}]
135
  for user, assistant in history:
136
  if user:
 
150
  if len(chunk["choices"][0]["delta"]) != 0:
151
  history[-1][1] = history[-1][1] + chunk["choices"][0]["delta"]["content"]
152
  yield history
153
+ if history[-1][1] == "Thank you for conducting the evaluation! We will get back to you shortly.":
154
+ print("finished")
155
+ send_evaluation(history, job, resume, job_params)
156
  return
157
 
158
+ def send_evaluation(history, job, resume, job_params):
159
+
160
+ # Chatverlauf in einen Textstring umwandeln
161
+ chat_text = ""
162
+ for entry in history:
163
+ if entry[0]:
164
+ chat_text += "Applicant: " + entry[0] + "\n"
165
+ if entry[1]:
166
+ chat_text += "Chatbot: " + entry[1] + "\n"
167
+
168
+ # Einstellungen für den SMTP-Server
169
+ smtp_server = "smtp.gmail.com"
170
+ smtp_port = 587
171
+ smtp_username = "[email protected]"
172
+ smtp_password = os_mail_password
173
+
174
+ # Sender- und Empfänger-E-Mail-Adressen
175
+ sender_email = "[email protected]"
176
+ receiver_email = job_params[1]
177
+
178
+ ai_summary = "TEST Summary"
179
+ prompt = "You are a professional recruiter who has been given a CV and a job description and has created 10 questions based on that. The eventual applicant has entered his answers to the questions. Now you have to evaluate on the basis of the answers if the applicant fits the job in principle. This is the case when about 70percent of all questions have been answered satisfactorily and positively. Keep in mind that an answer must always be fact-based, so if, for example, the question asks for examples, the potential applicant must also give such examples. Please also provide details of which questions were answered positively and why."
180
+ res = openai.ChatCompletion.create(
181
+ model="gpt-4",
182
+ temperature=0.2,
183
+ messages=[
184
+ {
185
+ "role": "system",
186
+ "content": prompt,
187
+ },
188
+ {"role": "system", "content": "Job description: "+job+"; Resume: "+resume},
189
+ {"role": "system", "content": "Chathistory: "+chat_text},
190
+ ],
191
+ )
192
+ ai_summary = res.choices[0]["message"]["content"]
193
+ # E-Mail-Nachricht erstellen
194
+ subject = "Evaluation for the job: "+job_params[0]
195
+ message = f"""
196
+ Dear Recruiter,
197
+
198
+ Please find attached the complete chat history for this evaluation and resume.
199
+
200
+ The evaluation AI-supported summarized:
201
+
202
+ {ai_summary}
203
+
204
+ Sincerely,
205
+ Your Evaluation Tool
206
+ """
207
+
208
+ msg = MIMEMultipart()
209
+ msg['From'] = sender_email
210
+ msg['To'] = receiver_email
211
+ msg['Subject'] = subject
212
+ msg.attach(MIMEText(message, 'plain'))
213
+
214
+ # Chatverlauf in eine Textdatei schreiben
215
+ chat_file_path = "chat_history.txt"
216
+ with open(chat_file_path, 'w', encoding='utf-8') as chat_file:
217
+ chat_file.write(chat_text)
218
+
219
+ # Chatverlauf als Anhang hinzufügen
220
+ with open(chat_file_path, 'r', encoding='utf-8') as chat_file:
221
+ chat_attachment = MIMEText(chat_file.read(), _subtype='plain')
222
+ chat_attachment.add_header('Content-Disposition', 'attachment', filename='chat_history.txt')
223
+ msg.attach(chat_attachment)
224
+
225
+ # Resume-Bytes in eine TXT-Datei schreiben und als Anhang hinzufügen
226
+ resume_file = io.BytesIO()
227
+ resume_file.write(resume.encode('utf-8'))
228
+ resume_file.seek(0)
229
+ resume_attachment = MIMEText(resume_file.read().decode('utf-8'), _subtype='plain')
230
+ resume_attachment.add_header('Content-Disposition', 'attachment', filename='resume.txt')
231
+ msg.attach(resume_attachment)
232
+
233
+ # SMTP-Verbindung herstellen und E-Mail senden
234
+ try:
235
+ server = smtplib.SMTP(smtp_server, smtp_port)
236
+ server.starttls()
237
+ server.login(smtp_username, smtp_password)
238
+ text = msg.as_string()
239
+ server.sendmail(sender_email, receiver_email, text)
240
+ server.quit()
241
+ print("E-Mail wurde erfolgreich gesendet.")
242
+ except Exception as e:
243
+ print("Fehler beim Senden der E-Mail:", str(e))
244
 
245
  css = "footer {visibility: hidden} #component-0{height: 90vh !important} #chatbot{height: 85vh !important}}"
246
 
247
  with gr.Blocks(css=css) as app:
248
+ job_params = gr.JSON({}, visible=False, label="URL Params")
249
  job = gr.State("")
250
  resume = gr.State("")
251
+ gr.Markdown(
252
+ f"<div style='display: flex; justify-content: space-between;align-items: center;margin-bottom: 1rem' ><h1>CV Evaluation</h1><img width='150' src='https://www.workgenius.com/wp-content/uploads/2023/03/WorkGenius_navy-1.svg' alt='WorkGeniusLogo' /></div>"
253
+ )
254
+ input_test = gr.Label("An error occurred and the job description could not be loaded. Please contact the recruiter.", show_label=False)
255
+ app.load(load_job_data,[job, job_params], [job, job_params, input_test], _js=get_window_url_params)
256
  chat = gr.Chatbot(
257
+ [[None, "Please upload your resume to begin the evaluation process. After uploading, approximately 10 questions will be asked to determine if the position is a good fit for you. The entire process takes about 10 to 15 minutes."]], height=600, elem_id="chatbot"
258
  )
259
  with gr.Row():
260
  clr = gr.Button("Clear", scale=0)
261
  msg = gr.Textbox(lines=1, show_label=False, scale=1)
262
  file = gr.UploadButton("Browse", file_types=[".pdf", ".txt"], scale=0)
263
  msg.submit(user, [msg, chat], [msg, chat], queue=False).then(
264
+ bot, [chat, job, resume, job_params], chat
265
  )
266
  file.upload(
267
  add_file, [file, chat, job, resume], [chat, job, resume], queue=False
268
+ ).then(bot, [chat, job, resume, job_params], chat)
269
  clr.click(lambda: None, None, chat, queue=False)
270
 
271
  app.queue()