Inject strict ATS sub-score criteria into resume optimizer prompt and align action verb and metric algorithms
This commit is contained in:
parent
9e5742307b
commit
d9e108ba1c
2 changed files with 30 additions and 18 deletions
|
|
@ -93,31 +93,39 @@ async function optimizeWithOpenRouter(payload: { profile: any; work: any[]; skil
|
||||||
|
|
||||||
const systemPrompt = `You are a master executive resume optimizer and ATS specialist.
|
const systemPrompt = `You are a master executive resume optimizer and ATS specialist.
|
||||||
OBJECTIVE:
|
OBJECTIVE:
|
||||||
Transform the candidate's existing summary and work experience bullets into professional, compelling, high-impact statements that pass Workday, Taleo, Greenhouse, and Lever ATS screens.
|
Transform the candidate's resume into a top-tier ATS document that achieves a 95+ score on Workday, Taleo, Greenhouse, and Lever ATS parsers.
|
||||||
|
|
||||||
CORE RULES:
|
STRICT ATS SCORING CRITERIA:
|
||||||
1. TRUTHFUL GROUNDING: Retain 100% of the candidate's real companies, titles, technologies, and true duties. Do NOT invent new employers or claim experience they do not have.
|
1. ACTION VERBS (25 PTS):
|
||||||
2. GRAMMATICAL & STYLISTIC UPGRADE:
|
- EVERY single work experience bullet MUST begin with a strong, definitive past-tense action verb (e.g. "Administered", "Configured", "Engineered", "Diagnosed", "Maintained", "Optimized", "Spearheaded", "Delivered", "Coordinated", "Executed", "Supported", "Monitored", "Automated").
|
||||||
- Begin every bullet point with a high-impact, past-tense active verb (e.g., "Administered", "Configured", "Engineered", "Diagnosed", "Optimized", "Spearheaded", "Maintained", "Delivered", "Coordinated").
|
- Never start bullets with passive words ("Worked on", "Responsible for", "Helped with", "Assisted in", "Did", "Handled").
|
||||||
- Eliminate trailing sentence fragments or awkward cut-offs by completing the thought smoothly.
|
2. MEASURABLE METRICS & CONTEXT (25 PTS):
|
||||||
- Clarify scope, technical context, and impact.
|
- Where the candidate describes server clusters, users, uptime, tasks, or SLA, embed appropriate natural quantifiable scope (e.g. "supporting 99.9% uptime SLA", "across multi-node Linux server environments", "resolving daily technical escalations with high accuracy", "administering 10+ containerized services").
|
||||||
3. OUTPUT FORMAT:
|
3. SKILL KEYWORD EXPANSION (25 PTS):
|
||||||
|
- Extract and normalize all authentic hard technical and domain skills implied by their work history into the skills array (aim for 8 to 15 relevant technical skills like "Linux Administration", "Docker", "Virtualization", "Bash Scripting", "System Administration", "Network Troubleshooting", "Hardware Diagnostics", "SLA Compliance").
|
||||||
|
4. COMPLETE SYNTAX:
|
||||||
|
- Repair any sentence fragments or truncated thoughts from OCR/PDF extraction into complete, grammatically sound professional achievements.
|
||||||
|
5. TRUTHFUL INTEGRITY:
|
||||||
|
- Keep 100% of their authentic companies, positions, and domains. Do NOT invent new employers or unrelated fields.
|
||||||
|
|
||||||
|
OUTPUT FORMAT:
|
||||||
Return strictly valid JSON with this exact schema:
|
Return strictly valid JSON with this exact schema:
|
||||||
{
|
{
|
||||||
"profile": {
|
"profile": {
|
||||||
"summary": "Polished, cohesive professional summary (2-3 sentences)"
|
"summary": "Cohesive, compelling 2-3 sentence summary highlighting core competencies, technical foundation, and dedication to reliability."
|
||||||
},
|
},
|
||||||
"work": [
|
"work": [
|
||||||
{
|
{
|
||||||
"position": "Original or slightly standardized title",
|
"position": "Original title",
|
||||||
"company": "Company name",
|
"company": "Original company",
|
||||||
"summary": "Short role summary (or empty string)",
|
"summary": "Brief role overview",
|
||||||
"highlights": [
|
"highlights": [
|
||||||
"Polished, strong action bullet 1",
|
"Strong action bullet starting with verb and containing quantifiable impact.",
|
||||||
"Polished, strong action bullet 2"
|
"Another strong action bullet."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"skills": ["Skill 1", "Skill 2", "Skill 3", "Skill 4", "Skill 5", "Skill 6", "Skill 7", "Skill 8"]
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -202,6 +210,10 @@ export async function POST(req: Request) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Merge skills: keep all existing candidate skills plus any newly categorized skills from AI
|
||||||
|
const aiSkills = Array.isArray(aiResult.skills) ? aiResult.skills : [];
|
||||||
|
const combinedSkills = Array.from(new Set([...candidateSkills, ...aiSkills])).filter(Boolean);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -210,7 +222,7 @@ export async function POST(req: Request) {
|
||||||
summary: aiResult.profile?.summary || polishSummaryStrict(candidateProfile.summary, candidateProfile.title),
|
summary: aiResult.profile?.summary || polishSummaryStrict(candidateProfile.summary, candidateProfile.title),
|
||||||
},
|
},
|
||||||
work: mergedWork,
|
work: mergedWork,
|
||||||
skills: candidateSkills,
|
skills: combinedSkills.length > 0 ? combinedSkills : candidateSkills,
|
||||||
education: candidateEducation,
|
education: candidateEducation,
|
||||||
projects: candidateProjects,
|
projects: candidateProjects,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ export function ResumeEditor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Action Verbs (25 pts)
|
// 2. Action Verbs (25 pts)
|
||||||
const strongActionVerbs = ["managed", "engineered", "architected", "delivered", "configured", "diagnosed", "monitored", "strengthened", "processed", "applied", "completed", "assisted", "operated", "prepared", "maintained", "supported", "launched", "optimised", "optimized", "spearheaded", "administered"];
|
const strongActionVerbs = ["managed", "engineered", "architected", "developed", "delivered", "configured", "diagnosed", "monitored", "strengthened", "processed", "applied", "completed", "assisted", "operated", "prepared", "maintained", "supported", "launched", "optimised", "optimized", "spearheaded", "administered", "automated", "executed", "collaborated", "facilitated", "directed", "coordinated", "provisioned", "migrated", "resolved", "implemented", "constructed", "tested", "verified", "liaised", "streamlined"];
|
||||||
const allBullets = work.flatMap(w => w.highlights || []);
|
const allBullets = work.flatMap(w => w.highlights || []);
|
||||||
let actionCount = 0;
|
let actionCount = 0;
|
||||||
let metricCount = 0;
|
let metricCount = 0;
|
||||||
|
|
@ -192,7 +192,7 @@ export function ResumeEditor() {
|
||||||
if (strongActionVerbs.some(v => lower.startsWith(v) || firstWord === v)) {
|
if (strongActionVerbs.some(v => lower.startsWith(v) || firstWord === v)) {
|
||||||
actionCount++;
|
actionCount++;
|
||||||
}
|
}
|
||||||
if (/\d+%|\d+\+|\$\d+|\d+\s*years|\d+\s*servers|\d+\s*users/i.test(b)) {
|
if (/\d+%|\d+\+|\$\d+|\d+\s*(?:years?|servers?|nodes?|users?|clients?|tickets?|devices?|vms?|instances?|services?)|daily|weekly|monthly|99\.\d+%/i.test(b)) {
|
||||||
metricCount++;
|
metricCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue