mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 21:37:11 +00:00
feat: add support for bing(beta and WIP)
This commit is contained in:
parent
83c058ab85
commit
3ff591d205
5 changed files with 91 additions and 19 deletions
|
|
@ -5,9 +5,11 @@
|
|||
* 支持问答图片截图
|
||||
* 仅需OpenAI Api Key,开箱即用
|
||||
* 提供基于浏览器的解决方案作为备选,有条件且希望得到更好回答质量可以选择使用浏览器模式。
|
||||
* 支持新Bing(Beta)
|
||||
|
||||
## 版本要求
|
||||
Node.js >= 18 / Node.js >= 14(with node-fetch)
|
||||
小白尽可能使用18版本以上的nodejs
|
||||
|
||||
## 安装
|
||||
首先判断自己需要使用哪种模式,本插件支持官方API、第三方API和浏览器两种模式。也可以选择**我全都要**,通过qq发送命令`#chatgpt切换浏览器/API/API2`实时切换。对于轻量用户可以先使用API模式,有较高要求再转为使用其他模式。
|
||||
|
|
@ -15,9 +17,9 @@ Node.js >= 18 / Node.js >= 14(with node-fetch)
|
|||
> API模式和浏览器模式如何选择?
|
||||
>
|
||||
> * API模式会调用OpenAI官方提供的GPT-3 LLM API,只需要提供API Key。一般情况下,该种方式响应速度更快,可配置项多,且不会像chatGPT官网一样总出现不可用的现象,但其聊天效果明显较官网差。但注意GPT-3的API调用是收费的,新用户有18美元试用金可用于支付,价格为`$0.0200/ 1K tokens`.(问题和回答加起来算token)
|
||||
> * API2模式会调用第三方提供的基于OpenAI text-davinci-002-render模型(官网同款)的API,需要提供ChatGPT的Token。效果比单纯的GPT-3 API好很多,但同时将Token提供给了第三方API,其中风险自行承担。
|
||||
> * API2模式会调用第三方提供的基于OpenAI text-davinci-002-render模型(官网同款)的API,需要提供ChatGPT的Token。效果比单纯的GPT-3 API好很多,但同时将Token提供给了第三方API,其中风险自行承担。#chatgpt设置token
|
||||
> * 浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站,使得获得和官方以及API2模式一模一样的回复质量,同时保证安全性。缺点是本方法对环境要求较高,需要提供桌面环境和一个可用的代理(能够访问ChatGPT的IP地址),且响应速度不如API,而且高峰期容易无法使用。
|
||||
|
||||
> * 必应(Bing)将调用微软新必应接口进行对话。需要在必应网页能够正常使用新必应且设置有效的Bing 登录Cookie方可使用。#chatgpt设置必应token. ("_U" cookie from bing.com)
|
||||
1. 进入 Yunzai根目录
|
||||
2. 检查 Node.js 版本
|
||||
|
||||
|
|
@ -74,7 +76,6 @@ git clone https://github.com/ikechan8370/chatgpt-plugin.git ./plugins/chatgpt-pl
|
|||
|
||||
## TODO
|
||||
* 更灵活的Conversation管理
|
||||
* 支持Bing版本
|
||||
* 版本号和归档
|
||||
* API2模式下自动获取/刷新Token
|
||||
|
||||
|
|
|
|||
47
apps/chat.js
47
apps/chat.js
|
|
@ -6,7 +6,7 @@ import mjAPI from 'mathjax-node'
|
|||
import { uuid } from 'oicq/lib/common.js'
|
||||
import delay from 'delay'
|
||||
import { ChatGPTAPI } from 'chatgpt'
|
||||
import { ChatGPTClient } from '@waylaidwanderer/chatgpt-api'
|
||||
import { ChatGPTClient, BingAIClient } from '@waylaidwanderer/chatgpt-api'
|
||||
import { getMessageById, tryTimes, upsertMessage } from '../utils/common.js'
|
||||
import { ChatGPTPuppeteer } from '../utils/browser.js'
|
||||
import { KeyvFile } from 'keyv-file'
|
||||
|
|
@ -247,15 +247,25 @@ export class chatgpt extends plugin {
|
|||
previousConversation = JSON.parse(previousConversation)
|
||||
conversation = {
|
||||
conversationId: previousConversation.conversation.conversationId,
|
||||
parentMessageId: previousConversation.conversation.parentMessageId
|
||||
parentMessageId: previousConversation.conversation.parentMessageId,
|
||||
clientId: previousConversation.clientId,
|
||||
invocationId: previousConversation.invocationId,
|
||||
conversationSignature: previousConversation.conversationSignature
|
||||
}
|
||||
}
|
||||
|
||||
const use = await redis.get('CHATGPT:USE')
|
||||
try {
|
||||
let chatMessage = await this.sendMessage(prompt, conversation)
|
||||
let chatMessage = await this.sendMessage(prompt, conversation, use)
|
||||
previousConversation.conversation = {
|
||||
conversationId: chatMessage.conversationId,
|
||||
parentMessageId: chatMessage.id
|
||||
conversationId: chatMessage.conversationId
|
||||
}
|
||||
if (use === 'bing') {
|
||||
previousConversation.clientId = chatMessage.clientId
|
||||
previousConversation.invocationId = chatMessage.invocationId
|
||||
previousConversation.conversationSignature = chatMessage.conversationSignature
|
||||
} else {
|
||||
// 或许这样切换回来不会404?
|
||||
previousConversation.conversation.parentMessageId = chatMessage.id
|
||||
}
|
||||
console.log(chatMessage)
|
||||
let response = chatMessage?.text
|
||||
|
|
@ -284,7 +294,7 @@ export class chatgpt extends plugin {
|
|||
// !response.trimEnd().endsWith('!') && !response.trimEnd().endsWith('!') && !response.trimEnd().endsWith(']') && !response.trimEnd().endsWith('】')
|
||||
// ) {
|
||||
await this.reply('内容有点多,我正在奋笔疾书,请再等一会', true, { recallMsg: 5 })
|
||||
let responseAppend = await this.sendMessage('Continue', conversation)
|
||||
let responseAppend = await this.sendMessage('Continue', conversation, use)
|
||||
previousConversation.conversation = {
|
||||
conversationId: responseAppend.conversationId,
|
||||
parentMessageId: responseAppend.id
|
||||
|
|
@ -325,8 +335,8 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async sendMessage (prompt, conversation = {}) {
|
||||
const use = await redis.get('CHATGPT:USE')
|
||||
async sendMessage (prompt, conversation = {}, use) {
|
||||
|
||||
// console.log(use)
|
||||
if (use === 'browser') {
|
||||
return await this.chatgptBrowserBased(prompt, conversation)
|
||||
|
|
@ -350,7 +360,7 @@ export class chatgpt extends plugin {
|
|||
// (Optional) Set a custom name for ChatGPT
|
||||
chatGptLabel: Config.assistantLabel,
|
||||
// (Optional) Set to true to enable `console.debug()` logging
|
||||
debug: false
|
||||
debug: Config.debug
|
||||
}
|
||||
const cacheOptions = {
|
||||
// Options for the Keyv cache, see https://www.npmjs.com/package/keyv
|
||||
|
|
@ -371,6 +381,23 @@ export class chatgpt extends plugin {
|
|||
id: response.messageId,
|
||||
parentMessageId: conversation?.parentMessageId
|
||||
}
|
||||
} else if (use === 'bing') {
|
||||
let bingToken = await redis.get('CHATGPT:BING_TOKEN')
|
||||
if (!bingToken) {
|
||||
throw new Error('未绑定Bing Cookie,请使用#chatgpt设置Bing Cookie命令绑定Bing Cookie')
|
||||
}
|
||||
const bingAIClient = new BingAIClient({
|
||||
userToken: bingToken, // "_U" cookie from bing.com
|
||||
debug: Config.debug
|
||||
})
|
||||
let response = await bingAIClient.sendMessage(prompt, conversation)
|
||||
return {
|
||||
text: response.response,
|
||||
conversationId: response.conversationId,
|
||||
clientId: response.clientId,
|
||||
invocationId: response.invocationId,
|
||||
conversationSignature: response.conversationSignature
|
||||
}
|
||||
} else {
|
||||
let completionParams = {}
|
||||
if (Config.model) {
|
||||
|
|
|
|||
|
|
@ -63,8 +63,13 @@ let helpData = [
|
|||
},
|
||||
{
|
||||
icon: 'switch',
|
||||
title: '#chatgpt切换浏览器/API/API2',
|
||||
desc: '切换使用的后端为浏览器或OpenAI API/第三方API'
|
||||
title: '#chatgpt切换浏览器/API/API2/Bing',
|
||||
desc: '切换使用的后端为浏览器或OpenAI API/第三方API/Bing'
|
||||
},
|
||||
{
|
||||
icon: 'help',
|
||||
title: '#chatgpt设置(必应)token',
|
||||
desc: '设置ChatGPT或bing的Token'
|
||||
},
|
||||
{
|
||||
icon: 'help',
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ export class ChatgptManagement extends plugin {
|
|||
fnc: 'setAccessToken',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: '#chatgpt设置必应token',
|
||||
fnc: 'setBingAccessToken',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: '^#chatgpt切换浏览器$',
|
||||
fnc: 'useBrowserBasedSolution',
|
||||
|
|
@ -38,6 +43,11 @@ export class ChatgptManagement extends plugin {
|
|||
fnc: 'useReversedAPIBasedSolution',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: '^#chatgpt切换(必应|Bing)$',
|
||||
fnc: 'useReversedBingSolution',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: '^#chatgpt模式帮助$',
|
||||
fnc: 'modeHelp'
|
||||
|
|
@ -68,9 +78,28 @@ export class ChatgptManagement extends plugin {
|
|||
return false
|
||||
}
|
||||
|
||||
async setBingAccessToken (e) {
|
||||
this.setContext('saveBingToken')
|
||||
await this.reply('请发送Bing Cookie Token.("_U" cookie from bing.com)', true)
|
||||
return false
|
||||
}
|
||||
|
||||
async saveBingToken () {
|
||||
if (!this.e.msg) return
|
||||
let token = this.e.msg
|
||||
// todo 未知bing token是什么样的,有号的可以加个校验在这
|
||||
await redis.set('CHATGPT:BING_TOKEN', token)
|
||||
await this.reply('Bing Token设置成功', true)
|
||||
this.finish('saveBingToken')
|
||||
}
|
||||
|
||||
async saveToken () {
|
||||
if (!this.e.msg) return
|
||||
let token = this.e.msg
|
||||
if (!token.startsWith('ey') || token.length < 20) {
|
||||
await this.reply('ChatGPT AccessToken格式错误', true)
|
||||
this.finish('saveToken')
|
||||
}
|
||||
await redis.set('CHATGPT:TOKEN', token)
|
||||
await this.reply('ChatGPT AccessToken设置成功', true)
|
||||
this.finish('saveToken')
|
||||
|
|
@ -91,12 +120,18 @@ export class ChatgptManagement extends plugin {
|
|||
await this.reply('已切换到基于第三方Reversed API的解决方案,如果已经对话过建议执行`#结束对话`避免引起404错误')
|
||||
}
|
||||
|
||||
async useReversedBingSolution (e) {
|
||||
await redis.set('CHATGPT:USE', 'bing')
|
||||
await this.reply('已切换到基于第三方Reversed API的解决方案,如果已经对话过务必执行`#结束对话`避免引起404错误')
|
||||
}
|
||||
|
||||
async modeHelp () {
|
||||
let mode = await redis.get('CHATGPT:USE')
|
||||
const modeMap = {
|
||||
browser: '浏览器',
|
||||
apiReverse: 'API2',
|
||||
api: 'API'
|
||||
api: 'API',
|
||||
bing: '必应'
|
||||
}
|
||||
let modeText = modeMap[mode || 'api']
|
||||
let message = ` API模式和浏览器模式如何选择?
|
||||
|
|
@ -104,11 +139,14 @@ export class ChatgptManagement extends plugin {
|
|||
// eslint-disable-next-line no-irregular-whitespace
|
||||
API模式会调用OpenAI官方提供的GPT-3 LLM API,只需要提供API Key。一般情况下,该种方式响应速度更快,可配置项多,且不会像chatGPT官网一样总出现不可用的现象,但其聊天效果明显较官网差。但注意GPT-3的API调用是收费的,新用户有18美元试用金可用于支付,价格为$0.0200/ 1K tokens.(问题和回答加起来算token)
|
||||
|
||||
API2模式会调用第三方提供的基于OpenAI text-davinci-002-render模型(官网同款)的API,需要提供ChatGPT的Token。效果比单纯的GPT-3 API好很多,但同时将Token提供给了第三方API,其中风险自行承担。
|
||||
API2模式会调用第三方提供的基于OpenAI text-davinci-002-render模型(官网同款)的API,需要提供ChatGPT的Token。效果比单纯的GPT-3 API好很多,但同时将Token提供给了第三方API,其中风险自行承担。#chatgpt设置token
|
||||
|
||||
浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站,使得获得和官方以及API2模式一模一样的回复质量,同时保证安全性。缺点是本方法对环境要求较高,需要提供桌面环境和一个可用的代理(能够访问ChatGPT的IP地址),且响应速度不如API,而且高峰期容易无法使用。
|
||||
|
||||
您可以使用‘#chatgpt切换浏览器/API/API2’来切换到指定模式。
|
||||
必应(Bing)将调用微软新必应接口进行对话。需要在必应网页能够正常使用新必应且设置有效的Bing 登录Cookie方可使用。#chatgpt设置必应token
|
||||
|
||||
您可以使用‘#chatgpt切换浏览器/API/API2/Bing’来切换到指定模式。
|
||||
|
||||
当前为${modeText}模式。
|
||||
`
|
||||
await this.reply(message)
|
||||
|
|
|
|||
|
|
@ -49,5 +49,6 @@ export const Config = {
|
|||
// 可注册2captcha实现跳过验证码,收费服务但很便宜。否则可能会遇到验证码而卡住。
|
||||
'2captchaToken': '',
|
||||
// http或socks5代理
|
||||
proxy: PROXY
|
||||
proxy: PROXY,
|
||||
debug: false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue