import json
import os
from concurrent.futures import ThreadPoolExecutor
import gradio as gr
import requests
from langchain.chat_models import ChatOpenAI
import utils
from prompts import preprocess, recruiting_assistant, matches, intro
llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"])
MAX_SKILLS = 10
def preprocess_resume(llm, resume) -> str:
result = preprocess.preprocess_resume(llm, resume)
resume_preprocess = result["resume_preprocess"]
return resume_preprocess
def call_endpoint(resume_preprocessed):
url = f"https://3jxjznzonb.execute-api.eu-west-1.amazonaws.com/dev/prediction" # vervang met uw API-eindpunt
headers = {
"Content-Type": "application/json",
"x-api-key": os.environ["API_KEY"],
} # pas headers indien nodig aan
response = requests.post(
url,
headers=headers,
data=json.dumps({"text": resume_preprocessed, "limit": 10}),
)
response_data = response.json()
return response_data
def postprocess_vancy(vacancies, resume):
if "prediction" in vacancies:
prediction = vacancies["prediction"]
if isinstance(prediction, list):
# Convert prediction to HTML table
html_table = "
"
# Add table headers
html_table += "Vacancy | Match |
"
# Prepare a list to hold the futures
futures = []
matches_score_tuples = []
# Create a ThreadPoolExecutor
with ThreadPoolExecutor() as executor:
for i, vacancy in enumerate(prediction):
# Schedule the get_skills_match function to run and store the future
future = executor.submit(
matches.get_skills_match, llm, vacancy, resume
)
futures.append((i, vacancy, future))
# Collect the results as they become available
for i, vacancy, future in futures:
skills_match = future.result()
skills_match_predicted = utils.get_json_list_from_result(
skills_match, "skills_match_predicted"
)
print("getting matched skills ...")
counter = 0
matched_skills = []
for element in skills_match_predicted:
if element["resume_index"] > 0 and element["vacancy_index"] > 0:
counter += 1
if counter > MAX_SKILLS:
break
matched_skills.append(element["content"])
# matched_skills = [
# element["content"]
# for element in skills_match_predicted
# if element["resume_index"] > 0 and element["vacancy_index"] > 0
# ]
for element in matched_skills:
vacancy = vacancy.lower().replace(
element.lower(),
f'{element}',
)
matches_score_tuples.append(
(vacancy, matched_skills, len(matched_skills))
)
print("sorting matches based on the score.")
matches_score_tuples.sort(key=lambda x: x[-1], reverse=True)
print("constructing html table.")
for i, element in enumerate(matches_score_tuples, 1):
vacancy, matched_skills, score = element
vacancy_formatted = vacancy.replace(".,", "
")
vacancy_formatted = f"VACATURE {i}:
{vacancy_formatted}"
matches_html = "
- ".join(matched_skills)
resume_matched_formatted = f"Score: {score}
-{matches_html}"
html_table += f"{vacancy_formatted} | {resume_matched_formatted} |
"
html_table += "
"
return html_table
return "niets teruggevonden, probeer nogmaals ..."
def search(resume):
original_resume = resume
resume_preprocessed = preprocess_resume(llm, resume)
vacancies = call_endpoint(resume_preprocessed)
vacancies_formatted = postprocess_vancy(vacancies, original_resume)
return vacancies_formatted
def get_intro_jobseeker(vacancy, resume):
intro_ = intro.get_intro_jobseeker(llm, vacancy, resume)
return intro_["intro"]
def get_intro_jobissuer(vacancy, resume):
intro_ = intro.get_intro_jobissuer(llm, vacancy, resume)
return intro_["intro"]
def get_intro(vacancy, resume):
jobseeker = get_intro_jobseeker(vacancy, resume)
jobissuer = get_intro_jobissuer(vacancy, resume)
return f"""
EMAIL KANDIDAAT:
=================
{jobseeker}
EMAIL BEDRIJF:
===============
{jobissuer}
"""
examples = [
"""
Jan De Vries
Magazijnier
Adres: Hoofdstraat 123, 1000 Brussel
Telefoon: +32 123 456 789
E-mail: jan.devries@email.com
Ervaren magazijnier met meer dan 7 jaar ervaring in het beheer van auto-onderdelen in grootschalige distributiecentra. Ik zoek een positie waar ik mijn expertise in voorraadbeheer, orderverwerking en teammanagement kan toepassen om de efficiëntie en productiviteit van het magazijn te verbeteren.
Werkervaring
Magazijnier, AutoParts Warehouse, Gent
Januari 2017 - Heden
Verantwoordelijk voor de ontvangst en verwerking van inkomende leveringen.
Coördinatie van de dagelijkse pick- en pack-activiteiten.
Beheer van een team van 5 medewerkers om te zorgen voor tijdige leveringen.
Implementatie van een nieuw voorraadsysteem wat resulteerde in een vermindering van 15% in overstock.
Assistent Magazijnier, CarParts Distributie, Antwerpen
Juni 2014 - December 2016
Geholpen bij het organiseren van het magazijn voor optimale opslag.
Bijgehouden van voorraadniveaus en tijdig bestellingen geplaatst.
Geholpen bij het trainen van nieuwe medewerkers.
Opleiding
Diploma Secundair Onderwijs, Technisch Onderwijs, VTI Brussel
2010 - 2013
Vaardigheden
Grondige kennis van auto-onderdelen.
Ervaren in het gebruik van voorraadbeheersystemen.
Uitstekende organisatorische en multitasking-vaardigheden.
Sterke communicatieve vaardigheden en teamspeler.
Bekwaam in het gebruik van heftrucks en andere magazijnapparatuur.
Talen
Nederlands (Moedertaal)
Engels (Vloeiend)
Frans (Basis)
Certificaten
Heftruckcertificaat, VDAB, 2014
""",
"""
Johannes van der Meer
Chef-kok
Adres: Klaverstraat 45, 3000 Leiden
Telefoon: +31 6 1234 5678
E-mail: johannesvdm@email.nl
Gepassioneerde en ervaren chef-kok met meer dan 12 jaar ervaring in zowel traditionele Nederlandse als internationale keukens. Bekend om het creëren van innovatieve en heerlijke gerechten met een focus op verse en lokale ingrediënten. Sterke leiderschapsvaardigheden en een bewezen vermogen om keukenteams te leiden en te trainen.
WERKERVARING
Executive Chef – Luxe Restaurant De Zon, Amsterdam
Januari 2019 - Heden
Verantwoordelijk voor het dagelijks beheer van de keuken.
Ontwikkeling en implementatie van nieuwe menu's volgens seizoensgebonden beschikbaarheid.
Training en begeleiding van een team van 15 koks en keukenpersoneel.
Sous Chef – Brasserie Lente, Utrecht
Juni 2013 - December 2018
Assisteerde de hoofdchef bij het plannen van menu's en het organiseren van speciale evenementen.
Beheerde voedselvoorraden en budgetten.
Onderhield relaties met leveranciers en zorgde voor de hoogste kwaliteit ingrediënten.
Chef de Partie – Restaurant De Oude Molen, Den Haag
Augustus 2008 - Mei 2013
Gespecialiseerd in sauzen en was verantwoordelijk voor de sauzen- en soepensectie.
Assisteerde bij de voorbereiding van dagelijkse specials.
Hielp bij het opleiden van junior koks.
OPLEIDING
Diploma Culinaire Kunst, Culinaire School van Amsterdam
2005 - 2007
Vakdiploma Kok, ROC Leiden
2003 - 2005
VAARDIGHEDEN
Uitstekende kooktechnieken
Menuontwikkeling
Teamleiderschap
Voedselveiligheid en hygiëne
Voorraadbeheer
Budgetbeheer
TALEN
Nederlands (Moedertaal)
Engels (Vloeiend)
Frans (Basis)
""",
"""
Naam: John Doe
Koeltechnieker
Adres: Parkstraat 123, 1000 Stadsveld
Telefoon: +31 6 1234 5678
E-mail: john.doe@email.com
Geboortedatum: 15 juli 1985
Nationaliteit: Nederlandse
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.
Werkervaring:
Service Technicus bij KoelTech B.V. - januari 2018 tot heden
Verantwoordelijk voor het installeren en onderhouden van commerciële en industriële koelsystemen.
Diagnose stellen en repareren van storingen in koelapparatuur.
Uitvoeren van preventief onderhoud om de prestaties van koelinstallaties te optimaliseren.
Klantgerichte aanpak om vragen en problemen van klanten op te lossen.
Assistent Koeltechnieker bij CoolAir Installaties - maart 2014 tot december 2017
Betrokken bij het ontwerp en de installatie van nieuwe koelsystemen in residentiële gebouwen.
Uitvoeren van druk- en temperatuurmetingen om de juiste werking van de systemen te waarborgen.
Oplossen van technische problemen en het vervangen van defecte onderdelen.
Het trainen van klanten in het juiste gebruik en onderhoud van koelapparatuur.
Opleiding:
MBO Koeltechniek - Technische School Stadsveld - 2014
Certificaat Veilig werken met koelinstallaties - Koelacademie Nederland - 2014
Vaardigheden:
Uitgebreide kennis van verschillende koeltechnieken en -systemen.
Sterk technisch inzicht en probleemoplossend vermogen.
Bekend met veiligheidsvoorschriften en -procedures in de koeltechniek.
Goede communicatieve vaardigheden om effectief te kunnen samenwerken met collega's en klanten.
Bekwaamheid in het lezen van technische tekeningen en schema's.
Talen:
Nederlands: Moedertaal
Engels: Goed
Referenties:
Beschikbaar op verzoek.
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.
""",
]
demo = gr.Blocks(theme=gr.themes.Soft())
with demo:
with gr.Group():
with gr.Box():
with gr.Row(elem_id="prompt-container").style(
mobile_collapse=False, equal_height=True
):
with gr.Column():
text_cv = gr.Textbox(
lines=7,
label="1. Voer een CV in en krijg relevante vacatures terug.",
)
b1 = gr.Button("Zoek Vacatures", variant='primary', size="sm")
html_search_result = gr.HTML(
label="Top vacatures gevonden in de database",
)
b1.click(search, inputs=text_cv, outputs=html_search_result)
gr.Markdown(
"""
"""
)
text_vacature = gr.Textbox(
label="2. Selecteer een geschikte vacature voor deze CV, plak deze in het tekstveld hieronder en krijg een relevante intro.",
lines=7,
)
b2 = gr.Button("Schrijf Intro", variant='primary', size="sm")
gr.Markdown(
"""
"""
)
text_intro = gr.Textbox(
label="3. Introductie E-mail",
lines=7,
)
b2.click(
get_intro,
inputs=[text_vacature, text_cv],
outputs=[text_intro],
)
gr.Markdown(
"""
"""
)
gr.Examples(
examples=examples,
fn=search,
inputs=text_cv,
outputs=html_search_result,
cache_examples=False,
)
demo.launch()