Jonah Ramponi commited on
Commit
98eaa40
1 Parent(s): 8983fcf

total restructure

Browse files
Files changed (5) hide show
  1. app.py +134 -72
  2. backend.py +24 -18
  3. utils/format.py +142 -0
  4. utils/gpt.py +18 -0
  5. utils/prompts.py +128 -93
app.py CHANGED
@@ -3,13 +3,16 @@
3
  """
4
 
5
  import json
 
6
  import concurrent.futures
7
 
8
  import streamlit as st
9
 
 
 
10
  from utils.process_doc import parse_docx, parse_pdf
11
- from backend import process_cv, process_job_posting
12
- from utils.gpt import test_api_key
13
 
14
  st.set_page_config(layout="wide")
15
 
@@ -21,7 +24,7 @@ with st.sidebar:
21
  )
22
 
23
  if "state" not in st.session_state:
24
- st.session_state.state = {"formatted": False}
25
 
26
  STATE = st.session_state.state
27
 
@@ -38,93 +41,152 @@ cv_upload_box = st.file_uploader(
38
  )
39
  job_posting_upload_box = st.text_area(
40
  "Job Description Upload Box",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  placeholder="Copy and Paste a job post you are interested in. Make sure to include the full post! More information is better.",
42
  help="In this box, please dump text content for a job description you are interested in. This could easily be setup to work directly with a webpage (we'd simply need to scrape said page) however I do not want to do that on HF spaces.",
43
  )
44
 
45
  if cv_upload_box and job_posting_upload_box != "":
 
46
 
47
- process_files = st.button("Process Files", type="primary")
48
-
49
- if process_files:
50
- if test_api_key(COHERE_API_KEY):
51
-
52
- # Process our two uploaded files into state variables
53
- STATE["job_posting"] = job_posting_upload_box
54
 
55
- cv_filetype = cv_upload_box.name.split(".")[-1]
56
- cv_file_contents = cv_upload_box.getvalue()
57
-
58
- STATE["cv"] = (
59
- parse_docx(cv_file_contents)
60
- if cv_filetype == "docx"
61
- else parse_pdf(cv_file_contents)
62
- )
63
 
64
- # Now, use Cohere to get structured output for both cv and job_posting
 
 
65
 
66
- # Making these calls in parallel
67
  with concurrent.futures.ThreadPoolExecutor() as executor:
 
 
 
 
 
 
 
68
 
69
- future1 = executor.submit(process_cv, STATE["cv"], COHERE_API_KEY)
70
  future2 = executor.submit(
71
- process_job_posting, STATE["job_posting"], COHERE_API_KEY
 
 
 
 
72
  )
73
 
74
- cv_json_text = future1.result()
75
- job_posting_json_text = future2.result()
76
-
77
- cv_json_text = (
78
- "{" + cv_json_text.lstrip().lstrip("{").rstrip().rstrip("}") + "}"
79
- )
80
- job_posting_json_text = (
81
- "{"
82
- + job_posting_json_text.lstrip().lstrip("{").rstrip().rstrip("}")
83
- + "}"
84
- )
85
- try:
86
- STATE["cv_json"] = json.loads(cv_json_text)
87
- except json.JSONDecodeError as e:
88
- print(
89
- f"Error parsing JSON Output for CV: {e}. Response content: {cv_json_text}"
90
  )
91
- STATE["cv_json"] = {"name": "Failed"}
92
 
93
- try:
94
- STATE["job_posting_json"] = json.loads(job_posting_json_text)
 
95
 
96
- except json.JSONDecodeError as e:
97
- print(
98
- f"Error parsing JSON Output for Job Posting: {e}. Response content: {job_posting_json_text}"
99
- )
100
- STATE["job_posting_json"] = {"companyName": "Failed"}
 
 
 
101
 
102
- STATE["formatted"] = True
103
- else:
104
- st.error(
105
- "You entered an invalid Cohere API Key. Please enter a valid API key in the sidebar."
106
- )
107
 
108
- # Now, we can work with this !
109
- if STATE["formatted"]:
110
- lcol, rcol = st.columns((0.5, 0.5))
111
- with lcol:
112
- st.download_button(
113
- label="Download Job Posting JSON",
114
- data=json.dumps(STATE["job_posting_json"], indent=4),
115
- file_name=f"job_posting_formatted_{STATE['job_posting_json']['companyName']}.json",
116
- mime="application/json",
117
- use_container_width=True,
118
- )
119
- with rcol:
120
- st.download_button(
121
- label="Download CV JSON",
122
- data=json.dumps(STATE["cv_json"], indent=4),
123
- file_name=f"cv_formatted_{STATE['cv_json']['name']}.json",
124
- mime="application/json",
125
- use_container_width=True,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  )
127
 
128
- cv_critique, practice_interview, general_cv_critique = st.tabs(
129
- ["Role Specific CV Critique", "Practice Interview", "General CV Critique"]
130
- )
 
3
  """
4
 
5
  import json
6
+ import random
7
  import concurrent.futures
8
 
9
  import streamlit as st
10
 
11
+ from backend import paired_critique
12
+
13
  from utils.process_doc import parse_docx, parse_pdf
14
+ from utils.gpt import test_api_key, gpt_stream_response_chat_history
15
+ from utils.format import extract_json, generate_markdown_report
16
 
17
  st.set_page_config(layout="wide")
18
 
 
24
  )
25
 
26
  if "state" not in st.session_state:
27
+ st.session_state.state = {"successful_report_flag": True, "paired_report": {}}
28
 
29
  STATE = st.session_state.state
30
 
 
41
  )
42
  job_posting_upload_box = st.text_area(
43
  "Job Description Upload Box",
44
+ value="""Job description
45
+ As a Data Scientist at Meta, you will shape the future of people-facing and business-facing products we build across our entire family of applications (Facebook, Instagram, Messenger, WhatsApp, Oculus). By applying your technical skills, analytical mindset, and product intuition to one of the richest data sets in the world, you will help define the experiences we build for billions of people and hundreds of millions of businesses around the world. You will collaborate on a wide array of product and business problems with a diverse set of cross-functional partners across Product, Engineering, Research, Data Engineering, Marketing, Sales, Finance and others. You will use data and analysis to identify and solve product development’s biggest challenges. You will influence product strategy and investment decisions with data, be focused on impact, and collaborate with other teams. By joining Meta, you will become part of a world-class analytics community dedicated to skill development and career growth in analytics and beyond.Product leadership: You will use data to shape product development, quantify new opportunities, identify upcoming challenges, and ensure the products we build bring value to people, businesses, and Meta. You will help your partner teams prioritize what to build, set goals, and understand their product’s ecosystem.Analytics: You will guide teams using data and insights. You will focus on developing hypotheses and employ a diverse toolkit of rigorous analytical approaches, different methodologies, frameworks, and technical approaches to test them.Communication and influence: You won’t simply present data, but tell data-driven stories. You will convince and influence your partners using clear insights and recommendations. You will build credibility through structure and clarity, and be a trusted strategic partner.
46
+
47
+ Data Scientist, Product Analytics Responsibilities:
48
+
49
+ Work with large and complex data sets to solve a wide array of challenging problems using different analytical and statistical approaches.
50
+ Apply technical expertise with quantitative analysis, experimentation, data mining, and the presentation of data to develop strategies for our products that serve billions of people and hundreds of millions of businesses.
51
+ Identify and measure success of product efforts through goal setting, forecasting, and monitoring of key product metrics to understand trends.
52
+ Define, understand, and test opportunities and levers to improve the product, and drive roadmaps through your insights and recommendations.
53
+ Partner with Product, Engineering, and cross-functional teams to inform, influence, support, and execute product strategy and investment decisions.
54
+
55
+ Minimum Qualifications:
56
+
57
+ A minimum of 6 years of work experience in analytics (minimum of 4 years with a Ph.D.).
58
+ Bachelor's degree in Mathematics, Statistics, a relevant technical field, or equivalent practical experience.
59
+ Experience with data querying languages (e.g. SQL), scripting languages (e.g. Python), and/or statistical/mathematical software (e.g. R).
60
+
61
+ Preferred Qualifications:
62
+
63
+ Masters or Ph.D. Degree in a quantitative field.
64
+
65
+ About Meta:
66
+
67
+ Meta builds technologies that help people connect, find communities, and grow businesses. When Facebook launched in 2004, it changed the way people connect. Apps like Messenger, Instagram and WhatsApp further empowered billions around the world. Now, Meta is moving beyond 2D screens toward immersive experiences like augmented and virtual reality to help build the next evolution in social technology. People who choose to build their careers by building with us at Meta help shape a future that will take us beyond what digital connection makes possible today—beyond the constraints of screens, the limits of distance, and even the rules of physics.
68
+
69
+ Individual compensation is determined by skills, qualifications, experience, and location. Compensation details listed in this posting reflect the base hourly rate, monthly rate, or annual salary only, and do not include bonus, equity or sales incentives, if applicable. In addition to base compensation, Meta offers benefits. Learn more about benefits at Meta.""",
70
  placeholder="Copy and Paste a job post you are interested in. Make sure to include the full post! More information is better.",
71
  help="In this box, please dump text content for a job description you are interested in. This could easily be setup to work directly with a webpage (we'd simply need to scrape said page) however I do not want to do that on HF spaces.",
72
  )
73
 
74
  if cv_upload_box and job_posting_upload_box != "":
75
+ STATE["job_posting"] = job_posting_upload_box
76
 
77
+ cv_filetype = cv_upload_box.name.split(".")[-1]
78
+ cv_file_contents = cv_upload_box.getvalue()
 
 
 
 
 
79
 
80
+ STATE["cv"] = (
81
+ parse_docx(cv_file_contents)
82
+ if cv_filetype == "docx"
83
+ else parse_pdf(cv_file_contents)
84
+ )
85
+ cv_critique, practice_interview, general_cv_critique = st.tabs(
86
+ ["Role Specific CV Critique", "Practice Interview", "General CV Critique"]
87
+ )
88
 
89
+ with cv_critique:
90
+ produce_report = st.button("Produce Suitability Report")
91
+ if produce_report:
92
 
93
+ # Make 3 calls in parallel
94
  with concurrent.futures.ThreadPoolExecutor() as executor:
95
+ future1 = executor.submit(
96
+ paired_critique,
97
+ STATE["cv"],
98
+ STATE["job_posting"],
99
+ "basic",
100
+ COHERE_API_KEY,
101
+ )
102
 
 
103
  future2 = executor.submit(
104
+ paired_critique,
105
+ STATE["cv"],
106
+ STATE["job_posting"],
107
+ "general",
108
+ COHERE_API_KEY,
109
  )
110
 
111
+ future3 = executor.submit(
112
+ paired_critique,
113
+ STATE["cv"],
114
+ STATE["job_posting"],
115
+ "specific",
116
+ COHERE_API_KEY,
 
 
 
 
 
 
 
 
 
 
117
  )
 
118
 
119
+ basic_details_out = future1.result()
120
+ general_details_out = future2.result()
121
+ specific_details_out = future3.result()
122
 
123
+ # merge the outputs
124
+ resultsDict = {}
125
+ for jsonText in [
126
+ basic_details_out,
127
+ general_details_out,
128
+ specific_details_out,
129
+ ]:
130
+ valid_json_flag, output_report_json = extract_json(jsonText)
131
 
132
+ if not valid_json_flag:
133
+ STATE["successful_report_flag"] = False
 
 
 
134
 
135
+ resultsDict.update(output_report_json)
136
+
137
+ STATE["paired_report"] = resultsDict
138
+
139
+ if STATE["successful_report_flag"] and STATE["paired_report"]:
140
+
141
+ paired_report = STATE["paired_report"]
142
+
143
+ name = paired_report.get("personName", "MissingPersonName")
144
+ job_title = paired_report.get("jobTitle", "MissingTitle")
145
+ company_name = paired_report.get("companyName", "MissingCompany")
146
+
147
+ with cv_critique:
148
+ st.markdown(generate_markdown_report(STATE["paired_report"]))
149
+
150
+ st.download_button(
151
+ label="Download Report JSON",
152
+ data=json.dumps(STATE["paired_report"], indent=4),
153
+ file_name=f"{name}_{job_title}_{company_name}.json",
154
+ mime="application/json",
155
+ use_container_width=True,
156
+ )
157
+
158
+ # Streaming Chatbot !!!
159
+ with practice_interview:
160
+ initial_questions = [
161
+ "What do you think is the biggest reason you're unsuitable for the role?",
162
+ "Why are you interested in this role specifically?",
163
+ "What do you know about the company?",
164
+ ]
165
+
166
+ if "messages" not in st.session_state:
167
+ st.session_state["messages"] = [
168
+ {"role": "assistant", "message": random.choice(initial_questions)}
169
+ ]
170
+
171
+ # Populate the chat with historic messages
172
+ for msg in st.session_state.messages:
173
+ st.chat_message(msg["role"]).write(msg["message"])
174
+
175
+ if prompt := st.chat_input():
176
+ st.session_state.messages.append({"role": "user", "message": prompt})
177
+ st.chat_message("user").write(prompt)
178
+
179
+ assistant_message = st.chat_message("assistant")
180
+
181
+ response = assistant_message.write_stream(
182
+ gpt_stream_response_chat_history(
183
+ st.session_state.messages,
184
+ background_info={
185
+ "cv": STATE["cv"],
186
+ "job_posting": STATE["job_posting"],
187
+ },
188
+ api_key=COHERE_API_KEY,
189
+ )
190
  )
191
 
192
+ st.session_state.messages.append({"role": "assistant", "message": response})
 
 
backend.py CHANGED
@@ -1,31 +1,31 @@
1
  from utils.prompts import (
2
- cv_extract_prompt,
3
- cv_format,
4
- job_posting_extract_prompt,
5
- job_posting_format,
6
  )
7
 
8
  from utils.gpt import gpt_response
9
 
 
 
 
 
 
10
 
11
- def process_cv(cv_contents: str, API_KEY: str) -> str:
 
 
 
12
  """Process CV contents, using Cohere"""
13
 
14
- prompt = cv_extract_prompt.replace("<input-cv>", cv_contents)
 
15
 
16
- response = gpt_response(
17
- prompt=prompt,
18
- api_key=API_KEY,
19
  )
20
 
21
- return response
22
-
23
-
24
- def process_job_posting(job_post_contents: str, API_KEY: str) -> str:
25
- """Process a job posting, using Cohere"""
26
-
27
- prompt = job_posting_extract_prompt.replace("<job-posting>", job_post_contents)
28
-
29
  response = gpt_response(
30
  prompt=prompt,
31
  api_key=API_KEY,
@@ -38,4 +38,10 @@ if __name__ == "__main__":
38
  with open("sample_data/meta_job.txt", "r") as file:
39
  post_contents = file.read()
40
 
41
- output = process_job_posting(post_contents)
 
 
 
 
 
 
 
1
  from utils.prompts import (
2
+ basic_details_extraction_prompt,
3
+ general_skils_extraction_prompt,
4
+ specific_skills_comparison_prompt,
 
5
  )
6
 
7
  from utils.gpt import gpt_response
8
 
9
+ prompt_mapping = {
10
+ "basic": basic_details_extraction_prompt,
11
+ "general": general_skils_extraction_prompt,
12
+ "specific": specific_skills_comparison_prompt,
13
+ }
14
 
15
+
16
+ def paired_critique(
17
+ cv_contents: str, job_post_contents: str, response_type: str, API_KEY: str
18
+ ) -> str:
19
  """Process CV contents, using Cohere"""
20
 
21
+ # First, get the prompt from the prompt dict
22
+ prompt = prompt_mapping.get(response_type)
23
 
24
+ # Now, populate with the contents of the CV and job posting
25
+ prompt = prompt.replace("<cv>", cv_contents).replace(
26
+ "<job-posting>", job_post_contents
27
  )
28
 
 
 
 
 
 
 
 
 
29
  response = gpt_response(
30
  prompt=prompt,
31
  api_key=API_KEY,
 
38
  with open("sample_data/meta_job.txt", "r") as file:
39
  post_contents = file.read()
40
 
41
+ with open("sample_data/example_cv.txt", "r") as file:
42
+ cv_contents = file.read()
43
+
44
+ COHERE_API_KEY = ""
45
+
46
+ output = paired_critique(post_contents, cv_contents, "specific", COHERE_API_KEY)
47
+ print(output)
utils/format.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+
4
+ def extract_json(input_string: str) -> dict:
5
+ """String to Json function"""
6
+
7
+ # First, ensure we remove json wrapper
8
+ input_string = input_string.replace("```json", "```").replace("```", "")
9
+
10
+ # Now, ensure we have stripped everything so it is just json
11
+ input_string_formatted = input_string.lstrip("{").rstrip("}")
12
+
13
+ # Ensure we do not have the weird \_ behaviour that models sometimes include
14
+ input_string_formatted = input_string_formatted.replace("\_", "_")
15
+
16
+ try:
17
+ return True, json.loads(input_string_formatted)
18
+
19
+ except json.JSONDecodeError as e:
20
+ print(f"Error parsing JSON Output: {input_string}. Error: {e}")
21
+ return False, {}
22
+
23
+
24
+ def generate_markdown_report(data):
25
+ # Header
26
+ report = f"# CV Analysis Report\n\n"
27
+ report += f"**Name:** {data.get('personName', 'Unknown')} \n"
28
+ report += f"**Job:** {data.get('jobTitle', 'N/A')} at {data.get('companyName', 'N/A')} \n"
29
+ report += (
30
+ f"**Job Description:** {data.get('jobDesc', 'No description available.')}\n\n"
31
+ )
32
+ report += "---\n\n"
33
+ report += "## Key Findings\n\n"
34
+
35
+ experiences = data.get("experience", [])
36
+ if experiences:
37
+
38
+ report += "### Experience\n\n"
39
+ report += (
40
+ "| Job Posting Requirement | CV Details | Explanation | Impact Score |\n"
41
+ )
42
+ report += (
43
+ "| ----------------------- | ---------- | ----------- | -------------- |\n"
44
+ )
45
+ for exp in experiences:
46
+ report += f"| {exp.get('jobPostingDetails', 'N/A')} | {exp.get('cvDetails', 'N/A')} | {exp.get('explanation', '')} | **{exp.get('severityScore', 0)}** |\n"
47
+ report += "\n"
48
+
49
+ education = data.get("education", [])
50
+ if education:
51
+ report += "### Education\n\n"
52
+ report += (
53
+ "| Job Posting Requirement | CV Details | Explanation | Impact Score |\n"
54
+ )
55
+ report += (
56
+ "| ----------------------- | ---------- | ----------- | -------------- |\n"
57
+ )
58
+ for edu in education:
59
+ report += f"| {edu.get('jobPostingDetails', 'N/A')} | {edu.get('cvDetails', 'N/A')} | {edu.get('explanation', '')} | **{edu.get('severityScore', 0)}** |\n"
60
+ report += "\n"
61
+
62
+ responsibilities = data.get("responsibilities", [])
63
+ if responsibilities:
64
+ report += "### Responsibilities\n\n"
65
+ report += (
66
+ "| Job Posting Requirement | CV Details | Explanation | Impact Score |\n"
67
+ )
68
+ report += (
69
+ "| ----------------------- | ---------- | ----------- | -------------- |\n"
70
+ )
71
+ for resp in responsibilities:
72
+ report += f"| {resp.get('jobPostingDetails', 'N/A')} | {resp.get('cvDetails', 'N/A')} | {resp.get('explanation', '')} | **{resp.get('severityScore', 0)}** |\n"
73
+ report += "\n"
74
+
75
+ languages = data.get("languages", [])
76
+ if languages:
77
+ report += "### Languages\n\n"
78
+ report += (
79
+ "| Job Posting Requirement | CV Details | Explanation | Impact Score |\n"
80
+ )
81
+ report += (
82
+ "| ----------------------- | ---------- | ----------- | -------------- |\n"
83
+ )
84
+ for lang in languages:
85
+ report += f"| {lang.get('jobPostingDetails', 'N/A')} | {lang.get('cvDetails', 'N/A')} | {lang.get('explanation', '')} | **{lang.get('severityScore', 0)}** |\n"
86
+ report += "\n"
87
+
88
+ # Tools
89
+ tools = data.get("tools", [])
90
+ if tools:
91
+ report += "### Tools\n\n"
92
+ report += (
93
+ "| Job Posting Requirement | CV Details | Explanation | Impact Score |\n"
94
+ )
95
+ report += (
96
+ "| ----------------------- | ---------- | ----------- | -------------- |\n"
97
+ )
98
+ for tool in tools:
99
+ report += f"| {tool.get('jobPostingDetails', 'N/A')} | {tool.get('cvDetails', 'N/A')} | {tool.get('explanation', '')} | **{tool.get('severityScore', 0)}** |\n"
100
+ report += "\n"
101
+
102
+ # Closing
103
+ report += "---\n"
104
+
105
+ return report
106
+
107
+
108
+ def format_chat_history_cohere(chat_history: list, background_info: dict) -> list:
109
+ """Takes streamlit chat history, and converts to cohere format"""
110
+
111
+ # Could use cohere to track history, maybe for the future
112
+ new_output = [
113
+ {
114
+ "role": "USER",
115
+ "message": f"Hi there! Here is my CV! {background_info['cv']}.\n\n I'd like you to act as a senior technical recruiter, recruiting for a role at a specific company. I want you to ask highly specific questions about the role, and critique my CV and its' suitability for the role. Please also ask general interview questions.",
116
+ },
117
+ {
118
+ "role": "CHATBOT",
119
+ "message": f"Thanks. Can you send me the job posting?",
120
+ },
121
+ {
122
+ "role": "USER",
123
+ "message": f"Here is the job posting: {background_info['job_posting']}",
124
+ },
125
+ ]
126
+
127
+ for item in chat_history:
128
+ new_output.append(
129
+ {
130
+ "role": "USER" if item["role"] == "user" else "CHATBOT",
131
+ "message": item["message"],
132
+ }
133
+ )
134
+
135
+ return new_output
136
+
137
+
138
+ if __name__ == "__main__":
139
+ example_json = """
140
+
141
+ """
142
+ extract_json(example_json)
utils/gpt.py CHANGED
@@ -1,4 +1,5 @@
1
  import cohere
 
2
 
3
 
4
  def test_api_key(api_key: str):
@@ -14,6 +15,23 @@ def test_api_key(api_key: str):
14
  return False
15
 
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  def gpt_stream_response(prompt: str, api_key: str):
18
  """Get response from Cohere and stream response"""
19
 
 
1
  import cohere
2
+ from utils.format import format_chat_history_cohere
3
 
4
 
5
  def test_api_key(api_key: str):
 
15
  return False
16
 
17
 
18
+ def gpt_stream_response_chat_history(chat_history, background_info, api_key):
19
+ """Get response from Cohere and stream response"""
20
+ co = cohere.Client(
21
+ api_key=api_key,
22
+ )
23
+
24
+ cohere_history = format_chat_history_cohere(chat_history, background_info)
25
+
26
+ stream = co.chat_stream(
27
+ chat_history=cohere_history[:-1], message=cohere_history[-1]["message"]
28
+ )
29
+
30
+ for event in stream:
31
+ if event.event_type == "text-generation":
32
+ yield event.text
33
+
34
+
35
  def gpt_stream_response(prompt: str, api_key: str):
36
  """Get response from Cohere and stream response"""
37
 
utils/prompts.py CHANGED
@@ -1,124 +1,159 @@
1
- # NOTE: The _format variables may be useful for testing the beta of Cohere's structured output endpoints.
2
-
3
- cv_format = {
4
- "type": "object",
5
- "required": [
6
- "name",
7
- "roles",
8
- "projects",
9
- "languages",
10
- "packages",
11
- "tools",
12
- "qualifications",
13
- "responsibilities",
14
- ],
15
- "properties": {
16
- "name": {"type": "string"},
17
- "roles": {"type": "list"},
18
- "projects": {"type": "list"},
19
- "languages": {"type": "list"},
20
- "packages": {"type": "list"},
21
- "tools": {"type": "list"},
22
- "qualifications": {"type": "list"},
23
- "responsibilities": {"type": "list"},
24
- },
 
25
  }
26
 
 
 
 
 
 
 
27
 
28
- cv_extract_prompt = """
29
- You are an expert at extracting information from CVs
 
 
 
 
 
 
30
 
31
  **Goal**
32
- For a given CV, you must extract structured information and present it to the user in json form
33
 
34
- **Input**
35
- <input-cv>
 
 
 
 
 
36
 
37
  **Output Format**
38
- You will respond with a json object, in the form given.
39
- You will ensure that you are concise.
40
 
 
41
  {
42
- "name": ,
43
- "roles": [],
44
- "projects": [],
45
- "languages": [],
46
- "packages": [],
47
- "tools": [],
48
- "qualifications": [] ,
49
- "responsibilities": [],
50
  }
51
 
52
- **Guidance**
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- - languages: programming languages mentioned in the CV. Each should be tagged with a number between 1 and 5. 5 suggests they must be fully fluent, 1 suggests they may have some experience. If the CV does not indicate the level of required experience, approximate it, and if no information at all is given put 3
55
- - packages: specific packages mentioned in the CV. Each package should be tagged with a number between 1 and 5, 5 suggesting fully fluent and 1 suggesting just tried it once. Use your best judgement to gauge the individual's level of understanding.
56
- - tools: a list of other tools the individual has experience with
57
- - qualifications: of form [{"type": , "grade": ,"location": }] where type is the qualification type identified. Available Education Levels are: bsc,msc,phd. grade should be the grade achieved (number between 0 and 100. Make relevant conversions, if no number is given, assume 60). location is the location of where the education was taken.
58
- - responsibilities: an extensive list of the responsibilities demonstrated in the CV.
59
 
60
- You will now respond clearly, only responding with the desired json output.
 
 
 
 
61
  """
62
 
63
- job_posting_format = {
64
- "type": "object",
65
- "required": [
66
- "companyName",
67
- "roleShortDesc",
68
- "roleLongDesc",
69
- "requiredExperience",
70
- "languages",
71
- "packages",
72
- "tools",
73
- "qualifications",
74
- "responsibilities",
75
- ],
76
- "properties": {
77
- "name": {"type": "string"},
78
- "roleShortDesc": {"type": "string"},
79
- "roleLongDesc": {"type": "string"},
80
- "requiredExperience": {"type": "list"},
81
- "languages": {"type": "list"},
82
- "packages": {"type": "list"},
83
- "tools": {"type": "list"},
84
- "qualifications": {"type": "list"},
85
- "responsibilities": {"type": "list"},
86
- },
87
- }
88
 
89
- job_posting_extract_prompt = """
90
- You are an expert at extracting information from job postings
 
91
 
92
  **Goal**
93
- For a given job posting, you must extract structured information and present it to the user
94
 
95
- **Input**
 
96
  <job-posting>
97
 
 
 
 
 
98
  **Output Format**
99
- You will respond with a json object, in the form given.
100
- You will ensure that you are concise.
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  {
103
- "companyName": ,
104
- "roleShortDesc": ,
105
- "roleLongDesc": ,
106
- "requiredExperience": [],
107
  "languages": [],
108
  "packages": [],
109
- "tools": [],
110
- "qualifications": [] ,
111
- "responsibilities": [],
112
  }
113
 
114
- **Guidance**
115
- - roleShortDesc should be one sentence only
116
- - requiredExperience: a standaredized list of items, each item should be at most one short sentence
117
- - languages: programming languages mentioned in the post. Each should be tagged with a number between 1 and 5. 5 suggests they must be fully fluent, 1 suggests they may have some experience. If the job does not indicate the level of required experience, put 3
118
- - packages: specific packages mentioned in the post. Each package should be tagged with a number between 1 and 5, 5 suggesting fully fluent and 1 suggesting just tried it once. If no level is given, assume level 3
119
- - tools: a list of other tools that would be useful to know
120
- - qualifications: of form [{"type": , "strictness": }] where type is the qualification type identified, and strictness is your approximation of how strict the job posting suggests the requirement is. 1 being not strict at all, 5 being absolute necessity. Available Education Levels are: bsc,msc,phd.
121
- - responsibilities: an extensive list of the responsibilities given in the advert.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
- You will now respond clearly, only responding with the desired json output.
124
  """
 
1
+ basic_details_extraction_prompt = """
2
+ You are an expert at understanding how suitable a given CV is for a given job posting.
3
+ You will focus on evaluating the candidates experience quality
4
+
5
+ **Goal**
6
+ To summarize the information provided in a clear form
7
+
8
+ **Job Posting**
9
+ Here are the Job Posting contents:
10
+ <job-posting>
11
+
12
+ **CV**
13
+ Here are the CV contents:
14
+ <cv>
15
+
16
+ **Output Format**
17
+
18
+ You will produce a json, summarizing the input data.
19
+
20
+ Here is the overall structure of your output:
21
+ {
22
+ "jobTitle": str,
23
+ "companyName": str,
24
+ "personName": str,
25
+ "jobDesc": str
26
  }
27
 
28
+ * jobTitle: at most 5 words giving role title
29
+ * companyName: name of company in job posting
30
+ * personName: name of person who submitted CV (if no name, put Example Name)
31
+ * jobDesc: a short description of the job
32
+
33
+ Respond only with a json, wrapped in ```json.
34
 
35
+ If you wish to leave a field blank in a given json, use "". You must never use null as this will be loaded using json.loads!
36
+
37
+ Now respond with your professional, concise, answer.
38
+ """
39
+
40
+ general_skils_extraction_prompt = """
41
+ You are an expert at understanding how suitable a given CV is for a given job posting.
42
+ You will focus on evaluating the candidates experience quality
43
 
44
  **Goal**
45
+ To evaluate the candidate, against the job posting, given set criteria
46
 
47
+ **Job Posting**
48
+ Here are the Job Posting contents:
49
+ <job-posting>
50
+
51
+ **CV**
52
+ Here are the CV contents:
53
+ <cv>
54
 
55
  **Output Format**
56
+ You will produce a json, summarizing the candidates suitability.
57
+ The fields will all be lists, each item in those lists will be a dictionary with 4 keys.
58
 
59
+ That required form is
60
  {
61
+ "jobPostingDetails": str,
62
+ "cvDetails": str,
63
+ "explanation": str,
64
+ "SeverityScore": float
 
 
 
 
65
  }
66
 
67
+ * SeverityScore is between 0 and 10, marking how much of a critical miss the given thing is.
68
+ * Explanation will contain a brief explanation of what the problem was
69
+
70
+ For instance
71
+ (3 Years using R, No Mention of R, Missing Language Experience, 4)
72
+
73
+ Here is the overall structure of your output:
74
+ {
75
+ "experience": [],
76
+ "education": [],
77
+ "responsibilities": []
78
+ }
79
 
80
+ * experience should look at the desired experiences in the job posting. For each experience listed, it should be understood if the user's CV showed that trait.
81
+ * education should compare required / desired education levels with the user's CV's education levels
82
+ * responsibilities refers to the list of responsibilities in the job posting, which should each be compared with the user's CV
 
 
83
 
84
+ Respond only with a json, wrapped in ```json.
85
+
86
+ If you wish to leave a field blank in a given json, use "". You must never use null as this will be loaded using json.loads!
87
+
88
+ Now respond with your professional, concise, answer.
89
  """
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ specific_skills_comparison_prompt = """
93
+ You are an expert at understanding how suitable a given CV is for a given job posting.
94
+ You will focus on evaluating the candidates experience quality
95
 
96
  **Goal**
97
+ To evaluate the candidate, against the job posting, given set criteria
98
 
99
+ **Job Posting**
100
+ Here are the Job Posting contents:
101
  <job-posting>
102
 
103
+ **CV**
104
+ Here are the CV contents:
105
+ <cv>
106
+
107
  **Output Format**
 
 
108
 
109
+ You will produce a json, summarizing the candidates suitability.
110
+ The fields will all be lists, each item in those lists will be a dictionary with 4 keys.
111
+
112
+ That required form is
113
+ {
114
+ "jobPostingDetails": str,
115
+ "cvDetails": str,
116
+ "explanation": str,
117
+ "SeverityScore": float
118
+ }
119
+
120
+ * SeverityScore is between 0 and 10, marking how much of a critical miss the given thing is.
121
+ * Explanation will contain a brief explanation of what the problem was
122
+
123
+ For instance this could look like: (3 Years using R, No Mention of R, Missing Language Experience, 4)
124
+
125
+ Here is the overall structure of your output:
126
  {
 
 
 
 
127
  "languages": [],
128
  "packages": [],
129
+ "tools": []
 
 
130
  }
131
 
132
+ * languages should compare either programming, or regular language, requirements
133
+ * packages refers specifically to packages of programming languages. Leave blank if job posting gives no details on specific packages.
134
+ * tools refers to specific tools referenced in the job posting, leave blank if job posting gives no details on tools.
135
+
136
+ Be incredibly careful that you do not confuse the content of the CV with the content of the Job Posting.
137
+
138
+ Respond only with a json, wrapped in ```json.
139
+
140
+ You must never use null as this will be loaded using json.loads! If there is nothing relevant, leave the list empty. If a field is missing from the dictionary of 4, then just put "".
141
+
142
+ Now respond with your professional, concise, answer.
143
+ """
144
+
145
+ interviewer_prompt = """
146
+ **Goal**
147
+ You are an interviewer, and will carry out a natural interview
148
+
149
+ **Background Information**
150
+ The user has the following CV:
151
+ <cv>
152
+
153
+ The user is interested in the following job:
154
+ <job-posting>
155
+
156
+ You will act like an interviewer for that job, critiquing the user's CV and asking them questions. Follow the conversation naturally.
157
 
158
+ Ask either STAR reasoning, or technical questions, based on the job posting, or general job title.
159
  """