package moonshot import ( "bytes" "encoding/json" "fmt" "github.com/PuerkitoBio/goquery" "github.com/tidwall/gjson" "io" "log" "mime/multipart" "net/http" "os" "strings" "week/tools" "week/udesk" ) //请求月之暗面所需要的常量 const ( MoonshotFileApiUrl = "https://api.moonshot.cn/v1/files/" moonshotApiKey = "sk-DwKNLIVfGFi5CUocISixedd2kLcNzYVRFShbScKtbxMNOPkQ" ) // 上传文件 func ReqMoonShotFileSendApi() *string { filePath := "./周报.xlsx" // 打开文件 file, err := os.Open(filePath) if err != nil { log.Printf("打开周报excel失败,错误是:%v", err) } defer file.Close() // 创建一个缓冲区 body := &bytes.Buffer{} writer := multipart.NewWriter(body) // 创建一个文件表单字段 part, err := writer.CreateFormFile("file", filePath) if err != nil { log.Printf("写文件缓存失败,错误是%v", err) } // 将文件内容拷贝到表单字段 _, err = io.Copy(part, file) if err != nil { log.Printf("拷贝文件到缓存失败,错误是%v", err) } // 添加其他表单字段 writer.WriteField("purpose", "file-extract") // 完成表单写入 writer.Close() // 创建 HTTP 请求 req, err := http.NewRequest("POST", MoonshotFileApiUrl, body) if err != nil { log.Printf("请求月之暗面api过程,创建http请求失败,错误是:%s", err) } // 设置请求头 req.Header.Set("Content-Type", writer.FormDataContentType()) req.Header.Set("Authorization", "Bearer "+moonshotApiKey) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Printf("请求月之暗面api过程,请求失败,错误是:%s", err) } defer resp.Body.Close() // 读取响应 responseBody, err := io.ReadAll(resp.Body) if err != nil { log.Printf("请求月之暗面api过程,读取响应失败,错误是:%s", err) } // 打印响应内容 fileId := gjson.Get(string(responseBody), "id").String() log.Printf("文件上传成功,你上传的文件id是:%s", fileId) return &fileId } // 删除文件 func ReqMoonShotFileDeleteApi(fileID *string) { // 设置 API endpoint url := fmt.Sprintf(MoonshotFileApiUrl + *fileID) // 创建 HTTP 请求 req, err := http.NewRequest("DELETE", url, nil) if err != nil { log.Printf("调用月之暗面删除文件api过程,创建http请求失败,错误是%v", err) return } // 设置请求头(如果需要的话) req.Header.Set("Authorization", "Bearer "+moonshotApiKey) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Printf("调用月之暗面删除文件api过程,发送http请求失败,错误是%v", err) return } defer resp.Body.Close() // 检查响应状态码 if resp.StatusCode == http.StatusOK { log.Printf("请求月之暗面删除文件api成功~") } else { log.Println("请求月之暗面删除文件api失败>_<, http状态码是:", resp.StatusCode) } } // 开启ai对话主函数 func AiChat() (string, error) { fileId := ReqMoonShotFileSendApi() contentStr := GetFileContent(fileId) // 设置 API endpoint url := "https://api.moonshot.cn/v1/chat/completions" // 构造请求体 requestBody := map[string]interface{}{ "model": "moonshot-v1-128k", "messages": []map[string]string{ {"role": "system", "content": contentStr}, {"role": "user", "content": "帮忙分析下工单中的错别字,告诉我对应的工单id"}, }, "temperature": 0.2, } // 将请求体转换为 JSON 格式 jsonBody, err := json.Marshal(requestBody) if err != nil { log.Printf("开启会话过程,将请求体转换为json格式失败,错误是:%v", err) return "", err } // 创建 HTTP 请求 req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody)) if err != nil { log.Printf("开启会话过程,创建请求失败,错误是:%v", err) return "", err } // 设置请求头 req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+moonshotApiKey) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Printf("开启会话过程,发送请求失败,错误是:%v:", err) return "", err } defer resp.Body.Close() // 读取响应 responseBody := new(bytes.Buffer) _, err = responseBody.ReadFrom(resp.Body) if err != nil { log.Printf("开启会话过程,读取响应失败,错误是:%v:", err) return "", err } defer ReqMoonShotFileDeleteApi(fileId) //对话后清空文件 // 打印响应内容 jsonData := responseBody.String() repFromAi := gjson.Get(jsonData, "choices.#.message.content").String() repFromAi = strings.Replace(repFromAi, "\\n", "\n", -1) repFromAi = strings.Replace(repFromAi, "\\", "", -1) repFromAi = strings.Replace(repFromAi, "[", "", -1) repFromAi = strings.Replace(repFromAi, "]", "", -1) repFromAi = strings.Replace(repFromAi, "\"", "", 1) log.Println(repFromAi) return repFromAi, nil } // 获取文件内容 func GetFileContent(fileID *string) string { // 设置 API endpoint url := fmt.Sprintf(MoonshotFileApiUrl + *fileID + "/content") // 创建 HTTP 请求 req, err := http.NewRequest("GET", url, nil) if err != nil { log.Printf("月之暗面api,获取文件内容过程,创建http请求,错误是:%v:", err) } // 设置请求头 req.Header.Set("Authorization", "Bearer "+moonshotApiKey) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { log.Printf("月之暗面api,获取文件内容过程,发送请求,错误是:%v", err) } defer resp.Body.Close() // 读取响应内容 content, err := io.ReadAll(resp.Body) if err != nil { log.Printf("月之暗面api,获取文件内容过程,读取响应失败,错误是:%v", err) } contentStr := string(content) // 打印文件内容 fmt.Println(contentStr) return contentStr } // 根据工单id循环获取工单回复内容 func CreateExcel() error { totalPages, err := udesk.GetUdeskTicketId() if err != nil { return err } id, err := udesk.LoopGetTicketId(totalPages) if err != nil { return err } contentMap := make(map[string][]string) j := 1 for _, v := range id { idUrl := fmt.Sprintf("https://servicecenter-alauda.udesk.cn/open_api_v1/tickets/%v/replies?", v) repliesUrl := udesk.Geturlstring(idUrl) resp, err := http.Get(repliesUrl) if err != nil { // 处理错误 log.Printf("获取工单过滤器下的回复信息失败,发送请求过程,错误是:%v\n", err) return err } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { } }(resp.Body) body, err := io.ReadAll(resp.Body) if err != nil { // 处理错误 log.Printf("获取工单过滤器下的回复信息失败,读取返回体过程,错误是:%v\n", err) return err } jsonData := string(body) repliesContent := gjson.Get(jsonData, "replies.#.content").String() repliesContent = strings.Trim(repliesContent, "[]") //repliesContent = trimHtml(repliesContent) //查找回复内容和配图 doc, err := goquery.NewDocumentFromReader(strings.NewReader(repliesContent)) var s = make([]string, 0) doc.Find("p,img").Each(func(i int, selection *goquery.Selection) { imgSrc, exists := selection.Attr("src") if exists { s = append(s, imgSrc) s = append(s, "\n") } s = append(s, selection.Text()) s = append(s, "\n") }) //跳过没有回复内容的工单,即运维服务,减少给模型的错误条件 if len(s) == 0 { continue } repliesContentSlice := tools.ReverseSlice(s) cloudId := udesk.Id2CloudId(v) log.Printf("正在处理map中的第%v个数据,键是%v\n", j, v) if cloudId == "" { contentMap[v] = repliesContentSlice } else { contentMap[cloudId] = repliesContentSlice } log.Printf("第%v个数据数据处理完成\n", j) j++ } log.Printf("所有回复数据处理完成,map中键的数量:%v\n", len(contentMap)) //fmt.Printf("map的值:%v\n", contentMap) //回复内容的map,待办:将这个map中的建存储第一列,将这个map中的值作为第二列存储 // 生成excel表格内容为id --> 回复内容 // 保存到某地 tools.CreateNewExcel(contentMap) //创建了excel //sk-DwKNLIVfGFi5CUocISixedd2kLcNzYVRFShbScKtbxMNOPkQ //卡点,如何根据文件内容获取回复,目前这个结构只能开启单轮对话 return nil }