feat: add support for the third party reverse proxy mode

This commit is contained in:
ikechan8370 2023-02-12 15:05:03 +08:00
parent 36aaa12586
commit a8ec5f41e3
6 changed files with 201 additions and 72 deletions

34
LowerNode.md Normal file
View file

@ -0,0 +1,34 @@
### Node.js >= 14 (并且 <18)时的安装方法
**如果不是 CentOS 7, RHEL 7, Ubuntu 18 请自行搜索并升级你的 Node.js 版本!**
**此教程是为了因 glibc 不支持升级 Node.js 的Linux发行版准备的。**
1. 进入 Yunzai 根目录
2. 安装依赖
```
pnpm install -w undici chatgpt showdown mathjax-node delay uuid remark strip-markdown node-fetch @waylaidwanderer/chatgpt-api keyv-file
```
**若使用API模式chatgpt的版本号注意要大于4.2.0**
若不使用浏览器模式,可以不安装`random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth`这几个
3. 克隆项目
```
git clone https://github.com/ikechan8370/chatgpt-plugin.git ./plugins/chatgpt-plugin
```
4. 修改配置
修改 Yunzai根目录/node_modules/.pnpm/chatgpt\@4.1.0/node_modules/chatgpt/build/index.js
**此处 chatgpt\@4.1.0 路径不是绝对的!请根据自己安装的版本进行替换!**
**将 // src/fetch.ts 部分修改成如下样子,其他部分不要动**
```
// src/fetch.ts
import fetch from 'node-fetch';
globalThis.fetch = fetch;
```
再编辑`Yunzai根目录/plugins/chatgpt-plugin/config/index.js`文件,根据其中的注释修改必要配置项。
---

View file

@ -15,26 +15,27 @@ 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)
> * 浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站使得获得和官方一模一样的回复质量。缺点是本方法对环境要求较高需要提供桌面环境和一个可用的代理能够访问ChatGPT的IP地址且响应速度不如API而且高峰期容易无法使用。
> * API2模式会调用第三方提供的基于OpenAI text-davinci-002-render模型官网同款的API需要提供ChatGPT的Token。效果比单纯的GPT-3 API好很多但同时将Token提供给了第三方API其中风险自行承担。
> * 浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站使得获得和官方以及API2模式一模一样的回复质量同时保证安全性。缺点是本方法对环境要求较高需要提供桌面环境和一个可用的代理能够访问ChatGPT的IP地址且响应速度不如API而且高峰期容易无法使用。
1. 进入 Yunzai根目录
2. 检查 Node.js 版本,并根据对应的 Node.js 版本选择安装教程。
2. 检查 Node.js 版本
```
node -v
```
### Node.js >= 18
若 Node.js >= 18根据下方步骤安装即可。否则参考[这里](LowerNode.md)
1. 进入 Yunzai根目录
2. 安装依赖
```
pnpm install -w undici chatgpt showdown mathjax-node delay uuid remark strip-markdown random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth
pnpm install -w undici chatgpt showdown mathjax-node delay uuid remark strip-markdown random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth @waylaidwanderer/chatgpt-api keyv-file
```
**若使用API模式chatgpt的版本号注意要大于4.2.0**
若不使用浏览器模式,可以不安装`random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth`这几个
若不使用浏览器模式,可以不安装`random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth`这几个依赖,这几个依赖仅用于模拟浏览器登录。
3. 克隆项目
```
@ -46,75 +47,46 @@ git clone https://github.com/ikechan8370/chatgpt-plugin.git ./plugins/chatgpt-pl
---
### Node.js >= 14 (并且 <18)
**如果不是 CentOS 7, RHEL 7, Ubuntu 18 请自行搜索并升级你的 Node.js 版本!**
**此教程是为了因 glibc 不支持升级 Node.js 的Linux发行版准备的。**
1. 进入 Yunzai 根目录
2. 安装依赖
```
pnpm install -w undici chatgpt showdown mathjax-node delay uuid remark strip-markdown node-fetch
```
**若使用API模式chatgpt的版本号注意要大于4.2.0**
若不使用浏览器模式,可以不安装`random puppeteer-extra-plugin-recaptcha puppeteer-extra puppeteer-extra-plugin-stealth`这几个
3. 克隆项目
```
git clone https://github.com/ikechan8370/chatgpt-plugin.git ./plugins/chatgpt-plugin
```
4. 修改配置
修改 Yunzai根目录/node_modules/.pnpm/chatgpt\@4.1.0/node_modules/chatgpt/build/index.js
**此处 chatgpt\@4.1.0 路径不是绝对的!请根据自己安装的版本进行替换!**
**将 // src/fetch.ts 部分修改成如下样子,其他部分不要动**
```
// src/fetch.ts
import fetch from 'node-fetch';
globalThis.fetch = fetch;
```
再编辑`Yunzai根目录/plugins/chatgpt-plugin/config/index.js`文件,根据其中的注释修改必要配置项。
---
## 使用
### 基本使用
@机器人 发送聊内容即可
将配置文件中的toggleMode修改为prefix可以将触发方式改为【#chat+问题】,可以避免指令冲突。
根据配置文件中的toggleMode决定联通方式。
* at模式@机器人 发送聊内容即可
* prefix模式#chat+问题】,本模式可以避免指令冲突。
![img.png](resources/img/example1.png)
发挥你的想象力吧!
关于配置中的一些模型的配置项:
* `model`通常保持空即可除非你想调用特定的模型比如你用gpt-3微调的学到特定领域知识的机器人。
关于API及API1模式下配置中的一些模型的配置项
* `model`通常保持空即可除非你想调用特定的模型比如你用gpt-3微调的学到特定领域知识的机器人。API1模式下将强制使用chatGPT模型。
* `promptPrefixOverride`:通常保持空即可。如果你想调整机器人回复的风格,可以在这里加入对机器人的一些暗示,比如要求用中文,要求回答长一点/短一点。甚至可以让它有自己的小脾气。下图为我让他不要回答太简单的问题,并且表现出不耐烦。
![)T@~XY~NWXUM S1)D$7%I3H](https://user-images.githubusercontent.com/21212372/217540723-0b97553a-f4ba-41df-ae0c-0449f73657fc.png)
![image](https://user-images.githubusercontent.com/21212372/217545618-3793d9f8-7941-476b-81f8-4255ac216cf7.png)
* `assistantLabel`默认为ChatGPT表示机器人认知中的自己的名字。你可以修改为其他名字。
* `plus`如果你购买了ChatGPT Plus将这个值改为true可以使响应速度更快。
### 获取帮助
发送#chatgpt帮助
## TODO
* 更灵活的Conversation管理
* 支持Bing版本
* 版本号和归档
* API2模式下自动获取/刷新Token
## 关于openai账号
1. 注册openai账号
进入https://chat.openai.com/ 选择signup注册。目前openai不对包括俄罗斯、乌克兰、伊朗、中国等国家和地区提供服务所以自行寻找办法使用其他国家和地区的ip登录。此外注册可能需要验证所在国家和地区的手机号码如果没有国外手机号可以试试解码网站收费的推荐https://sms-activate.org/。
2. 获取API key
进入账户后台创建API keyhttps://platform.openai.com/account/api-keys
3. 获取Access Token
登录后访问https://chat.openai.com/api/auth/session
其他问题可以参考使用的api库 https://github.com/transitive-bullshit/chatgpt-api
其他问题可以参考使用的api库 https://github.com/transitive-bullshit/chatgpt-api 以及 https://github.com/waylaidwanderer/node-chatgpt-api
## 其他
@ -138,8 +110,12 @@ OpenAI 即将开放其官方ChatGPT API且微软必应也公开发布了基
>
> 实测该方案资源占用低运行稳定基本1核2G的轻量云服务器就足够了。
3. 我和机器人聊天但没有任何反应怎么办?
可能是由于Yunzai-bot异常退出等原因造成Redis 队列中有残留的等待问题。使用`#清空队列`命令清除队列后再试。
## 感谢
* https://github.com/transitive-bullshit/chatgpt-api
* https://github.com/waylaidwanderer/node-chatgpt-api
* https://chat.openai.com/
![Alt](https://repobeats.axiom.co/api/embed/076d597ede41432208435f233d18cb20052fb90a.svg "Repobeats analytics image")

View file

@ -6,8 +6,10 @@ 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 { getMessageById, tryTimes, upsertMessage } from '../utils/common.js'
import { ChatGPTPuppeteer } from '../utils/browser.js'
import { KeyvFile } from 'keyv-file'
// import puppeteer from '../utils/browser.js'
// import showdownKatex from 'showdown-katex'
const blockWords = Config.blockWords
@ -86,17 +88,8 @@ export class chatgpt extends plugin {
reg: '#移出(chat)?队列首位',
fnc: 'removeQueueFirst',
permission: 'master'
},
{
reg: '#chatgpt切换浏览器',
fnc: 'useBrowserBasedSolution',
permission: 'master'
},
{
reg: '#chatgpt切换[(api)|(API)]',
fnc: 'useOpenAIAPIBasedSolution',
permission: 'master'
}
]
})
this.toggleMode = toggleMode
@ -221,6 +214,7 @@ export class chatgpt extends plugin {
if (confirmOn) {
let length = await redis.lLen('CHATGPT:CHAT_QUEUE') - 1
await this.reply(`我正在思考如何回复你,请稍等,当前队列前方还有${length}个问题`, true, { recallMsg: 8 })
logger.info(`chatgpt队列前方还有${length}个问题。管理员可通过#清空队列来强制清除所有等待的问题。`)
}
// 开始排队
while (true) {
@ -331,11 +325,52 @@ export class chatgpt extends plugin {
}
}
async sendMessage (prompt, conversation) {
async sendMessage (prompt, conversation = {}) {
const use = await redis.get('CHATGPT:USE')
console.log(use)
// console.log(use)
if (use === 'browser') {
return await this.chatgptBrowserBased(prompt, conversation)
} else if (use === 'apiReverse') {
const currentDate = new Date().toISOString().split('T')[0]
let promptPrefix = `You are ${Config.assistantLabel}, a large language model trained by OpenAI. ${Config.promptPrefixOverride || defaultPropmtPrefix}
Current date: ${currentDate}`
const clientOptions = {
// (Optional) Support for a reverse proxy for the completions endpoint (private API server).
// Warning: This will expose your `openaiApiKey` to a third-party. Consider the risks before using this.
reverseProxyUrl: 'https://chatgpt.pawan.krd/api/completions',
// (Optional) Parameters as described in https://platform.openai.com/docs/api-reference/completions
modelOptions: {
// You can override the model name and any other parameters here.
model: Config.plus ? 'text-davinci-002-render-paid' : 'text-davinci-002-render'
},
// (Optional) Set custom instructions instead of "You are ChatGPT...".
promptPrefix,
// (Optional) Set a custom name for the user
// userLabel: 'User',
// (Optional) Set a custom name for ChatGPT
chatGptLabel: Config.assistantLabel,
// (Optional) Set to true to enable `console.debug()` logging
debug: false
}
const cacheOptions = {
// Options for the Keyv cache, see https://www.npmjs.com/package/keyv
// This is used for storing conversations, and supports additional drivers (conversations are stored in memory by default)
// For example, to use a JSON file (`npm i keyv-file`) as a database:
store: new KeyvFile({ filename: 'cache.json' })
}
let accessToken = await redis.get('CHATGPT:TOKEN')
if (!accessToken) {
throw new Error('未绑定ChatGPT AccessToken')
}
// console.log(accessToken)
this.chatGPTApi = new ChatGPTClient(accessToken, clientOptions, cacheOptions)
let response = await tryTimes(async () => await this.chatGPTApi.sendMessage(prompt, conversation || {}), 5)
return {
text: response.response,
conversationId: response.response,
id: response.messageId,
parentMessageId: conversation?.parentMessageId
}
} else {
let completionParams = {}
if (Config.model) {
@ -363,15 +398,6 @@ export class chatgpt extends plugin {
}
}
async useBrowserBasedSolution (e) {
await redis.set('CHATGPT:USE', 'browser')
await this.reply('已切换到基于浏览器的解决方案')
}
async useOpenAIAPIBasedSolution (e) {
await redis.set('CHATGPT:USE', 'api')
await this.reply('已切换到基于OpenAI API的解决方案')
}
async emptyQueue (e) {
await redis.lTrim('CHATGPT:CHAT_QUEUE', 1, 0)

View file

@ -63,8 +63,13 @@ let helpData = [
},
{
icon: 'switch',
title: '#chatgpt切换浏览器/API',
desc: '切换使用的后端为浏览器或OpenAI API'
title: '#chatgpt切换浏览器/API/API2',
desc: '切换使用的后端为浏览器或OpenAI API/第三方API'
},
{
icon: 'help',
title: '#chatgpt模式帮助',
desc: '查看多种聊天模式的区别及当前使用的模式'
},
{
icon: 'help',

View file

@ -17,6 +17,34 @@ export class ChatgptManagement extends plugin {
reg: '#chatgpt关闭(问题)?(回复)?确认',
fnc: 'turnOffConfirm',
permission: 'master'
},
{
reg: '#chatgpt设置token',
fnc: 'setAccessToken',
permission: 'master'
},
{
reg: '^#chatgpt切换浏览器$',
fnc: 'useBrowserBasedSolution',
permission: 'master'
},
{
reg: '^#chatgpt切换API$',
fnc: 'useOpenAIAPIBasedSolution',
permission: 'master'
},
{
reg: '^#chatgpt切换API2$',
fnc: 'useReversedAPIBasedSolution',
permission: 'master'
},
{
reg: '^#chatgpt模式帮助$',
fnc: 'modeHelp'
},
{
reg: '^#chatgpt模式$',
fnc: 'modeHelp'
}
]
})
@ -33,4 +61,56 @@ export class ChatgptManagement extends plugin {
await this.reply('已关闭消息确认', true)
return false
}
async setAccessToken (e) {
this.setContext('saveToken')
await this.reply('请发送ChatGPT AccessToken', true)
return false
}
async saveToken () {
if (!this.e.msg) return
let token = this.e.msg
await redis.set('CHATGPT:TOKEN', token)
await this.reply('ChatGPT AccessToken设置成功', true)
this.finish('saveToken')
}
async useBrowserBasedSolution (e) {
await redis.set('CHATGPT:USE', 'browser')
await this.reply('已切换到基于浏览器的解决方案')
}
async useOpenAIAPIBasedSolution (e) {
await redis.set('CHATGPT:USE', 'api')
await this.reply('已切换到基于OpenAI API的解决方案')
}
async useReversedAPIBasedSolution (e) {
await redis.set('CHATGPT:USE', 'apiReverse')
await this.reply('已切换到基于第三方Reversed API的解决方案')
}
async modeHelp () {
let mode = await redis.get('CHATGPT:USE')
const modeMap = {
browser: '浏览器',
apiReverse: 'API2',
api: 'API'
}
let modeText = modeMap[mode || 'api']
let message = ` API模式和浏览器模式如何选择
// 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其中风险自行承担
浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站使得获得和官方以及API2模式一模一样的回复质量同时保证安全性缺点是本方法对环境要求较高需要提供桌面环境和一个可用的代理能够访问ChatGPT的IP地址且响应速度不如API而且高峰期容易无法使用
您可以使用#chatgpt切换浏览器/API/API2来切换到指定模式
当前为${modeText}模式
`
await this.reply(message)
}
}

View file

@ -13,7 +13,7 @@ export const Config = {
// 每个人发起的对话保留时长。超过这个时长没有进行对话,再进行对话将开启新的对话。单位:秒
conversationPreserveTime: 0,
// 触发方式 可选值at 或 prefix 。at模式下只有at机器人才会回复。prefix模式下不需要at但需要添加前缀#chat
toggleMode: 'prefix',
toggleMode: 'at',
// ***********************************************************************************************************************************
// 以下为API方式(默认)的配置 *
// ***********************************************************************************************************************************
@ -21,7 +21,15 @@ export const Config = {
// 模型名称选填。如无特殊需求保持默认即可会使用chatgpt-api库提供的当前可用的最适合的默认值。保底可用的是 text-davinci-003。当发现新的可用的chatGPT模型会更新这里的值
// 20230211 text-chat-davinci-002-sh-alpha-aoruigiofdj83 中午存活了几分钟
model: '',
// 给模型的暗示promt。选填。默认完整值`You are ${this._assistantLabel}, a large language model trained by OpenAI. You answer as concisely as possible for each response (e.g. dont be verbose). It is very important that you answer as concisely as possible, so please remember this. If you are generating a list, do not have too many items. Keep the number of items short. Current date: ${currentDate}\n\n
// ***********************************************************************************************************************************
// 以下为API2方式的配置 *
// ***********************************************************************************************************************************
// 如果购买了plus改为true将使用收费模型响应更快
plus: false,
// ***********************************************************************************************************************************
// 以下为API/API2方式公用的配置 *
// ***********************************************************************************************************************************
// 给模型的前言promt。选填。默认完整值`You are ${this._assistantLabel}, a large language model trained by OpenAI. You answer as concisely as possible for each response (e.g. dont be verbose). It is very important that you answer as concisely as possible, so please remember this. If you are generating a list, do not have too many items. Keep the number of items short. Current date: ${currentDate}\n\n
// 此项配置会覆盖掉中间部分。保持为空将使用网友从对话中推测出的指令。
// 你可以在这里写入你希望AI回答的风格比如希望优先回答中文回答长一点等
promptPrefixOverride: 'Your answer shouldn\'t be too verbose. If you are generating a list, do not have too many items. Keep the number of items short. Prefer to answer in Chinese.',