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 += "" # 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"" html_table += "
VacancyMatch
{vacancy_formatted}{resume_matched_formatted}
" 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()