diff --git a/.gitignore b/.gitignore index 62a7112..7b7a0c4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ data resources/extraResources/whisper utils/test.js out +.env # Editor directories and files .vscode/* diff --git a/index.js b/index.js index d13cbe8..969b2df 100644 --- a/index.js +++ b/index.js @@ -7,11 +7,13 @@ const sound = require('sound-play') const _ = require('lodash') const lancedb = require('vectordb') const windowStateKeeper = require('electron-window-state') +const { EdgeTTS } = require('node-edge-tts') +require('dotenv').config() const { STORE_PATH, LOG_PATH, AUDIO_PATH } = require('./utils/initFile.js') const { getStore, setStore } = require('./modules/store.js') const { getSpeechText } = require('./modules/whisper.js') -const { EdgeTTS } = require('node-edge-tts') +const { getTokenLength } = require('./modules/tiktoken.js') const { openaiChatStream, openaiEmbedding, azureOpenaiChatStream, azureOpenaiEmbedding } = require('./modules/common.js') const { functionAction, functionInfo, functionList } = require('./modules/functions.js') const { config } = require('./utils/loadConfig.js') @@ -31,7 +33,15 @@ const messageLog = (message) => { logFile.write(format(new Date().toLocaleString('zh-CN'), JSON.stringify(message)) + '\n') } const messageSend = (message) => { - mainWindow.webContents.send('send-message', message) + if (message.countToken) { + let tokenCount = 0 + message.messages.forEach((item) => { + tokenCount += getTokenLength(item.content || JSON.stringify(item.function_call)) + }) + tokenCount += getTokenLength(message.text) + message.tokenCount = tokenCount + } + mainWindow.webContents.send('send-message', _.omit(message, 'messages')) } const messageLogAndSend = (message) => { messageLog(message) @@ -269,6 +279,8 @@ const resolveMessages = async ({ resArgument, resFunction, resText, resTextTemp, messageLogAndSend({ id: nanoid(), from, + messages, + countToken: true, text: functionAction[resFunction](JSON.parse(resArgument)) }) switch (resFunction) { @@ -338,6 +350,15 @@ const resolveMessages = async ({ resArgument, resFunction, resText, resTextTemp, }) } } + if (resText) { + messageSend({ + id: clientMessageId, + from, + messages, + countToken: true, + text: resText + }) + } return { messages, @@ -356,11 +377,11 @@ const resolveMessages = async ({ resArgument, resFunction, resText, resTextTemp, * @param {Object} options.triggerRecord - The trigger record object. * @return {Promise} - A promise that resolves with the generated response. */ -const resloveAdminPrompt = async ({ prompt, triggerRecord }) => { +const resloveAdminPrompt = async ({ prompt, triggerRecord, miraiSystemPrompt }) => { let from = triggerRecord ? `(${AI_NAME})` : AI_NAME let history = getStore('history') let messages = [ - { role: 'system', content: systemPrompt }, + { role: 'system', content: miraiSystemPrompt ? miraiSystemPrompt : systemPrompt }, { role: 'user', content: `我的名字是${ADMIN_NAME}` }, { role: 'assistant', content: `你好, ${ADMIN_NAME}` }, ..._.takeRight(history, 12), @@ -404,6 +425,7 @@ const resloveAdminPrompt = async ({ prompt, triggerRecord }) => { console.log(e) if (triggerRecord && STATUS.isSpeechTalk) triggerSpeech() } + return resText } const sendHistory = () => { @@ -514,4 +536,20 @@ ipcMain.handle('load-setting', async () => { ipcMain.handle('save-setting', async (event, receiveSetting) => { return await fs.promises.writeFile(path.join(STORE_PATH, 'config.json'), JSON.stringify(receiveSetting, null, ' '), { encoding: 'utf-8' }) -}) \ No newline at end of file +}) + +// mirai connect +// console.log(process.env.useMirai) +// if (process.env.useMirai) { +// const { registerMessageHandle, sendMessage } = require('./modules/mirai.js') +// let tempMessage = '' +// registerMessageHandle(async (data) => { +// let messageObject = JSON.parse(data) +// if (messageObject.type === 'GroupMessage') { +// let member = messageObject.sender.memberName +// messageObject.messageChain.forEach(part => { + +// }) +// } +// }) +// } \ No newline at end of file diff --git a/modules/mirai.js b/modules/mirai.js new file mode 100644 index 0000000..0c7d59a --- /dev/null +++ b/modules/mirai.js @@ -0,0 +1,16 @@ +require('dotenv').config() +const WebSocket = require('ws') + +const wss = new WebSocket(`ws://localhost:8080/message?verifyKey=${process.env.verifyKey}`) + +const registerMessageHandle = (func) => { + wss.on('message', func) +} + +const sendMessage = (message) => { + wss.send(JSON.stringify(message)) +} + +module.exports = { + registerMessageHandle, sendMessage +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c18931a..1dd879f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@schneehertz/google-it": "^1.7.3", "axios": "^1.4.0", + "dotenv": "^16.3.1", "electron-window-state": "^5.0.3", "html-to-text": "^9.0.5", "https-proxy-agent": "^7.0.1", @@ -22,7 +23,7 @@ "quickjs-emscripten": "^0.23.0", "sound-play": "^1.1.0", "vectordb": "^0.2.2", - "ws": "^8.13.0" + "ws": "^8.14.1" }, "devDependencies": { "@vicons/fa": "^0.12.0", @@ -2522,17 +2523,6 @@ "rc9": "^2.0.1" } }, - "node_modules/c12/node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/cacheable-lookup": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", @@ -3395,12 +3385,14 @@ } }, "node_modules/dotenv": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", - "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", - "dev": true, + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, "node_modules/dotenv-expand": { @@ -5953,6 +5945,15 @@ "node": ">=12.0.0" } }, + "node_modules/read-config-file/node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -7349,9 +7350,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", + "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", "engines": { "node": ">=10.0.0" }, @@ -9300,16 +9301,6 @@ "pathe": "^1.1.0", "pkg-types": "^1.0.2", "rc9": "^2.0.1" - }, - "dependencies": { - "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "dev": true, - "optional": true, - "peer": true - } } }, "cacheable-lookup": { @@ -9949,10 +9940,9 @@ } }, "dotenv": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", - "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", - "dev": true + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" }, "dotenv-expand": { "version": "5.1.0", @@ -11892,6 +11882,14 @@ "js-yaml": "^4.1.0", "json5": "^2.2.0", "lazy-val": "^1.0.4" + }, + "dependencies": { + "dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true + } } }, "readable-stream": { @@ -12927,9 +12925,9 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", + "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", "requires": {} }, "xmlbuilder": { diff --git a/package.json b/package.json index 34ec2ee..8322086 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "dependencies": { "@schneehertz/google-it": "^1.7.3", "axios": "^1.4.0", + "dotenv": "^16.3.1", "electron-window-state": "^5.0.3", "html-to-text": "^9.0.5", "https-proxy-agent": "^7.0.1", @@ -72,6 +73,6 @@ "quickjs-emscripten": "^0.23.0", "sound-play": "^1.1.0", "vectordb": "^0.2.2", - "ws": "^8.13.0" + "ws": "^8.14.1" } } diff --git a/src/App.vue b/src/App.vue index 60177cc..0f3594e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -38,6 +38,8 @@ onMounted(() => { let findExist = _.find(messageHistory.value, { id: arg.id }) if (findExist) { findExist.text = arg.text + findExist.tokenCount = arg.tokenCount + findExist.countToken = arg.countToken } else { messageHistory.value.push(arg) messageHistory.value = _.takeRight(messageHistory.value, 1000) @@ -125,6 +127,7 @@ const emptyHistory = () => { embedded >

+          

Used {{ message.tokenCount }} tokens

{ .message-right-text text-align: left float: right +.token-count + font-size: 12px + color: #999 .code-block position: relative