Vincent Claes
commited on
Commit
•
df97380
1
Parent(s):
dfa8a30
preprocess resume
Browse files- app.py +81 -51
- preprocess.py +44 -0
- scripts/convert-csv-to-parquet.py +1 -1
- scripts/jobfixers.csv +0 -0
- scripts/preprocess-vacancies.py +4 -1
app.py
CHANGED
@@ -9,23 +9,35 @@ from langchain.chat_models import ChatOpenAI
|
|
9 |
import recruiting_assistant # Assuming this module provides the required reversed functionality
|
10 |
import skills
|
11 |
import utils
|
|
|
12 |
|
13 |
llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"])
|
14 |
|
15 |
|
16 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
url = f"https://3jxjznzonb.execute-api.eu-west-1.amazonaws.com/dev/prediction" # vervang met uw API-eindpunt
|
18 |
headers = {
|
19 |
"Content-Type": "application/json",
|
20 |
"x-api-key": os.environ["API_KEY"],
|
21 |
} # pas headers indien nodig aan
|
22 |
response = requests.post(
|
23 |
-
url,
|
|
|
|
|
24 |
)
|
25 |
response_data = response.json()
|
|
|
26 |
|
27 |
-
|
28 |
-
|
|
|
|
|
29 |
if isinstance(prediction, list):
|
30 |
# Convert prediction to HTML table
|
31 |
html_table = "<table>"
|
@@ -52,63 +64,32 @@ def search(resume):
|
|
52 |
skills_match, "skills_match_predicted"
|
53 |
)
|
54 |
for skill in skills_match_predicted:
|
55 |
-
vacancy = vacancy.lower().replace(
|
|
|
|
|
|
|
56 |
formatted_vacancy = vacancy.replace(".,", "<br/>")
|
57 |
formatted_vacancy = f"VACATURE {i + 1}:<br/>{formatted_vacancy}"
|
58 |
html_table += f"<tr><td>{formatted_vacancy}</td><td>{len(skills_match_predicted)}</td><td>{', '.join(skills_match_predicted)}</td></tr>"
|
59 |
html_table += "</table>"
|
60 |
return html_table
|
61 |
|
62 |
-
return "niets teruggevonden ..."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
examples = [
|
65 |
-
"""
|
66 |
-
Naam: John Doe
|
67 |
-
Adres: Parkstraat 123, 1000 Stadsveld
|
68 |
-
Telefoon: +31 6 1234 5678
|
69 |
-
E-mail: john.doe@email.com
|
70 |
-
Geboortedatum: 15 juli 1985
|
71 |
-
Nationaliteit: Nederlandse
|
72 |
-
|
73 |
-
Profiel:
|
74 |
-
Een toegewijde en bekwame koeltechnieker met 8 jaar ervaring in het ontwerpen, installeren, onderhouden en repareren van koelsystemen. Technisch onderlegd en bekend met verschillende koeltechnieken. Een probleemoplosser die snel storingen kan diagnosticeren en efficiënte oplossingen kan implementeren. Goed in teamverband en klantgericht.
|
75 |
-
|
76 |
-
Werkervaring:
|
77 |
-
|
78 |
-
Service Technicus bij KoelTech B.V. - januari 2018 tot heden
|
79 |
-
|
80 |
-
Verantwoordelijk voor het installeren en onderhouden van commerciële en industriële koelsystemen.
|
81 |
-
Diagnose stellen en repareren van storingen in koelapparatuur.
|
82 |
-
Uitvoeren van preventief onderhoud om de prestaties van koelinstallaties te optimaliseren.
|
83 |
-
Klantgerichte aanpak om vragen en problemen van klanten op te lossen.
|
84 |
-
Assistent Koeltechnieker bij CoolAir Installaties - maart 2014 tot december 2017
|
85 |
-
|
86 |
-
Betrokken bij het ontwerp en de installatie van nieuwe koelsystemen in residentiële gebouwen.
|
87 |
-
Uitvoeren van druk- en temperatuurmetingen om de juiste werking van de systemen te waarborgen.
|
88 |
-
Oplossen van technische problemen en het vervangen van defecte onderdelen.
|
89 |
-
Het trainen van klanten in het juiste gebruik en onderhoud van koelapparatuur.
|
90 |
-
Opleiding:
|
91 |
-
|
92 |
-
MBO Koeltechniek - Technische School Stadsveld - 2014
|
93 |
-
Certificaat Veilig werken met koelinstallaties - Koelacademie Nederland - 2014
|
94 |
-
Vaardigheden:
|
95 |
-
|
96 |
-
Uitgebreide kennis van verschillende koeltechnieken en -systemen.
|
97 |
-
Sterk technisch inzicht en probleemoplossend vermogen.
|
98 |
-
Bekend met veiligheidsvoorschriften en -procedures in de koeltechniek.
|
99 |
-
Goede communicatieve vaardigheden om effectief te kunnen samenwerken met collega's en klanten.
|
100 |
-
Bekwaamheid in het lezen van technische tekeningen en schema's.
|
101 |
-
Talen:
|
102 |
-
|
103 |
-
Nederlands: Moedertaal
|
104 |
-
Engels: Goed
|
105 |
-
Referenties:
|
106 |
-
Beschikbaar op verzoek.
|
107 |
-
|
108 |
-
Opmerking: Dit CV bevat fictieve gegevens en dient alleen ter illustratie. Gebruik het als een sjabloon en vervang de gegevens door je eigen informatie bij het maken van een CV.
|
109 |
-
""",
|
110 |
"""
|
111 |
Jan De Vries
|
|
|
|
|
112 |
Adres: Hoofdstraat 123, 1000 Brussel
|
113 |
Telefoon: +32 123 456 789
|
114 |
E-mail: jan.devries@email.com
|
@@ -155,6 +136,8 @@ examples = [
|
|
155 |
""",
|
156 |
"""
|
157 |
Johannes van der Meer
|
|
|
|
|
158 |
Adres: Klaverstraat 45, 3000 Leiden
|
159 |
Telefoon: +31 6 1234 5678
|
160 |
E-mail: johannesvdm@email.nl
|
@@ -204,7 +187,54 @@ examples = [
|
|
204 |
Engels (Vloeiend)
|
205 |
Frans (Basis)
|
206 |
|
|
|
207 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
]
|
209 |
|
210 |
demo = gr.Blocks(theme=gr.themes.Soft())
|
|
|
9 |
import recruiting_assistant # Assuming this module provides the required reversed functionality
|
10 |
import skills
|
11 |
import utils
|
12 |
+
import preprocess
|
13 |
|
14 |
llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"])
|
15 |
|
16 |
|
17 |
+
def preprocess_resume(llm, resume) -> str:
|
18 |
+
result = preprocess.preprocess_resume(llm, resume)
|
19 |
+
resume_preprocess = result["resume_preprocess"]
|
20 |
+
return resume_preprocess
|
21 |
+
|
22 |
+
|
23 |
+
def call_endpoint(resume_preprocessed):
|
24 |
url = f"https://3jxjznzonb.execute-api.eu-west-1.amazonaws.com/dev/prediction" # vervang met uw API-eindpunt
|
25 |
headers = {
|
26 |
"Content-Type": "application/json",
|
27 |
"x-api-key": os.environ["API_KEY"],
|
28 |
} # pas headers indien nodig aan
|
29 |
response = requests.post(
|
30 |
+
url,
|
31 |
+
headers=headers,
|
32 |
+
data=json.dumps({"text": resume_preprocessed, "limit": 10}),
|
33 |
)
|
34 |
response_data = response.json()
|
35 |
+
return response_data
|
36 |
|
37 |
+
|
38 |
+
def postprocess_vancy(vacancies, resume):
|
39 |
+
if "prediction" in vacancies:
|
40 |
+
prediction = vacancies["prediction"]
|
41 |
if isinstance(prediction, list):
|
42 |
# Convert prediction to HTML table
|
43 |
html_table = "<table>"
|
|
|
64 |
skills_match, "skills_match_predicted"
|
65 |
)
|
66 |
for skill in skills_match_predicted:
|
67 |
+
vacancy = vacancy.lower().replace(
|
68 |
+
skill.lower(),
|
69 |
+
f'<span style="background-color: yellow;">{skill}</span>',
|
70 |
+
)
|
71 |
formatted_vacancy = vacancy.replace(".,", "<br/>")
|
72 |
formatted_vacancy = f"VACATURE {i + 1}:<br/>{formatted_vacancy}"
|
73 |
html_table += f"<tr><td>{formatted_vacancy}</td><td>{len(skills_match_predicted)}</td><td>{', '.join(skills_match_predicted)}</td></tr>"
|
74 |
html_table += "</table>"
|
75 |
return html_table
|
76 |
|
77 |
+
return "niets teruggevonden, probeer nogmaals ..."
|
78 |
+
|
79 |
+
|
80 |
+
def search(resume):
|
81 |
+
original_resume = resume
|
82 |
+
resume_preprocessed = preprocess_resume(llm, resume)
|
83 |
+
vacancies = call_endpoint(resume_preprocessed)
|
84 |
+
vacancies_formatted = postprocess_vancy(vacancies, original_resume)
|
85 |
+
return vacancies_formatted
|
86 |
+
|
87 |
|
88 |
examples = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
"""
|
90 |
Jan De Vries
|
91 |
+
Magazijnier
|
92 |
+
|
93 |
Adres: Hoofdstraat 123, 1000 Brussel
|
94 |
Telefoon: +32 123 456 789
|
95 |
E-mail: jan.devries@email.com
|
|
|
136 |
""",
|
137 |
"""
|
138 |
Johannes van der Meer
|
139 |
+
Chef-kok
|
140 |
+
|
141 |
Adres: Klaverstraat 45, 3000 Leiden
|
142 |
Telefoon: +31 6 1234 5678
|
143 |
E-mail: johannesvdm@email.nl
|
|
|
187 |
Engels (Vloeiend)
|
188 |
Frans (Basis)
|
189 |
|
190 |
+
""",
|
191 |
"""
|
192 |
+
Naam: John Doe
|
193 |
+
Koeltechnieker
|
194 |
+
|
195 |
+
Adres: Parkstraat 123, 1000 Stadsveld
|
196 |
+
Telefoon: +31 6 1234 5678
|
197 |
+
E-mail: john.doe@email.com
|
198 |
+
Geboortedatum: 15 juli 1985
|
199 |
+
Nationaliteit: Nederlandse
|
200 |
+
|
201 |
+
Profiel:
|
202 |
+
Een toegewijde en bekwame koeltechnieker met 8 jaar ervaring in het ontwerpen, installeren, onderhouden en repareren van koelsystemen. Technisch onderlegd en bekend met verschillende koeltechnieken. Een probleemoplosser die snel storingen kan diagnosticeren en efficiënte oplossingen kan implementeren. Goed in teamverband en klantgericht.
|
203 |
+
|
204 |
+
Werkervaring:
|
205 |
+
|
206 |
+
Service Technicus bij KoelTech B.V. - januari 2018 tot heden
|
207 |
+
|
208 |
+
Verantwoordelijk voor het installeren en onderhouden van commerciële en industriële koelsystemen.
|
209 |
+
Diagnose stellen en repareren van storingen in koelapparatuur.
|
210 |
+
Uitvoeren van preventief onderhoud om de prestaties van koelinstallaties te optimaliseren.
|
211 |
+
Klantgerichte aanpak om vragen en problemen van klanten op te lossen.
|
212 |
+
Assistent Koeltechnieker bij CoolAir Installaties - maart 2014 tot december 2017
|
213 |
+
|
214 |
+
Betrokken bij het ontwerp en de installatie van nieuwe koelsystemen in residentiële gebouwen.
|
215 |
+
Uitvoeren van druk- en temperatuurmetingen om de juiste werking van de systemen te waarborgen.
|
216 |
+
Oplossen van technische problemen en het vervangen van defecte onderdelen.
|
217 |
+
Het trainen van klanten in het juiste gebruik en onderhoud van koelapparatuur.
|
218 |
+
Opleiding:
|
219 |
+
|
220 |
+
MBO Koeltechniek - Technische School Stadsveld - 2014
|
221 |
+
Certificaat Veilig werken met koelinstallaties - Koelacademie Nederland - 2014
|
222 |
+
Vaardigheden:
|
223 |
+
|
224 |
+
Uitgebreide kennis van verschillende koeltechnieken en -systemen.
|
225 |
+
Sterk technisch inzicht en probleemoplossend vermogen.
|
226 |
+
Bekend met veiligheidsvoorschriften en -procedures in de koeltechniek.
|
227 |
+
Goede communicatieve vaardigheden om effectief te kunnen samenwerken met collega's en klanten.
|
228 |
+
Bekwaamheid in het lezen van technische tekeningen en schema's.
|
229 |
+
Talen:
|
230 |
+
|
231 |
+
Nederlands: Moedertaal
|
232 |
+
Engels: Goed
|
233 |
+
Referenties:
|
234 |
+
Beschikbaar op verzoek.
|
235 |
+
|
236 |
+
Opmerking: Dit CV bevat fictieve gegevens en dient alleen ter illustratie. Gebruik het als een sjabloon en vervang de gegevens door je eigen informatie bij het maken van een CV.
|
237 |
+
""",
|
238 |
]
|
239 |
|
240 |
demo = gr.Blocks(theme=gr.themes.Soft())
|
preprocess.py
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from langchain import LLMChain
|
4 |
+
from langchain.chains import SequentialChain
|
5 |
+
from langchain.chat_models import ChatOpenAI
|
6 |
+
from langchain.prompts import ChatPromptTemplate
|
7 |
+
|
8 |
+
|
9 |
+
def preprocess_resume(llm, resume) -> SequentialChain:
|
10 |
+
|
11 |
+
template_get_skills_intersection = """
|
12 |
+
|
13 |
+
```
|
14 |
+
{resume}
|
15 |
+
```
|
16 |
+
|
17 |
+
Can you summarize the above resume in the template below and fill in eveything that is delimited by '<' '>'?
|
18 |
+
Return only the filled in template nothing else.
|
19 |
+
|
20 |
+
position: < the job name or role >
|
21 |
+
location: < where does the person live >
|
22 |
+
description: < the description or the person's job or role and description of it's experience. >
|
23 |
+
profile: < can you describe the sector the person is working in >
|
24 |
+
competences: < can you describe some hard skills of the person>
|
25 |
+
"""
|
26 |
+
|
27 |
+
prompt_get_skills_intersection = ChatPromptTemplate.from_template(
|
28 |
+
template=template_get_skills_intersection
|
29 |
+
)
|
30 |
+
skills_match_chain = LLMChain(
|
31 |
+
llm=llm,
|
32 |
+
prompt=prompt_get_skills_intersection,
|
33 |
+
output_key="resume_preprocess",
|
34 |
+
)
|
35 |
+
|
36 |
+
chain = SequentialChain(
|
37 |
+
chains=[skills_match_chain],
|
38 |
+
input_variables=["resume"],
|
39 |
+
output_variables=[
|
40 |
+
skills_match_chain.output_key,
|
41 |
+
],
|
42 |
+
verbose=False,
|
43 |
+
)
|
44 |
+
return chain({"resume": resume})
|
scripts/convert-csv-to-parquet.py
CHANGED
@@ -3,4 +3,4 @@ import pathlib
|
|
3 |
|
4 |
current_directory = pathlib.Path(__file__).resolve().parent
|
5 |
df = pd.read_csv(current_directory / "vacancies-full-dataset-jobfixers.csv")
|
6 |
-
df.to_parquet(current_directory / "vacancies-full-dataset-jobfixers.parquet")
|
|
|
3 |
|
4 |
current_directory = pathlib.Path(__file__).resolve().parent
|
5 |
df = pd.read_csv(current_directory / "vacancies-full-dataset-jobfixers.csv")
|
6 |
+
df.to_parquet(current_directory / "vacancies-full-dataset-jobfixers.parquet")
|
scripts/jobfixers.csv
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
scripts/preprocess-vacancies.py
CHANGED
@@ -1,9 +1,12 @@
|
|
1 |
import pandas as pd
|
2 |
import pathlib
|
|
|
3 |
current_directory = pathlib.Path(__file__).resolve().parent
|
4 |
df = pd.read_csv(current_directory / "vacancies.csv")
|
5 |
df = df[["Vacancy"]]
|
|
|
6 |
df = df.drop_duplicates(subset=["Vacancy"])
|
|
|
7 |
# Remove all the new lines from each cell of the 'Resume' column
|
8 |
df["Vacancy"] = df["Vacancy"].replace("\n", ".,", regex=True)
|
9 |
-
df.to_csv(current_directory/"jobfixers.csv", index=False, header=False)
|
|
|
1 |
import pandas as pd
|
2 |
import pathlib
|
3 |
+
|
4 |
current_directory = pathlib.Path(__file__).resolve().parent
|
5 |
df = pd.read_csv(current_directory / "vacancies.csv")
|
6 |
df = df[["Vacancy"]]
|
7 |
+
print(df.shape)
|
8 |
df = df.drop_duplicates(subset=["Vacancy"])
|
9 |
+
print(df.shape)
|
10 |
# Remove all the new lines from each cell of the 'Resume' column
|
11 |
df["Vacancy"] = df["Vacancy"].replace("\n", ".,", regex=True)
|
12 |
+
df.to_csv(current_directory / "jobfixers.csv", index=False, header=False)
|