1
This commit is contained in:
123
api/services/job_type_ai_sync_service.js
Normal file
123
api/services/job_type_ai_sync_service.js
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* 根据 get_job_listings 返回的 Tab 列表,用 AI 更新 job_types 的 description / excludeKeywords / commonSkills
|
||||
*/
|
||||
const db = require('../middleware/dbProxy');
|
||||
const aiService = require('./ai_service');
|
||||
|
||||
/**
|
||||
* 从模型回复中解析 JSON 对象
|
||||
* @param {string} text
|
||||
* @returns {object|null}
|
||||
*/
|
||||
function parseJsonFromAi(text) {
|
||||
if (!text || typeof text !== 'string') return null;
|
||||
let s = text.trim();
|
||||
const fence = s.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
||||
if (fence) s = fence[1].trim();
|
||||
try {
|
||||
return JSON.parse(s);
|
||||
} catch (e) {
|
||||
const m = s.match(/\{[\s\S]*\}/);
|
||||
if (m) {
|
||||
try {
|
||||
return JSON.parse(m[0]);
|
||||
} catch (e2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功拉取 job_listings 后:若账号绑定了 job_type_id,则用 AI 更新对应 job_types 行
|
||||
* @param {string} sn_code
|
||||
* @param {Array<{ index?: number, text?: string }>} tabs
|
||||
* @param {string} platform
|
||||
* @returns {Promise<{ updated: boolean, jobTypeId?: number }|null>}
|
||||
*/
|
||||
async function maybeSyncAfterListings(sn_code, tabs, platform = 'boss') {
|
||||
if (!sn_code) return null;
|
||||
|
||||
const pla_account = db.getModel('pla_account');
|
||||
const account = await pla_account.findOne({
|
||||
where: { sn_code, is_delete: 0 }
|
||||
});
|
||||
if (!account || !account.job_type_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const job_types = db.getModel('job_types');
|
||||
const jobType = await job_types.findByPk(account.job_type_id);
|
||||
if (!jobType) {
|
||||
console.warn('[job_type_ai_sync] job_types 不存在, id=', account.job_type_id);
|
||||
return null;
|
||||
}
|
||||
|
||||
const tabTexts = (tabs || [])
|
||||
.map((t) => (t && t.text != null ? String(t.text).trim() : ''))
|
||||
.filter(Boolean);
|
||||
if (tabTexts.length === 0) {
|
||||
console.warn('[job_type_ai_sync] Tab 列表为空,跳过 AI 更新');
|
||||
return null;
|
||||
}
|
||||
|
||||
const typeName = jobType.name || '';
|
||||
const labelsStr = tabTexts.join('、');
|
||||
|
||||
const prompt = `你是招聘平台求职助手。用户在某招聘网站的「期望职类/Tab」列表如下(按顺序):
|
||||
${labelsStr}
|
||||
|
||||
当前在系统中登记的职位类型名称为:「${typeName}」
|
||||
平台标识:${platform}
|
||||
|
||||
请根据上述 Tab 名称,补充该求职方向的说明、自动投递时应排除的岗位关键词、以及该方向常见技能关键词。
|
||||
|
||||
请只输出一段 JSON(不要 Markdown 代码块,不要其它说明),格式严格如下:
|
||||
{"description":"50~200字中文,概括该求职方向","excludeKeywords":["关键词1","关键词2"],"commonSkills":["技能1","技能2"]}
|
||||
|
||||
要求:
|
||||
- description:面向求职者的简短说明。
|
||||
- excludeKeywords:5~12 个字符串,用于过滤明显不合适的岗位(如用户做研发可排除「纯销售」「客服」等,按 Tab 语义推断)。
|
||||
- commonSkills:8~20 个字符串,该方向常见技能或技术栈关键词,用于匹配加分。
|
||||
- 所有字符串使用中文或业界通用英文技术词均可。`;
|
||||
|
||||
const { content } = await aiService.callAPI(prompt, {
|
||||
systemPrompt: '你只输出合法 JSON 对象,键为 description、excludeKeywords、commonSkills,不要输出其它文字。',
|
||||
temperature: 0.35,
|
||||
maxTokens: 2000,
|
||||
sn_code,
|
||||
service_type: 'job_type_sync',
|
||||
business_type: 'job_type_listings'
|
||||
});
|
||||
|
||||
const parsed = parseJsonFromAi(content);
|
||||
if (!parsed || typeof parsed !== 'object') {
|
||||
throw new Error('AI 返回无法解析为 JSON');
|
||||
}
|
||||
|
||||
const description = String(parsed.description || '').slice(0, 4000);
|
||||
const excludeArr = Array.isArray(parsed.excludeKeywords) ? parsed.excludeKeywords.map(String) : [];
|
||||
const skillsArr = Array.isArray(parsed.commonSkills) ? parsed.commonSkills.map(String) : [];
|
||||
|
||||
await job_types.update(
|
||||
{
|
||||
description,
|
||||
excludeKeywords: JSON.stringify(excludeArr),
|
||||
commonSkills: JSON.stringify(skillsArr),
|
||||
pla_account_id: account.id
|
||||
},
|
||||
{ where: { id: jobType.id } }
|
||||
);
|
||||
|
||||
console.log(
|
||||
`[job_type_ai_sync] 已更新 job_types id=${jobType.id} pla_account_id=${account.id} exclude=${excludeArr.length} skills=${skillsArr.length}`
|
||||
);
|
||||
|
||||
return { updated: true, jobTypeId: jobType.id };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
maybeSyncAfterListings,
|
||||
parseJsonFromAi
|
||||
};
|
||||
Reference in New Issue
Block a user