├── go.mod ├── entity ├── Task.go └── Context.go ├── example.go ├── README.md └── chat └── ChatGlmService.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/solstice-gao/chatglm-go 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /entity/Task.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type TaskResponse struct { 4 | Message string `json:"message"` 5 | Result struct { 6 | TaskID string `json:"task_id"` 7 | } `json:"result"` 8 | Status int `json:"status"` 9 | } 10 | -------------------------------------------------------------------------------- /entity/Context.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type ContextResponse struct { 4 | Message string `json:"message"` 5 | Result struct { 6 | ContextID string `json:"context_id"` 7 | } `json:"result"` 8 | Status int `json:"status"` 9 | } 10 | -------------------------------------------------------------------------------- /example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/solstice-gao/chatglm-go/chat" 7 | ) 8 | 9 | func main() { 10 | // 获取方式见下方常见问题 11 | authorization := "Bearer eyxxxx" 12 | cookie := "acw_tc=xxx;" 13 | prompt := "请写一篇2000字的申请书" 14 | 15 | // 创建 ChatService 实例 16 | chatService := chat.NewChatService(authorization, cookie) 17 | 18 | // 获取任务ID 19 | task := chatService.GetTaskId(prompt) 20 | fmt.Println("task id-------") 21 | fmt.Println(task.Result.TaskID) 22 | fmt.Println("-------") 23 | 24 | // 获取上下文ID 25 | context := chatService.GetContextId(prompt, task.Result.TaskID) 26 | 27 | fmt.Println("context id-------") 28 | fmt.Println(context.Result.ContextID) 29 | fmt.Println("-------") 30 | 31 | // 调用获取聊天数据的方法 32 | ans, err := chatService.GetChat(context.Result.ContextID) 33 | 34 | if err != nil { 35 | fmt.Println(err) 36 | return 37 | } 38 | 39 | //var lastLine string 40 | fmt.Println(ans) 41 | r := []rune(ans) 42 | fmt.Println(len(r)) 43 | 44 | //// 处理聊天数据 45 | //// TODO: 根据自己的需求进行处理 46 | // 47 | //// 输出聊天数据 48 | //fmt.Println(chatData) 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chatglm-go 2 | 3 | ChatGLM Go SDK 4 | 5 | ## 项目简介 6 | 7 | ChatGLM Go SDK 是一个将网页版 ChatGLM 转换为 Go 语言的软件开发工具包。它提供了一组方便易用的函数和方法,使开发人员能够在 Go 项目中快速集成 ChatGLM 的功能。 8 | 9 | ## 特性 10 | 11 | - 与 ChatGLM 网页版一致的功能和交互体验 12 | - 支持从 ChatGLM 后端 API 获取实时聊天数据 13 | - 提供简洁的 API 接口,方便在 Go 项目中使用 14 | - 支持自定义输出方式,以满足不同的需求 15 | 16 | ## 安装 17 | 18 | 使用 Go 的包管理工具 `go get` 可以快速获取并安装 ChatGLM Go SDK: 19 | 20 | ``` 21 | go get github.com/solstice-gao/chatglm-go 22 | ``` 23 | 24 | ## 使用示例 25 | 26 | 下面是一个简单的示例代码,展示了如何在 Go 项目中使用 ChatGLM Go SDK: 27 | [example.go](example.go) 28 | 29 | ## 贡献 30 | 31 | 欢迎对 ChatGLM Go SDK 进行贡献!如果你发现了 bug,或者有改进建议,请提出 issue 或提交 pull request。在参与贡献之前,请阅读项目的贡献指南(CONTRIBUTING.md)。 32 | 33 | ## 许可证 34 | 35 | ChatGLM Go SDK 使用 MIT 许可证。详细信息请参阅许可证文件(LICENSE)。 36 | 37 | ## 联系方式 38 | 39 | 如果你有任何问题或建议,可以通过以下方式联系我: 40 | 41 | - 邮箱:原作者: 17604515707@163.com 42 | - GitHub 项目主页:https://github.com/solstice-gao 43 | 44 | 请随时提出问题或反馈,我会尽快回复。 45 | 46 | ## 常见问题 47 | 48 | 在这里列出一些常见问题和解答,以帮助其他用户更好地使用 ChatGLM Go SDK。 49 | 50 | 1. **怎么获取authorization/cookie?** 51 | - 首先需要有 https://chatglm.cn 的账号,目前可以直接注册登录 52 | - 登录账号,浏览器F12/开发者模式,选择Network 53 | - 输入问题进行提问 54 | - image 55 | - image 56 | 57 | ## 致谢 58 | 59 | 特别感谢以下人员对 ChatGLM Go SDK 的贡献和支持: 60 | 61 | - Gaoxu 62 | 63 | 感谢你们的支持! 64 | 65 | ## 更新 66 | -------------------------------------------------------------------------------- /chat/ChatGlmService.go: -------------------------------------------------------------------------------- 1 | package chat 2 | 3 | import ( 4 | "bufio" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | "strings" 10 | "time" 11 | 12 | "github.com/solstice-gao/chatglm-go/entity" 13 | ) 14 | 15 | type ChatService struct { 16 | // ... 可能的依赖或其他属性 17 | authorization string 18 | cookie string 19 | } 20 | 21 | type tpe string 22 | 23 | const ( 24 | baseUrl = "https://chatglm.cn/chatglm/backend-api/v1" 25 | chat = "/stream?context_id=" 26 | task = "/conversation" 27 | context = "/stream_context" 28 | 29 | cookie = "cookie" 30 | Authorization = "Authorization" 31 | accept = "accept" 32 | 33 | chatType tpe = "chat" 34 | taskType tpe = "task" 35 | contextType tpe = "context" 36 | 37 | streamAccept = "text/event-stream" 38 | jsonAccept = "application/json, text/plain, */*" 39 | ) 40 | 41 | var client = &http.Client{ 42 | Timeout: time.Minute * 3, 43 | } 44 | 45 | var ( 46 | headerCookie = map[string][]string{ 47 | "authority": {"chatglm.cn"}, 48 | "accept": {""}, 49 | "accept-language": {"zh-CN,zh;q=0.9"}, 50 | "cache-control": {"no-cache"}, 51 | "cookie": {""}, 52 | "referer": {"https://chatglm.cn/detail"}, 53 | "sec-ch-ua": {"\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\""}, 54 | "sec-ch-ua-mobile": {"?0"}, 55 | "sec-fetch-dest": {"empty"}, 56 | "sec-fetch-mode": {"cors"}, 57 | "sec-fetch-site": {"same-origin"}, 58 | "user-agent": {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"}, 59 | } 60 | 61 | headerAuth = map[string][]string{ 62 | "Accept": {"application/json, text/plain, */*"}, 63 | "Content-Type": {"application/json;charset=utf-8"}, 64 | "Authorization": {""}, 65 | } 66 | ) 67 | 68 | func NewChatService(authorization string, cookie string) *ChatService { 69 | return &ChatService{ 70 | // ... 初始化依赖或其他属性 71 | authorization: authorization, 72 | cookie: cookie, 73 | } 74 | } 75 | 76 | func (s *ChatService) GetChatStream(contextId string) (bufio.Scanner, error) { 77 | scanner := bufio.NewScanner(nil) 78 | url := baseUrl + chat + contextId 79 | req, err := http.NewRequest(http.MethodGet, url, nil) 80 | if err != nil { 81 | fmt.Println(err) 82 | return *scanner, err 83 | } 84 | 85 | req.Header = s.getHeaderByType(chatType) 86 | 87 | res, err1 := client.Do(req) 88 | if res != nil { 89 | defer res.Body.Close() 90 | } 91 | if err1 != nil { 92 | fmt.Println(err1) 93 | return *scanner, err1 94 | } 95 | 96 | scanner = bufio.NewScanner(res.Body) 97 | return *scanner, nil 98 | } 99 | 100 | func (s *ChatService) GetChat(contextId string) (string, error) { 101 | scanner := bufio.NewScanner(nil) 102 | url := baseUrl + chat + contextId 103 | 104 | req, err := http.NewRequest(http.MethodGet, url, nil) 105 | 106 | if err != nil { 107 | fmt.Println(err) 108 | return "", err 109 | } 110 | req.Header = s.getHeaderByType(chatType) 111 | res, err1 := client.Do(req) 112 | if res != nil { 113 | defer res.Body.Close() 114 | } 115 | if err1 != nil { 116 | fmt.Println(err1) 117 | return "", err1 118 | } 119 | scanner = bufio.NewScanner(res.Body) 120 | var ok bool 121 | var answer string 122 | for scanner.Scan() { 123 | str := scanner.Text() 124 | if ok { 125 | answer = answer + str + "\n" 126 | continue 127 | } 128 | if str == "event:finish" { 129 | ok = true 130 | } 131 | } 132 | answer = strings.ReplaceAll(answer, "data:", "") 133 | return answer, nil 134 | } 135 | 136 | func (s *ChatService) GetTaskId(prompt string) *entity.TaskResponse { 137 | url := baseUrl + task 138 | payload := strings.NewReader(`{"prompt":"` + prompt + `"}`) 139 | req, err := http.NewRequest(http.MethodPost, url, payload) 140 | if err != nil { 141 | fmt.Println(err) 142 | return nil 143 | } 144 | req.Header = s.getHeaderByType(taskType) 145 | res, err1 := client.Do(req) 146 | if res != nil { 147 | defer res.Body.Close() 148 | } 149 | if err1 != nil { 150 | fmt.Println(err1) 151 | return nil 152 | } 153 | 154 | body, err2 := io.ReadAll(res.Body) 155 | if err2 != nil { 156 | fmt.Println(err2) 157 | return nil 158 | } 159 | var response *entity.TaskResponse 160 | err = json.Unmarshal(body, &response) 161 | if err != nil { 162 | fmt.Println(err) 163 | return nil 164 | } 165 | 166 | return response 167 | } 168 | 169 | func (s *ChatService) GetContextId(prompt string, taskid string) *entity.ContextResponse { 170 | url := baseUrl + context 171 | str := `{"prompt":"` + prompt + `","seed":93549,"max_tokens":512,"conversation_task_id":"` + 172 | taskid + `","retry":false,"retry_history_task_id":null}` 173 | payload := strings.NewReader(str) 174 | req, err := http.NewRequest(http.MethodPost, url, payload) 175 | 176 | if err != nil { 177 | fmt.Println(err) 178 | return nil 179 | } 180 | 181 | req.Header = s.getHeaderByType(contextType) 182 | 183 | res, err1 := client.Do(req) 184 | if res != nil { 185 | defer res.Body.Close() 186 | } 187 | if err1 != nil { 188 | fmt.Println(err1) 189 | return nil 190 | } 191 | 192 | body, err2 := io.ReadAll(res.Body) 193 | if err2 != nil { 194 | fmt.Println(err2) 195 | return nil 196 | } 197 | var response *entity.ContextResponse 198 | err = json.Unmarshal(body, &response) 199 | if err != nil { 200 | fmt.Println(err) 201 | return nil 202 | } 203 | 204 | return response 205 | } 206 | 207 | func (s *ChatService) getHeaderByType(tpe tpe) map[string][]string { 208 | header := headerCookie 209 | switch tpe { 210 | case chatType: 211 | header[cookie][0] = s.cookie 212 | header[accept][0] = streamAccept 213 | case taskType: 214 | header = headerAuth 215 | header[Authorization][0] = s.authorization 216 | case contextType: 217 | header = headerAuth 218 | header[Authorization][0] = s.authorization 219 | default: 220 | 221 | } 222 | return header 223 | } 224 | --------------------------------------------------------------------------------