Vincent Claes commited on
Commit
237ec40
1 Parent(s): a1372cb

jobfixers add matching score + css template)

Browse files
Files changed (4) hide show
  1. app.py +28 -38
  2. recruiting_assistant.py +2 -1
  3. scripts/scrape_website.py +9 -10
  4. skills.py +42 -2
app.py CHANGED
@@ -1,5 +1,7 @@
1
  import json
2
  import os
 
 
3
  import gradio as gr
4
  import requests
5
  from langchain.chat_models import ChatOpenAI
@@ -17,7 +19,9 @@ def search(resume):
17
  "Content-Type": "application/json",
18
  "x-api-key": os.environ["API_KEY"],
19
  } # pas headers indien nodig aan
20
- response = requests.post(url, headers=headers, data=json.dumps({"text": resume, "limit":3}))
 
 
21
  response_data = response.json()
22
 
23
  if "prediction" in response_data:
@@ -27,46 +31,32 @@ def search(resume):
27
  html_table = "<table>"
28
 
29
  # Add table headers
30
- html_table += "<tr><th>Vacancy</th><th>Score</th><th>Skills Match</th><th>Skills Missing</th></tr>"
31
-
32
- for i, vacancy in enumerate(prediction):
33
- (
34
- score,
35
- skills_intersection,
36
- skills_not_in_intersection,
37
- ) = get_skills_score(vacancy=vacancy, resume=resume)
38
- # Voeg een nieuwe regel toe na elke '.' en voeg "Vacature <volgnummer>:\n" toe voor elk item
39
- updated_item = f"VACATURE {i + 1}: {vacancy}"
40
- html_table += f"<tr><td>{updated_item}</td><td>{score}</td><td>{skills_intersection}</td><td>{skills_not_in_intersection}</td></tr>"
41
- html_table += "</table>"
42
- return html_table
43
 
44
- return "niets teruggevonden ..."
 
45
 
 
 
 
 
 
 
 
 
46
 
47
- def get_skills_score(vacancy, resume):
48
- chain = skills.get_skills_chain(llm=llm)
49
- result = chain({"vacancy": vacancy, "resume": resume})
50
-
51
- vacancy_skills_predicted = utils.get_json_list_from_result(
52
- result, "vacancy_skills_predicted"
53
- )
54
- resume_skills_predicted = utils.get_json_list_from_result(
55
- result, "resume_skills_predicted"
56
- )
57
-
58
- skills_intersection = utils.get_intersection(
59
- vacancy_skills_predicted, resume_skills_predicted
60
- )
61
- skills_not_in_intersection = utils.not_in_intersection(
62
- vacancy_skills_predicted, resume_skills_predicted
63
- )
64
- match_score = utils.match(
65
- present_features=skills_intersection,
66
- not_present_features=skills_not_in_intersection,
67
- )
68
- return match_score, skills_intersection, skills_not_in_intersection
69
 
 
70
 
71
  examples = [
72
  """
@@ -116,7 +106,7 @@ examples = [
116
  """
117
  ]
118
 
119
- demo = gr.Blocks()
120
 
121
  with demo:
122
  with gr.Group():
 
1
  import json
2
  import os
3
+ from concurrent.futures import ThreadPoolExecutor
4
+
5
  import gradio as gr
6
  import requests
7
  from langchain.chat_models import ChatOpenAI
 
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, headers=headers, data=json.dumps({"text": resume, "limit": 7})
24
+ )
25
  response_data = response.json()
26
 
27
  if "prediction" in response_data:
 
31
  html_table = "<table>"
32
 
33
  # Add table headers
34
+ html_table += "<tr><th>Vacancy</th><th>Score</th><th>Skills Match</th></tr>"
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ # Prepare a list to hold the futures
37
+ futures = []
38
 
39
+ # Create a ThreadPoolExecutor
40
+ with ThreadPoolExecutor() as executor:
41
+ for i, vacancy in enumerate(prediction):
42
+ # Schedule the get_skills_match function to run and store the future
43
+ future = executor.submit(
44
+ skills.get_skills_match, llm, vacancy, resume
45
+ )
46
+ futures.append((i, vacancy, future))
47
 
48
+ # Collect the results as they become available
49
+ for i, vacancy, future in futures:
50
+ skills_match = future.result()
51
+ skills_match_predicted = utils.get_json_list_from_result(
52
+ skills_match, "skills_match_predicted"
53
+ )
54
+ updated_item = f"VACATURE {i + 1}: {vacancy}"
55
+ html_table += f"<tr><td>{updated_item}</td><td>{len(skills_match_predicted)}</td><td>{skills_match_predicted}</td></tr>"
56
+ html_table += "</table>"
57
+ return html_table
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
+ return "niets teruggevonden ..."
60
 
61
  examples = [
62
  """
 
106
  """
107
  ]
108
 
109
+ demo = gr.Blocks(theme=gr.themes.Soft())
110
 
111
  with demo:
112
  with gr.Group():
recruiting_assistant.py CHANGED
@@ -1,8 +1,9 @@
1
  import json
2
  import os
 
 
3
  from langchain.chat_models import ChatOpenAI
4
  from langchain.prompts import ChatPromptTemplate
5
- from langchain.chains import LLMChain, SequentialChain
6
 
7
  llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"])
8
 
 
1
  import json
2
  import os
3
+
4
+ from langchain.chains import LLMChain, SequentialChain
5
  from langchain.chat_models import ChatOpenAI
6
  from langchain.prompts import ChatPromptTemplate
 
7
 
8
  llm = ChatOpenAI(temperature=0.0, openai_api_key=os.environ["OPENAI"])
9
 
scripts/scrape_website.py CHANGED
@@ -1,21 +1,20 @@
 
1
  import os
 
 
 
2
  import openai
3
  import pandas as pd
4
- import json
5
  from selenium import webdriver
6
- from selenium.webdriver.chrome.service import Service
7
- from webdriver_manager.chrome import ChromeDriverManager
8
- from selenium.webdriver.common.by import By
9
  from selenium.common.exceptions import (
10
- NoSuchElementException,
11
- TimeoutException,
12
  WebDriverException,
13
  )
14
- from selenium.webdriver.support.ui import WebDriverWait
 
15
  from selenium.webdriver.support import expected_conditions as EC
16
- from bs4 import BeautifulSoup
17
- from urllib.parse import urlparse
18
- import time
19
 
20
  # Set up OpenAI API
21
  openai.api_key = os.getenv("OPENAI")
 
1
+ import json
2
  import os
3
+ import time
4
+ from urllib.parse import urlparse
5
+
6
  import openai
7
  import pandas as pd
8
+ from bs4 import BeautifulSoup
9
  from selenium import webdriver
 
 
 
10
  from selenium.common.exceptions import (
 
 
11
  WebDriverException,
12
  )
13
+ from selenium.webdriver.chrome.service import Service
14
+ from selenium.webdriver.common.by import By
15
  from selenium.webdriver.support import expected_conditions as EC
16
+ from selenium.webdriver.support.ui import WebDriverWait
17
+ from webdriver_manager.chrome import ChromeDriverManager
 
18
 
19
  # Set up OpenAI API
20
  openai.api_key = os.getenv("OPENAI")
skills.py CHANGED
@@ -5,7 +5,8 @@ from langchain.prompts import ChatPromptTemplate
5
 
6
  def get_vacancy_skills_chain(llm) -> LLMChain:
7
  template_vacancy_get_skills = """
8
- Given the following vacancy delimited by three backticks, retrieve the skills that are requested.
 
9
  Return the skills as a JSON list on 1 line, do not add newlines or any other text.
10
 
11
  ```
@@ -24,7 +25,8 @@ def get_vacancy_skills_chain(llm) -> LLMChain:
24
 
25
  def get_resume_skills_chain(llm) -> LLMChain:
26
  template_resume_skills = """
27
- Given the following resume delimited by three backticks, retrieve the skills this data scientist possesses.
 
28
  Return the skills as a JSON list on 1 line, do not add newlines or any other text.
29
 
30
  ```
@@ -95,3 +97,41 @@ def get_skills_chain(llm) -> SequentialChain:
95
  ],
96
  verbose=False,
97
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  def get_vacancy_skills_chain(llm) -> LLMChain:
7
  template_vacancy_get_skills = """
8
+ Given the following vacancy delimited by three backticks, retrieve the skills requested in the vacancy.
9
+ Describe the skills in preferably 1 word and maximum 3 words.
10
  Return the skills as a JSON list on 1 line, do not add newlines or any other text.
11
 
12
  ```
 
25
 
26
  def get_resume_skills_chain(llm) -> LLMChain:
27
  template_resume_skills = """
28
+ Given the following resume delimited by three backticks, retrieve the skills from the resume.
29
+ Describe the skills in preferably 1 word and maximum 3 words.
30
  Return the skills as a JSON list on 1 line, do not add newlines or any other text.
31
 
32
  ```
 
97
  ],
98
  verbose=False,
99
  )
100
+
101
+
102
+ def get_skills_match(llm, vacancy, resume) -> SequentialChain:
103
+
104
+ template_get_skills_intersection = """
105
+
106
+ ```
107
+ {vacancy}
108
+ ```
109
+
110
+ Can you list the matches between the vacancy above delimited by three backticks with the resume below delimited by three backticks.
111
+ Consider skills that are not exact but are close to each other in terms of meaning or usage, or that are related or in the neighbourhood.
112
+ If no skills match do not make up a response and return an empty list.
113
+ Return the matches as a JSON list on 1 line, do not add newlines or any other text.
114
+
115
+ ```
116
+ {resume}
117
+ ```
118
+ """
119
+
120
+ prompt_get_skills_intersection = ChatPromptTemplate.from_template(
121
+ template=template_get_skills_intersection
122
+ )
123
+ skills_match_chain = LLMChain(
124
+ llm=llm,
125
+ prompt=prompt_get_skills_intersection,
126
+ output_key="skills_match_predicted",
127
+ )
128
+
129
+ chain = SequentialChain(
130
+ chains=[skills_match_chain],
131
+ input_variables=["vacancy", "resume"],
132
+ output_variables=[
133
+ skills_match_chain.output_key,
134
+ ],
135
+ verbose=False,
136
+ )
137
+ return chain({"vacancy": vacancy, "resume": resume})