ai-week/moonshot/function.go

312 lines
8.2 KiB
Go
Raw Normal View History

2024-05-01 20:03:20 +08:00
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
}