Skip to content

Commit

Permalink
feature: 添加QAnything 支持和CozeV3 支持
Browse files Browse the repository at this point in the history
  • Loading branch information
leo committed Aug 6, 2024
1 parent 453230e commit a3d135c
Show file tree
Hide file tree
Showing 19 changed files with 997 additions and 207 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## 更新日志

### V1.6.60(2024-08-06)
1、添加有道QAnything 支持
2、添加CozeV3 支持
3、更新机器人头像
4、增长二维码过期时间

### V1.6.59(2024-07-12)
1、Dify 和 FastGPT 添加备注参数,可以获取用户的备注信息,更加个性化

Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wechaty-web-panel",
"version": "1.6.59",
"version": "1.6.60",
"description": "智能微秘书插件",
"exports": {
".": {
Expand Down Expand Up @@ -51,28 +51,29 @@
"devDependencies": {
"@chatie/semver": "^0.4.7",
"@chatie/tsconfig": "^4.6.3",
"@grpc/grpc-js": "1.9.14",
"@juzi/wechaty": "^1.0.87",
"@juzi/wechaty-puppet": "^1.0.78",
"@juzi/wechaty-puppet-service": "^1.0.87",
"babel-eslint": "^10.1.0",
"eslint": "^7.4.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.4",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"@juzi/wechaty": "^1.0.87",
"@grpc/grpc-js": "1.9.14",
"@juzi/wechaty-puppet": "^1.0.78",
"@juzi/wechaty-puppet-service": "^1.0.87",
"wechaty": "^1.20.2",
"wechaty-puppet-service": "^1.18.2",
"wechaty-puppet-wechat4u": "^1.14.12",
"wechaty-puppet": "^1.21.1",
"wechaty-puppet-padlocal": "^1.20.1",
"wechaty-puppet": "^1.21.1"
"wechaty-puppet-service": "^1.18.2",
"wechaty-puppet-wechat4u": "^1.14.12"
},
"readme": "README.md",
"engines": {
"node": ">=16",
"npm": ">=7"
},
"dependencies": {
"@coze/coze-js": "^0.1.2",
"@dqbd/tiktoken": "^1.0.2",
"axios": "^1.6.6",
"baidu-aip-sdk": "^4.16.10",
Expand Down
136 changes: 136 additions & 0 deletions src/botInstance/cozev3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { CozeV3Api } from "./sdk/cozev3.js";
import { addAichatRecord } from "../db/aichatDb.js";
import { getPromotInfo } from "../proxy/aibotk.js";
import { ContentCensor } from "../lib/contentCensor.js";
import { getPuppetEol, isWindowsPlatform } from '../const/puppet-type.js'
import dayjs from "dayjs";
import { extractImageLinks } from '../lib/index.js'


class CozeV3Ai {
constructor(config = {
isAiAgent: false, // 是否为 ai agent 模式
showDownloadUrl: false, // 显示文件下载链接
token: '', // api 秘钥
proxyPass: '', // 请求地址
showQuestion: true, // 显示原文
timeoutMs: 60, // 超时时间 s
promotId: '',
systemMessage: '', // 预设promotion
}) {
this.cozeV3Chat = null;
this.config = { showDownloadUrl: false, isAiAgent: false, ...config };
this.contentCensor = null
this.chatOption = {};
this.eol = '\n'
this.iswindows = false;
}


async init() {
this.eol = await getPuppetEol();
this.iswindows = await isWindowsPlatform()
if(this.config.promotId) {
const promotInfo = await getPromotInfo(this.config.promotId)
if(promotInfo) {
this.config.systemMessage = promotInfo.promot
}
}
if(this.config.filter) {
this.contentCensor = new ContentCensor(this.config.filterConfig)
}
const baseOptions = {
baseUrl: this.config.proxyPass,
apiKey: this.config.token,
botId: this.config.botId,
stream: this.config.stream,
debug: !!this.config.debug,
systemMessage: this.config.systemMessage || '',
}

console.log(`api请求地址:${this.config.proxyPass}`);
this.cozeV3Chat = new CozeV3Api({
...baseOptions,
});
}
/**
* 重置apikey
* @return {Promise<void>}
*/
reset () {
this.cozeV3Chat = null
}


async getReply({ content, inputs }, id, adminId = '', systemMessage = '') {
try {
if(!this.cozeV3Chat) {
console.log('启用Coze v3对话平台');
await this.init()
}
if(this.config.filter) {
const censor = await this.contentCensor.checkText(content)
if(!censor) {
console.log(`问题:${content},包含违规词,已拦截`);
return [{ type: 1, content: '这个话题不适合讨论,换个话题吧。' }]
}
}
if(systemMessage || content === 'reset' || content === '重置') {
console.log('重新更新上下文对话');
this.chatOption[id] = {}
if(content === 'reset' || content === '重置') {
return [{type: 1, content: '上下文已重置'}]
}
}
const { conversationId, text } = systemMessage ? await this.cozeV3Chat.sendMessage(content, { ...this.chatOption[id], variables: inputs, systemMessage, timeoutMs: this.config.timeoutMs * 1000 || 80 * 1000, user: id }) : await this.cozeV3Chat.sendMessage(content, { ...this.chatOption[id], variables: inputs, timeoutMs: this.config.timeoutMs * 1000 || 80 * 1000, user: id });
if(this.config.filter) {
const censor = await this.contentCensor.checkText(text)
if(!censor) {
console.log(`回复: ${text},包含违规词,已拦截`);
return [{ type: 1, content: '这个话题不适合讨论,换个话题吧。' }]
}
}
if(this.config.record) {
void addAichatRecord({ contactId: id, adminId, input: content, output: text, time: dayjs().format('YYYY-MM-DD HH:mm:ss') })
}
// 保存对话id 对于同一个用户的对话不更新conversationId
if(!this.chatOption[id]?.conversationId) {
this.chatOption[id] = {
conversationId
};
}
let replys = []
let message;
if(this.config.showQuestion) {
message = `${content}${this.eol}-----------${this.eol}` + (this.iswindows ? text.replaceAll('\n', this.eol) : text);
} else {
message = this.iswindows ? text.replaceAll('\n', this.eol) : text;
}
const imgs = extractImageLinks(message)

while (message.length > 1500) {
replys.push(message.slice(0, 1500));
message = message.slice(1500);
}
replys.push(message);
replys = replys.map(item=> {
return {
type: 1,
content: item.trim()
}
})

if(imgs.length) {
console.log('提取到内容中的图片', imgs)
replys = replys.concat(imgs)
}

return replys
} catch (e) {
console.log('Coze V3 请求报错:'+ e);
return []
}
}
}

export default CozeV3Ai;
139 changes: 139 additions & 0 deletions src/botInstance/qany.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { QAnyApi } from './sdk/qanything.js'
import { addAichatRecord } from '../db/aichatDb.js'
import { ContentCensor } from '../lib/contentCensor.js'
import { getPuppetEol, isWindowsPlatform } from '../const/puppet-type.js'
import dayjs from 'dayjs'
import { extractImageLinks } from '../lib/index.js'

class QAnyAi {
constructor(config = {
token: '', // api 秘钥
botId: '', // botId
proxyPass: '', // 请求地址
showQuestion: true, // 显示原文
showSuggestions: false, // 显示建议问题
timeoutMs: 180, // 超时时间 s
promotId: '',
systemMessage: '' // 预设promotion
}) {
this.qanyChat = null
this.config = { ...config }
this.contentCensor = null
this.chatOption = {}
this.eol = '\n'
this.iswindows = false
}


async init() {
this.eol = await getPuppetEol()
this.iswindows = await isWindowsPlatform()
if (this.config.filter) {
this.contentCensor = new ContentCensor(this.config.filterConfig)
}
const baseOptions = {
apiKey: this.config.token,
apiBaseUrl: this.config.proxyPass,
debug: !!this.config.debug,
botId: this.config.botId,
}

console.log(`api请求地址:${this.config.proxyPass}`)
this.qanyChat = new QAnyApi({
...baseOptions,
})
}

/**
* 重置apikey
* @return {Promise<void>}
*/
reset() {
this.qanyChat = null
}


async getReply(content, uid, adminId = '', systemMessage = '') {
try {
if (!this.qanyChat) {
console.log('启用QAnything对话平台')
await this.init()
}
if (this.config.filter) {
const censor = await this.contentCensor.checkText(content)
if (!censor) {
console.log(`问题:${content},包含违规词,已拦截`)
return [{ type: 1, content: '这个话题不适合讨论,换个话题吧。' }]
}
}
if (content === 'reset' || content === '重置') {
console.log('重新更新上下文对话')
this.chatOption[uid] = {
needHistory: false
}
if (content === 'reset' || content === '重置') {
return [{ type: 1, content: '上下文已重置' }]
}
}
const { text, id } = await this.qanyChat.sendMessage(content, {
...this.chatOption[uid],
timeoutMs: this.config.timeoutMs * 1000 || 180 * 1000,
user: uid
})
if (this.config.filter) {
const censor = await this.contentCensor.checkText(text)
if (!censor) {
console.log(`回复: ${text},包含违规词,已拦截`)
return [{ type: 1, content: '这个话题不适合讨论,换个话题吧。' }]
}
}
if (this.config.record) {
void addAichatRecord({
contactId: uid,
adminId,
input: content,
output: text,
time: dayjs().format('YYYY-MM-DD HH:mm:ss')
})
}
// 保存对话id 对于同一个用户的对话不更新conversationId

this.chatOption[uid] = {
needHistory: true
}
let replys = []
let message
if (this.config.showQuestion) {
message = `${content}${this.eol}-----------${this.eol}` + (this.iswindows ? text.replaceAll('\n', this.eol) : text)
} else {
message = this.iswindows ? text.replaceAll('\n', this.eol) : text
}

const imgs = extractImageLinks(message)

while (message.length > 1500) {
replys.push(message.slice(0, 1500))
message = message.slice(1500)
}
replys.push(message)
replys = replys.map(item => {
return {
type: 1,
content: item.trim()
}
})

if (imgs.length) {
console.log('提取到内容中的图片', imgs)
replys = replys.concat(imgs)
}

return replys
} catch (e) {
console.log('QAnything请求报错:' + e)
return []
}
}
}

export default QAnyAi
Loading

0 comments on commit a3d135c

Please sign in to comment.