Commit
·
1b088ec
1
Parent(s):
79e8566
Added gap assessment step.
Browse files
app.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
| 1 |
-
|
| 2 |
from time import sleep
|
| 3 |
|
| 4 |
import gradio as gr
|
| 5 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 6 |
-
# from smolagents import ToolCallingAgent
|
| 7 |
import torch
|
| 8 |
from duckduckgo_search import DDGS
|
| 9 |
|
|
@@ -14,6 +12,96 @@ tokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
| 14 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 15 |
model.to(device)
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
class Role:
|
| 18 |
def __init__(self, company_name, company_url, job_description, clean_job_description, job_title):
|
| 19 |
self.company_name = company_name
|
|
@@ -37,11 +125,6 @@ def smol_lm_jd_process(job_description, system_prompt, max_new_tokens=512):
|
|
| 37 |
response = response[start_idx + len("<|im_start|>assistant\n"):end_idx].strip()
|
| 38 |
return response
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
return smol_lm_jd_process(job_description, system_prompt_get_job_title)
|
| 44 |
-
|
| 45 |
def process_job_description(company_name, company_url, job_description):
|
| 46 |
|
| 47 |
# Step 2: Extract key qualifications, skills, and requirements
|
|
@@ -94,7 +177,7 @@ def process_job_description(company_name, company_url, job_description):
|
|
| 94 |
summaries[key] = summary
|
| 95 |
print(f"Summarizing {key} successful")
|
| 96 |
|
| 97 |
-
|
| 98 |
"Company Name": company_name,
|
| 99 |
"Company URL": company_url,
|
| 100 |
"job_title": job_title,
|
|
@@ -115,6 +198,34 @@ def process_job_description(company_name, company_url, job_description):
|
|
| 115 |
}
|
| 116 |
}
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
# Create the Gradio app
|
| 119 |
demo = gr.Blocks()
|
| 120 |
|
|
@@ -124,10 +235,32 @@ with demo:
|
|
| 124 |
company_url = gr.Textbox(label="Company URL")
|
| 125 |
job_description = gr.TextArea(label="Paste Job Description")
|
| 126 |
|
|
|
|
|
|
|
| 127 |
gr.Button("Submit").click(
|
| 128 |
process_job_description,
|
| 129 |
inputs=[company_name, company_url, job_description],
|
| 130 |
-
outputs=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
)
|
| 132 |
|
| 133 |
if __name__ == "__main__":
|
|
|
|
|
|
|
| 1 |
from time import sleep
|
| 2 |
|
| 3 |
import gradio as gr
|
| 4 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
|
|
| 5 |
import torch
|
| 6 |
from duckduckgo_search import DDGS
|
| 7 |
|
|
|
|
| 12 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 13 |
model.to(device)
|
| 14 |
|
| 15 |
+
GAP_ASSESSMENT_PROMPT = """
|
| 16 |
+
|
| 17 |
+
# Do a gap assessment on this job role and resume looking for gaps that can be overcome by strategy in writing the resume and cover letter. For each gap, include a strategy for remediation. Ignore and do not mention any gap that is structural and for which improved writing will not be helpful. Consider things like:
|
| 18 |
+
|
| 19 |
+
1. Missing Keywords or Phrases
|
| 20 |
+
|
| 21 |
+
Consider: Does the resume lack important keywords or phrases from the job description?
|
| 22 |
+
Strategy: Integrate relevant keywords naturally into the resume and cover letter, especially in the summary, skills, and experience sections.
|
| 23 |
+
2. Unclear or Weakly Stated Achievements
|
| 24 |
+
|
| 25 |
+
Consider: Are the candidate’s accomplishments described in vague or generic terms?
|
| 26 |
+
Strategy: Rewrite bullet points to be achievement-oriented and quantify results where possible (e.g., “Increased sales by 20% in six months”).
|
| 27 |
+
3. Transferable Skills Not Highlighted
|
| 28 |
+
|
| 29 |
+
Consider: Are transferable skills from other roles or industries not clearly connected to the target job?
|
| 30 |
+
Strategy: Explicitly map transferable skills to job requirements in both the resume and cover letter, using language that mirrors the job posting.
|
| 31 |
+
4. Relevant Experience Buried or Underemphasized
|
| 32 |
+
|
| 33 |
+
Consider: Is relevant experience hidden or not given enough prominence?
|
| 34 |
+
Strategy: Reorder sections or bullet points to lead with the most relevant experiences, and use bolding or section headings to draw attention.
|
| 35 |
+
5. Lack of Tailoring to the Job
|
| 36 |
+
|
| 37 |
+
Consider: Is the resume too generic and not tailored to the specific job?
|
| 38 |
+
Strategy: Customize the summary/profile, skills, and experience sections to directly address the job requirements and company values.
|
| 39 |
+
6. Gaps in Demonstrating Required Soft Skills
|
| 40 |
+
|
| 41 |
+
Consider: Are important soft skills (e.g., leadership, communication) not clearly demonstrated?
|
| 42 |
+
Strategy: Add specific examples or brief stories in the resume and cover letter that illustrate these soft skills in action.
|
| 43 |
+
7. Unclear Career Progression or Role Context
|
| 44 |
+
|
| 45 |
+
Consider: Is it unclear how past roles relate to the target position?
|
| 46 |
+
Strategy: Add brief context or explanations in job descriptions or the cover letter to clarify how previous roles prepared the candidate for this job.
|
| 47 |
+
8. Formatting or Readability Issues
|
| 48 |
+
|
| 49 |
+
Consider: Is the resume difficult to scan or visually unappealing?
|
| 50 |
+
Strategy: Improve formatting for clarity and readability—use bullet points, clear headings, and consistent formatting.
|
| 51 |
+
9. Missing Education or Certification Details (If Present)
|
| 52 |
+
|
| 53 |
+
Consider: Are relevant credentials present but not highlighted?
|
| 54 |
+
Strategy: Move education or certifications to a more prominent position or call them out in the summary if they are key requirements.
|
| 55 |
+
10. Absence of Action Verbs
|
| 56 |
+
|
| 57 |
+
Consider: Are bullet points passive or lacking strong action verbs?
|
| 58 |
+
Strategy: Revise statements to start with powerful action verbs that convey impact and initiative.
|
| 59 |
+
|
| 60 |
+
11. Non-Linear Career Trajectory
|
| 61 |
+
|
| 62 |
+
Consider: Does the resume reflect a career path with frequent changes in industry, function, or direction, which may appear unfocused to employers?
|
| 63 |
+
|
| 64 |
+
Remediation Strategies: Craft a strong narrative in the summary section to tie diverse experiences together, emphasizing adaptability, learning agility, and the unique value brought by varied roles
|
| 65 |
+
|
| 66 |
+
. Use a skills-based or hybrid resume format to foreground transferable skills and relevant achievements rather than strict chronology
|
| 67 |
+
|
| 68 |
+
. In the cover letter, proactively explain the logic and benefits behind career pivots, highlighting how each transition contributed to your professional growth and how it aligns with the target role
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
12. Lack of Progression
|
| 72 |
+
|
| 73 |
+
Consider: Does the resume show little upward movement or increased responsibility over time?
|
| 74 |
+
|
| 75 |
+
Remediation Strategies: Highlight progression in responsibilities, even within the same job title or company, by emphasizing new projects, leadership roles, or skill development
|
| 76 |
+
|
| 77 |
+
. Quantify achievements and use action verbs to demonstrate impact and growth, even if formal titles did not change
|
| 78 |
+
. In the cover letter, address the context (e.g., company structure, personal choices) and focus on continuous learning or expanded scope within roles
|
| 79 |
+
|
| 80 |
+
13. Gaps in Employment History
|
| 81 |
+
|
| 82 |
+
Consider: Are there periods of unemployment or unaccounted time between jobs?
|
| 83 |
+
|
| 84 |
+
Remediation Strategies: Briefly explain significant gaps in the cover letter, framing them as periods of skill development, education, caregiving, or personal growth
|
| 85 |
+
|
| 86 |
+
. Include any freelance, contract, volunteer, or project work during gaps to demonstrate ongoing engagement and skill application
|
| 87 |
+
|
| 88 |
+
. Use a functional or hybrid resume format to de-emphasize strict chronology and spotlight relevant skills and accomplishments
|
| 89 |
+
|
| 90 |
+
. By strategically reframing these potential red flags, you can present a compelling, cohesive story that emphasizes your adaptability, continuous development, and readiness for the target role—turning perceived weaknesses into strengths
|
| 91 |
+
|
| 92 |
+
# This is the role description, company information, and results of company research, and
|
| 93 |
+
|
| 94 |
+
{JOB_AND_COMPANY_INFO}
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
## This is the candidate's resume:
|
| 98 |
+
|
| 99 |
+
{RESUME}
|
| 100 |
+
|
| 101 |
+
# For this task, do not re-write their resume. Simply identify any of these described gaps or other potential gaps and strategies in re-writing and re-framing the resume which are likely to be effective in improving the odds of being offered an interview or job.
|
| 102 |
+
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
class Role:
|
| 106 |
def __init__(self, company_name, company_url, job_description, clean_job_description, job_title):
|
| 107 |
self.company_name = company_name
|
|
|
|
| 125 |
response = response[start_idx + len("<|im_start|>assistant\n"):end_idx].strip()
|
| 126 |
return response
|
| 127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
def process_job_description(company_name, company_url, job_description):
|
| 129 |
|
| 130 |
# Step 2: Extract key qualifications, skills, and requirements
|
|
|
|
| 177 |
summaries[key] = summary
|
| 178 |
print(f"Summarizing {key} successful")
|
| 179 |
|
| 180 |
+
job_and_company_info = {
|
| 181 |
"Company Name": company_name,
|
| 182 |
"Company URL": company_url,
|
| 183 |
"job_title": job_title,
|
|
|
|
| 198 |
}
|
| 199 |
}
|
| 200 |
|
| 201 |
+
return job_and_company_info
|
| 202 |
+
|
| 203 |
+
def generate_gap_assessment_prompt(job_and_company_info, resume):
|
| 204 |
+
job_and_company_info_str = f"""
|
| 205 |
+
Company Name: {job_and_company_info['Company Name']}
|
| 206 |
+
Company URL: {job_and_company_info['Company URL']}
|
| 207 |
+
Job Title: {job_and_company_info['job_title']}
|
| 208 |
+
Role Requirements: {job_and_company_info['Role Requirements']}
|
| 209 |
+
Clean Job Description: {job_and_company_info['Clean Job Description']}
|
| 210 |
+
Company Research:
|
| 211 |
+
Company Values: {job_and_company_info['Company Research']['Company Values Summary']}
|
| 212 |
+
Corporate Culture: {job_and_company_info['Company Research']['Corporate Culture Summary']}
|
| 213 |
+
Leadership Team and Possible Key Opinion Leaders: {job_and_company_info['Company Research']['Leadership Team Summary']}
|
| 214 |
+
Recent Company News: {job_and_company_info['Company Research']['Recent News Summary']}
|
| 215 |
+
Company Competitive Advantages: {job_and_company_info['Company Research']['Competitive Advantages Summary']}
|
| 216 |
+
"""
|
| 217 |
+
|
| 218 |
+
prompt = GAP_ASSESSMENT_PROMPT.replace("{JOB_AND_COMPANY_INFO}", job_and_company_info_str).replace("{RESUME}", resume)
|
| 219 |
+
|
| 220 |
+
return prompt
|
| 221 |
+
|
| 222 |
+
def gap_assessment_interface(job_and_company_info, resume):
|
| 223 |
+
prompt = generate_gap_assessment_prompt(job_and_company_info, resume)
|
| 224 |
+
return gr.TextArea(label="Gap Assessment Prompt", value=prompt, interactive=False)
|
| 225 |
+
|
| 226 |
+
def submit_gap_assessment_result(gap_assessment_result):
|
| 227 |
+
return gap_assessment_result
|
| 228 |
+
|
| 229 |
# Create the Gradio app
|
| 230 |
demo = gr.Blocks()
|
| 231 |
|
|
|
|
| 235 |
company_url = gr.Textbox(label="Company URL")
|
| 236 |
job_description = gr.TextArea(label="Paste Job Description")
|
| 237 |
|
| 238 |
+
job_and_company_info_output = gr.JSON(label="Job and Company Info")
|
| 239 |
+
|
| 240 |
gr.Button("Submit").click(
|
| 241 |
process_job_description,
|
| 242 |
inputs=[company_name, company_url, job_description],
|
| 243 |
+
outputs=job_and_company_info_output
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
gr.Markdown("# Resume Input")
|
| 247 |
+
resume = gr.TextArea(label="Paste Resume")
|
| 248 |
+
|
| 249 |
+
gap_assessment_prompt_output = gr.TextArea(label="Gap Assessment Prompt")
|
| 250 |
+
|
| 251 |
+
gr.Button("Generate Gap Assessment Prompt").click(
|
| 252 |
+
gap_assessment_interface,
|
| 253 |
+
inputs=[job_and_company_info_output, resume],
|
| 254 |
+
outputs=gap_assessment_prompt_output
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
gr.Markdown("# Gap Assessment Result")
|
| 258 |
+
gap_assessment_result = gr.TextArea(label="Paste Gap Assessment Result")
|
| 259 |
+
|
| 260 |
+
gr.Button("Submit Gap Assessment Result").click(
|
| 261 |
+
submit_gap_assessment_result,
|
| 262 |
+
inputs=[gap_assessment_result],
|
| 263 |
+
outputs=gr.TextArea(label="Gap Assessment Result")
|
| 264 |
)
|
| 265 |
|
| 266 |
if __name__ == "__main__":
|