From 901c3a51a078181dfe5e326fc6bd65d951007f29 Mon Sep 17 00:00:00 2001 From: geekgeekrun Date: Fri, 11 Apr 2025 23:36:55 +0800 Subject: [PATCH] feat: enhance resume editor and `formatResumeJsonToMarkdown`; add the logic to send resume read from local to llm --- .../utils/format-resume-json-to-markdown.ts | 55 +++++++++++++ .../boss-operation.ts | 12 +-- .../renderer/src/page/ResumeEditor/index.vue | 81 ++++++++++--------- 3 files changed, 107 insertions(+), 41 deletions(-) create mode 100644 packages/ui/src/common/utils/format-resume-json-to-markdown.ts diff --git a/packages/ui/src/common/utils/format-resume-json-to-markdown.ts b/packages/ui/src/common/utils/format-resume-json-to-markdown.ts new file mode 100644 index 0000000..b972112 --- /dev/null +++ b/packages/ui/src/common/utils/format-resume-json-to-markdown.ts @@ -0,0 +1,55 @@ +export function formatResumeJsonToMarkdown(resume) { + const basicInfoText = [ + ['# 姓名', resume.content.name], + ['# 工作年限', resume.content.workYearDesc], + ['# 期望职位', resume.content.expectJob], + ['# 个人优势', resume.content.userDescription] + ] + .filter((it) => { + return Boolean(it[1]?.trim()) + }) + .map((it) => it.join('\n')) + .join('\n\n') + + let formattedWorkExpText = resume.content.geekWorkExpList + .filter((it) => Boolean(it.company?.trim())) + .map((it) => { + const info = [ + [`职务`, it.positionName], + [`任职时间`], + [`工作描述`, it.workDescription], + [`工作业绩`, it.performance] + ].filter((it) => { + return Boolean(it[1]?.trim()) + }) + return [[`## ${it.company}`], ...info].map((it) => it.join('\n')).join('\n\n') + }) + .join('\n') + if (formattedWorkExpText?.trim()) { + formattedWorkExpText = '# 工作经历\n' + formattedWorkExpText + } + + let formattedProjWorkExpText = resume.content.geekProjExpList + .filter((it) => Boolean(it.name?.trim())) + .map((it) => { + const info = [ + [`## ${it.name}`], + [`项目角色`, it.roleName], + [`项目时间`], + [`工作描述`, it.projectDescription], + [`工作业绩`, it.performance] + ].filter((it) => { + return Boolean(it[1]?.trim()) + }) + + return [[`## ${it.name}`], ...info].map((it) => it.join('\n')).join('\n\n') + }) + .join('\n') + if (formattedProjWorkExpText?.trim()) { + formattedProjWorkExpText = '# 项目经历\n' + formattedProjWorkExpText + } + + const result = `${basicInfoText}\n\n${formattedWorkExpText}\n\n${formattedProjWorkExpText}` + + return result +} diff --git a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/boss-operation.ts b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/boss-operation.ts index 7f4007b..ffcf13c 100644 --- a/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/boss-operation.ts +++ b/packages/ui/src/main/flow/READ_NO_REPLY_AUTO_REMINDER/boss-operation.ts @@ -2,6 +2,7 @@ import { Page } from 'puppeteer' import { sleepWithRandomDelay, sleep } from '@geekgeekrun/utils/sleep.mjs' import { completes } from '@geekgeekrun/utils/gpt-request.mjs' import { readConfigFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import { formatResumeJsonToMarkdown } from '../../../common/utils/format-resume-json-to-markdown' export const sendLookForwardReplyEmotion = async (page: Page) => { const emotionEntryButtonProxy = await page.$('.chat-conversation .message-controls .btn-emotion') @@ -18,10 +19,11 @@ export const sendLookForwardReplyEmotion = async (page: Page) => { await lookForwardReplyEmojiProxy!.click() } -const resumeContent = `` // let _index = 0 export const sendGptContent = async (page: Page, chatRecords) => { + const resumeObject = (await readConfigFile('resumes.json'))?.[0] + const resumeContent = formatResumeJsonToMarkdown(resumeObject) const chatList = [ { role: 'system', @@ -32,12 +34,12 @@ export const sendGptContent = async (page: Page, chatRecords) => { - √ 包含1个核心技能 + 1个成果量化 - √ 使用不同句式模板(至少准备5种) - √ 谦虚一些,头衔、工作年限等在历史记录信息中出现一次就好 - - ✗ 禁止与最近发送的几条相似或雷同 - - ✗ 禁止使用专业术语堆砌 + - ✗ 严禁与最近发送的几条相似或雷同 - ✗ 严禁出现简历之外的词语 + - ✗ 严禁包含最近8条已经发过的内容(包括但不限于职位名称) **简历分析层:** -请从以下简历内容中提取关键要素:\n${resumeContent}\n +请从以下简历内容中提取关键要素:\n\`\`\`markdown\n${resumeContent}\n\`\`\`\n --- 要求提取: @@ -53,7 +55,7 @@ export const sendGptContent = async (page: Page, chatRecords) => { 每次生成前执行: 1. 检查历史记录 2. 确保技能/成果组合未重复 -3. 所生成的新消息,严禁包含最近8条已经发过的内容(包括但不限于职位名称) +3. 确保所生成的新消息不包含最近8条已经发过的内容(包括但不限于职位名称) 4. 字数严格控制在10-40字 5. 避免感叹号等激进符号 6. 减少头衔“资深”、“高级”出现的频率,严禁出现“专家”、“老兵”;减少工作年限“x年”出现的频率 diff --git a/packages/ui/src/renderer/src/page/ResumeEditor/index.vue b/packages/ui/src/renderer/src/page/ResumeEditor/index.vue index c910217..5a8a319 100644 --- a/packages/ui/src/renderer/src/page/ResumeEditor/index.vue +++ b/packages/ui/src/renderer/src/page/ResumeEditor/index.vue @@ -5,6 +5,14 @@
简历编辑器
+ + + - + - - - - - - - - - - + - + + +
+ + +
+
- + -