feat: 尝试支持连续对话

This commit is contained in:
ikechan8370 2022-12-07 18:29:44 +08:00 committed by GitHub
parent ade4e078a6
commit 31af39f257
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

139
index.js
View file

@ -3,7 +3,13 @@ import { ChatGPTAPI } from 'chatgpt'
import _ from 'lodash' import _ from 'lodash'
const SESSION_TOKEN='' const SESSION_TOKEN=''
export class example extends plugin { /**
* 每个对话保留的时长单个对话内ai是保留上下文的超时后销毁对话再次对话创建新的对话
* 单位
* @type {number}
*/
const CONVERSATION_PRESERVE_TIME = 600
export class chatgpt extends plugin {
constructor () { constructor () {
super({ super({
/** 功能名称 */ /** 功能名称 */
@ -20,30 +26,131 @@ export class example extends plugin {
reg: '^#chatgpt([\s\S]*)', reg: '^#chatgpt([\s\S]*)',
/** 执行方法 */ /** 执行方法 */
fnc: 'chatgpt' fnc: 'chatgpt'
},
{
reg: 'chatgpt对话列表',
fnc: 'getConversations'
},
{
reg: '^#结束对话([\s\S]*)',
fnc: 'destroyConversations'
},
{
reg: 'chatgpt帮助',
fnc: 'help'
} }
] ]
}) })
const api = new ChatGPTAPI({ sessionToken: SESSION_TOKEN, markdown: false }) this.chatGPTApi = new ChatGPTAPI({
this.chatGPTApi = api 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接口 * 获取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' +
'#chatgpt+聊天内容: 发起对话与AI进行聊天\n' +
'chatgpt对话列表: 查看当前发起的对话\n' +
'#结束对话: 结束自己或@用户的对话'
await this.reply(response)
}
/**
* #chatgpt
* @param e oicq传递的事件参数e * @param e oicq传递的事件参数e
*/ */
async chatgpt (e) { async chatgpt (e) {
logger.info(e.msg) let question = _.trimStart(e.msg, '#chatgpt')
let question = _.trimStart(e.msg, "#chatgpt")
question = question.trimStart() question = question.trimStart()
logger.info(`chatgpt question: ${question}`)
await this.chatGPTApi.ensureAuth() await this.chatGPTApi.ensureAuth()
// @todo conversation let c
// const response = await this.chatGPTApi.sendMessage(question, { conversationId: '0c382256-d267-4dd4-90e3-a01dd22c20a2', onProgress: this.onProgress }) logger.info(`chatgpt question: ${question}`)
const response = await this.chatGPTApi.sendMessage(question) let previousConversation = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
/** 最后回复消息 */ if (!previousConversation) {
await this.reply(`${response}`, true) c = this.chatGPTApi.getConversation()
} previousConversation = {
sender: e.sender,
onProgress(partialResponse) { conversation: c,
console.log(partialResponse) ctime: new Date(),
utime: new Date(),
num: 0
}
await redis.set(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`, JSON.stringify(previousConversation), { EX: CONVERSATION_PRESERVE_TIME })
} else {
c = this.chatGPTApi.getConversation({
conversationId: JSON.parse(previousConversation).conversation.conversationId,
parentMessageId: JSON.parse(previousConversation).conversation.parentMessageId
})
}
try {
// console.log({ c })
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}`, true)
} catch (e) {
logger.error(e)
await this.reply(`与OpenAI通信异常请稍后重试${e}`, true)
}
} }
} }