From b7376407af8fdbc2ff6f55975c4f953ea4d27df0 Mon Sep 17 00:00:00 2001 From: HalcyonAlcedo <41666148+HalcyonAlcedo@users.noreply.github.com> Date: Wed, 25 Oct 2023 23:06:10 +0800 Subject: [PATCH 01/17] =?UTF-8?q?=E9=80=82=E9=85=8D=E6=98=9F=E7=81=ABv3=20?= =?UTF-8?q?(#598)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复星火api上下文 * 将无星火ck的情况降低为warn * feat: 添加星火设定自定义代码功能 * 修复星火api模式的一些问题 * 修复导出配置问题 * feat:添加工具箱快捷登录接口 * 添加工具箱快捷登录指令 * 阻止群聊使用快捷登录 * 添加Azure配置支持,修复重复的配置项冲突 * 移除旧版本渲染和新版本帮助 * 添加工具箱 * 更新工具箱替换原有后台 * 更新工具箱适配代码 * 后台适配Trss * 修复trss不支持sendPrivateMsg的问题 * 优化路由 * 修复路由 * 适配其他uin * 添加bing第三方绘图 * 修复bing绘图第三方调用错误 * 添加bing第三方绘图采样配置 * 修复错误 * 添加bing第三方绘图图片大小配置 * 修复视图错误 * 使用ap替换第三方绘图 * 适配trss * server 适配trss * 修复错误的后台版本更新 * 添加锅巴用户数据 * 修复server初始化消息错误 * 添加锅巴插件适配 * 更新后台页面 * 添加锅巴代理接口 * 优化锅巴接口代理 * 修复锅巴代理参数 * 删除调试信息 * 修复headers * 更新后台锅巴插件支持 * 适配星火v3 * 适配星火v3 * 修复星火domain错误 --- resources/view/setting_view.json | 4 ++++ utils/xinghuo/xinghuo.js | 12 +++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/resources/view/setting_view.json b/resources/view/setting_view.json index 78ebca4..c3d7c0d 100644 --- a/resources/view/setting_view.json +++ b/resources/view/setting_view.json @@ -718,6 +718,10 @@ "label": "讯飞星火认知大模型V2.0", "value": "apiv2" }, + { + "label": "讯飞星火认知大模型V3.0", + "value": "apiv3" + }, { "label": "讯飞星火助手", "value": "assistants" diff --git a/utils/xinghuo/xinghuo.js b/utils/xinghuo/xinghuo.js index 6ee1bf0..04aa728 100644 --- a/utils/xinghuo/xinghuo.js +++ b/utils/xinghuo/xinghuo.js @@ -90,6 +90,8 @@ export default class XinghuoClient { let APILink = '/v1.1/chat' if (Config.xhmode == 'apiv2') { APILink = '/v2.1/chat' + } else if (Config.xhmode == 'apiv3') { + APILink = '/v3.1/chat' } const date = new Date().toGMTString() const algorithm = 'hmac-sha256' @@ -179,7 +181,11 @@ export default class XinghuoClient { // 获取ws链接 const wsUrl = Config.xhmode == 'assistants' ? Config.xhAssistants : await this.getWsUrl() if (!wsUrl) throw new Error('缺少依赖:crypto。请安装依赖后重试') - + let domain = 'general' + if (Config.xhmode == 'apiv2') + domain = "generalv2" + else if (Config.xhmode == 'apiv3') + domain = "generalv3" // 编写消息内容 const wsSendData = { header: { @@ -188,7 +194,7 @@ export default class XinghuoClient { }, parameter: { chat: { - domain: Config.xhmode == 'api' ? "general" : "generalv2", + domain: domain, temperature: Config.xhTemperature, // 核采样阈值 max_tokens: Config.xhMaxTokens, // tokens最大长度 chat_id: chatId, @@ -378,7 +384,7 @@ export default class XinghuoClient { let chatId = option?.chatId let image = option?.image - if (Config.xhmode == 'api' || Config.xhmode == 'apiv2' || Config.xhmode == 'assistants') { + if (Config.xhmode == 'api' || Config.xhmode == 'apiv2' || Config.xhmode == 'apiv3' || Config.xhmode == 'assistants') { if (!Config.xhAppId || !Config.xhAPISecret || !Config.xhAPIKey) throw new Error('未配置api') let Prompt = [] // 设定 From 2a713ca15822dce52a1da36b55b70e34d2f38c30 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Sun, 29 Oct 2023 15:59:03 +0800 Subject: [PATCH 02/17] fix: reconstruction clients --- client/BaseClient.js | 101 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 client/BaseClient.js diff --git a/client/BaseClient.js b/client/BaseClient.js new file mode 100644 index 0000000..46232df --- /dev/null +++ b/client/BaseClient.js @@ -0,0 +1,101 @@ +/** + * Base LLM Chat Client \ + * All the Chat Models should extend this class + * + * @since 2023-10-26 + * @author ikechan8370 + */ +export class BaseClient { + /** + * create a new client + * + * @param props required fields: e, getMessageById, upsertMessage + */ + constructor (props = {}) { + this.supportFunction = false + this.maxToken = 4096 + this.tools = [] + const { + e, getMessageById, upsertMessage + } = props + this.e = e + this.getMessageById = getMessageById + this.upsertMessage = upsertMessage + } + + /** + * get a message according to the id. note that conversationId is not needed + * + * @type function + * @param {string} id + * @return {Promise} message + */ + getMessageById + + /** + * insert or update a message with the id + * + * @type function + * @param {string} id + * @param {object} message + * @return {Promise} + */ + upsertMessage + + /** + * Send prompt message with history and return response message \ + * if function called, handled internally \ + * override this method to implement logic of sending and receiving message + * + * @param msg + * @param opt other options, optional fields: [conversationId, parentMessageId], if not set, random uuid instead + * @returns {Promise} required fields: [text, conversationId, parentMessageId, id] + */ + async sendMessage (msg, opt = {}) { + throw new Error('not implemented in abstract client') + } + + /** + * Get chat history between user and assistant + * override this method to implement logic of getting history + * keyv with local file or redis recommended + * + * @param userId such as qq number + * @param opt other options + * @returns {Promise} + */ + async getHistory (userId, opt = {}) { + throw new Error('not implemented in abstract client') + } + + /** + * Destroy a chat history + * @param conversationId conversationId of the chat history + * @param opt other options + * @returns {Promise} + */ + async destroyHistory (conversationId, opt = {}) { + throw new Error('not implemented in abstract client') + } + + addTools (...tools) { + if (!this.isSupportFunction) { + throw new Error('function not supported') + } + if (!this.tools) { + this.tools = [] + } + this.tools.push(tools) + } + + getTools () { + if (!this.isSupportFunction) { + throw new Error('function not supported') + } + return this.tools || [] + } + + get isSupportFunction () { + return this.supportFunction + } +} From 5cecea07834b3c001770e426c99d1c048801df62 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Sun, 29 Oct 2023 20:19:31 +0800 Subject: [PATCH 03/17] =?UTF-8?q?fix:=20=E5=8D=83=E9=97=AE=E7=BB=93?= =?UTF-8?q?=E6=9D=9F=E5=85=A8=E9=83=A8=E5=AF=B9=E8=AF=9Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/chat.js b/apps/chat.js index d6f65c3..fb14c7a 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -565,6 +565,18 @@ export class chatgpt extends plugin { } break } + case 'qwen': { + let qcs = await redis.keys('CHATGPT:CONVERSATIONS_QWEN:*') + for (let i = 0; i < qcs.length; i++) { + await redis.del(qcs[i]) + // todo clean last message id + if (Config.debug) { + logger.info('delete qwen conversation bind: ' + qcs[i]) + } + deleted++ + } + break + } } await this.reply(`结束了${deleted}个用户的对话。`, true) } From efa7fff57439685a6db426e546e5d53b7765dc38 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Sun, 29 Oct 2023 20:48:15 +0800 Subject: [PATCH 04/17] =?UTF-8?q?fix:=20=E5=A4=8D=E7=94=A8API=E5=92=8C?= =?UTF-8?q?=E5=8D=83=E9=97=AE=E6=A8=A1=E5=BC=8F=E7=9A=84=E8=AE=BE=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/prompts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/prompts.js b/apps/prompts.js index 3b5098c..a2b2809 100644 --- a/apps/prompts.js +++ b/apps/prompts.js @@ -157,7 +157,8 @@ export class help extends plugin { const keyMap = { api: 'promptPrefixOverride', Custom: 'sydney', - claude: 'slackClaudeGlobalPreset' + claude: 'slackClaudeGlobalPreset', + qwen: 'promptPrefixOverride' } if (keyMap[use]) { From e5959b01906f9a8217c57ee801a36f3515deb8ee Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Mon, 30 Oct 2023 11:49:46 +0800 Subject: [PATCH 05/17] docs: Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c682394..d3c5388 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ ### 推荐的相关文档和参考资料 本README -[手册](https://chatgptplugin.ikechan8370.com/) +[手册](https://yunzai.chat) [文档1(建设中)](https://chatgpt-docs.err0r.top/) [插件常见问题(鹤望兰版)](https://chatgptplugin.ikechan8370.com/guide/) [Yunzai常见问题(LUCK小运版)](https://www.wolai.com/oA43vuW71aBnv7UsEysn4T) From ea687296a51083f4902e0f267e8fe22e8280e75d Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Mon, 30 Oct 2023 15:35:05 +0800 Subject: [PATCH 06/17] =?UTF-8?q?fix:=20=E6=95=B4=E7=90=86=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E9=95=BF=E6=9C=9F=E9=81=97=E7=95=99=E6=87=92=E5=BE=97?= =?UTF-8?q?=E4=BF=AE=E7=9A=84=E5=B0=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 13 ++++++++----- utils/SydneyAIClient.js | 6 +++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/chat.js b/apps/chat.js index fb14c7a..b7c635f 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -1102,9 +1102,7 @@ export class chatgpt extends plugin { logger.mark({ conversation }) } let chatMessage = await this.sendMessage(prompt, conversation, use, e) - if (chatMessage.image) { - this.setContext('solveBingCaptcha', false, 60) - await e.reply([chatMessage.text, segment.image(`base64://${chatMessage.image}`)]) + if (chatMessage?.noMsg) { return false } // 处理星火和bard图片 @@ -1869,10 +1867,10 @@ export class chatgpt extends plugin { text: errorMessage, error: true } - } else { + } else if (response?.response) { return { text: response?.response, - quote: response.quote, + quote: response?.quote, suggestedResponses: response.suggestedResponses, conversationId: response.conversationId, clientId: response.clientId, @@ -1881,6 +1879,11 @@ export class chatgpt extends plugin { parentMessageId: response.apology ? conversation.parentMessageId : response.messageId, bingToken } + } else { + logger.debug('no message') + return { + noMsg: true + } } } case 'api3': { diff --git a/utils/SydneyAIClient.js b/utils/SydneyAIClient.js index 701f2ec..c425f7c 100644 --- a/utils/SydneyAIClient.js +++ b/utils/SydneyAIClient.js @@ -138,7 +138,11 @@ export default class SydneyAIClient { agent = proxy(this.opts.proxy) } if (Config.sydneyWebsocketUseProxy) { - sydneyHost = Config.sydneyReverseProxy.replace('https://', 'wss://').replace('http://', 'ws://') + if (!Config.sydneyReverseProxy) { + logger.warn('用户开启了对话反代,但是没有配置反代,忽略反代配置') + } else { + sydneyHost = Config.sydneyReverseProxy.replace('https://', 'wss://').replace('http://', 'ws://') + } } logger.mark(`use sydney websocket host: ${sydneyHost}`) let host = sydneyHost + '/sydney/ChatHub' From 7289ae6f35270fe126a6721a9988c22ce3c05147 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Mon, 30 Oct 2023 17:00:26 +0800 Subject: [PATCH 07/17] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=A6=96?= =?UTF-8?q?=E6=AC=A1=E4=BD=BF=E7=94=A8=E6=8F=92=E4=BB=B6bing=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=E9=AA=8C=E8=AF=81=E7=A0=81=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E8=A2=AB=E9=98=BB=E6=8B=A6=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/chat.js b/apps/chat.js index b7c635f..875402c 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -1788,7 +1788,7 @@ export class chatgpt extends plugin { const { maxConv } = error if (message && typeof message === 'string' && message.indexOf('CaptchaChallenge') > -1) { if (bingToken) { - if (maxConv > 20) { + if (maxConv >= 20) { // maxConv为30说明token有效,可以通过解验证码码服务过码 await e.reply('出现必应验证码,尝试解决中') try { From 6c149265f0a02349f0f58a1afc1d1b500b33a536 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Mon, 30 Oct 2023 17:00:53 +0800 Subject: [PATCH 08/17] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=BF=85?= =?UTF-8?q?=E5=BA=94=E5=88=9D=E5=A7=8B=E5=AF=B9=E8=AF=9D=E6=AC=A1=E6=95=B0?= =?UTF-8?q?=E4=B8=BA30?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/config.js b/utils/config.js index f63cde2..308338d 100644 --- a/utils/config.js +++ b/utils/config.js @@ -93,7 +93,7 @@ const defaultConfig = { groupContextTip: '你看看我们群里的聊天记录吧,回答问题的时候要主动参考我们的聊天记录进行回答或提问。但要看清楚哦,不要把我和其他人弄混啦,也不要把自己看晕啦~~', groupContextLength: 50, enableRobotAt: true, - maxNumUserMessagesInConversation: 20, + maxNumUserMessagesInConversation: 30, sydneyApologyIgnored: true, enforceMaster: false, bingAPDraw: false, From 7cc22e487a7aef819d88df6ea3e793cf09808ec9 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Wed, 1 Nov 2023 10:54:58 +0800 Subject: [PATCH 09/17] Update README.md --- README.md | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d3c5388..6d0e971 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![chatgpt-plugin](https://user-images.githubusercontent.com/21212372/232115814-de9a0633-371f-4733-8da0-dd6e912c8a1e.png) -

云崽QQ机器人的ChatGPT插件

+

云崽系机器人的智能聊天插件

@@ -52,16 +52,6 @@ Node.js >= 18 / Node.js >= 14(with node-fetch) ## 安装与使用方法 ### 安装 - -在安装之前,请先判断自己需要使用哪种模式,本插件支持官方API/第三方API/~~浏览器~~/必应四种模式。也可以选择**我全都要**(通过qq发送命令`#chatgpt切换浏览器/API/API3/Bing`实时切换) - -> #### API模式和浏览器模式如何选择? -> -> * API模式会调用OpenAI官方提供的gpt-3.5-turbo API,ChatGPT官网同款模型,只需要提供API Key。一般情况下,该种方式响应速度更快,可配置项多,且不会像chatGPT官网一样总出现不可用的现象,但注意API调用是收费的,新用户有18美元试用金可用于支付,价格为`$0.0020/ 1K tokens`。(问题和回答**加起来**算token) -> * API3模式会调用第三方提供的官网反代API,他会帮你绕过CF防护,需要提供ChatGPT的Token。效果与官网和浏览器一致,但稳定性不一定。发送#chatgpt设置token来设置token。 -> * (Deprecated)浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站,使得获得和官方以及API2模式一模一样的回复质量,同时保证安全性。缺点是本方法对环境要求较高,需要提供桌面环境和一个可用的代理(能够访问ChatGPT的IP地址),且响应速度不如API,而且高峰期容易无法使用。一般作为API3的下位替代。 -> * 必应(Bing)将调用微软新必应接口进行对话。需要在必应网页能够正常使用新必应且设置有效的Bing登录Cookie方可使用。强烈推荐 - 1. 进入 Yunzai根目录 2. 请将 chatgpt-plugin 放置在 Yunzai-Bot 的 plugins 目录下 @@ -83,12 +73,8 @@ pnpm i 如果是手工下载的 zip 压缩包,请将解压后的 chatgpt-plugin 文件夹(请删除压缩自带的-master或版本号后缀)放置在 Yunzai-Bot 目录下的 plugins 文件夹内 -> ~~浏览器模式仅为备选,如您需要使用浏览器模式,您还需要有**桌面环境**,优先级建议:API≈必应>API3>浏览器~~\ -> ~~2.20更新:必应被大削,变得蠢了,建议还是API/API3优先~~\ -> 4.2更新:必应站起来了,必应天下第一。建议都用必应,别用API/API3了。浏览器模式除非极其特殊的需求否则强烈建议不使用,已经不维护了。 - 3. 修改配置 -**本插件配置项比较多,强烈建议使用后台面板或[锅巴面板](https://github.com/guoba-yunzai/Guoba-Plugin)修改** +**本插件配置项比较多,强烈建议使用后台工具箱或[锅巴面板](https://github.com/guoba-yunzai/Guoba-Plugin)修改** 或者创建和编辑config/config.json文件。 From 61d3b487810664006c183e1c25b2068e053d82d6 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Sat, 4 Nov 2023 11:49:36 +0800 Subject: [PATCH 10/17] =?UTF-8?q?fix:=20=E5=88=9D=E6=AD=A5=E9=80=82?= =?UTF-8?q?=E9=85=8D=E9=93=83=E9=9F=B3=E8=AF=AD=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/common.js | 33 ++++++++++++++++++--------------- utils/uploadRecord.js | 5 ++++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/utils/common.js b/utils/common.js index 098c34c..1c63816 100644 --- a/utils/common.js +++ b/utils/common.js @@ -847,14 +847,13 @@ export function getMaxModelTokens (model = 'gpt-3.5-turbo') { export function getUin (e) { if (e?.bot?.uin) return e.bot.uin if (Array.isArray(Bot.uin)) { - if (Config.trssBotUin && Bot.uin.indexOf(Config.trssBotUin) > -1) {return Config.trssBotUin} - else { - Bot.uin.forEach((u) => { - if (Bot[u].self_id) { - return Bot[u].self_id - } - }) - return Bot.uin[Bot.uin.length - 1] + if (Config.trssBotUin && Bot.uin.indexOf(Config.trssBotUin) > -1) { return Config.trssBotUin } else { + Bot.uin.forEach((u) => { + if (Bot[u].self_id) { + return Bot[u].self_id + } + }) + return Bot.uin[Bot.uin.length - 1] } } else return Bot.uin } @@ -871,6 +870,7 @@ export async function generateAudio (e, pendingText, speakingEmotion, emotionDeg if (!Config.ttsSpace && !Config.azureTTSKey && !Config.voicevoxSpace) return false let wav const speaker = getUserSpeaker(await getUserReplySetting(e)) + let ignoreEncode = getUin(e) === 88888 try { if (Config.ttsMode === 'vits-uma-genshin-honkai' && Config.ttsSpace) { if (Config.autoJapanese) { @@ -883,7 +883,7 @@ export async function generateAudio (e, pendingText, speakingEmotion, emotionDeg } wav = await generateVitsAudio(pendingText, speaker, '中日混合(中文用[ZH][ZH]包裹起来,日文用[JA][JA]包裹起来)') } else if (Config.ttsMode === 'azure' && Config.azureTTSKey) { - return await generateAzureAudio(pendingText, speaker, speakingEmotion, emotionDegree) + return await generateAzureAudio(pendingText, speaker, speakingEmotion, emotionDegree, ignoreEncode) } else if (Config.ttsMode === 'voicevox' && Config.voicevoxSpace) { pendingText = (await translate(pendingText, '日')).replace('\n', '') wav = await VoiceVoxTTS.generateAudio(pendingText, { @@ -897,7 +897,7 @@ export async function generateAudio (e, pendingText, speakingEmotion, emotionDeg let sendable try { try { - sendable = await uploadRecord(wav, Config.ttsMode) + sendable = await uploadRecord(wav, Config.ttsMode, ignoreEncode) if (!sendable) { // 如果合成失败,尝试使用ffmpeg合成 sendable = segment.record(wav) @@ -927,9 +927,10 @@ export async function generateAudio (e, pendingText, speakingEmotion, emotionDeg * @param role - 发言人 * @param speakingEmotion - 发言人情绪 * @param emotionDegree - 发言人情绪强度 + * @param ignoreEncode - 不在客户端处理编码 * @returns {Promise<{file: string, type: string}|boolean>} */ -export async function generateAzureAudio (pendingText, role = '随机', speakingEmotion, emotionDegree = 1) { +export async function generateAzureAudio (pendingText, role = '随机', speakingEmotion, emotionDegree = 1, ignoreEncode = false) { if (!Config.azureTTSKey) return false let speaker try { @@ -970,11 +971,13 @@ export async function generateAzureAudio (pendingText, role = '随机', speaking pendingText, emotionDegree }) + let record = await AzureTTS.generateAudio(pendingText, { + speaker + }, await ssml) return await uploadRecord( - await AzureTTS.generateAudio(pendingText, { - speaker - }, await ssml) - , Config.ttsMode + record + , Config.ttsMode, + ignoreEncode ) } catch (err) { logger.error(err) diff --git a/utils/uploadRecord.js b/utils/uploadRecord.js index f689537..4e16bab 100644 --- a/utils/uploadRecord.js +++ b/utils/uploadRecord.js @@ -39,7 +39,7 @@ if (module) { // import { pcm2slk } from 'node-silk' let errors = {} -async function uploadRecord (recordUrl, ttsMode = 'vits-uma-genshin-honkai') { +async function uploadRecord (recordUrl, ttsMode = 'vits-uma-genshin-honkai', ignoreEncode = false) { let recordType = 'url' let tmpFile = '' if (ttsMode === 'azure') { @@ -48,6 +48,9 @@ async function uploadRecord (recordUrl, ttsMode = 'vits-uma-genshin-honkai') { recordType = 'buffer' tmpFile = `data/chatgpt/tts/tmp/${crypto.randomUUID()}.wav` } + if (ignoreEncode) { + return segment.record(recordUrl) + } let result if (pcm2slk) { result = await getPttBuffer(recordUrl, Bot.config.ffmpeg_path) From 0bff8c85b096f786b59f6350bbffce9d0f2adc69 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 18:54:58 +0800 Subject: [PATCH 11/17] =?UTF-8?q?feat:=20=E8=BF=9B=E4=B8=80=E6=AD=A5?= =?UTF-8?q?=E9=80=82=E9=85=8D=E9=93=83=E9=9F=B3+shamrock;=E8=AF=8D?= =?UTF-8?q?=E4=BA=91=E8=BF=9B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 40 +----------- apps/entertainment.js | 58 ++++++++++++++++- utils/SydneyAIClient.js | 2 +- utils/chat.js | 33 ++++++++++ utils/common.js | 2 +- utils/wordcloud/tokenizer.js | 117 ++++++++++++++++++++++++++++++----- utils/wordcloud/wordcloud.js | 22 ++++--- 7 files changed, 209 insertions(+), 65 deletions(-) create mode 100644 utils/chat.js diff --git a/apps/chat.js b/apps/chat.js index 875402c..58ea9b1 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -77,6 +77,7 @@ import {solveCaptchaOneShot} from '../utils/bingCaptcha.js' import {ClaudeAIClient} from '../utils/claude.ai/index.js' import {getProxy} from '../utils/proxy.js' import {QwenApi} from '../utils/alibaba/qwen-api.js' +import {getChatHistoryGroup} from '../utils/chat.js' try { await import('@azure/openai') @@ -1660,28 +1661,7 @@ export class chatgpt extends plugin { if (master && !e.group) { opt.masterName = e.bot.getFriendList().get(parseInt(master))?.nickname } - let latestChats = await e.group.getChatHistory(0, 1) - if (latestChats.length > 0) { - let latestChat = latestChats[0] - if (latestChat) { - let seq = latestChat.seq - let chats = [] - while (chats.length < Config.groupContextLength) { - let chatHistory = await e.group.getChatHistory(seq, 20) - chats.push(...chatHistory) - } - chats = chats.slice(0, Config.groupContextLength) - let mm = await e.group.getMemberMap() - chats.forEach(chat => { - let sender = mm.get(chat.sender.user_id) - if (sender) { - chat.sender = sender - } - }) - // console.log(chats) - opt.chats = chats - } - } + opt.chats = await getChatHistoryGroup(e, Config.groupContextLength) } catch (err) { logger.warn('获取群聊聊天记录失败,本次对话不携带聊天记录', err) } @@ -2171,21 +2151,7 @@ export class chatgpt extends plugin { if (master && !e.group) { opt.masterName = e.bot.getFriendList().get(parseInt(master))?.nickname } - let latestChat = await e.group.getChatHistory(0, 1) - let seq = latestChat[0].seq - let chats = [] - while (chats.length < Config.groupContextLength) { - let chatHistory = await e.group.getChatHistory(seq, 20) - chats.push(...chatHistory.reverse()) - } - chats = chats.slice(0, Config.groupContextLength) - // 太多可能会干扰AI对自身qq号和用户qq的判断,感觉gpt3.5也处理不了那么多信息 - chats = chats > 50 ? 50 : chats - let mm = await e.group.getMemberMap() - chats.forEach(chat => { - let sender = mm.get(chat.sender.user_id) - chat.sender = sender - }) + let chats = await getChatHistoryGroup(e, Config.groupContextLength) opt.chats = chats const namePlaceholder = '[name]' const defaultBotName = 'ChatGPT' diff --git a/apps/entertainment.js b/apps/entertainment.js index fb8ff7f..eb6e9d8 100644 --- a/apps/entertainment.js +++ b/apps/entertainment.js @@ -50,6 +50,10 @@ export class Entertainment extends plugin { reg: '^#(|最新)词云(\\d{1,2}h{0,1}|)$', fnc: 'wordcloud_latest' }, + { + reg: '^#(我的)?(本月|本周|今日)?词云$', + fnc: 'wordcloud_new' + }, { reg: '^#((寄批踢|gpt|GPT)?翻.*|chatgpt翻译帮助)', fnc: 'translate' @@ -215,10 +219,10 @@ ${translateLangLabels} const regExp = /词云(\d{0,2})(|h)/ const match = e.msg.trim().match(regExp) - const duration = !match[1] ? 12 : parseInt(match[1]) // default 12h + const duration = !match[1] ? 12 : parseInt(match[1]) // default 12h if (duration > 24) { - await e.reply('最多只能统计24小时内的记录哦') + await e.reply('最多只能统计24小时内的记录哦,你可以使用#本周词云和#本月词云获取更长时间的统计~') return false } await e.reply('在统计啦,请稍等...') @@ -236,6 +240,56 @@ ${translateLangLabels} } } + async wordcloud_new (e) { + if (e.isGroup) { + let groupId = e.group_id + let userId + if (e.msg.includes('我的')) { + userId = e.sender.user_id + } + let at = e.message.find(m => m.type === 'at') + if (at) { + userId = at.qq + } + let lock = await redis.get(`CHATGPT:WORDCLOUD_NEW:${groupId}_${userId}`) + if (lock) { + await e.reply('别着急,上次统计还没完呢') + return true + } + await e.reply('在统计啦,请稍等...') + let duration = 24 + if (e.msg.includes('本周')) { + const now = new Date() // Get the current date and time + let day = now.getDay() + let diff = now.getDate() - day + (day === 0 ? -6 : 1) + const startOfWeek = new Date(new Date().setDate(diff)) + startOfWeek.setHours(0, 0, 0, 0) // Set the time to midnight (start of the day) + duration = (now - startOfWeek) / 1000 / 60 / 60 + } else if (e.msg.includes('本月')) { + const now = new Date() // Get the current date and time + const startOfMonth = new Date(new Date().setDate(0)) + startOfMonth.setHours(0, 0, 0, 0) // Set the time to midnight (start of the day) + duration = (now - startOfMonth) / 1000 / 60 / 60 + } else { + // 默认今天 + const now = new Date() + const startOfToday = new Date() // Get the current date and time + startOfToday.setHours(0, 0, 0, 0) // Set the time to midnight (start of the day) + duration = (now - startOfToday) / 1000 / 60 / 60 + } + await redis.set(`CHATGPT:WORDCLOUD_NEW:${groupId}_${userId}`, '1', { EX: 600 }) + try { + await makeWordcloud(e, e.group_id, duration, userId) + } catch (err) { + logger.error(err) + await e.reply(err) + } + await redis.del(`CHATGPT:WORDCLOUD_NEW:${groupId}_${userId}`) + } else { + await e.reply('请在群里发送此命令') + } + } + async combineEmoj (e) { let left = e.msg.codePointAt(0).toString(16).toLowerCase() let right = e.msg.codePointAt(2).toString(16).toLowerCase() diff --git a/utils/SydneyAIClient.js b/utils/SydneyAIClient.js index c425f7c..7f2e315 100644 --- a/utils/SydneyAIClient.js +++ b/utils/SydneyAIClient.js @@ -476,7 +476,7 @@ export default class SydneyAIClient { context += chats .map(chat => { let sender = chat.sender || chat || {} - if (chat.raw_message.startsWith('建议的回复')) { + if (chat.raw_message?.startsWith('建议的回复')) { // 建议的回复太容易污染设定导致对话太固定跑偏了 return '' } diff --git a/utils/chat.js b/utils/chat.js new file mode 100644 index 0000000..3263c6c --- /dev/null +++ b/utils/chat.js @@ -0,0 +1,33 @@ +export async function getChatHistoryGroup (e, num) { + if (e.adapter === 'shamrock') { + return await e.group.getChatHistory(0, num) + } else { + let latestChats = await e.group.getChatHistory(0, 1) + if (latestChats.length > 0) { + let latestChat = latestChats[0] + if (latestChat) { + let seq = latestChat.seq + let chats = [] + while (chats.length < num) { + let chatHistory = await e.group.getChatHistory(seq, 20) + chats.push(...chatHistory) + } + chats = chats.slice(0, num) + try { + let mm = await e.group.getMemberMap() + chats.forEach(chat => { + let sender = mm.get(chat.sender.user_id) + if (sender) { + chat.sender = sender + } + }) + } catch (err) { + logger.warn(err) + } + // console.log(chats) + return chats + } + } + } + return [] +} diff --git a/utils/common.js b/utils/common.js index 1c63816..03c5271 100644 --- a/utils/common.js +++ b/utils/common.js @@ -870,7 +870,7 @@ export async function generateAudio (e, pendingText, speakingEmotion, emotionDeg if (!Config.ttsSpace && !Config.azureTTSKey && !Config.voicevoxSpace) return false let wav const speaker = getUserSpeaker(await getUserReplySetting(e)) - let ignoreEncode = getUin(e) === 88888 + let ignoreEncode = e.adapter === 'shamrock' try { if (Config.ttsMode === 'vits-uma-genshin-honkai' && Config.ttsSpace) { if (Config.autoJapanese) { diff --git a/utils/wordcloud/tokenizer.js b/utils/wordcloud/tokenizer.js index dec121a..7ec06c3 100644 --- a/utils/wordcloud/tokenizer.js +++ b/utils/wordcloud/tokenizer.js @@ -10,11 +10,11 @@ try { } export class Tokenizer { - async getHistory (groupId, date = new Date(), duration = 0) { + async getHistory (e, groupId, date = new Date(), duration = 0, userId) { if (!groupId) { throw new Error('no valid group id') } - let group = Bot.pickGroup(groupId, true) + let group = e.bot.pickGroup(groupId, true) let latestChat = await group.getChatHistory(0, 1) let seq = latestChat[0].seq let chats = latestChat @@ -41,14 +41,15 @@ export class Tokenizer { let startOfSpecifiedDate = date.getTime() // if duration > 0, go back to the specified number of hours if (duration > 0) { - // duration should be in range [0, 24] - duration = Math.min(duration, 24) - startOfSpecifiedDate = currentTime - (duration * 60 * 60 * 1000) + // duration should be in range [0, 24] + // duration = Math.min(duration, 24) + startOfSpecifiedDate = currentTime - (duration * 60 * 60 * 1000) } - // Step 4: Get the end of the specified date by adding 24 hours (in milliseconds) - const endOfSpecifiedDate = startOfSpecifiedDate + (24 * 60 * 60 * 1000) - while (isTimestampInDateRange(chats[0]?.time, startOfSpecifiedDate, endOfSpecifiedDate) && isTimestampInDateRange(chats[chats.length - 1]?.time, startOfSpecifiedDate, endOfSpecifiedDate)) { + // Step 4: Get the end of the specified date by current time + const endOfSpecifiedDate = currentTime + while (isTimestampInDateRange(chats[0]?.time, startOfSpecifiedDate, endOfSpecifiedDate) && + isTimestampInDateRange(chats[chats.length - 1]?.time, startOfSpecifiedDate, endOfSpecifiedDate)) { let chatHistory = await group.getChatHistory(seq, 20) if (chatHistory.length === 1) { if (chats[0].seq === chatHistory[0].seq) { @@ -64,28 +65,31 @@ export class Tokenizer { } } chats = chats.filter(chat => isTimestampInDateRange(chat.time, startOfSpecifiedDate, endOfSpecifiedDate)) + if (userId) { + chats = chats.filter(chat => chat.sender.user_id === userId) + } return chats } - async getKeywordTopK (groupId, topK = 100, duration = 0) { + async getKeywordTopK (e, groupId, topK = 100, duration = 0, userId) { if (!nodejieba) { throw new Error('未安装node-rs/jieba,娱乐功能-词云统计不可用') } // duration represents the number of hours to go back, should in range [0, 24] - let chats = await this.getHistory(groupId, new Date(), duration) - let duration_str = duration > 0 ? `${duration}小时` : '今日' - logger.mark(`聊天记录拉取完成,获取到${duration_str}内${chats.length}条聊天记录,准备分词中`) - + let chats = await this.getHistory(e, groupId, new Date(), duration, userId) + let durationStr = duration > 0 ? `${duration}小时` : '今日' + logger.mark(`聊天记录拉取完成,获取到${durationStr}内${chats.length}条聊天记录,准备分词中`) + const _path = process.cwd() let stopWordsPath = `${_path}/plugins/chatgpt-plugin/utils/wordcloud/cn_stopwords.txt` const data = fs.readFileSync(stopWordsPath) const stopWords = String(data)?.split('\n') || [] let chatContent = chats .map(c => c.message - //只统计文本内容 - .filter(item => item.type == 'text') - .map(textItem => `${textItem.text}`) - .join("").trim() + // 只统计文本内容 + .filter(item => item.type == 'text') + .map(textItem => `${textItem.text}`) + .join('').trim() ) .map(c => { let length = c.length @@ -132,6 +136,85 @@ export class Tokenizer { } } +export class ShamrockTokenizer extends Tokenizer { + async getHistory (e, groupId, date = new Date(), duration = 0, userId) { + logger.mark('当前使用Shamrock适配器') + if (!groupId) { + throw new Error('no valid group id') + } + let group = e.bot.pickGroup(groupId, true) + // 直接加大力度 + let pageSize = 500 + let chats = (await group.getChatHistory(0, pageSize, false)) || [] + // Get the current timestamp + let currentTime = date.getTime() + + // Step 2: Set the hours, minutes, seconds, and milliseconds to 0 + date.setHours(0, 0, 0, 0) + + // Step 3: Calculate the timestamp representing the start of the specified date + // duration represents the number of hours to go back + // if duration is 0, keeping the original date (start of today) + let startOfSpecifiedDate = date.getTime() + // if duration > 0, go back to the specified number of hours + if (duration > 0) { + // duration should be in range [0, 24] + // duration = Math.min(duration, 24) + startOfSpecifiedDate = currentTime - (duration * 60 * 60 * 1000) + } + + // Step 4: Get the end of the specified date by currentTime + const endOfSpecifiedDate = currentTime + let cursor = chats.length + // ------------------------------------------------------- + // | | | + // ------------------------------------------------------- + // ^ ^ + // long ago cursor+pageSize cursor current + while (isTimestampInDateRange(chats[0]?.time, startOfSpecifiedDate, endOfSpecifiedDate)) { + // 由于Shamrock消息是从最新的开始拉,结束时由于动态更新,一旦有人发送消息就会立刻停止,所以不判断结束时间 + // 拉到后面会巨卡,所以增大page减少次数 + pageSize = Math.floor(Math.max(cursor / 2, pageSize)) + cursor = cursor + pageSize + let retries = 3 + let chatHistory + while (retries >= 0) { + try { + chatHistory = await group.getChatHistory(0, cursor, false) + break + } catch (err) { + if (retries === 0) { + logger.error(err) + } + retries-- + } + } + if (retries < 0) { + logger.warn('拉不动了,就这样吧') + break + } + if (chatHistory.length === 1) { + break + } + if (chatHistory.length === chats.length) { + // 没有了!再拉也没有了 + break + } + let oldLength = chats.length + chats = chatHistory + // chats.sort(compareByTime) + if (Config.debug) { + logger.info(`拉取到${chats.length - oldLength}条聊天记录,当前已累计获取${chats.length}条聊天记录,继续拉...`) + } + } + chats = chats.filter(chat => isTimestampInDateRange(chat.time, startOfSpecifiedDate, endOfSpecifiedDate)) + if (userId) { + chats = chats.filter(chat => chat.sender.user_id === userId) + } + return chats + } +} + function isTimestampInDateRange (timestamp, startOfSpecifiedDate, endOfSpecifiedDate) { if (!timestamp) { return false diff --git a/utils/wordcloud/wordcloud.js b/utils/wordcloud/wordcloud.js index 08b1392..09d7614 100644 --- a/utils/wordcloud/wordcloud.js +++ b/utils/wordcloud/wordcloud.js @@ -1,11 +1,19 @@ -import { Tokenizer } from './tokenizer.js' +import { ShamrockTokenizer, Tokenizer } from './tokenizer.js' import { render } from '../common.js' -export async function makeWordcloud (e, groupId, duration = 0) { - let tokenizer = new Tokenizer() - let topK = await tokenizer.getKeywordTopK(groupId, 100, duration) +export async function makeWordcloud (e, groupId, duration = 0, userId) { + let tokenizer = getTokenizer(e) + let topK = await tokenizer.getKeywordTopK(e, groupId, 100, duration, userId) let list = JSON.stringify(topK) - // let list = topK - console.log(list) - await render(e, 'chatgpt-plugin', 'wordcloud/index', { list }) + logger.info(list) + let img = await render(e, 'chatgpt-plugin', 'wordcloud/index', { list }, { retType: 'base64' }) + await e.reply(img, true) +} + +function getTokenizer (e) { + if (e.adapter === 'shamrock') { + return new ShamrockTokenizer() + } else { + return new Tokenizer() + } } From e43b490edb903b8e62f941ff5ad08ed2f439db0e Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 19:47:49 +0800 Subject: [PATCH 12/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dmicrosoft-cognit?= =?UTF-8?q?iveservices-speech-sdk=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dbd3040..b593ce4 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "js-tiktoken": "^1.0.5", "keyv": "^4.5.3", "keyv-file": "^0.2.0", - "microsoft-cognitiveservices-speech-sdk": "^1.30.1", + "microsoft-cognitiveservices-speech-sdk": "1.32.0", "node-fetch": "^3.3.1", "openai": "^3.2.1", "p-timeout": "^6.1.2", From ce65cc862f63a03049e80c391fdb66f68c3ab083 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 19:59:10 +0800 Subject: [PATCH 13/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dlain=E4=B8=8B?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=B7=A5=E5=85=B7=E5=A4=B1=E6=95=88=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/tools/SendAudioMessageTool.js | 7 ++++++- utils/tools/SendAvatarTool.js | 8 ++++++-- utils/tools/SendDiceTool.js | 7 ++++++- utils/tools/SendMessageToSpecificGroupOrUserTool.js | 7 ++++++- utils/tools/SendPictureTool.js | 7 ++++++- utils/tools/SendRPSTool.js | 7 ++++++- 6 files changed, 36 insertions(+), 7 deletions(-) diff --git a/utils/tools/SendAudioMessageTool.js b/utils/tools/SendAudioMessageTool.js index 99b1d49..65945a0 100644 --- a/utils/tools/SendAudioMessageTool.js +++ b/utils/tools/SendAudioMessageTool.js @@ -102,7 +102,12 @@ export class SendAudioMessageTool extends AbstractTool { return `audio generation failed, error: ${JSON.stringify(err)}` } if (sendable) { - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } try { if (groupList.get(target)) { let group = await e.bot.pickGroup(target) diff --git a/utils/tools/SendAvatarTool.js b/utils/tools/SendAvatarTool.js index 5853b0a..ed6fde4 100644 --- a/utils/tools/SendAvatarTool.js +++ b/utils/tools/SendAvatarTool.js @@ -27,8 +27,12 @@ export class SendAvatarTool extends AbstractTool { const target = isNaN(targetGroupIdOrQQNumber) || !targetGroupIdOrQQNumber ? defaultTarget : parseInt(targetGroupIdOrQQNumber) === e.bot.uin ? defaultTarget : parseInt(targetGroupIdOrQQNumber) - - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } console.log('sendAvatar', target, pictures) if (groupList.get(target)) { let group = await e.bot.pickGroup(target) diff --git a/utils/tools/SendDiceTool.js b/utils/tools/SendDiceTool.js index 4ba82a1..ae3df91 100644 --- a/utils/tools/SendDiceTool.js +++ b/utils/tools/SendDiceTool.js @@ -24,7 +24,12 @@ export class SendDiceTool extends AbstractTool { const target = isNaN(targetGroupIdOrQQNumber) || !targetGroupIdOrQQNumber ? defaultTarget : parseInt(targetGroupIdOrQQNumber) === e.bot.uin ? defaultTarget : parseInt(targetGroupIdOrQQNumber) - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } num = isNaN(num) || !num ? 1 : num > 5 ? 5 : num if (groupList.get(target)) { let group = await e.bot.pickGroup(target, true) diff --git a/utils/tools/SendMessageToSpecificGroupOrUserTool.js b/utils/tools/SendMessageToSpecificGroupOrUserTool.js index c194c5e..6c71310 100644 --- a/utils/tools/SendMessageToSpecificGroupOrUserTool.js +++ b/utils/tools/SendMessageToSpecificGroupOrUserTool.js @@ -25,7 +25,12 @@ export class SendMessageToSpecificGroupOrUserTool extends AbstractTool { ? defaultTarget : parseInt(targetGroupIdOrQQNumber) === e.bot.uin ? defaultTarget : parseInt(targetGroupIdOrQQNumber) - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } try { if (groupList.get(target)) { let group = await e.bot.pickGroup(target) diff --git a/utils/tools/SendPictureTool.js b/utils/tools/SendPictureTool.js index 89653e8..d3d81cc 100644 --- a/utils/tools/SendPictureTool.js +++ b/utils/tools/SendPictureTool.js @@ -32,7 +32,12 @@ export class SendPictureTool extends AbstractTool { let pictures = urlOfPicture.trim().split(' ') logger.mark('pictures to send: ', pictures) pictures = pictures.map(img => segment.image(img)) - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } try { if (groupList.get(target)) { let group = await e.bot.pickGroup(target) diff --git a/utils/tools/SendRPSTool.js b/utils/tools/SendRPSTool.js index 73f87d0..0481ba3 100644 --- a/utils/tools/SendRPSTool.js +++ b/utils/tools/SendRPSTool.js @@ -20,7 +20,12 @@ export class SendRPSTool extends AbstractTool { const target = isNaN(targetGroupIdOrQQNumber) || !targetGroupIdOrQQNumber ? defaultTarget : parseInt(targetGroupIdOrQQNumber) === e.bot.uin ? defaultTarget : parseInt(targetGroupIdOrQQNumber) - let groupList = await e.bot.getGroupList() + let groupList + try { + groupList = await e.bot.getGroupList() + } catch (err) { + groupList = e.bot.gl + } if (groupList.get(target)) { let group = await e.bot.pickGroup(target, true) await group.sendMsg(segment.rps(num)) From e29e370f25cae33b053253af00652e0bdc4b075c Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 21:37:38 +0800 Subject: [PATCH 14/17] =?UTF-8?q?fix:=20=E6=A8=A1=E5=9E=8BmaxToken?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20gpt4=E5=90=8E=E7=BB=AD=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/common.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/common.js b/utils/common.js index 03c5271..5f45572 100644 --- a/utils/common.js +++ b/utils/common.js @@ -832,8 +832,10 @@ export function getMaxModelTokens (model = 'gpt-3.5-turbo') { if (model.startsWith('gpt-3.5-turbo')) { if (model.includes('16k')) { return 16000 - } else { + } else if (model.includes('0613') || model.includes('0314')) { return 4000 + } else { + return 16000 } } else { if (model.includes('32k')) { From 0d8ef840d46585fafe315a0da01ce014e3679d85 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 21:59:34 +0800 Subject: [PATCH 15/17] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BE=A4?= =?UTF-8?q?=E5=90=8D=E6=8B=BF=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/chat.js | 2 +- utils/chat.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/chat.js b/apps/chat.js index 58ea9b1..b407296 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -2142,7 +2142,7 @@ export class chatgpt extends plugin { opt.groupId = e.group_id opt.qq = e.sender.user_id opt.nickname = e.sender.card - opt.groupName = e.group.name + opt.groupName = e.group.name || e.group_name opt.botName = e.isGroup ? (e.group.pickMember(getUin(e)).card || e.group.pickMember(getUin(e)).nickname) : e.bot.nickname let master = (await getMasterQQ())[0] if (master && e.group) { diff --git a/utils/chat.js b/utils/chat.js index 3263c6c..31102dd 100644 --- a/utils/chat.js +++ b/utils/chat.js @@ -1,6 +1,6 @@ export async function getChatHistoryGroup (e, num) { if (e.adapter === 'shamrock') { - return await e.group.getChatHistory(0, num) + return await e.group.getChatHistory(0, num, false) } else { let latestChats = await e.group.getChatHistory(0, 1) if (latestChats.length > 0) { From a45be2e2112e770159d3971ab887f10aa872f822 Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 22:11:09 +0800 Subject: [PATCH 16/17] =?UTF-8?q?fix:=20=E8=AF=8D=E4=BA=91bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/wordcloud/tokenizer.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utils/wordcloud/tokenizer.js b/utils/wordcloud/tokenizer.js index 7ec06c3..5f8e7be 100644 --- a/utils/wordcloud/tokenizer.js +++ b/utils/wordcloud/tokenizer.js @@ -59,7 +59,10 @@ export class Tokenizer { } chats.push(...chatHistory) chats.sort(compareByTime) - seq = chatHistory[0].seq + seq = chatHistory?.[0]?.seq + if (!seq) { + break + } if (Config.debug) { logger.info(`拉取到${chatHistory.length}条聊天记录,当前已累计获取${chats.length}条聊天记录,继续拉...`) } From 56a893734cd623c81efa79bbec44180b4747525a Mon Sep 17 00:00:00 2001 From: ikechan8370 Date: Tue, 7 Nov 2023 22:13:21 +0800 Subject: [PATCH 17/17] =?UTF-8?q?fix:=20=E9=99=8D=E4=BD=8E=E8=AF=8D?= =?UTF-8?q?=E4=BA=91=E9=98=88=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/wordcloud/tokenizer.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/utils/wordcloud/tokenizer.js b/utils/wordcloud/tokenizer.js index 5f8e7be..8593e11 100644 --- a/utils/wordcloud/tokenizer.js +++ b/utils/wordcloud/tokenizer.js @@ -95,15 +95,15 @@ export class Tokenizer { .join('').trim() ) .map(c => { - let length = c.length - let threshold = 10 - if (length < 100 && length > 50) { - threshold = 6 - } else if (length <= 50 && length > 25) { - threshold = 3 - } else if (length <= 25) { - threshold = 2 - } + // let length = c.length + let threshold = 2 + // if (length < 100 && length > 50) { + // threshold = 6 + // } else if (length <= 50 && length > 25) { + // threshold = 3 + // } else if (length <= 25) { + // threshold = 2 + // } return nodejieba.extract(c, threshold) }) .reduce((acc, curr) => acc.concat(curr), [])