From 49bbb5ceb84f3bd71b5c6661afa6f44fe98072cf Mon Sep 17 00:00:00 2001 From: HalcyonAlcedo <41666148+HalcyonAlcedo@users.noreply.github.com> Date: Sat, 4 Mar 2023 00:40:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=9E=E9=AA=8C=E6=80=A7?= =?UTF-8?q?=E6=82=89=E5=B0=BC=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=BF=85=E5=BA=94?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=A8=A1=E5=BC=8F=E6=A0=B7=E5=BC=8F=E8=87=AA?= =?UTF-8?q?=E9=80=82=E5=BA=94=20(#216)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复引用转发,默认bing模式并发 * 开启stream增加稳定性 * fix: remove queue element only in non-bing mode * 使用chatgpt-api自带的超时逻辑,文字过多时启动切换到图片输出防止被吞 * Update chat.js * 添加Bing专用的图片输出样式 * 添加chatgpt的新图片模式,临时处理切换api导致的对话异常 * 修改bing样式表 * 为图片添加外部页面缓存 * 为图片模式添加MathJax * feat: add switch for qrcode * 防止script攻击 * 修复网页模板错误 * 修复bing页面引用错误 * 缓存服务器异常时处理 * 添加默认配置加载 * 修复配置文件路径错误 * 删除重复的模板文件,修复二维码地址错误 * 修正图片渲染错误 * 修复引用渲染错误 * 二维码网址统一改为使用本地配置 * 添加关闭思考提示的配置项 * 修复在Windows上无法载入配置文件的问题 * 修复关闭qr的情况下渲染错误 * 改为使用base64传递返回数据 * 当异常过多时使用图片输出 * 添加锅巴面板配置支持 * 补充遗漏的默认配置 * 修复qr模式下引用未被传递的问题 * 修复未将引用数据传输给缓存服务器的问题 * 删除无用的bingTimeoutMs配置项 * 添加消息队列超时弹出 * 优化图片模式处理,解决对话队列卡住的问题 * 添加对图片ocr的支持 * 添加图片识别配置项 * 添加黑名单配置项 * 修复一些bug * 修改锅巴配置格式和描述 * 传入数据也使用markdown * 图片识别换行改为marked兼容 * 添加绘图CD配置项 * 独立render模块,添加图片回复引用 * 添加必应风格 * 修复上下文,修改bing样式 * 修复上下文 * 添加Sydney上下文支持 * 调整不同模式下的bing渲染颜色 * 修复样式 * 修复无法结束会话的问题 * fix: 更新版本号 --------- Co-authored-by: ikechan8370 --- apps/chat.js | 56 +++- guoba.support.js | 39 ++- resources/content/Bing/index.html | 20 +- resources/content/Bing/style.css | 60 +++++ utils/SydneyAIClient.js | 431 ++++++++++++++++++++++++++++++ utils/config.js | 5 +- 6 files changed, 579 insertions(+), 32 deletions(-) create mode 100644 utils/SydneyAIClient.js diff --git a/apps/chat.js b/apps/chat.js index ab2a700..d551186 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -5,9 +5,11 @@ import { v4 as uuid } from 'uuid' import delay from 'delay' import { ChatGPTAPI } from 'chatgpt' import { ChatGPTClient, BingAIClient } from '@waylaidwanderer/chatgpt-api' +import SydneyAIClient from '../utils/SydneyAIClient.js' import { render, getMessageById, makeForwardMsg, tryTimes, upsertMessage, randomString } from '../utils/common.js' import { ChatGPTPuppeteer } from '../utils/browser.js' import { KeyvFile } from 'keyv-file' +import Keyv from 'keyv' import { OfficialChatGPTClient } from '../utils/message.js' import fetch from 'node-fetch' import { deleteConversation, getConversations, getLatestMessageIdByConversationId } from '../utils/conversation.js' @@ -155,6 +157,15 @@ export class chatgpt extends plugin { if (use === 'api3') { await redis.del(`CHATGPT:QQ_CONVERSATION:${e.sender.user_id}`) await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true) + } else if (use === 'bing' && Config.toneStyle === 'Sydney') { + const conversation = { + store: new KeyvFile({ filename: 'cache.json' }), + namespace: 'Sydney', + } + const conversationsCache = new Keyv(conversation) + console.log(`SydneyUser_${e.sender.user_id}`,await conversationsCache.get(`SydneyUser_${e.sender.user_id}`)) + await conversationsCache.delete(`SydneyUser_${e.sender.user_id}`) + await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true) } else { let c = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`) if (!c) { @@ -171,6 +182,14 @@ export class chatgpt extends plugin { if (use === 'api3') { await redis.del(`CHATGPT:QQ_CONVERSATION:${qq}`) await this.reply(`${atUser}已退出TA当前的对话,TA仍可以@我进行聊天以开启新的对话`, true) + } else if (use === 'bing' && Config.toneStyle === 'Sydney') { + const conversation = { + store: new KeyvFile({ filename: 'cache.json' }), + namespace: 'Sydney', + } + const conversationsCache = new Keyv(conversation) + await conversationsCache.delete(`SydneyUser_${qq}`) + await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true) } else { let c = await redis.get(`CHATGPT:CONVERSATIONS:${qq}`) if (!c) { @@ -448,7 +467,7 @@ export class chatgpt extends plugin { previousConversation = JSON.parse(previousConversation) conversation = { conversationId: previousConversation.conversation.conversationId, - parentMessageId: previousConversation.conversation.parentMessageId, + parentMessageId: previousConversation.parentMessageId, clientId: previousConversation.clientId, invocationId: previousConversation.invocationId, conversationSignature: previousConversation.conversationSignature @@ -468,6 +487,7 @@ export class chatgpt extends plugin { if (use === 'bing') { previousConversation.clientId = chatMessage.clientId previousConversation.invocationId = chatMessage.invocationId + previousConversation.parentMessageId = chatMessage.parentMessageId previousConversation.conversationSignature = chatMessage.conversationSignature } else { // 或许这样切换回来不会404? @@ -576,6 +596,7 @@ export class chatgpt extends plugin { quote: quote.length > 0, quotes: quote, cache: cacheData, + style: Config.toneStyle, version }, { retType: Config.quoteReply ? 'base64' : '' }), e.isGroup && Config.quoteReply) } @@ -602,12 +623,30 @@ export class chatgpt extends plugin { if (bingToken?.indexOf('=') > -1) { cookie = bingToken } - const bingAIClient = new BingAIClient({ - userToken: bingToken, // "_U" cookie from bing.com - cookie, - debug: Config.debug, - proxy: Config.proxy - }) + let bingAIClient + if (Config.bingStyle === 'Sydney') { + const cacheOptions = { + namespace: 'Sydney', + store: new KeyvFile({ filename: 'cache.json' }), + } + bingAIClient = new SydneyAIClient({ + userToken: bingToken, // "_U" cookie from bing.com + cookie, + debug: Config.debug, + cache: cacheOptions, + user: e.sender.user_id + }) + // Sydney不实现上下文传递,删除上下文索引 + delete conversation.clientId + delete conversation.invocationId + delete conversation.conversationSignature + } else { + bingAIClient = new BingAIClient({ + userToken: bingToken, // "_U" cookie from bing.com + cookie, + debug: Config.debug + }) + } let response let reply = '' try { @@ -642,7 +681,8 @@ export class chatgpt extends plugin { conversationId: response.conversationId, clientId: response.clientId, invocationId: response.invocationId, - conversationSignature: response.conversationSignature + conversationSignature: response.conversationSignature, + parentMessageId: response.messageId } } case 'api3': { diff --git a/guoba.support.js b/guoba.support.js index f27fd10..cd4a27d 100644 --- a/guoba.support.js +++ b/guoba.support.js @@ -200,13 +200,37 @@ export function supportGuoba () { { field: 'temperature', label: 'temperature', - bottomHelpMessage: 'temperature。', + bottomHelpMessage: '用于控制回复内容的多样性,数值越大回复越加随机、多元化,数值越小回复越加保守。', component: 'InputNumber', componentProps: { min: 0, max: 2 } }, + { + label: '以下为必应方式的配置。', + component: 'Divider' + }, + { + field: 'toneStyle', + label: 'Bing模式', + bottomHelpMessage: '微软必应官方的三种应答风格。默认为均衡,Sydney为实验风格,独立与三种风格之外。', + component: 'Select', + componentProps: { + options: [ + { label: '均衡', value: 'balanced' }, + { label: '创意', value: 'creative' }, + { label: '精确', value: 'precise' }, + { label: 'Sydney(可能存在风险)', value: 'Sydney' } + ] + } + }, + { + field: 'sydney', + label: 'Sydney的设定', + bottomHelpMessage: '你可以自己改写Sydney的设定,让Sydney变成你希望的样子,不过请注意,Sydney仍然是Sydney。', + component: 'InputTextArea' + }, { label: '以下为API3方式的配置。', component: 'Divider' @@ -262,19 +286,6 @@ export function supportGuoba () { label: '验证码平台Token', bottomHelpMessage: '可注册2captcha实现跳过验证码,收费服务但很便宜。否则可能会遇到验证码而卡住。', component: 'InputPassword' - }, - { - field: 'toneStyle', - label: 'Bing模式', - bottomHelpMessage: '微软必应官方的三种应答风格。默认为均衡', - component: 'Select', - componentProps: { - options: [ - { label: '均衡', value: 'balanced' }, - { label: '创意', value: 'creative' }, - { label: '精确', value: 'precise' } - ] - } } ], // 获取配置数据方法(用于前端填充显示数据) diff --git a/resources/content/Bing/index.html b/resources/content/Bing/index.html index c2b00c5..9cce772 100644 --- a/resources/content/Bing/index.html +++ b/resources/content/Bing/index.html @@ -1,4 +1,4 @@ - + @@ -13,7 +13,7 @@ - +