From eafc19a0939f944f1a18fb5bade2d053a9acb114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E9=B8=BF=E8=BF=90?= <1836017030@qq.com> Date: Sun, 10 Dec 2023 11:04:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20go=E5=8C=85=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=94=B9=E6=88=90module=E6=96=B9=E5=BC=8F=EF=BC=9B=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B9=E5=A2=9E=E5=8A=A0gpt-model=EF=BC=9Bgpt?= =?UTF-8?q?=E5=93=8D=E5=BA=94=E4=BD=93=E3=80=81=E8=AF=B7=E6=B1=82=E4=BD=93?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bootstrap/bootstrap.go | 17 +++++--- config.dev.json | 5 ++- config/config.go | 6 +++ go.mod | 6 +-- go.sum | 4 +- gtp/gtp.go | 82 ++++++++++++++++++++--------------- handlers/group_msg_handler.go | 4 +- handlers/handler.go | 2 +- handlers/user_msg_handler.go | 2 +- main.go | 4 +- 10 files changed, 79 insertions(+), 53 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 7049740..fab4609 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -1,13 +1,12 @@ package bootstrap import ( - "github.com/869413421/wechatbot/handlers" "github.com/eatmoreapple/openwechat" + "io" "log" + "wechatbot/handlers" ) - - func Run() { //bot := openwechat.DefaultBot() bot := openwechat.DefaultBot(openwechat.Desktop) // 桌面模式,上面登录不上的可以尝试切换这种模式 @@ -18,9 +17,17 @@ func Run() { bot.UUIDCallback = openwechat.PrintlnQrcodeUrl // 创建热存储容器对象 - reloadStorage := openwechat.NewJsonFileHotReloadStorage("storage.json") + reloadStorage := openwechat.NewFileHotReloadStorage("storage.json") + + defer func(reloadStorage io.ReadWriteCloser) { + err := reloadStorage.Close() + if err != nil { + log.Printf("storage.json close error: %v \n", err) + } + }(reloadStorage) + // 执行热登录 - err := bot.HotLogin(reloadStorage) + err := bot.HotLogin(reloadStorage, openwechat.NewRetryLoginOption()) if err != nil { if err = bot.Login(); err != nil { log.Printf("login error: %v \n", err) diff --git a/config.dev.json b/config.dev.json index b78e4db..e21a160 100644 --- a/config.dev.json +++ b/config.dev.json @@ -1,4 +1,5 @@ { "api_key": "your api key", - "auto_pass": true -} + "auto_pass": true, + "gpt_model": "gpt-3.5-turbo" +} \ No newline at end of file diff --git a/config/config.go b/config/config.go index 6afede1..8b9cc94 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,8 @@ type Configuration struct { ApiKey string `json:"api_key"` // 自动通过好友 AutoPass bool `json:"auto_pass"` + // gpt 版本 + GptModel string `json:"gpt_model"` } var config *Configuration @@ -39,12 +41,16 @@ func LoadConfig() *Configuration { // 如果环境变量有配置,读取环境变量 ApiKey := os.Getenv("ApiKey") AutoPass := os.Getenv("AutoPass") + GptModel := os.Getenv("GptModel") if ApiKey != "" { config.ApiKey = ApiKey } if AutoPass == "true" { config.AutoPass = true } + if AutoPass != "" { + config.GptModel = GptModel + } }) return config } diff --git a/go.mod b/go.mod index a3f92ad..f106b74 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ -module github.com/869413421/wechatbot +module wechatbot -go 1.16 +go 1.20 -require github.com/eatmoreapple/openwechat v1.2.1 +require github.com/eatmoreapple/openwechat v1.4.6 // indirect \ No newline at end of file diff --git a/go.sum b/go.sum index 6fe8c3d..7a68d0c 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -github.com/eatmoreapple/openwechat v1.2.1 h1:ez4oqF/Y2NSEX/DbPV8lvj7JlfkYqvieeo4awx5lzfU= -github.com/eatmoreapple/openwechat v1.2.1/go.mod h1:61HOzTyvLobGdgWhL68jfGNwTJEv0mhQ1miCXQrvWU8= +github.com/eatmoreapple/openwechat v1.4.6 h1:m/Run2wN9zptKnoS8R3edLNWLlZOOgk13Bq8Y61zSTU= +github.com/eatmoreapple/openwechat v1.4.6/go.mod h1:h4m2N8m0XsUKlm7UR8BUGkV89GNuKHCnlGV3J8n9Mpw= diff --git a/gtp/gtp.go b/gtp/gtp.go index 15cd8e2..1d37fde 100644 --- a/gtp/gtp.go +++ b/gtp/gtp.go @@ -3,52 +3,68 @@ package gtp import ( "bytes" "encoding/json" - "github.com/869413421/wechatbot/config" "io/ioutil" "log" "net/http" + "wechatbot/config" ) -const BASEURL = "https://api.openai.com/v1/" +type Role int -// ChatGPTResponseBody 请求体 +const ( + User Role = iota // User = 0 + System // System = 1 + Assistant // Assistant = 2 +) + +func (r Role) String() string { + return []string{"user", "system", "assistant"}[r] +} + +const BASEURL = "https://api.openai.com/v1/chat/" + +// ChatGPTResponseBody 响应体 type ChatGPTResponseBody struct { - ID string `json:"id"` - Object string `json:"object"` - Created int `json:"created"` - Model string `json:"model"` - Choices []map[string]interface{} `json:"choices"` - Usage map[string]interface{} `json:"usage"` + ID string `json:"id"` + Object string `json:"object"` + Created int `json:"created"` + Model string `json:"model"` + Choices []ChoiceItem `json:"choices"` + Usage map[string]interface{} `json:"usage"` } type ChoiceItem struct { + Index int `json:"index"` + Message MessageItem `json:"message"` + FinishReason string `json:"finish_reason"` +} + +type MessageItem struct { + Role string `json:"role"` + Content string `json:"content"` } -// ChatGPTRequestBody 响应体 +// ChatGPTRequestBody 请求体 type ChatGPTRequestBody struct { - Model string `json:"model"` - Prompt string `json:"prompt"` - MaxTokens int `json:"max_tokens"` - Temperature float32 `json:"temperature"` - TopP int `json:"top_p"` - FrequencyPenalty int `json:"frequency_penalty"` - PresencePenalty int `json:"presence_penalty"` + Model string `json:"model"` + Messages []MessageItem `json:"messages"` } // Completions gtp文本模型回复 -//curl https://api.openai.com/v1/completions -//-H "Content-Type: application/json" -//-H "Authorization: Bearer your chatGPT key" -//-d '{"model": "text-davinci-003", "prompt": "give me good song", "temperature": 0, "max_tokens": 7}' +// curl https://api.openai.com/v1/chat/completions +// -H "Content-Type: application/json" +// -H "Authorization: Bearer your chatGPT key" +// -d '{"model": "gpt-3.5-turbo", "messages: [{"role": "user", "content": "your problem"}]"}' func Completions(msg string) (string, error) { + gptModel := config.LoadConfig().GptModel requestBody := ChatGPTRequestBody{ - Model: "text-davinci-003", - Prompt: msg, - MaxTokens: 2048, - Temperature: 0.7, - TopP: 1, - FrequencyPenalty: 0, - PresencePenalty: 0, + Model: gptModel, + Messages: []MessageItem{ + { + Role: Role(0).String(), + Content: msg, + }, + }, } requestData, err := json.Marshal(requestBody) @@ -82,12 +98,10 @@ func Completions(msg string) (string, error) { if err != nil { return "", err } - var reply string - if len(gptResponseBody.Choices) > 0 { - for _, v := range gptResponseBody.Choices { - reply = v["text"].(string) - break - } + reply := "暂无回复" + choicesLength := len(gptResponseBody.Choices) + if choicesLength > 0 { + reply = gptResponseBody.Choices[choicesLength-1].Message.Content } log.Printf("gpt response text: %s \n", reply) return reply, nil diff --git a/handlers/group_msg_handler.go b/handlers/group_msg_handler.go index ec0560a..9fbe962 100644 --- a/handlers/group_msg_handler.go +++ b/handlers/group_msg_handler.go @@ -1,10 +1,10 @@ package handlers import ( - "github.com/869413421/wechatbot/gtp" "github.com/eatmoreapple/openwechat" "log" "strings" + "wechatbot/gtp" ) var _ MessageHandlerInterface = (*GroupMessageHandler)(nil) @@ -39,7 +39,7 @@ func (g *GroupMessageHandler) ReplyText(msg *openwechat.Message) error { } // 替换掉@文本,然后向GPT发起请求 - replaceText := "@" + sender.Self.NickName + replaceText := "@" + sender.Self().NickName requestText := strings.TrimSpace(strings.ReplaceAll(msg.Content, replaceText, "")) reply, err := gtp.Completions(requestText) if err != nil { diff --git a/handlers/handler.go b/handlers/handler.go index 50d2b54..ea23fd6 100644 --- a/handlers/handler.go +++ b/handlers/handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/869413421/wechatbot/config" "github.com/eatmoreapple/openwechat" "log" + "wechatbot/config" ) // MessageHandlerInterface 消息处理接口 diff --git a/handlers/user_msg_handler.go b/handlers/user_msg_handler.go index e2e250f..bfe0439 100644 --- a/handlers/user_msg_handler.go +++ b/handlers/user_msg_handler.go @@ -1,10 +1,10 @@ package handlers import ( - "github.com/869413421/wechatbot/gtp" "github.com/eatmoreapple/openwechat" "log" "strings" + "wechatbot/gtp" ) var _ MessageHandlerInterface = (*UserMessageHandler)(nil) diff --git a/main.go b/main.go index 0e18cf1..4ced241 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,6 @@ package main -import ( - "github.com/869413421/wechatbot/bootstrap" -) +import "wechatbot/bootstrap" func main() { bootstrap.Run() From c06e7a20ef59b83e94fbed43bc8d163444ba4547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E9=B8=BF=E8=BF=90?= <1836017030@qq.com> Date: Sun, 10 Dec 2023 11:23:50 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0docker=E9=83=A8?= =?UTF-8?q?=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 22 ++++++++++++++++++++++ README.md | 17 +++++++++++++++++ docker-compose.yml | 10 ++++++++++ 3 files changed, 49 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7637753 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM golang:1.20.12-alpine AS builder + +MAINTAINER hongyun + +WORKDIR /work + +COPY . /work + +ENV GOPROXY=https://goproxy.cn,direct GO111MODULE=on + +RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build main.go + +FROM alpine AS runner + +WORKDIR /work + +COPY --from=builder /work/main . + +# 按需添加代理 +# ENV http_proxy=http://192.168.0.101:7890 https_proxy=http://192.168.0.101:7890 all_proxy=socks5://192.168.0.101:7890 + +ENTRYPOINT ["./main"] \ No newline at end of file diff --git a/README.md b/README.md index cc69d9b..96d9f38 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,20 @@ copy config.dev.json config.json go run main.go 启动前需替换config中的api_key +```` + +# docker 部署 + +> - 注意修改 docker-compose.yml 文件中 config.json 挂载地址 +> - 可在 Dockerfile 中增加代理地址,以此来访问 https://api.openai.com + +```shell +# 获取项目 +git clone https://github.com/869413421/wechatbot.git + +# 进入项目目录 +cd wechatbot + +# docker-compose 启动 +docker-compose up -d +``` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d5af85b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3.7' +services: + wechatbot: + build: + context: "." + container_name: "wechatbot" + network_mode: "bridge" + volumes: + - "/etc/localtime:/etc/localtime" + - "/volume1/docker/container/wechatbot/config.json:/work/config.json" # 按需填写 \ No newline at end of file