mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
feat: ai mode
This commit is contained in:
parent
c87ce5526f
commit
41fd60f580
3 changed files with 191 additions and 22 deletions
22
README.md
22
README.md
|
|
@ -8,7 +8,7 @@ Node.js >= 16.8
|
||||||
```
|
```
|
||||||
pnpm install -w chatgpt undici
|
pnpm install -w chatgpt undici
|
||||||
```
|
```
|
||||||
> 目前要求依赖chatgpt版本要大于2.0.0,如果报错可使用`pnpm update`更新一下。
|
> chatgpt从2.0开始支持Conversation,因此要求依赖chatgpt版本要大于2.0.0,如果使用了低版本导致报错可使用`pnpm update`更新一下。
|
||||||
2. 克隆项目
|
2. 克隆项目
|
||||||
```
|
```
|
||||||
git clone https://github.com/ikechan8370/yunzai-chatgpt.git ./plugins/chatgpt
|
git clone https://github.com/ikechan8370/yunzai-chatgpt.git ./plugins/chatgpt
|
||||||
|
|
@ -17,6 +17,7 @@ git clone https://github.com/ikechan8370/yunzai-chatgpt.git ./plugins/chatgpt
|
||||||
编辑`plugins/chatgpt/index.js`文件主要修改其中的`SESSION_TOKEN`常量,修改为你的openai账号的token。token获取参见下文。
|
编辑`plugins/chatgpt/index.js`文件主要修改其中的`SESSION_TOKEN`常量,修改为你的openai账号的token。token获取参见下文。
|
||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
### 默认方式
|
||||||
#chatgpt开头即可,例如:#chatgpt 介绍一下米哈游
|
#chatgpt开头即可,例如:#chatgpt 介绍一下米哈游
|
||||||

|

|
||||||
(图片仅供参考,chatgpt在某些领域依然是人工智障,但语言起码流畅自信多了)
|
(图片仅供参考,chatgpt在某些领域依然是人工智障,但语言起码流畅自信多了)
|
||||||
|
|
@ -27,6 +28,11 @@ git clone https://github.com/ikechan8370/yunzai-chatgpt.git ./plugins/chatgpt
|
||||||
比如让他写剧本
|
比如让他写剧本
|
||||||
<img width="835" alt="image" src="https://user-images.githubusercontent.com/21212372/206387421-db00728d-1869-40f3-bde4-0dd6a4b67913.png">
|
<img width="835" alt="image" src="https://user-images.githubusercontent.com/21212372/206387421-db00728d-1869-40f3-bde4-0dd6a4b67913.png">
|
||||||
|
|
||||||
|
### 群聊使用艾特(@)的方式
|
||||||
|
如果你的机器人插件少不担心冲突问题的话,将 `index.js` 重命名为 `index.js.bak`,将 `index_no#.js` 重命名为 `index.js`,此时将基于艾特模式进行聊天。\
|
||||||
|
此时只需在群聊中@机器人+聊天内容即可。\
|
||||||
|
同时,此模式下私聊直接打字聊天即可,也无需加#chatgpt前缀。
|
||||||
|
|
||||||
发挥你的想象力吧!
|
发挥你的想象力吧!
|
||||||
|
|
||||||
## 关于openai token获取
|
## 关于openai token获取
|
||||||
|
|
@ -38,18 +44,10 @@ git clone https://github.com/ikechan8370/yunzai-chatgpt.git ./plugins/chatgpt
|
||||||
|
|
||||||
其他问题可以参考使用的api库https://github.com/transitive-bullshit/chatgpt-api
|
其他问题可以参考使用的api库https://github.com/transitive-bullshit/chatgpt-api
|
||||||
|
|
||||||
## 其他
|
|
||||||
`index.js`文件中,
|
|
||||||
```
|
|
||||||
this.chatGPTApi = new ChatGPTAPI({
|
|
||||||
sessionToken: SESSION_TOKEN,
|
|
||||||
markdown: true,
|
|
||||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
|
|
||||||
})
|
|
||||||
```
|
|
||||||
默认关闭了markdown支持,如果发现代码类回答显示有问题可以将其改为true试试。
|
|
||||||
|
|
||||||
此外,该api响应速度可能由于模型本身及网络原因不会太快,请勿频繁重发。后续准备加入限速等功能。
|
## 其他
|
||||||
|
|
||||||
|
该api响应速度可能由于模型本身及网络原因不会太快,请勿频繁重发。后续准备加入限速等功能。因网络问题和模型响应速度问题可能出现500、503、404等各种异常状态码,此时等待官方恢复即可。实测复杂的中文对话更容易触发503错误(超时)。如出现429则意味着超出了免费账户调用频率,只能暂时停用,放置一段时间再继续使用。
|
||||||
|
|
||||||
openai目前开放chatgpt模型的免费试用,在此期间本项目应该都可用,后续如果openai调整其收费策略,到时候视情况进行调整。
|
openai目前开放chatgpt模型的免费试用,在此期间本项目应该都可用,后续如果openai调整其收费策略,到时候视情况进行调整。
|
||||||
|
|
||||||
|
|
|
||||||
18
index.js
18
index.js
|
|
@ -103,7 +103,9 @@ export class chatgpt extends plugin {
|
||||||
let response = 'chatgpt-plugin使用帮助文字版\n' +
|
let response = 'chatgpt-plugin使用帮助文字版\n' +
|
||||||
'#chatgpt+聊天内容: 发起对话与AI进行聊天\n' +
|
'#chatgpt+聊天内容: 发起对话与AI进行聊天\n' +
|
||||||
'chatgpt对话列表: 查看当前发起的对话\n' +
|
'chatgpt对话列表: 查看当前发起的对话\n' +
|
||||||
'#结束对话: 结束自己或@用户的对话'
|
'#结束对话: 结束自己或@用户的对话\n' +
|
||||||
|
'chatgpt帮助: 查看本帮助\n' +
|
||||||
|
'源代码:https://github.com/ikechan8370/chatgpt-plugin'
|
||||||
await this.reply(response)
|
await this.reply(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,18 +122,20 @@ export class chatgpt extends plugin {
|
||||||
let previousConversation = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
let previousConversation = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
||||||
if (!previousConversation) {
|
if (!previousConversation) {
|
||||||
c = this.chatGPTApi.getConversation()
|
c = this.chatGPTApi.getConversation()
|
||||||
|
let ctime = new Date()
|
||||||
previousConversation = {
|
previousConversation = {
|
||||||
sender: e.sender,
|
sender: e.sender,
|
||||||
conversation: c,
|
conversation: c,
|
||||||
ctime: new Date(),
|
ctime,
|
||||||
utime: new Date(),
|
utime: ctime,
|
||||||
num: 0
|
num: 0
|
||||||
}
|
}
|
||||||
await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(previousConversation), { EX: CONVERSATION_PRESERVE_TIME })
|
await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(previousConversation), { EX: CONVERSATION_PRESERVE_TIME })
|
||||||
} else {
|
} else {
|
||||||
|
previousConversation = JSON.parse(previousConversation)
|
||||||
c = this.chatGPTApi.getConversation({
|
c = this.chatGPTApi.getConversation({
|
||||||
conversationId: JSON.parse(previousConversation).conversation.conversationId,
|
conversationId: previousConversation.conversation.conversationId,
|
||||||
parentMessageId: JSON.parse(previousConversation).conversation.parentMessageId
|
parentMessageId: previousConversation.conversation.parentMessageId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
@ -147,10 +151,10 @@ export class chatgpt extends plugin {
|
||||||
num: previousConversation.num + 1
|
num: previousConversation.num + 1
|
||||||
}), { EX: CONVERSATION_PRESERVE_TIME })
|
}), { EX: CONVERSATION_PRESERVE_TIME })
|
||||||
/** 最后回复消息 */
|
/** 最后回复消息 */
|
||||||
await this.reply(`${response}`, true)
|
await this.reply(`${response}`, e.isGroup)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
await this.reply(`与OpenAI通信异常,请稍后重试:${e}`, true)
|
await this.reply(`与OpenAI通信异常,请稍后重试:${e}`, e.isGroup, { recallMsg: e.isGroup ? 10 : 0 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
167
index_no#.js
Normal file
167
index_no#.js
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
import plugin from '../../lib/plugins/plugin.js'
|
||||||
|
import { ChatGPTAPI } from 'chatgpt'
|
||||||
|
import _ from 'lodash'
|
||||||
|
const SESSION_TOKEN = ''
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个对话保留的时长。单个对话内ai是保留上下文的。超时后销毁对话,再次对话创建新的对话。
|
||||||
|
* 单位:秒
|
||||||
|
* @type {number}
|
||||||
|
*/
|
||||||
|
const CONVERSATION_PRESERVE_TIME = 600
|
||||||
|
export class chatgpt extends plugin {
|
||||||
|
constructor () {
|
||||||
|
super({
|
||||||
|
/** 功能名称 */
|
||||||
|
name: 'chatgpt',
|
||||||
|
/** 功能描述 */
|
||||||
|
dsc: 'chatgpt from openai',
|
||||||
|
/** https://oicqjs.github.io/oicq/#events */
|
||||||
|
event: 'message',
|
||||||
|
/** 优先级,数字越小等级越高 */
|
||||||
|
priority: 5000,
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
/** 命令正则匹配 */
|
||||||
|
reg: '^[^#][sS]*',
|
||||||
|
/** 执行方法 */
|
||||||
|
fnc: 'chatgpt'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reg: '#chatgpt对话列表',
|
||||||
|
fnc: 'getConversations',
|
||||||
|
permission: 'master'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reg: '^#结束对话([sS]*)',
|
||||||
|
fnc: 'destroyConversations'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reg: '#chatgpt帮助',
|
||||||
|
fnc: 'help'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
this.chatGPTApi = new ChatGPTAPI({
|
||||||
|
sessionToken: SESSION_TOKEN,
|
||||||
|
markdown: true,
|
||||||
|
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取chatgpt当前对话列表
|
||||||
|
* @param e
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async getConversations (e) {
|
||||||
|
let keys = await redis.keys('CHATGPT:CONVERSATIONS:*')
|
||||||
|
if (!keys || keys.length === 0) {
|
||||||
|
await this.reply('当前没有人正在与机器人对话', true)
|
||||||
|
} else {
|
||||||
|
let response = '当前对话列表:(格式为【开始时间 | qq昵称 | 对话长度 | 最后活跃时间】)\n'
|
||||||
|
await Promise.all(keys.map(async (key) => {
|
||||||
|
let conversation = await redis.get(key)
|
||||||
|
if (conversation) {
|
||||||
|
conversation = JSON.parse(conversation)
|
||||||
|
response += `${conversation.ctime} | ${conversation.sender.nickname} | ${conversation.num} | ${conversation.utime} \n`
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
await this.reply(`${response}`, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁指定人的对话
|
||||||
|
* @param e
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async destroyConversations (e) {
|
||||||
|
let ats = e.message.filter(m => m.type === 'at')
|
||||||
|
if (ats.length === 0) {
|
||||||
|
let c = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
||||||
|
if (!c) {
|
||||||
|
await this.reply('当前没有开启对话', true)
|
||||||
|
} else {
|
||||||
|
await redis.del(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
||||||
|
await this.reply('已结束当前对话,请使用#chatgpt进行聊天以开启新的对话', true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let at = ats[0]
|
||||||
|
let qq = at.qq
|
||||||
|
let atUser = _.trimStart(at.text, '@')
|
||||||
|
let c = await redis.get(`CHATGPT:CONVERSATIONS:${qq}`)
|
||||||
|
if (!c) {
|
||||||
|
await this.reply(`当前${atUser}没有开启对话`, true)
|
||||||
|
} else {
|
||||||
|
await redis.del(`CHATGPT:CONVERSATIONS:${qq}`)
|
||||||
|
await this.reply(`已结束${atUser}的对话,他仍可以使用#chatgpt进行聊天以开启新的对话`, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async help (e) {
|
||||||
|
let response = 'chatgpt-plugin使用帮助文字版\n' +
|
||||||
|
'@我+聊天内容: 发起对话与AI进行聊天\n' +
|
||||||
|
'#chatgpt对话列表: 查看当前发起的对话\n' +
|
||||||
|
'#结束对话: 结束自己或@用户的对话\n' +
|
||||||
|
'#chatgpt帮助: 查看本帮助' +
|
||||||
|
'源代码:https://github.com/ikechan8370/chatgpt-plugin'
|
||||||
|
await this.reply(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* #chatgpt
|
||||||
|
* @param e oicq传递的事件参数e
|
||||||
|
*/
|
||||||
|
async chatgpt (e) {
|
||||||
|
if (e.msg.startsWith("#")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (e.isGroup && !e.atme) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// let question = _.trimStart(e.msg, '#chatgpt')
|
||||||
|
let question = e.msg.trimStart()
|
||||||
|
let c
|
||||||
|
logger.info(`chatgpt question: ${question}`)
|
||||||
|
let previousConversation = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
||||||
|
if (!previousConversation) {
|
||||||
|
c = this.chatGPTApi.getConversation()
|
||||||
|
let ctime = new Date()
|
||||||
|
previousConversation = {
|
||||||
|
sender: e.sender,
|
||||||
|
conversation: c,
|
||||||
|
ctime,
|
||||||
|
utime: ctime,
|
||||||
|
num: 0
|
||||||
|
}
|
||||||
|
await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(previousConversation), { EX: CONVERSATION_PRESERVE_TIME })
|
||||||
|
} else {
|
||||||
|
previousConversation = JSON.parse(previousConversation)
|
||||||
|
c = this.chatGPTApi.getConversation({
|
||||||
|
conversationId: previousConversation.conversation.conversationId,
|
||||||
|
parentMessageId: previousConversation.conversation.parentMessageId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// console.log({ c })
|
||||||
|
await this.chatGPTApi.ensureAuth()
|
||||||
|
const response = await c.sendMessage(question)
|
||||||
|
logger.info(response)
|
||||||
|
// 更新redis中的conversation对象,因为send后c已经被自动更新了
|
||||||
|
await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify({
|
||||||
|
sender: e.sender,
|
||||||
|
conversation: c,
|
||||||
|
ctime: previousConversation.ctime,
|
||||||
|
utime: new Date(),
|
||||||
|
num: previousConversation.num + 1
|
||||||
|
}), { EX: CONVERSATION_PRESERVE_TIME })
|
||||||
|
/** 最后回复消息 */
|
||||||
|
await this.reply(`${response}`, e.isGroup)
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(e)
|
||||||
|
await this.reply(`与OpenAI通信异常,请稍后重试:${e}`, true, { recallMsg: e.isGroup ? 10 : 0 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue