const axios = require('axios'); const config = require('../../../config/config'); const logs = require('../logProxy'); /** * DeepSeek大模型服务 * 集成DeepSeek API,提供智能化的岗位筛选、聊天生成、简历分析等功能 */ class aiService { constructor() { this.apiKey = config.deepseekApiKey || process.env.DEEPSEEK_API_KEY; this.apiUrl = config.deepseekApiUrl || 'https://api.deepseek.com/v1/chat/completions'; this.model = config.deepseekModel || 'deepseek-chat'; this.maxRetries = 3; } /** * 调用DeepSeek API * @param {string} prompt - 提示词 * @param {object} options - 配置选项 * @returns {Promise} API响应结果 */ async callAPI(prompt, options = {}) { const requestData = { model: this.model, messages: [ { role: 'system', content: options.systemPrompt || '你是一个专业的招聘顾问,擅长分析岗位信息、生成聊天内容和分析简历匹配度。' }, { role: 'user', content: prompt } ], temperature: options.temperature || 0.7, max_tokens: options.maxTokens || 2000, top_p: options.topP || 0.9 }; for (let attempt = 1; attempt <= this.maxRetries; attempt++) { try { const response = await axios.post(this.apiUrl, requestData, { headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, timeout: 30000 }); return { data: response.data, content: response.data.choices?.[0]?.message?.content || '' }; } catch (error) { console.log(`DeepSeek API调用失败 (尝试 ${attempt}/${this.maxRetries}): ${error.message}`); if (attempt === this.maxRetries) { throw new Error(error.message); } // 等待后重试 await new Promise(resolve => setTimeout(resolve, 1000 * attempt)); } } } /** * 岗位智能筛选 * @param {object} jobInfo - 岗位信息 * @param {object} resumeInfo - 简历信息 * @returns {Promise} 筛选结果 */ async analyzeJob(jobInfo, resumeInfo) { const prompt = ` 请分析以下岗位信息,并给出详细的评估结果: 岗位信息: - 公司名称:${jobInfo.companyName || '未知'} - 职位名称:${jobInfo.jobTitle || '未知'} - 薪资范围:${jobInfo.salary || '未知'} - 工作地点:${jobInfo.location || '未知'} - 岗位描述:${jobInfo.description || '未知'} - 技能要求:${jobInfo.skills || '未知'} 简历信息: - 技能标签:${resumeInfo.skills || '未知'} - 工作经验:${resumeInfo.experience || '未知'} - 教育背景:${resumeInfo.education || '未知'} - 期望薪资:${resumeInfo.expectedSalary || '未知'} 请从以下维度进行分析: 1. 技能匹配度(0-100分) 2. 经验匹配度(0-100分) 3. 薪资合理性(0-100分) 4. 公司质量评估(0-100分) 5. 是否为外包岗位(是/否) 6. 综合推荐指数(0-100分) 7. 详细分析说明 8. 投递建议 请以JSON格式返回结果。 `; const result = await this.callAPI(prompt, { systemPrompt: '你是一个专业的招聘分析师,擅长评估岗位与简历的匹配度。请提供客观、专业的分析结果。', temperature: 0.3 }); try { // 尝试解析JSON响应 const analysis = JSON.parse(result.content); return { analysis: analysis }; } catch (parseError) { // 如果解析失败,返回原始内容 return { analysis: { content: result.content, parseError: true } }; } } /** * 生成个性化聊天内容 * @param {object} jobInfo - 岗位信息 * @param {object} resumeInfo - 简历信息 * @param {string} chatType - 聊天类型 (greeting/interview/followup) * @returns {Promise} 聊天内容 */ async generateChatContent(jobInfo, resumeInfo, chatType = 'greeting') { const chatTypeMap = { 'greeting': '初次打招呼', 'interview': '面试邀约', 'followup': '跟进沟通' }; const prompt = ` 请为以下场景生成个性化的聊天内容: 聊天类型:${chatTypeMap[chatType] || chatType} 岗位信息: - 公司名称:${jobInfo.companyName || '未知'} - 职位名称:${jobInfo.jobTitle || '未知'} - 技能要求:${jobInfo.skills || '未知'} 简历信息: - 技能标签:${resumeInfo.skills || '未知'} - 工作经验:${resumeInfo.experience || '未知'} - 项目经验:${resumeInfo.projects || '未知'} 要求: 1. 内容要自然、专业、个性化 2. 突出简历与岗位的匹配点 3. 避免过于机械化的表达 4. 长度控制在100-200字 5. 体现求职者的诚意和热情 请直接返回聊天内容,不需要其他格式。 `; const result = await this.callAPI(prompt, { systemPrompt: '你是一个专业的招聘沟通专家,擅长生成自然、专业的求职聊天内容。', temperature: 0.8 }); return result; } /** * 分析简历要素 * @param {string} resumeText - 简历文本内容 * @returns {Promise} 简历分析结果 */ async analyzeResume(resumeText) { const prompt = ` 请分析以下简历内容,提取核心要素: 简历内容: ${resumeText} 请提取以下信息: 1. 技能标签(编程语言、框架、工具等) 2. 工作经验(年限、行业、项目等) 3. 教育背景(学历、专业、证书等) 4. 期望薪资范围 5. 期望工作地点 6. 核心优势 7. 职业发展方向 请以JSON格式返回结果。 `; const result = await this.callAPI(prompt, { systemPrompt: '你是一个专业的简历分析师,擅长提取简历的核心要素和关键信息。', temperature: 0.2 }); try { const analysis = JSON.parse(result.content); return { analysis: analysis }; } catch (parseError) { return { analysis: { content: result.content, parseError: true } }; } } /** * 生成面试邀约内容 * @param {object} jobInfo - 岗位信息 * @param {object} chatHistory - 聊天历史 * @returns {Promise} 面试邀约内容 */ async generateInterviewInvitation(jobInfo, chatHistory) { const prompt = ` 请基于以下信息生成面试邀约内容: 岗位信息: - 公司名称:${jobInfo.companyName || '未知'} - 职位名称:${jobInfo.jobTitle || '未知'} - 工作地点:${jobInfo.location || '未知'} 聊天历史: ${chatHistory || '无'} 要求: 1. 表达面试邀约的诚意 2. 提供灵活的时间选择 3. 说明面试形式和地点 4. 体现对候选人的重视 5. 语言自然、专业 请直接返回面试邀约内容。 `; const result = await this.callAPI(prompt, { systemPrompt: '你是一个专业的HR,擅长生成面试邀约内容。', temperature: 0.6 }); return result; } /** * 识别外包岗位 * @param {object} jobInfo - 岗位信息 * @returns {Promise} 外包识别结果 */ async identifyOutsourcingJob(jobInfo) { const prompt = ` 请分析以下岗位信息,判断是否为外包岗位: 岗位信息: - 公司名称:${jobInfo.companyName || '未知'} - 职位名称:${jobInfo.jobTitle || '未知'} - 岗位描述:${jobInfo.description || '未知'} - 技能要求:${jobInfo.skills || '未知'} - 工作地点:${jobInfo.location || '未知'} 外包岗位特征: 1. 公司名称包含"外包"、"派遣"、"人力"等关键词 2. 岗位描述提到"项目外包"、"驻场开发"等 3. 技能要求过于宽泛或具体 4. 工作地点频繁变动 5. 薪资结构不明确 请判断是否为外包岗位,并给出详细分析。 `; const result = await this.callAPI(prompt, { systemPrompt: '你是一个专业的岗位分析师,擅长识别外包岗位的特征。', temperature: 0.3 }); return result; } } module.exports = new aiService();