keli-chatgpt
Version:
keli 的 OpenAI / ChatGPT 插件
138 lines (108 loc) • 3.76 kB
JavaScript
const { Plugin } = require('keli')
const { Configuration, OpenAIApi } = require('openai')
const { name, version } = require('./package.json')
const plugin = new Plugin(name, version)
const config = {
// OpenAI apiKey
apiKey: '',
// 使用的模型,参考这里:https://platform.openai.com/docs/models/models
model: 'gpt-3.5-turbo',
// 触发命令前缀
cmdPrefix: '%',
// 超时时间(毫秒,默认一分钟)
timeout: 60000,
temperature: 0.3,
max_tokens: 1200,
// 是否开启 at 触发
enableAt: true,
// 是否在群聊中开启(发言不可控,为了账号安全可以关闭群聊功能,仅保留私聊)
enableGroup: true
}
const msgs = {
needConfig: `ChatGPT: 请先配置 apiKey,格式:/chatgpt setkey <apikey>`,
apiError: 'ChatGPT: API 请求异常,可能是 apiKey 错误或请求太频繁,请查看日志',
emptyMessage: '这个 OpenAI 不知道哦'
}
const cmds = [
'/chatgpt setkey <apiKey>',
'/chatgpt at on/off',
'/chatgpt group on/off',
'/chatgpt prefix <触发前缀>'
]
plugin.onMounted(async bot => {
plugin.saveConfig(Object.assign(config, plugin.loadConfig()))
plugin.onAdminCmd('/chatgpt', (e, params) => {
const [cmd, value] = params
if (cmd === 'setkey' && value) {
config.apiKey = value
plugin.saveConfig(config)
return e.reply('apiKey 配置完成,重载插件生效', true)
}
if (cmd === 'at' && ['on', 'off'].includes(value)) {
config.enableAt = value === 'on'
plugin.saveConfig(config)
return e.reply(`已${config.enableAt ? '开启' : '关闭'} at 触发`, true)
}
if (cmd === 'group' && ['on', 'off'].includes(value)) {
config.enableGroup = value === 'on'
plugin.saveConfig(config)
return e.reply(`已${config.enableGroup ? '开启' : '关闭'}群聊功能`, true)
}
if (cmd === 'prefix' && value) {
config.cmdPrefix = value
plugin.saveConfig(config)
return e.reply('已修改命令触发前缀', true)
}
return e.reply(cmds.join('\n'), true)
})
if (!config.apiKey) {
bot.sendPrivateMsg(plugin.mainAdmin, msgs.needConfig)
return plugin.log(msgs.needConfig)
}
const configuration = new Configuration({
apiKey: config.apiKey,
basePath: 'https://gpt.viki.moe/v1'
})
const openai = new OpenAIApi(configuration)
plugin.onMessage(async event => {
const { message, message_type } = event
const text = message
.filter(e => e.type === 'text')
.map(e => e.text)
.join('')
// 配置关闭群聊时,过滤群聊信息
if (!config.enableGroup && message_type !== 'private') {
return
}
// 消息符合命令前缀
const isCmd = text.startsWith(config.cmdPrefix)
// Bot 被艾特
const isAt = message.some(e => e.type === 'at' && e.qq === bot.uin)
// 触发条件(符合命令前缀 或者 在启用艾特触发时,Bot 被艾特)
const isHit = isCmd || (config.enableAt && isAt)
// 过滤不触发的消息
if (!isHit) {
return
}
try {
const question = text.replace(config.cmdPrefix, '').trim()
const { data } = await openai.createChatCompletion(
{
model: config.model,
temperature: config.temperature,
max_tokens: config.max_tokens,
messages: [{ role: 'user', content: question }]
},
{
timeout: config.timeout
}
)
const res = data.choices[0]?.message?.content?.trim() ?? ''
event.reply(res ?? msgs.emptyMessage, true)
} catch (err) {
plugin.logger.error(err?.message ?? err)
return event.reply(err?.message ?? msgs.apiError, true)
}
})
})
module.exports = { plugin }