Compare commits
No commits in common. "main" and "master" have entirely different histories.
27
.drone.yml
27
.drone.yml
@ -10,11 +10,9 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
# - sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
# - sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||||||
# - apk update && apk add build-base
|
# - apk update && apk add build-base
|
||||||
- mkdir wechatbot
|
- CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o chatgpt-arm64
|
||||||
- CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ./wechatbot/chatgpt-arm64
|
- name: upload
|
||||||
- CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./wechatbot/chatgpt-amd64
|
image: rainerosion/gocos
|
||||||
- name: upload-tencent-cos
|
|
||||||
image: rainteam/gocos:latest
|
|
||||||
settings:
|
settings:
|
||||||
secret_id:
|
secret_id:
|
||||||
from_secret: cos_secret_id
|
from_secret: cos_secret_id
|
||||||
@ -22,19 +20,9 @@ steps:
|
|||||||
from_secret: cos_secret_key
|
from_secret: cos_secret_key
|
||||||
bucket_url:
|
bucket_url:
|
||||||
from_secret: cos_bucket_url
|
from_secret: cos_bucket_url
|
||||||
source: wechatbot
|
source: chatgpt-arm64
|
||||||
target: cicd
|
target: cicd/wechatbot
|
||||||
- name: upload-upyun
|
|
||||||
image: rainteam/upcos:latest
|
|
||||||
settings:
|
|
||||||
up_operator:
|
|
||||||
from_secret: up_operator
|
|
||||||
up_password:
|
|
||||||
from_secret: up_password
|
|
||||||
up_bucket:
|
|
||||||
from_secret: up_bucket
|
|
||||||
local_base_path: wechatbot
|
|
||||||
remote_base_path: gitea/devops
|
|
||||||
- name: gitea_release
|
- name: gitea_release
|
||||||
image: plugins/gitea-release
|
image: plugins/gitea-release
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
@ -43,8 +31,7 @@ steps:
|
|||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
base_url: https://git.rainss.cn
|
base_url: https://git.rainss.cn
|
||||||
files:
|
files:
|
||||||
- ./wechatbot/chatgpt-arm64
|
- chatgpt-arm64
|
||||||
- ./wechatbot/chatgpt-amd64
|
|
||||||
checksum:
|
checksum:
|
||||||
- sha256
|
- sha256
|
||||||
when:
|
when:
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
storage.json
|
storage.json
|
||||||
/.idea/wechatbot.iml
|
/.idea/wechatbot.iml
|
||||||
/config.json
|
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
## 微信机器人[](http://ci.rainss.cn/rainerosion/wechatbot)
|
## 微信机器人
|
||||||
|
|
||||||
最近ChatGPT异常火爆,想到将其接入到个人微信是件比较有趣的事,所以有了这个项目。项目基于[openwechat](https://github.com/eatmoreapple/openwechat)开发,支持ChatGPT和New Bing,其中New Bing[依赖于new-bing项目](../new-bing)提供的http接口。
|
最近ChatGPT异常火爆,想到将其接入到个人微信是件比较有趣的事,所以有了这个项目。项目基于[openwechat](https://github.com/eatmoreapple/openwechat)开发,支持ChatGPT和New Bing,其中New Bing[依赖于new-bing项目](../new-bing)提供的http接口。
|
||||||
|
|
||||||
## 自动构建
|
|
||||||
- [chatgpt-arm64](https://cos.suger.live/cicd/wechatbot/chatgpt-arm64)
|
|
||||||
- [chatgpt-amd64](https://cos.suger.live/cicd/wechatbot/chatgpt-amd64)
|
|
||||||
|
|
||||||
## 目前实现了以下功能
|
## 目前实现了以下功能
|
||||||
+ 群聊@回复
|
+ 群聊@回复
|
||||||
+ 私聊回复
|
+ 私聊回复
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
"api_key": "", # chatgpt api key
|
"api_key": "", # chatgpt api key
|
||||||
"auto_pass": true, # 是否自动通过好友申请
|
"auto_pass": true, # 是否自动通过好友申请
|
||||||
"bing_chat_url": "" # New Bing 聊天接口
|
"bing_chat_url": "" # New Bing 聊天接口
|
||||||
"gpt_chat_url": "https://gpt.rains.work/v1/chat/", # Gpt 聊天接口
|
|
||||||
"bing_chat_wake_word": "#bing", # new Bing唤醒词
|
"bing_chat_wake_word": "#bing", # new Bing唤醒词
|
||||||
"gpt_chat_wake_word": "#gpt" # ChatGPT唤醒词
|
"gpt_chat_wake_word": "#gpt" # ChatGPT唤醒词
|
||||||
"gpt_message_cache": 20, # 消息缓存数量
|
"gpt_message_cache": 1 # 消息缓存数量
|
||||||
"gpt_clean_context": "#cls" # 清理Gpt上下文
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ func BingSearch(msg string, nickName string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
req.Header.Set("Referer", Referer)
|
req.Header.Set("Referer", Referer)
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
response, err := client.Do(req)
|
response, err := client.Do(req)
|
||||||
|
|||||||
@ -7,9 +7,9 @@ import (
|
|||||||
|
|
||||||
func TestBing(t *testing.T) {
|
func TestBing(t *testing.T) {
|
||||||
reply, err := BingSearch("今天北京的天气怎么样", "nickname")
|
reply, err := BingSearch("今天北京的天气怎么样", "nickname")
|
||||||
if err != nil {
|
if err != nil{
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%+v\n", reply)
|
fmt.Printf("%+v\n", reply)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
11
gpt/gpt.go
11
gpt/gpt.go
@ -25,16 +25,12 @@ type ChatGPTResponseBody struct {
|
|||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Choices []ChoiceItem `json:"choices"`
|
Choices []ChoiceItem `json:"choices"`
|
||||||
Usage map[string]interface{} `json:"usage"`
|
Usage map[string]interface{} `json:"usage"`
|
||||||
Error ErrorGPTResponseBody `json:"error"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChoiceItem struct {
|
type ChoiceItem struct {
|
||||||
Message Message `json:"message"`
|
Message Message `json:"message"`
|
||||||
FinishReason string `json:"finish_reason"`
|
FinishReason string `json:"finish_reason"`
|
||||||
}
|
}
|
||||||
type ErrorGPTResponseBody struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChatGPTRequestBody 响应体
|
// ChatGPTRequestBody 响应体
|
||||||
type ChatGPTRequestBody struct {
|
type ChatGPTRequestBody struct {
|
||||||
@ -49,8 +45,7 @@ var MessageCacheRegistry = make(map[string][]Message)
|
|||||||
func CleanContext(nickName string) (string, error) {
|
func CleanContext(nickName string) (string, error) {
|
||||||
messageCache := []Message{}
|
messageCache := []Message{}
|
||||||
MessageCacheRegistry[nickName] = messageCache
|
MessageCacheRegistry[nickName] = messageCache
|
||||||
log.Println("用户[" + nickName + "]上下文已清空")
|
return "用户[" + nickName + "]上下文已清空", nil
|
||||||
return "上下文已清空", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Completions(msg string, nickName string) (string, error) {
|
func Completions(msg string, nickName string) (string, error) {
|
||||||
@ -69,7 +64,7 @@ func Completions(msg string, nickName string) (string, error) {
|
|||||||
MessageCacheRegistry[nickName] = messageCache
|
MessageCacheRegistry[nickName] = messageCache
|
||||||
requestBody := ChatGPTRequestBody{
|
requestBody := ChatGPTRequestBody{
|
||||||
Model: "gpt-3.5-turbo",
|
Model: "gpt-3.5-turbo",
|
||||||
MaxTokens: 2048,
|
MaxTokens: 4096,
|
||||||
Temperature: 1.2,
|
Temperature: 1.2,
|
||||||
Messages: messageCache,
|
Messages: messageCache,
|
||||||
}
|
}
|
||||||
@ -112,8 +107,6 @@ func Completions(msg string, nickName string) (string, error) {
|
|||||||
reply = v.Message.Content
|
reply = v.Message.Content
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
reply = gptResponseBody.Error.Message
|
|
||||||
}
|
}
|
||||||
log.Printf("gpt response text: %s \n", reply)
|
log.Printf("gpt response text: %s \n", reply)
|
||||||
return reply, nil
|
return reply, nil
|
||||||
|
|||||||
@ -42,19 +42,10 @@ func (g *GroupMessageHandler) ReplyText(msg *openwechat.Message) error {
|
|||||||
sender, err := msg.Sender()
|
sender, err := msg.Sender()
|
||||||
group := openwechat.Group{User: sender}
|
group := openwechat.Group{User: sender}
|
||||||
log.Printf("Received Group %v Text Msg : %v", group.NickName, msg.Content)
|
log.Printf("Received Group %v Text Msg : %v", group.NickName, msg.Content)
|
||||||
inGroup, _ := msg.SenderInGroup()
|
|
||||||
// 组合群名+用户名
|
|
||||||
userName := inGroup.UserName + group.UserName
|
|
||||||
|
|
||||||
bingWakeWord := config.LoadConfig().BingChatWakeWord
|
bingWakeWord := config.LoadConfig().BingChatWakeWord
|
||||||
gptWakeWord := config.LoadConfig().GptChatWakeWord
|
gptWakeWord := config.LoadConfig().GptChatWakeWord
|
||||||
|
|
||||||
// gpt上下文清理
|
|
||||||
if strings.EqualFold(msg.Content, config.LoadConfig().GptCleanContext) {
|
|
||||||
cleanReply, _ := gpt.CleanContext(userName)
|
|
||||||
msg.ReplyText(cleanReply)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @GPTBot 或者 @bing的消息才处理
|
// @GPTBot 或者 @bing的消息才处理
|
||||||
if !(strings.Contains(msg.Content, gptWakeWord) || strings.Contains(msg.Content, bingWakeWord)) {
|
if !(strings.Contains(msg.Content, gptWakeWord) || strings.Contains(msg.Content, bingWakeWord)) {
|
||||||
return nil
|
return nil
|
||||||
@ -62,14 +53,17 @@ func (g *GroupMessageHandler) ReplyText(msg *openwechat.Message) error {
|
|||||||
|
|
||||||
requestText := strings.TrimSpace(strings.ReplaceAll(msg.Content, gptWakeWord, ""))
|
requestText := strings.TrimSpace(strings.ReplaceAll(msg.Content, gptWakeWord, ""))
|
||||||
var reply = ""
|
var reply = ""
|
||||||
if strings.Contains(msg.Content, bingWakeWord) {
|
if strings.EqualFold(msg.Content, config.LoadConfig().GptCleanContext) {
|
||||||
|
cleanReply, _ := gpt.CleanContext(group.UserName)
|
||||||
|
reply = "\n" + cleanReply
|
||||||
|
} else if strings.Contains(msg.Content, bingWakeWord) {
|
||||||
requestText = strings.TrimSpace(strings.ReplaceAll(msg.Content, bingWakeWord, ""))
|
requestText = strings.TrimSpace(strings.ReplaceAll(msg.Content, bingWakeWord, ""))
|
||||||
reply, err = gpt.BingSearch(requestText, userName)
|
reply, err = gpt.BingSearch(requestText, group.UserName)
|
||||||
if reply != "" && strings.HasPrefix(reply, "[") {
|
if reply != "" && strings.HasPrefix(reply, "[") {
|
||||||
reply = "\n" + reply
|
reply = "\n" + reply
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reply, err = gpt.Completions(requestText, userName)
|
reply, err = gpt.Completions(requestText, group.UserName)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("gpt request error: %v \n", err)
|
log.Printf("gpt request error: %v \n", err)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user