Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b643c23a8a | |||
| f286199d89 | |||
| b3329448eb | |||
| 8905f0e5ae | |||
| 140182aef8 | |||
|
|
48bf5368b5 | ||
| dcac1149f9 | |||
| a2ac7b02a6 | |||
| a6244f7a5a |
27
.drone.yml
27
.drone.yml
@ -10,9 +10,11 @@ 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
|
||||||
- CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o chatgpt-arm64
|
- mkdir wechatbot
|
||||||
- name: upload
|
- CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ./wechatbot/chatgpt-arm64
|
||||||
image: rainerosion/gocos
|
- CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./wechatbot/chatgpt-amd64
|
||||||
|
- name: upload-tencent-cos
|
||||||
|
image: rainteam/gocos:latest
|
||||||
settings:
|
settings:
|
||||||
secret_id:
|
secret_id:
|
||||||
from_secret: cos_secret_id
|
from_secret: cos_secret_id
|
||||||
@ -20,9 +22,19 @@ 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: chatgpt-arm64
|
source: wechatbot
|
||||||
target: cicd/wechatbot
|
target: cicd
|
||||||
|
- 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
|
||||||
@ -31,7 +43,8 @@ steps:
|
|||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
base_url: https://git.rainss.cn
|
base_url: https://git.rainss.cn
|
||||||
files:
|
files:
|
||||||
- chatgpt-arm64
|
- ./wechatbot/chatgpt-arm64
|
||||||
|
- ./wechatbot/chatgpt-amd64
|
||||||
checksum:
|
checksum:
|
||||||
- sha256
|
- sha256
|
||||||
when:
|
when:
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
storage.json
|
storage.json
|
||||||
/.idea/wechatbot.iml
|
/.idea/wechatbot.iml
|
||||||
|
/config.json
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
## 微信机器人
|
## 微信机器人[](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,7 +2,9 @@
|
|||||||
"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": 1 # 消息缓存数量
|
"gpt_message_cache": 20, # 消息缓存数量
|
||||||
}
|
"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,12 +25,16 @@ 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 {
|
||||||
@ -45,7 +49,8 @@ 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
|
||||||
return "用户[" + nickName + "]上下文已清空", nil
|
log.Println("用户[" + nickName + "]上下文已清空")
|
||||||
|
return "上下文已清空", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Completions(msg string, nickName string) (string, error) {
|
func Completions(msg string, nickName string) (string, error) {
|
||||||
@ -64,7 +69,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: 4096,
|
MaxTokens: 2048,
|
||||||
Temperature: 1.2,
|
Temperature: 1.2,
|
||||||
Messages: messageCache,
|
Messages: messageCache,
|
||||||
}
|
}
|
||||||
@ -107,6 +112,8 @@ 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,10 +42,19 @@ 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
|
||||||
@ -53,17 +62,14 @@ 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.EqualFold(msg.Content, config.LoadConfig().GptCleanContext) {
|
if strings.Contains(msg.Content, bingWakeWord) {
|
||||||
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, group.UserName)
|
reply, err = gpt.BingSearch(requestText, userName)
|
||||||
if reply != "" && strings.HasPrefix(reply, "[") {
|
if reply != "" && strings.HasPrefix(reply, "[") {
|
||||||
reply = "\n" + reply
|
reply = "\n" + reply
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reply, err = gpt.Completions(requestText, group.UserName)
|
reply, err = gpt.Completions(requestText, 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