mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
feat: add support for chatglm
This commit is contained in:
parent
9929d55bea
commit
94d5691e8a
5 changed files with 164 additions and 15 deletions
46
apps/chat.js
46
apps/chat.js
|
|
@ -22,6 +22,7 @@ import fetch from 'node-fetch'
|
|||
import { deleteConversation, getConversations, getLatestMessageIdByConversationId } from '../utils/conversation.js'
|
||||
import { convertSpeaker, generateAudio, speakers } from '../utils/tts.js'
|
||||
import { segment } from 'oicq'
|
||||
import ChatGLMClient from "../utils/chatglm.js";
|
||||
try {
|
||||
await import('keyv')
|
||||
} catch (err) {
|
||||
|
|
@ -194,6 +195,21 @@ export class chatgpt extends plugin {
|
|||
logger.info(`SydneyUser_${e.sender.user_id}`, await conversationsCache.get(`SydneyUser_${e.sender.user_id}`))
|
||||
await conversationsCache.delete(`SydneyUser_${e.sender.user_id}`)
|
||||
await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true)
|
||||
} else if (use === 'chatglm') {
|
||||
const conversation = {
|
||||
store: new KeyvFile({ filename: 'cache.json' }),
|
||||
namespace: 'chatglm'
|
||||
}
|
||||
let Keyv
|
||||
try {
|
||||
Keyv = (await import('keyv')).default
|
||||
} catch (err) {
|
||||
await this.reply('依赖keyv未安装,请执行pnpm install keyv', true)
|
||||
}
|
||||
const conversationsCache = new Keyv(conversation)
|
||||
logger.info(`ChatGLMUser_${e.sender.user_id}`, await conversationsCache.get(`SydneyUser_${e.sender.user_id}`))
|
||||
await conversationsCache.delete(`SydneyUser_${e.sender.user_id}`)
|
||||
await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true)
|
||||
} else {
|
||||
let c = await redis.get(`CHATGPT:CONVERSATIONS:${e.sender.user_id}`)
|
||||
if (!c) {
|
||||
|
|
@ -224,6 +240,21 @@ export class chatgpt extends plugin {
|
|||
const conversationsCache = new Keyv(conversation)
|
||||
await conversationsCache.delete(`SydneyUser_${qq}`)
|
||||
await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true)
|
||||
} else if (use === 'chatglm') {
|
||||
const conversation = {
|
||||
store: new KeyvFile({ filename: 'cache.json' }),
|
||||
namespace: 'chatglm'
|
||||
}
|
||||
let Keyv
|
||||
try {
|
||||
Keyv = (await import('keyv')).default
|
||||
} catch (err) {
|
||||
await this.reply('依赖keyv未安装,请执行pnpm install keyv', true)
|
||||
}
|
||||
const conversationsCache = new Keyv(conversation)
|
||||
logger.info(`SydneyUser_${e.sender.user_id}`, await conversationsCache.get(`SydneyUser_${e.sender.user_id}`))
|
||||
await conversationsCache.delete(`ChatGLMUser_${qq}`)
|
||||
await this.reply('已退出当前对话,该对话仍然保留。请@我进行聊天以开启新的对话', true)
|
||||
} else {
|
||||
let c = await redis.get(`CHATGPT:CONVERSATIONS:${qq}`)
|
||||
if (!c) {
|
||||
|
|
@ -527,9 +558,6 @@ export class chatgpt extends plugin {
|
|||
if (!lastMessageId) {
|
||||
lastMessageId = await getLatestMessageIdByConversationId(conversationId, newFetch)
|
||||
}
|
||||
// let lastMessagePrompt = await redis.get(`CHATGPT:CONVERSATION_LAST_MESSAGE_PROMPT:${conversationId}`)
|
||||
// let conversationCreateTime = await redis.get(`CHATGPT:CONVERSATION_CREATE_TIME:${conversationId}`)
|
||||
// let conversationLength = await redis.get(`CHATGPT:CONVERSATION_LENGTH:${conversationId}`)
|
||||
conversation = {
|
||||
conversationId,
|
||||
parentMessageId: lastMessageId
|
||||
|
|
@ -855,6 +883,18 @@ export class chatgpt extends plugin {
|
|||
}
|
||||
return sendMessageResult
|
||||
}
|
||||
case 'chatglm': {
|
||||
const cacheOptions = {
|
||||
namespace: 'chatglm_6b',
|
||||
store: new KeyvFile({ filename: 'cache.json' })
|
||||
}
|
||||
this.chatGPTApi = new ChatGLMClient({
|
||||
user: e.sender.user_id,
|
||||
cache: cacheOptions
|
||||
})
|
||||
let sendMessageResult = await this.chatGPTApi.sendMessage(prompt, conversation)
|
||||
return sendMessageResult
|
||||
}
|
||||
default: {
|
||||
let completionParams = {}
|
||||
if (Config.model) {
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ let helpData = [
|
|||
},
|
||||
{
|
||||
icon: 'switch',
|
||||
title: '#chatgpt切换浏览器/API/API2/API3/Bing',
|
||||
desc: '切换使用的后端为浏览器或OpenAI API/第三方API/反代官网API/Bing'
|
||||
title: '#chatgpt切换浏览器/API/API3/Bing/ChatGLM',
|
||||
desc: '切换使用的后端为浏览器或OpenAI API/反代官网API/Bing/自建ChatGLM'
|
||||
},
|
||||
{
|
||||
icon: 'confirm',
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ export class ChatgptManagement extends plugin {
|
|||
permission: 'master'
|
||||
},
|
||||
{
|
||||
reg: '^#chatgpt切换API2$',
|
||||
fnc: 'useReversedAPIBasedSolution',
|
||||
reg: '^#chatgpt切换(ChatGLM|chatglm)$',
|
||||
fnc: 'useChatGLMSolution',
|
||||
permission: 'master'
|
||||
},
|
||||
{
|
||||
|
|
@ -207,10 +207,9 @@ export class ChatgptManagement extends plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async useReversedAPIBasedSolution (e) {
|
||||
await this.reply('API2已废弃,处于不可用状态,不会为你切换')
|
||||
// await redis.set('CHATGPT:USE', 'apiReverse')
|
||||
// await this.reply('【暂时不可用,请关注仓库更新和群公告】已切换到基于第三方Reversed CompletionAPI的解决方案,如果已经对话过建议执行`#结束对话`避免引起404错误')
|
||||
async useChatGLMSolution (e) {
|
||||
await redis.set('CHATGPT:USE', 'chatglm')
|
||||
await this.reply('已切换到ChatGLM-6B解决方案,如果已经对话过建议执行`#结束对话`避免引起404错误')
|
||||
}
|
||||
|
||||
async useReversedAPIBasedSolution2 (e) {
|
||||
|
|
@ -340,10 +339,11 @@ export class ChatgptManagement extends plugin {
|
|||
let mode = await redis.get('CHATGPT:USE')
|
||||
const modeMap = {
|
||||
browser: '浏览器',
|
||||
apiReverse: 'API2',
|
||||
// apiReverse: 'API2',
|
||||
api: 'API',
|
||||
bing: '必应',
|
||||
api3: 'API3'
|
||||
api3: 'API3',
|
||||
chatglm: 'ChatGLM-6B'
|
||||
}
|
||||
let modeText = modeMap[mode || 'api']
|
||||
let message = ` API模式和浏览器模式如何选择?
|
||||
|
|
@ -356,8 +356,10 @@ export class ChatgptManagement extends plugin {
|
|||
浏览器模式通过在本地启动Chrome等浏览器模拟用户访问ChatGPT网站,使得获得和官方以及API2模式一模一样的回复质量,同时保证安全性。缺点是本方法对环境要求较高,需要提供桌面环境和一个可用的代理(能够访问ChatGPT的IP地址),且响应速度不如API,而且高峰期容易无法使用。
|
||||
|
||||
必应(Bing)将调用微软新必应接口进行对话。需要在必应网页能够正常使用新必应且设置有效的Bing 登录Cookie方可使用。#chatgpt设置必应token
|
||||
|
||||
自建ChatGLM模式会调用自建的ChatGLM-6B服务器API进行对话,需要自建。参考https://github.com/ikechan8370/SimpleChatGLM6BAPI
|
||||
|
||||
您可以使用‘#chatgpt切换浏览器/API/API2/API3/Bing’来切换到指定模式。
|
||||
您可以使用‘#chatgpt切换浏览器/API/API3/Bing/ChatGLM’来切换到指定模式。
|
||||
|
||||
当前为${modeText}模式。
|
||||
`
|
||||
|
|
|
|||
106
utils/chatglm.js
Normal file
106
utils/chatglm.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import { Config } from './config.js'
|
||||
import fetch from 'node-fetch'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
async function getKeyv () {
|
||||
let Keyv
|
||||
try {
|
||||
Keyv = (await import('keyv')).default
|
||||
} catch (error) {
|
||||
throw new Error('keyv依赖未安装,请使用pnpm install keyv安装')
|
||||
}
|
||||
return Keyv
|
||||
}
|
||||
|
||||
export default class ChatGLMClient {
|
||||
constructor (opts) {
|
||||
// user: qq号
|
||||
this.opts = opts
|
||||
}
|
||||
|
||||
async initCache () {
|
||||
if (!this.conversationsCache) {
|
||||
const cacheOptions = this.opts.cache || {}
|
||||
cacheOptions.namespace = cacheOptions.namespace || 'chatglm'
|
||||
let Keyv = await getKeyv()
|
||||
this.conversationsCache = new Keyv(cacheOptions)
|
||||
}
|
||||
}
|
||||
|
||||
async sendMessage (prompt, opts) {
|
||||
const {
|
||||
conversationId = uuidv4(),
|
||||
messageId = uuidv4(),
|
||||
parentMessageId,
|
||||
temperature = Config.temperature
|
||||
} = opts
|
||||
await this.initCache()
|
||||
let url = Config.chatglmBaseUrl + '/api/chat'
|
||||
if (Config.debug) {
|
||||
logger.info('use chatglm api server endpoint: ' + url)
|
||||
}
|
||||
const conversationKey = `ChatGLMUser_${this.opts.user}`
|
||||
const conversation = (await this.conversationsCache.get(conversationKey)) || {
|
||||
messages: [],
|
||||
createdAt: Date.now()
|
||||
}
|
||||
let history = getMessagesForConversation(conversation.messages, parentMessageId)
|
||||
if (Config.debug) {
|
||||
logger.info(history)
|
||||
}
|
||||
console.log(history)
|
||||
let option = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
temperature,
|
||||
history
|
||||
}),
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
library: 'chatgpt-plugin'
|
||||
}
|
||||
}
|
||||
let response = await fetch(url, option)
|
||||
let result = await response.text()
|
||||
try {
|
||||
result = JSON.parse(result)
|
||||
conversation.messages.push({
|
||||
id: messageId,
|
||||
role: 'user',
|
||||
content: prompt,
|
||||
parentMessageId
|
||||
})
|
||||
let responseId = uuidv4()
|
||||
conversation.messages.push({
|
||||
id: responseId,
|
||||
role: 'AI',
|
||||
content: result.data,
|
||||
parentMessageId: messageId
|
||||
})
|
||||
await this.conversationsCache.set(conversationKey, conversation)
|
||||
return {
|
||||
conversationId,
|
||||
id: responseId,
|
||||
text: result.data
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(result)
|
||||
throw new Error(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMessagesForConversation (messages, parentMessageId) {
|
||||
const orderedMessages = []
|
||||
let currentMessageId = parentMessageId
|
||||
while (currentMessageId) {
|
||||
const message = messages.find((m) => m.id === currentMessageId)
|
||||
if (!message) {
|
||||
break
|
||||
}
|
||||
orderedMessages.unshift(message)
|
||||
currentMessageId = message.parentMessageId
|
||||
}
|
||||
|
||||
return orderedMessages
|
||||
}
|
||||
|
|
@ -66,7 +66,8 @@ const defaultConfig = {
|
|||
initiativeChatGroups: [],
|
||||
enableDraw: true,
|
||||
helloPrompt: '写一段话让大家来找我聊天。类似于“有人找我聊天吗?"这种风格,轻松随意一点控制在20个字以内',
|
||||
version: 'v2.2.3'
|
||||
chatglmBaseUrl: 'http://localhost:8080',
|
||||
version: 'v2.2.4'
|
||||
}
|
||||
const _path = process.cwd()
|
||||
let config = {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue