From add42dd77488a59879c02fa20cf97a966f16840f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Thu, 13 Apr 2023 22:03:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=95=8F=E6=84=9F?= =?UTF-8?q?=E8=AF=8D=E5=8A=9F=E8=83=BD=20(#204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ config.example.yml | 2 ++ config/config.go | 6 ++++++ docker-compose.yml | 1 + main.go | 8 ++++++++ pkg/process/process_request.go | 6 ++++++ public/tools.go | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 59 insertions(+) diff --git a/README.md b/README.md index 37e1ca1..72afaf6 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,7 @@ $ docker run -itd --name chatgpt -p 8090:8090 \ -e DEFAULT_MODE="单聊" -e MAX_REQUEST=0 -e PORT=8090 \ -e SERVICE_URL="你当前服务外网可访问的URL" -e CHAT_TYPE="0" \ -e ALLOW_GROUPS=a,b -e ALLOW_OUTGOING_GROUPS=a,b -e ALLOW_USERS=a,b -e DENY_USERS=a,b -e VIP_USERS=a,b -e ADMIN_USERS=a,b -e APP_SECRETS="xxx,yyy" \ + -e SENSITIVE_WORDS="aa,bb" \ -e AZURE_ON="false" -e AZURE_API_VERSION="" -e AZURE_RESOURCE_NAME="" \ -e AZURE_DEPLOYMENT_NAME="" -e AZURE_OPENAI_TOKEN="" \ -e HELP="欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/) @@ -493,6 +494,8 @@ vip_users: [] admin_users: [] # 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret app_secrets: [] +# 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替 +sensitive_words: [] # 帮助信息,放在配置文件,可供自定义 help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连." diff --git a/config.example.yml b/config.example.yml index 24cdbda..2513270 100644 --- a/config.example.yml +++ b/config.example.yml @@ -42,6 +42,8 @@ vip_users: [] admin_users: [] # 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret app_secrets: [] +# 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替 +sensitive_words: [] # 帮助信息,放在配置文件,可供自定义 help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连." diff --git a/config/config.go b/config/config.go index c01afaa..270a726 100644 --- a/config/config.go +++ b/config/config.go @@ -52,6 +52,8 @@ type Configuration struct { AdminUsers []string `yaml:"admin_users"` // 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret AppSecrets []string `yaml:"app_secrets"` + // 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替 + SensitiveWords []string `yaml:"sensitive_words"` // 自定义帮助信息 Help string `yaml:"help"` // AzureOpenAI 配置 @@ -160,6 +162,10 @@ func LoadConfig() *Configuration { if appSecrets != "" { config.AppSecrets = strings.Split(appSecrets, ",") } + sensitiveWords := os.Getenv("SENSITIVE_WORDS") + if sensitiveWords != "" { + config.SensitiveWords = strings.Split(sensitiveWords, ",") + } help := os.Getenv("HELP") if help != "" { config.Help = help diff --git a/docker-compose.yml b/docker-compose.yml index f7750d9..363287f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,7 @@ services: ADMIN_USERS: "" # 指定哪些人为此系统的管理员,如果留空,则表示没有人是管理员,如果要限制,则列表中写用户的userid # 注意:如果下边的app_secrets为空,以及使用outgoing的方式配置机器人,这两种情况下,都表示没有人是管理员 APP_SECRETS: "" # 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret,比如 "xxxx,yyyy" + SENSITIVE_WORDS: "" # 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替 AZURE_ON: "false" # 是否走Azure OpenAi API, 默认false ,如果为true,则需要配置下边的四个参数 AZURE_API_VERSION: "" # Azure OpenAi API 版本,比如 "2023-03-15-preview" AZURE_RESOURCE_NAME: "" # Azure OpenAi API 资源名称,比如 "openai" diff --git a/main.go b/main.go index 3ce6cc2..37f2e96 100644 --- a/main.go +++ b/main.go @@ -48,6 +48,14 @@ func Start() { } // 去除问题的前后空格 msgObj.Text.Content = strings.TrimSpace(msgObj.Text.Content) + if public.JudgeSensitiveWord(msgObj.Text.Content) { + _, err = msgObj.ReplyToDingtalk(string(dingbot.MARKDOWN), "**🤷 抱歉,您提问的问题中包含敏感词汇,请审核自己的对话内容之后再进行!**") + if err != nil { + logger.Warning(fmt.Errorf("send message error: %v", err)) + return err + } + return nil + } // 打印钉钉回调过来的请求明细,调试时打开 logger.Debug(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj)) diff --git a/pkg/process/process_request.go b/pkg/process/process_request.go index baf5adb..3d5e311 100644 --- a/pkg/process/process_request.go +++ b/pkg/process/process_request.go @@ -146,6 +146,9 @@ func Do(mode string, rmsg *dingbot.ReceiveMsg) error { logger.Error("往MySQL新增数据失败,错误信息:", err) } logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply)) + if public.JudgeSensitiveWord(reply) { + reply = public.SolveSensitiveWord(reply) + } // 回复@我的用户 _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply) if err != nil { @@ -204,6 +207,9 @@ func Do(mode string, rmsg *dingbot.ReceiveMsg) error { // 将当前回答的ID放入缓存 public.UserService.SetAnswerID(rmsg.SenderNick, rmsg.GetChatTitle(), aid) logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply)) + if public.JudgeSensitiveWord(reply) { + reply = public.SolveSensitiveWord(reply) + } // 回复@我的用户 _, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply) if err != nil { diff --git a/public/tools.go b/public/tools.go index 7f77739..9d67e4a 100644 --- a/public/tools.go +++ b/public/tools.go @@ -9,6 +9,7 @@ import ( "os" "strings" "time" + "unicode/utf8" ) // 将内容写入到文件,如果文件名带路径,则会判断路径是否存在,不存在则创建 @@ -140,3 +141,35 @@ func CheckRequest(ts, sg string) bool { } return false } + +// JudgeSensitiveWord 判断内容是否包含敏感词 +func JudgeSensitiveWord(s string) bool { + if len(Config.SensitiveWords) == 0 { + return false + } + for _, v := range Config.SensitiveWords { + if strings.Contains(s, v) { + return true + } + } + return false +} + +// SolveSensitiveWord 将敏感词用*号占位 +func SolveSensitiveWord(s string) string { + for _, v := range Config.SensitiveWords { + if strings.Contains(s, v) { + return strings.Replace(s, v, printStars(utf8.RuneCountInString(v)), -1) + } + } + return s +} + +// 将对应敏感词替换为* +func printStars(num int) string { + s := "" + for i := 0; i < num; i++ { + s += "*" + } + return s +}