add basic code to call deepseek

This commit is contained in:
geekgeekrun
2025-04-12 14:35:58 +08:00
parent 7458067708
commit 85e27dc6ef
5 changed files with 166 additions and 15 deletions

View File

@@ -1,5 +1,6 @@
import { Page } from 'puppeteer'
import { sleepWithRandomDelay } from '@geekgeekrun/utils/sleep.mjs'
import { sleepWithRandomDelay, sleep } from '@geekgeekrun/utils/sleep.mjs';
import { completes } from '@geekgeekrun/utils/gpt-request.mjs'
export const sendLookForwardReplyEmotion = async (page: Page) => {
const emotionEntryButtonProxy = await page.$('.chat-conversation .message-controls .btn-emotion')
@@ -15,3 +16,64 @@ export const sendLookForwardReplyEmotion = async (page: Page) => {
)
await lookForwardReplyEmojiProxy!.click()
}
export const sendGptContent = async (page: Page, chatRecords) => {
const chatList = [
{
role: 'system',
content:
'你是一个求职消息发送机器人正在帮助一位求职者在Boss直聘上寻找一份工作。求职者需要向招聘者聊天得到招聘者的回复后方能获得一次投递简历的机会。你需要“从求职者简历中提取到的信息来生成一个要发送给招聘者的消息”。同时你需要注意每次发送的内容一定要接续之前发送的内容最好不要和已发过的内容重复。求职者简历信息如下' +
``
}
]
chatList.push({
role: 'user',
content:
'请帮我写一句开场白。请确保仅响应一句话以JSON响应数据结构参考`{"response": "这里是将会发送给招聘者的内容"}`'
})
for (const record of chatRecords) {
const assistantJsonContent = JSON.stringify({
response: record.text
})
chatList.push({
role: 'assistant',
content: `\`\`\`json\n${assistantJsonContent}\n\`\`\``
})
chatList.push({
role: 'user',
content:
'请根据接续之前你所回复的内容根据我的简历写一句自我介绍注意尽量不要和之前的聊天内容重复。请确保仅响应一句话以JSON响应数据结构参考`{"response": "这里是将会发送给招聘者的内容"}`'
})
}
console.log(chatList)
debugger
const res = await completes(chatList)
console.log(res)
let textToSend
try {
const rawMarkdownText = res?.message?.content
textToSend = JSON.parse(
rawMarkdownText.replace(/^```json/m, '').replace(/```$/m, '')
)?.response
if (!textToSend) {
throw new Error(`empty content. ${err?.message} ${res?.message?.content}`)
}
} catch (err) {
throw new Error(`fail to parse response. ${err?.message} ${res?.message?.content}`)
}
const chatInputSelector = `.chat-conversation .message-controls .chat-input`
const chatInputHandle = await page.$(chatInputSelector)
await chatInputHandle.click()
await sleep(500)
await chatInputHandle.click()
await chatInputHandle.type(
textToSend,
{
delay: 50
}
)
await sleep(1000)
const sendButtonSelector = `.chat-conversation .message-controls .chat-op .btn-send:not(.disabled)`
await page.click(sendButtonSelector)
}

View File

@@ -1,7 +1,7 @@
import { bootstrap, launchBoss } from './bootstrap'
import { MsgStatus, type ChatListItem } from './types'
import { Browser, Page } from 'puppeteer'
import { sendLookForwardReplyEmotion } from './boss-operation'
import { sendGptContent, sendLookForwardReplyEmotion } from './boss-operation'
import { sleep, sleepWithRandomDelay } from '@geekgeekrun/utils/sleep.mjs'
import attachListenerForKillSelfOnParentExited from '../../utils/attachListenerForKillSelfOnParentExited'
import { app } from 'electron'
@@ -277,7 +277,19 @@ const mainLoop = async () => {
(throttleIntervalMinutes + 4 * Math.random()) * 60 * 1000
) {
await sleepWithRandomDelay(3250)
await sendLookForwardReplyEmotion(pageMapByName.boss!)
// execute reply
// eslint-disable-next-line no-constant-condition
if (1 + 1 === 2) {
try {
const messageListForGpt = historyMessageList.filter(it => it.bizType !== 101 && it.isSelf)
debugger
await sendGptContent(pageMapByName.boss!, messageListForGpt)
} catch (err) {
await sendLookForwardReplyEmotion(pageMapByName.boss!)
}
} else {
await sendLookForwardReplyEmotion(pageMapByName.boss!)
}
} else {
cursorToContinueFind += 1
}

View File

@@ -0,0 +1,21 @@
import OpenAI from "openai";
const GPT_API_KEY = `sk-40fdef46fee24402bc05311304fce7a1`
export async function completes(messages) {
const openai = new OpenAI({
baseURL: 'https://api.deepseek.com',
apiKey: GPT_API_KEY
});
const completion = await openai.chat.completions.create({
messages,
model: "deepseek-chat",
frequency_penalty: 0,
max_tokens: 100,
temperature: 0.2
});
console.log(completion.choices[0].message.content);
return completion.choices?.[0] ?? null;
}

View File

@@ -3,9 +3,10 @@
"private": true,
"version": "1.0.0",
"description": "utils",
"scripts": {
},
"scripts": {},
"author": "geekgeekrun",
"license": "ISC",
"dependencies": {}
"dependencies": {
"openai": "^4.91.1"
}
}

73
pnpm-lock.yaml generated
View File

@@ -257,7 +257,11 @@ importers:
specifier: ^1.8.27
version: 1.8.27(typescript@5.3.3)
packages/utils: {}
packages/utils:
dependencies:
openai:
specifier: ^4.91.1
version: 4.91.1
packages:
@@ -1679,6 +1683,13 @@ packages:
/@types/ms@0.7.34:
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
/@types/node-fetch@2.6.12:
resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==}
dependencies:
'@types/node': 18.19.15
form-data: 4.0.0
dev: false
/@types/node@18.19.15:
resolution: {integrity: sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==}
dependencies:
@@ -2302,6 +2313,13 @@ packages:
requiresBuild: true
dev: false
/abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
dependencies:
event-target-shim: 5.0.1
dev: false
/acorn-jsx@5.3.2(acorn@8.11.3):
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2349,7 +2367,6 @@ packages:
dependencies:
humanize-ms: 1.2.1
dev: false
optional: true
/aggregate-error@3.1.0:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
@@ -2546,7 +2563,6 @@ packages:
/asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
dev: true
/at-least-node@1.0.0:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
@@ -2904,7 +2920,6 @@ packages:
engines: {node: '>= 0.8'}
dependencies:
delayed-stream: 1.0.0
dev: true
/commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -3108,7 +3123,6 @@ packages:
/delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
dev: true
/delegates@1.0.0:
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
@@ -3607,6 +3621,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
dev: false
/execa@5.1.1:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
@@ -3776,6 +3795,10 @@ packages:
signal-exit: 4.1.0
dev: true
/form-data-encoder@1.7.2:
resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
dev: false
/form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
@@ -3783,7 +3806,14 @@ packages:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: true
/formdata-node@4.4.1:
resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
engines: {node: '>= 12.20'}
dependencies:
node-domexception: 1.0.0
web-streams-polyfill: 4.0.0-beta.3
dev: false
/formdata-polyfill@4.0.10:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
@@ -4162,7 +4192,6 @@ packages:
dependencies:
ms: 2.1.2
dev: false
optional: true
/iconv-corefoundation@1.1.7:
resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==}
@@ -4643,14 +4672,12 @@ packages:
/mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
dev: true
/mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.52.0
dev: true
/mime@2.6.0:
resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
@@ -5002,6 +5029,29 @@ packages:
mimic-fn: 2.1.0
dev: true
/openai@4.91.1:
resolution: {integrity: sha512-DbjrR0hIMQFbxz8+3qBsfPJnh3+I/skPgoSlT7f9eiZuhGBUissPQULNgx6gHNkLoZ3uS0uYS6eXPUdtg4nHzw==}
hasBin: true
peerDependencies:
ws: ^8.18.0
zod: ^3.23.8
peerDependenciesMeta:
ws:
optional: true
zod:
optional: true
dependencies:
'@types/node': 18.19.15
'@types/node-fetch': 2.6.12
abort-controller: 3.0.0
agentkeepalive: 4.5.0
form-data-encoder: 1.7.2
formdata-node: 4.4.1
node-fetch: 2.6.7
transitivePeerDependencies:
- encoding
dev: false
/optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
engines: {node: '>= 0.8.0'}
@@ -6499,6 +6549,11 @@ packages:
engines: {node: '>= 8'}
dev: false
/web-streams-polyfill@4.0.0-beta.3:
resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
engines: {node: '>= 14'}
dev: false
/webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
dev: false