saw-go/service/spark/spark-ppt.go

485 lines
15 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package spark
import (
"StuAcaWorksAI/dao"
"StuAcaWorksAI/proto"
"StuAcaWorksAI/service"
"StuAcaWorksAI/worker"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func SparkPPTThemeList(model *proto.ModelParam, req proto.GetSparkPPTThemeReq) (proto.SparkPPTThemeListResponse, error) {
url := "https://zwapi.xfyun.cn/api/ppt/v2/template/list"
headers, err := getSparkRequestHeaders(model.APPID, model.APISecret)
if err != nil {
log.Println("Spark PPT Theme Error getting headers:", err)
return proto.SparkPPTThemeListResponse{}, err
}
//log.Println("Spark PPT Theme headers:", headers)
req_ := proto.PPTThemeRequest{
Style: req.Style,
Color: req.Color,
Industry: req.Industry,
PageNum: 1,
PageSize: 10,
}
reqStr, err := json.Marshal(req_)
if err != nil {
log.Println("Spark PPT Theme Error encoding request:", err)
return proto.SparkPPTThemeListResponse{}, err
}
log.Println("Spark PPT Theme req:", string(reqStr))
err, resp := worker.DoPostRequestJSON(url, reqStr, headers)
var response proto.SparkPPTThemeListResponse
if err != nil {
log.Println("Spark PPT Theme Error:", err)
} else {
err = json.Unmarshal(resp, &response)
if err != nil {
log.Println("Spark PPT Theme Error decoding response:", err)
}
}
log.Println("Spark PPT Theme Response:", string(resp))
//log.Println("Spark PPT Theme Response:", response)
return response, err
}
func getSparkRequestHeaders(appId, apiSecret string) (map[string]string, error) {
headers := map[string]string{
"appId": "d3a4647c",
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
}
algorithm := ApiAuthAlgorithm{}
signature := algorithm.GetSignature(appId, apiSecret, time.Now().Unix())
headers["signature"] = signature
return headers, nil
}
// 根据用户输入及文档生成大纲,文档可以是docx、doc、txt、pdf格式
func SparkCreateOutlineByDoc(model *proto.ModelParam, userReq *proto.SparkCreateOutlineRequest) (proto.SparkCreateOutlineResponse, error) {
url := "https://zwapi.xfyun.cn/api/ppt/v2/createOutlineByDoc"
headers, err := getSparkRequestHeaders(model.APPID, model.APISecret)
if err != nil {
log.Println("Spark PPT Theme Error getting headers:", err)
return proto.SparkCreateOutlineResponse{}, err
}
log.Println("Spark create outline by doc headers:", headers)
req := proto.SparkCreateOutlineByDocRequest{
Query: userReq.Query,
FileUrl: userReq.FileUrl,
FileName: userReq.FileName,
}
reqStr, err := json.Marshal(req)
if err != nil {
log.Println("Spark create outline by doc Error encoding request:", err)
}
log.Println("Spark create outline by doc req:", string(reqStr))
err, resp := worker.DoPostRequestForm(url, reqStr, headers)
//log.Println("Spark create outline by doc Response:", string(resp))
var response proto.SparkCreateOutlineResponse
if err != nil {
log.Println("Spark create outline by doc Error:", err)
} else {
err = json.Unmarshal(resp, &response)
if err != nil {
log.Println("Spark create outline by doc Error decoding response:", err)
}
}
log.Println("Spark create outline by doc Response struct:", response)
return response, err
}
// 根据query生成大纲
func SparkCreateOutline(model *proto.ModelParam, userReq *proto.SparkCreateOutlineRequest) (proto.SparkCreateOutlineResponse, error) {
url := "https://zwapi.xfyun.cn/api/ppt/v2/createOutline"
headers, err := getSparkRequestHeaders(model.APPID, model.APISecret)
if err != nil {
log.Println("Spark PPT Theme Error getting headers:", err)
return proto.SparkCreateOutlineResponse{}, err
}
log.Println("Spark create outline by doc headers:", headers)
//自定义内容
req := proto.SparkCreateOutlineByDocRequest{
Query: userReq.Query,
}
reqStr, err := json.Marshal(req)
if err != nil {
log.Println("Spark create PPT Error encoding request:", err)
}
log.Println("Spark create PPT req:", string(reqStr))
err, resp := worker.DoPostRequestForm(url, reqStr, headers)
log.Println("Spark create PPT Response:", string(resp))
var response proto.SparkCreateOutlineResponse
if err != nil {
log.Println("Spark create PPT Error:", err)
} else {
err = json.Unmarshal(resp, &response)
if err != nil {
log.Println("Spark create PPT Error decoding response:", err)
}
}
log.Println("Spark create PPT Response struct:", response)
return response, err
}
func SparkCreatePPTByOutline(model *proto.ModelParam, userReq *proto.SparkCreatePPTByOutlineUserRequest) (proto.SparkCreatePPTResponse, error) {
url := "https://zwapi.xfyun.cn/api/ppt/v2/createPptByOutline"
headers, err := getSparkRequestHeaders(model.APPID, model.APISecret)
if err != nil {
log.Println("Spark create ppt by outline Error encoding request:", err)
return proto.SparkCreatePPTResponse{}, err
}
log.Println("Spark create ppt by outline headers:", headers)
req := proto.SparkCreatePptByOutlineRequest{
Query: userReq.Query,
FileUrl: userReq.FileUrl,
FileName: userReq.FileName,
Outline: userReq.Outline,
}
reqStr, err := json.Marshal(req)
if err != nil {
log.Println("Spark create ppt by outline Error encoding request:", err)
}
log.Println("Spark create ppt by outline req:", string(reqStr))
err, resp := worker.DoPostRequestJSON(url, reqStr, headers)
log.Println("Spark create ppt by outline Response:", string(resp))
var response proto.SparkCreatePPTResponse
if err != nil {
log.Println("Spark create ppt by outline Error:", err)
} else {
err = json.Unmarshal(resp, &response)
if err != nil {
log.Println("Spark create ppt by outline Error decoding response:", err)
}
}
log.Println("Spark create ppt by outline Response struct:", response)
return response, err
}
func SparkGetPPTInfoBySID(model *proto.ModelParam, userReq *proto.SparkCreatePPTByOutlineUserRequest) (proto.SparkCreatePPTByOutlineResponse, error) {
url := "https://zwapi.xfyun.cn/api/ppt/v2/progress?sid=" + userReq.Sid
headers, err := getSparkRequestHeaders(model.APPID, model.APISecret)
if err != nil {
log.Println("Spark create ppt by outline Error encoding request:", err)
return proto.SparkCreatePPTByOutlineResponse{}, err
}
log.Println("Spark create ppt by outline headers:", headers)
err, resp := worker.DoGetRequest(url, headers)
log.Println("Spark create ppt by outline Response:", string(resp))
var response proto.SparkCreatePPTByOutlineResponse
if err != nil {
log.Println("Spark create ppt by outline Error:", err)
} else {
err = json.Unmarshal(resp, &response)
if err != nil {
log.Println("Spark create ppt by outline Error decoding response:", err)
}
}
log.Println("Spark create ppt by outline Response struct:", response)
return response, err
}
// 处理制作大纲请求
func SparkDoCreateOutline(userReq *proto.SparkCreateOutlineRequest, base *proto.SparkCreatePPTBaseInfo) (proto.SparkCreateOutlineResponse, error) {
var modelParam proto.ModelParam
var err error
//需要保存会话
sessionName := ""
if len(userReq.Query) > 10 {
sessionName = userReq.Query[:10]
} else {
sessionName = userReq.Query
}
err2, sessionID := service.CreateSession(base.UserID, proto.SessionTypeUserCreatePPT, sessionName)
if err2 != nil {
log.Println("Create session error:", err2)
return proto.SparkCreateOutlineResponse{}, err2
}
base.SessionID = sessionID
//获取模型
models, funcs, mferr := service.FindFuncModelListByFunctionV2(userReq.Function)
if mferr != nil {
return proto.SparkCreateOutlineResponse{}, mferr
}
model := models[0]
base.ModelID = int(model.ID)
err = json.Unmarshal([]byte(model.Parameter), &modelParam)
if err != nil {
return proto.SparkCreateOutlineResponse{}, err
}
modelParam.Url = model.Url
modelParam.System = funcs[0].Info //系统功能
//保存消息
userReqStr, err := json.Marshal(userReq)
if err != nil {
log.Println("Error parsing JSON:", err)
return proto.SparkCreateOutlineResponse{}, err
}
err3, userMsgID := service.CreateMessage(proto.UserToModelMsgType, int(sessionID), base.UserID, int(model.ID), string(userReqStr), proto.UserToModelPPTMsgType, int(funcs[0].ID))
if err3 != nil {
log.Println("Create message error:", err3, userMsgID)
return proto.SparkCreateOutlineResponse{}, err3
}
var outline proto.SparkCreateOutlineResponse
//获取大纲
//测试阶段
outline = testPPTOutline()
//if userReq.FileUrl == "" {
// outline, err = SparkCreateOutline(&modelParam, userReq) //根据query生成大纲
//} else {
// outline, err = SparkCreateOutlineByDoc(&modelParam, userReq) //根据文档生成大纲
//}
//进行保存
if err != nil {
log.Println("Spark create outline Error:", err)
return outline, err
}
outlineStr, _ := json.Marshal(userReq)
//返回的数据保存
service.CreateAIStreamMsg(base.UserID, base.ModelID, int(base.SessionID), outline, modelParam.Model)
//保存大纲
err3, userMsgID = service.CreateMessage(proto.ModelToUserMsgType, int(sessionID), base.UserID, int(model.ID), string(outlineStr), proto.UserToModelPPTMsgType, int(funcs[0].ID))
if err3 != nil {
log.Println("Create message error:", err3, userMsgID)
return proto.SparkCreateOutlineResponse{}, err3
}
return outline, err
}
// 处理制作PPT请求
func SparkDoCreatePPTByOutline(userReq *proto.SparkCreatePPTByOutlineUserRequest, base *proto.SparkCreatePPTBaseInfo) (proto.SparkCreatePPTResponse, error) {
var modelParam proto.ModelParam
var err error
//需要保存会话
if base.SessionID == 0 {
log.Println("session id is 0, create ppt")
return proto.SparkCreatePPTResponse{}, errors.New("create ppt,session id is 0, please create session first")
}
//获取模型
models, funcs, mferr := service.FindFuncModelListByFunctionV2(userReq.Function)
if mferr != nil {
return proto.SparkCreatePPTResponse{}, mferr
}
model := models[0]
base.ModelID = int(model.ID)
err = json.Unmarshal([]byte(model.Parameter), &modelParam)
if err != nil {
return proto.SparkCreatePPTResponse{}, err
}
modelParam.Url = model.Url
modelParam.System = funcs[0].Info //系统功能
//保存消息
userReqStr, err := json.Marshal(userReq)
if err != nil {
log.Println("Error parsing JSON:", err)
return proto.SparkCreatePPTResponse{}, err
}
err3, userMsgID := service.CreateMessage(proto.UserToModelMsgType, int(base.SessionID), base.UserID, int(model.ID), string(userReqStr), proto.UserToModelPPTMsgType, int(funcs[0].ID))
if err3 != nil {
log.Println("Create message error:", err3, userMsgID)
return proto.SparkCreatePPTResponse{}, err3
}
//测试阶段
resp := testPPTInfo()
//resp, err4 := SparkCreatePPTByOutline(&modelParam, userReq) //根据大纲生成ppt
//
//if err4 != nil {
// log.Println("Spark create ppt by outline Error:", err4)
// return proto.SparkCreatePPTResponse{}, err4
//}
//进行保存
service.CreateAIStreamMsg(base.UserID, base.ModelID, int(base.SessionID), resp, modelParam.Model) //保存消息
//新协程获取ppt制作进度
userReq.Sid = resp.Data.SID
go SparkDoGetPPTInfoBySID(&modelParam, userReq, base)
return resp, nil
}
// 每3秒查询一次ppt制作情况
func SparkDoGetPPTInfoBySID(modelParam *proto.ModelParam, userReq *proto.SparkCreatePPTByOutlineUserRequest, base *proto.SparkCreatePPTBaseInfo) {
//定时
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
i := 0
for {
select {
case <-ticker.C:
i += 1
if i > 20 {
log.Println("SparkDoGetPPTInfoBySID timeout more 1 min, stop ticker")
return
}
log.Println("SparkDoGetPPTInfoBySID ticker")
resp, err := SparkGetPPTInfoBySID(modelParam, userReq) //根据大纲生成ppt
if err != nil {
log.Println("Spark create ppt by outline Error:", err)
return
}
respStr, _ := json.Marshal(resp)
service.CreateAIStreamMsg(base.UserID, base.ModelID, int(base.SessionID), resp, modelParam.Model) //保存消息
//添加到消息队列,用于前端查询
key := fmt.Sprintf("user-%d-session-%d-create-pptx", base.UserID, base.SessionID)
worker.SetRedisWithExpire(key, string(respStr), time.Second*60*5) //设置5分钟过期
if resp.Data.PptStatus == "done" {
log.Println("ppt done")
//下载文件,保存到指定用户的文件
fileName, filePath, err2 := SparkSavePPTFileToUser(resp.Data.PptUrl)
if err2 != nil {
log.Println("Spark save ppt file to user Error:", err2)
return
}
//保存文件路径到数据库
fileRecord := dao.CreateFile(fileName, userReq.Outline.Title+".pptx", "", filePath, "", 0, base.UserID, false)
fileAuth := service.CreateUserFile(base.UserID, fileRecord.FileName, int(fileRecord.ID), proto.UserFileTypeFile)
if fileRecord.ID == 0 || fileAuth.ID == 0 {
log.Println("save file info failed", fileRecord.ID, fileAuth.ID)
}
return
}
}
}
}
// 将下载的文件保存到对应指定用户的文件并对该会话添加ppt完成消息
func SparkSavePPTFileToUser(fileUrl string) (string, string, error) {
log.Println("Spark save ppt file to user")
//https://bjcdn.openstorage.cn/xinghuo-privatedata/zhiwen/2025-04-02/6ebfc0b2-824a-4acc-a030-01acce938dab/3209de1bca814ac48884e015277360fd.pptx
fileName := fileUrl[strings.LastIndex(fileUrl, "/")+1:]
//文件保存路径
path := service.GetFilePath(proto.FILE_BASE_DIR)
saveFile := path + "/" + fileName
//下载文件
err := DownloadFile(fileUrl, saveFile)
if err != nil {
log.Println("Download file error:", err)
return "", "", err
}
log.Println("Download file success:", fileName)
return fileName, path, nil
}
func DownloadFile(url, filePath string) error {
// 创建 HTTP GET 请求
resp, err := http.Get(url)
if err != nil {
return err
}
// 确保在函数结束时关闭响应体
defer resp.Body.Close()
// 检查 HTTP 响应状态码
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
// 创建本地文件
out, err := os.Create(filePath)
if err != nil {
return err
}
// 确保在函数结束时关闭文件
defer out.Close()
// 将响应体内容复制到本地文件
_, err = io.Copy(out, resp.Body)
return err
}
func testPPTInfo() proto.SparkCreatePPTResponse {
path := "/home/saw/saw_ppt_info.json"
var pptInfo proto.SparkCreatePPTResponse
//读取文件
file, err := os.Open(path)
if err != nil {
log.Println("Error opening file:", err)
return pptInfo
}
defer file.Close()
//读取文件内容
data, err := io.ReadAll(file)
if err != nil {
log.Println("Error reading file:", err)
return pptInfo
}
err = json.Unmarshal(data, &pptInfo)
if err != nil {
log.Println("Error unmarshalling JSON:", err)
return pptInfo
}
return pptInfo
}
func testPPTOutline() proto.SparkCreateOutlineResponse {
path := "/home/saw/saw_ppt_outline.json"
var outline proto.SparkCreateOutlineResponse
//读取文件
file, err := os.Open(path)
if err != nil {
log.Println("Error opening file:", err)
return outline
}
defer file.Close()
//读取文件内容
data, err := io.ReadAll(file)
if err != nil {
log.Println("Error reading file:", err)
return outline
}
err = json.Unmarshal(data, &outline)
if err != nil {
log.Println("Error unmarshalling JSON:", err)
return outline
}
return outline
}
func TestPPTTHemeList() proto.SparkPPTThemeListResponse {
path := "/home/saw/saw_ppt_theme.json"
var themeList proto.SparkPPTThemeListResponse
//读取文件
file, err := os.Open(path)
if err != nil {
log.Println("Error opening file:", err)
return themeList
}
defer file.Close()
//读取文件内容
data, err := io.ReadAll(file)
if err != nil {
log.Println("Error reading file:", err)
return themeList
}
err = json.Unmarshal(data, &themeList)
if err != nil {
log.Println("Error unmarshalling JSON:", err)
return themeList
}
return themeList
}