使用GPT-4评分和Gmail通知自动化候选人评估
中级
这是一个HR, AI Summarization领域的自动化工作流,包含 12 个节点。主要使用 If, Set, Code, Gmail, Webhook 等节点。 使用GPT-4评分和Gmail通知自动化候选人评估
前置要求
- •Google 账号和 Gmail API 凭证
- •HTTP Webhook 端点(n8n 会自动生成)
- •可能需要目标 API 的认证凭证
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"nodes": [
{
"id": "1",
"name": "CV 提交 Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
240,
300
],
"parameters": {
"path": "cv-received",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 1
},
{
"id": "2",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
140,
180
],
"parameters": {
"width": 240,
"height": 160,
"content": "## 招聘 AI 配置"
},
"typeVersion": 1
},
{
"id": "3",
"name": "职位要求",
"type": "n8n-nodes-base.set",
"position": [
440,
300
],
"parameters": {
"values": {
"number": [
{
"name": "minExperience",
"value": 5
},
{
"name": "passingScore",
"value": 75
}
],
"string": [
{
"name": "requiredSkills",
"value": "JavaScript,React,Node.js,Python"
}
]
}
},
"typeVersion": 1
},
{
"id": "4",
"name": "使用 AI 解析简历",
"type": "n8n-nodes-base.httpRequest",
"position": [
640,
300
],
"parameters": {
"url": "https://api.openai.com/v1/chat/completions",
"body": {
"model": "gpt-4",
"messages": [
{
"role": "system",
"content": "You are a CV parsing expert. Extract key information from CVs and return structured JSON data."
},
{
"role": "user",
"content": "Parse this CV and extract: name, email, phone, skills, experience_years, education, previous_roles. CV content: {{ $json.cv_content }}"
}
],
"response_format": {
"type": "json_object"
}
},
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{ $credentials.openai.apiKey }}"
}
},
"typeVersion": 1
},
{
"id": "5",
"name": "候选人评分",
"type": "n8n-nodes-base.code",
"position": [
840,
300
],
"parameters": {
"jsCode": "// Intelligent candidate scoring algorithm\nconst candidate = $json.choices[0].message.content;\nconst requirements = $node['Job Requirements'].json;\nconst candidateData = JSON.parse(candidate);\n\nlet totalScore = 0;\n\n// Skills matching (40% weight)\nconst requiredSkills = requirements.requiredSkills.split(',');\nconst candidateSkills = candidateData.skills || [];\nconst skillsMatch = requiredSkills.filter(skill => \n candidateSkills.some(cSkill => cSkill.toLowerCase().includes(skill.toLowerCase()))\n);\nconst skillsScore = (skillsMatch.length / requiredSkills.length) * 40;\ntotalScore += skillsScore;\n\n// Experience scoring (30% weight)\nconst experienceYears = candidateData.experience_years || 0;\nlet experienceScore = 0;\nif (experienceYears >= requirements.minExperience) {\n experienceScore = 30;\n} else if (experienceYears >= requirements.minExperience * 0.8) {\n experienceScore = 25;\n} else if (experienceYears >= requirements.minExperience * 0.6) {\n experienceScore = 20;\n} else {\n experienceScore = 10;\n}\ntotalScore += experienceScore;\n\n// Education scoring (20% weight)\nconst education = candidateData.education || '';\nlet educationScore = 0;\nif (education.toLowerCase().includes('master') || education.toLowerCase().includes('phd')) {\n educationScore = 20;\n} else if (education.toLowerCase().includes('bachelor') || education.toLowerCase().includes('degree')) {\n educationScore = 15;\n} else {\n educationScore = 10;\n}\ntotalScore += educationScore;\n\n// Role relevance (10% weight)\nconst previousRoles = candidateData.previous_roles || [];\nconst roleRelevance = previousRoles.some(role => \n role.toLowerCase().includes('engineer') || role.toLowerCase().includes('developer')\n) ? 10 : 5;\ntotalScore += roleRelevance;\n\n// Determine recommendation\nlet recommendation = 'reject';\nlet priority = 'low';\n\nif (totalScore >= 85) {\n recommendation = 'hire';\n priority = 'high';\n} else if (totalScore >= requirements.passingScore) {\n recommendation = 'interview';\n priority = 'medium';\n} else if (totalScore >= 60) {\n recommendation = 'phone_screen';\n priority = 'low';\n}\n\nreturn {\n candidateData,\n scoring: {\n skillsScore,\n experienceScore,\n educationScore,\n roleRelevance,\n totalScore: Math.round(totalScore),\n recommendation,\n priority\n },\n jobTitle: requirements.jobTitle,\n evaluatedAt: new Date().toISOString()\n};"
},
"typeVersion": 1
},
{
"id": "6",
"name": "检查是否为顶尖候选人",
"type": "n8n-nodes-base.if",
"position": [
1040,
200
],
"parameters": {
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.scoring.recommendation }}",
"rightValue": "hire"
}
]
}
},
"typeVersion": 2
},
{
"id": "7",
"name": "提醒 HR 团队",
"type": "n8n-nodes-base.gmail",
"position": [
1240,
100
],
"parameters": {
"sendTo": "={{ $node['Job Requirements'].json.hrEmail }}",
"message": "=<!DOCTYPE html>\n<html>\n<head>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n .top-candidate { background: linear-gradient(45deg, #28a745, #20c997); color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 10px; }\n .candidate-info { background: #d4edda; padding: 15px; margin: 15px 0; border-radius: 5px; }\n .score-breakdown { background: #f8f9fa; padding: 15px; margin: 15px 0; border-radius: 5px; }\n .cta { background: #007bff; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"top-candidate\">\n <h2>🌟 EXCEPTIONAL CANDIDATE</h2>\n <p>High-priority candidate for {{ $json.jobTitle }}</p>\n </div>\n \n <div class=\"candidate-info\">\n <h3>👤 Candidate Profile</h3>\n <p><strong>Name:</strong> {{ $json.candidateData.name }}</p>\n <p><strong>Email:</strong> {{ $json.candidateData.email }}</p>\n <p><strong>Phone:</strong> {{ $json.candidateData.phone }}</p>\n <p><strong>Experience:</strong> {{ $json.candidateData.experience_years }} years</p>\n <p><strong>Education:</strong> {{ $json.candidateData.education }}</p>\n </div>\n \n <div class=\"score-breakdown\">\n <h3>📊 Scoring Breakdown</h3>\n <p><strong>Overall Score:</strong> {{ $json.scoring.totalScore }}/100</p>\n <p><strong>Skills Match:</strong> {{ $json.scoring.skillsScore }}/40</p>\n <p><strong>Experience:</strong> {{ $json.scoring.experienceScore }}/30</p>\n <p><strong>Education:</strong> {{ $json.scoring.educationScore }}/20</p>\n <p><strong>Role Relevance:</strong> {{ $json.scoring.roleRelevance }}/10</p>\n </div>\n \n <div style=\"text-align: center;\">\n <a href=\"mailto:{{ $json.candidateData.email }}\" class=\"cta\">📧 Contact Candidate</a>\n <a href=\"https://calendly.com/interview-{{ $json.candidateData.name }}\" class=\"cta\">📅 Schedule Interview</a>\n </div>\n \n <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n Recommendation: {{ $json.scoring.recommendation }} | Priority: {{ $json.scoring.priority }}\n </p>\n </div>\n</body>\n</html>",
"options": {
"contentType": "html"
},
"subject": "🌟 Top Candidate Alert - {{ $json.jobTitle }}"
},
"typeVersion": 1
},
{
"id": "8",
"name": "检查是否值得面试",
"type": "n8n-nodes-base.if",
"position": [
1040,
300
],
"parameters": {
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.scoring.recommendation }}",
"rightValue": "interview"
}
]
}
},
"typeVersion": 2
},
{
"id": "9",
"name": "发送面试邀请",
"type": "n8n-nodes-base.gmail",
"position": [
1240,
300
],
"parameters": {
"sendTo": "={{ $json.candidateData.email }}",
"message": "=<!DOCTYPE html>\n<html>\n<head>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n .interview-invite { background: #007bff; color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }\n .next-steps { background: #e8f4f8; padding: 15px; margin: 15px 0; border-radius: 5px; }\n .cta { background: #28a745; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"interview-invite\">\n <h2>🎉 Interview Invitation</h2>\n <p>Congratulations! We'd like to interview you for the {{ $json.jobTitle }} position.</p>\n </div>\n \n <p>Dear {{ $json.candidateData.name }},</p>\n \n <p>We were impressed by your profile and would like to invite you for an interview.</p>\n \n <div class=\"next-steps\">\n <h3>📅 Next Steps</h3>\n <ul>\n <li>Schedule your interview using the link below</li>\n <li>Prepare for technical questions about your experience</li>\n <li>Review our company culture and values</li>\n <li>Prepare questions about the role and team</li>\n </ul>\n </div>\n \n <div style=\"text-align: center;\">\n <a href=\"https://calendly.com/interview-{{ $json.candidateData.name }}\" class=\"cta\">\n 📅 Schedule Your Interview\n </a>\n </div>\n \n <p>Looking forward to meeting you!</p>\n \n <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n Best regards,<br>\n HR Team\n </p>\n </div>\n</body>\n</html>",
"options": {
"contentType": "html"
},
"subject": "Interview Invitation - {{ $json.jobTitle }} Position"
},
"typeVersion": 1
},
{
"id": "10",
"name": "检查是否被拒绝",
"type": "n8n-nodes-base.if",
"position": [
1040,
400
],
"parameters": {
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.scoring.recommendation }}",
"rightValue": "reject"
}
]
}
},
"typeVersion": 2
},
{
"id": "11",
"name": "发送拒绝邮件",
"type": "n8n-nodes-base.gmail",
"position": [
1240,
400
],
"parameters": {
"sendTo": "={{ $json.candidateData.email }}",
"message": "=<!DOCTYPE html>\n<html>\n<head>\n <style>\n body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n .thank-you { background: #6c757d; color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }\n .feedback { background: #f8f9fa; padding: 15px; margin: 15px 0; border-radius: 5px; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"thank-you\">\n <h2>Thank You for Your Interest</h2>\n <p>We appreciate you taking the time to apply for the {{ $json.jobTitle }} position.</p>\n </div>\n \n <p>Dear {{ $json.candidateData.name }},</p>\n \n <p>Thank you for your application. While your background is impressive, we have decided to move forward with other candidates who more closely match our current requirements.</p>\n \n <div class=\"feedback\">\n <h3>💡 For Future Opportunities</h3>\n <p>We encourage you to:</p>\n <ul>\n <li>Continue developing your technical skills</li>\n <li>Gain more relevant experience in your field</li>\n <li>Apply for future positions that match your expertise</li>\n </ul>\n </div>\n \n <p>We'll keep your resume on file and will reach out if a suitable position becomes available.</p>\n \n <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n Best regards,<br>\n HR Team\n </p>\n </div>\n</body>\n</html>",
"options": {
"contentType": "html"
},
"subject": "Thank you for your application - {{ $json.jobTitle }}"
},
"typeVersion": 1
},
{
"id": "12",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1140,
60
],
"parameters": {
"width": 240,
"height": 160,
"content": "## AI 驱动决策"
},
"typeVersion": 1
}
],
"connections": {
"Score Candidate": {
"main": [
[
{
"node": "Check If Top Candidate",
"type": "main",
"index": 0
},
{
"node": "Check If Interview Worthy",
"type": "main",
"index": 0
},
{
"node": "Check If Rejected",
"type": "main",
"index": 0
}
]
]
},
"Job Requirements": {
"main": [
[
{
"node": "Parse CV with AI",
"type": "main",
"index": 0
}
]
]
},
"Parse CV with AI": {
"main": [
[
{
"node": "Score Candidate",
"type": "main",
"index": 0
}
]
]
},
"Check If Rejected": {
"main": [
[
{
"node": "Send Rejection Email",
"type": "main",
"index": 0
}
]
]
},
"CV Submission Webhook": {
"main": [
[
{
"node": "Job Requirements",
"type": "main",
"index": 0
}
]
]
},
"Check If Top Candidate": {
"main": [
[
{
"node": "Alert HR Team",
"type": "main",
"index": 0
}
]
]
},
"Check If Interview Worthy": {
"main": [
[
{
"node": "Send Interview Invitation",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 人力资源, AI 摘要总结
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用AI评分和Gmail推广管理社交媒体影响者活动
使用AI评分和Gmail推广管理社交媒体影响者活动
If
Set
Code
+6
15 节点Rodrigue
社交媒体
供应商风险评分自动化
使用D&B、NewsAPI和Gmail提醒自动化供应商风险评分
If
Set
Code
+6
16 节点Rodrigue
杂项
多司法管辖区智能合约合规监控器 - 自动警报
多司法管辖区智能合约合规监控器,支持自动警报
If
Set
Code
+6
16 节点Rodrigue
文档提取
基于Stripe、Postgres和Gmail的订阅收入优化器 - 预测性留存
基于Stripe、Postgres和Gmail的订阅收入优化器 - 预测性留存
If
Set
Code
+5
15 节点Rodrigue
客户关系管理
使用JotForm、Azure OCR、GPT-4.1、Zoho CRM自动化简历分析与候选人筛选
使用JotForm、Azure OCR、GPT-4.1、Zoho CRM自动化简历分析与候选人筛选
If
Set
Code
+10
25 节点moosa
人力资源
AI驱动的自动化求职与申请工作流
AI驱动的自动化求职与申请
If
Set
Code
+10
21 节点Gerald Denor
人力资源