From 099ccc40e878d9cd1598a656bbfd06f21468f8cc Mon Sep 17 00:00:00 2001 From: Kyle Belanger Date: Thu, 20 Feb 2025 09:19:20 -0500 Subject: [PATCH] provide tailored Resume --- data/resume_parser_api.json | 2 +- public/css/base_styles.css | 7 ++++++- public/css/styles.css | 3 +++ public/index.html | 6 ++++++ public/js/script.js | 3 +++ routes/generate.js | 28 +++++++++++++++++++++------- 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/data/resume_parser_api.json b/data/resume_parser_api.json index 679a78b..ebcf44d 100644 --- a/data/resume_parser_api.json +++ b/data/resume_parser_api.json @@ -8,7 +8,7 @@ "content": [ { "type": "text", - "text": "You are an advanced resume parsing system designed to extract key information from resumes and organize it into a structured format. Your task is to analyze the following resume and create a JSON object containing the most relevant and insightful information.\n\nHere is the resume you need to parse:\n\n\n{{resume}}\n\n\nPlease follow these steps to complete the task:\n\n1. Carefully read through the entire resume.\n\n2. Extract the following information:\n - First name\n - Last name\n - Location\n - Work experience\n - School experience\n - Skills\n\n3. For each category, focus on the most insightful and relevant information.\n\n4. Organize the extracted information into a JSON object with the following keys:\n - first_name\n - last_name\n - location\n - work_experience\n - school_experience\n - skills\n\nBefore providing the final JSON output, break down the resume inside tags:\n\n- Quote the relevant sections for first name, last name, and location.\n- For work experience, list out each entry with numbers, quoting relevant details for company, position, duration, and key responsibilities.\n- For school experience, list out each entry with numbers, quoting relevant details for institution, degree, field of study, and graduation year.\n- For skills, categorize them into technical and soft skills, listing each skill.\n- Double-check that all required fields in the JSON structure have corresponding information from the resume.\n\nThis breakdown will help ensure a thorough and accurate parsing of the resume.\n\nHere's an example of the expected JSON structure (note that this is just a structural example and does not contain actual data):\n\n```json\n{\n \"first_name\": \"String\",\n \"last_name\": \"String\",\n \"location\": \"String\",\n \"work_experience\": [\n {\n \"company\": \"String\",\n \"position\": \"String\",\n \"duration\": \"String\",\n \"responsibilities\": [\"String\", \"String\"]\n }\n ],\n \"school_experience\": [\n {\n \"institution\": \"String\",\n \"degree\": \"String\",\n \"field_of_study\": \"String\",\n \"graduation_year\": \"Number\"\n }\n ],\n \"skills\": [\"String\", \"String\", \"String\"]\n}\n```\n\nPlease ensure that your final JSON output follows this structure, but with actual data extracted from the provided resume." + "text": "Here is the resume you need to parse:\n\n\n{{resume}}\n\n\nYou are an advanced resume parsing system designed to extract key information from resumes and organize it into a structured JSON format. Your task is to analyze the above resume and create a JSON object containing the most relevant and insightful information.\n\nPlease follow these steps to complete the task:\n\n1. Carefully read through the entire resume.\n\n2. Extract the following information:\n - First name\n - Last name\n - Location\n - Email\n - Phone Number\n - Work experience\n - School experience\n - Skills\n\n3. For each category, focus on the most insightful and relevant information.\n\n4. Wrap the resume breakdown in tags:\n\n - Quote the relevant sections for first name, last name, email, phone number, and location.\n - For work experience, list out each entry with numbers, quoting relevant details for the company, position, duration, and key responsibilities. Note any achievements or quantifiable results.\n - For school experience, list out each entry with numbers, quoting relevant details for institution, degree, field of study, and graduation year. Include any notable academic achievements.\n - For skills, categorize them into technical skills, soft skills, and domain-specific skills, listing each skill.\n - Identify any unique selling points or standout information in the resume.\n - If any information is missing from the resume, explicitly state that it's not found.\n\n5. Organize the extracted information into a JSON object with the following structure:\n\n```json\n{\n \"first_name\": \"String\",\n \"last_name\": \"String\",\n \"location\": \"String\",\n \"email\": \"String\",\n \"phone_number\": \"String\",\n \"work_experience\": [\n {\n \"company\": \"String\",\n \"position\": \"String\",\n \"duration\": \"String\",\n \"responsibilities\": [\"String\", \"String\"],\n \"achievements\": [\"String\", \"String\"]\n }\n ],\n \"school_experience\": [\n {\n \"institution\": \"String\",\n \"degree\": \"String\",\n \"field_of_study\": \"String\",\n \"graduation_year\": \"Number\",\n \"achievements\": [\"String\", \"String\"]\n }\n ],\n \"skills\": {\n \"technical\": [\"String\", \"String\"],\n \"soft\": [\"String\", \"String\"],\n \"domain_specific\": [\"String\", \"String\"]\n },\n \"unique_selling_points\": [\"String\", \"String\"]\n}\n```\n\nImportant: \n- Include all specified categories in the JSON output, even if the information is not found in the resume. \n- For missing information, use empty string values (\"\") or empty arrays ([]) as appropriate.\n- For work_experience and school_experience, if no entries are found, include an empty array.\n- For skills, if no skills are found in a category, include an empty array for that category.\n\nAfter the section, provide the final JSON output in tags. Ensure that your JSON output follows the structure provided above, with actual data extracted from the resume or empty values for missing information." } ] }, diff --git a/public/css/base_styles.css b/public/css/base_styles.css index 60aefcf..47e939b 100644 --- a/public/css/base_styles.css +++ b/public/css/base_styles.css @@ -11,8 +11,13 @@ display: none; } +#tailoredResumeSection { + display: none; +} + @layer base { textarea { resize: auto; } -} \ No newline at end of file +} + diff --git a/public/css/styles.css b/public/css/styles.css index 90fcb6f..3bfe3b7 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -549,6 +549,9 @@ #coverLetterSection { display: none; } +#tailoredResumeSection { + display: none; +} @layer base { textarea { resize: auto; diff --git a/public/index.html b/public/index.html index 63e6d45..45a5eec 100644 --- a/public/index.html +++ b/public/index.html @@ -34,6 +34,12 @@ +
+

Tailored Resume:

+ +

Key Updates

+
 
+  
diff --git a/public/js/script.js b/public/js/script.js index ea68b35..9c66580 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -104,6 +104,9 @@ document.getElementById("generateCoverLetterBtn").addEventListener("click", asyn const formattedText = formatCoverLetter(data.coverLetter); document.getElementById("coverLetterOutput").value = formattedText; document.getElementById("coverLetterSection").style.display = "grid"; // Show cover letter section + document.getElementById("tailoredResumeSection").style.display = "grid"; + document.getElementById("tailoredResumeOutput").value = data.tailoredResumeText; + document.getElementById("keyResumeUpdates").textContent = data.resumeChanges; generateBtn.textContent = "Generate New Cover Letter" } } catch (error) { diff --git a/routes/generate.js b/routes/generate.js index bb55c5e..34c8bcf 100644 --- a/routes/generate.js +++ b/routes/generate.js @@ -48,7 +48,7 @@ router.post('/extract-resume', upload.single('resume'), async (req, res) => { const resumeResponse = await anthropic.messages.create(resume_parser_api); // Extract JSON-formatted profile from the response - const candidateProfile = resumeResponse.content[0].text.split('```json')[1].split('```')[0].trim(); + const candidateProfile = resumeResponse.content[0].text.split('')[1].split('')[0].trim(); res.json({candidateProfile: JSON.parse(candidateProfile) }); @@ -61,20 +61,34 @@ router.post('/extract-resume', upload.single('resume'), async (req, res) => { // Handle Resume upload and user input for Job Description router.post('/', async (req, res) => { try { + // Load Variables const { candidateProfile, jobDescription, keyPoints } = req.body; + const coverLetterAPI = require('../data/cover_letter_api.json'); + const resumeTailoringAPI = require('../data/resume_tailoring_api.json'); - const cover_letter_api = require('../data/cover_letter_api.json'); - - cover_letter_api.messages[0].content[0].text = cover_letter_api.messages[0].content[0].text + // Replace API placeholders + coverLetterAPI.messages[0].content[0].text = coverLetterAPI.messages[0].content[0].text .replace('{{resume_json}}', candidateProfile) .replace('{{job_description}}', jobDescription) .replace('{{key_points}}', keyPoints ) .replace('{{date}}', new Date().toDateString()); - const coverLetterResponse = await anthropic.messages.create(cover_letter_api); - const coverLetterRawText = coverLetterResponse.content[0].text.split('')[1].split('')[0].trim(); - res.json({ coverLetter: coverLetterRawText }); + resumeTailoringAPI.messages[0].content[0].text = resumeTailoringAPI.messages[0].content[0].text + .replace('{{resume_json}}', candidateProfile) + .replace('{{job_description}}', jobDescription) + + // Send Messages to LLM + const coverLetterResponse = await anthropic.messages.create(coverLetterAPI); + const tailoredResumeResponse = await anthropic.messages.create(resumeTailoringAPI); + + // Extract Relevant Responses + const coverLetterRawText = coverLetterResponse.content[0].text.split('')[1].split('')[0].trim(); + const tailoredResumeText = tailoredResumeResponse.content[0].text.split('')[1].split('')[0].trim(); + const resumeChanges = tailoredResumeResponse.content[0].text.split('')[1].split('')[0].trim(); + + + res.json({ coverLetter: coverLetterRawText, tailoredResumeText, resumeChanges }); } catch (error) { console.error(error); res.status(500).json({ error: 'Error generating cover letter' });