Browse Source

提示词内容生成

kobe6258 2 weeks ago
parent
commit
ec55a359f9

+ 10 - 5
controllers/llm/promote_controller.go

@@ -64,7 +64,7 @@ func (pCtrl *PromoteController) PromoteTrainRecordList() {
 // GenerateContent @Title 生成问答内容
 // @Description 生成问答内容
 // @Success 101 {object} response.ListResp
-// @router /promote/generate_content [get]
+// @router /promote/generate_content [post]
 func (pCtrl *PromoteController) GenerateContent() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
@@ -95,12 +95,17 @@ func (pCtrl *PromoteController) GenerateContent() {
 		br.ErrMsg = "公众号文章编号非法"
 		return
 	}
-	facade.AIGCBaseOnPromote(facade.AIGC{
-		Promote:     gcReq.Promote,
+	res, err := facade.AIGCBaseOnPromote(facade.AIGC{
+		Promote:   gcReq.Promote,
 		ArticleId: gcReq.WechatArticleId,
 	})
-	br.Data = nil
+	if err != nil {
+		br.Msg = "内容生成失败"
+		br.ErrMsg = "内容生成失败,Err:" + err.Error()
+		return
+	}
+	br.Data = res
 	br.Ret = 200
 	br.Success = true
-	br.Msg = "获取聊天记录成功"
+	br.Msg = "内容生成成功"
 }

+ 1 - 1
routers/commentsRouter.go

@@ -8408,7 +8408,7 @@ func init() {
         beego.ControllerComments{
             Method: "GenerateContent",
             Router: `/promote/generate_content`,
-            AllowHTTPMethods: []string{"get"},
+            AllowHTTPMethods: []string{"post"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})

+ 44 - 21
services/llm/facade/llm_service.go

@@ -15,6 +15,8 @@ import (
 	"github.com/rdlucklib/rdluck_tools/uuid"
 	"gorm.io/gorm"
 	"os"
+	"strings"
+	"time"
 )
 
 var (
@@ -55,7 +57,7 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 	} else {
 		var kbId string
 		var file *os.File
-		var params map[string]interface{}
+		params := make(map[string]interface{})
 		if mapping.Id == 0 || mapping.KbId == "" {
 			article, fileErr := rag.GetArticleById(aigc.ArticleId)
 			if fileErr != nil {
@@ -95,6 +97,7 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 			err = rag.CreateArticleKbMapping(rag.ArticleKbMapping{
 				WechatArticleId: aigc.ArticleId,
 				KbId:            data.Id,
+				CreatedTime:     time.Now(),
 			})
 			if err != nil {
 				utils.FileLog.Warn("创建文章知识库映射关系失败,err:", err.Error())
@@ -115,14 +118,25 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 			err = fmt.Errorf("内容生成失败,code:%v,msg:%v", response.Ret, response.Msg)
 			return
 		} else {
-			var baseResp eta_llm_http.RagBaseResponse
-			parseErr := json.Unmarshal(response.Data, &baseResp)
-			if parseErr != nil {
-				utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
-				err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+			dataStr := string(response.Data)
+			// 去除 "data: " 前缀
+			if strings.HasPrefix(dataStr, "data: ") {
+				dataStr = strings.TrimPrefix(dataStr, "data: ")
+				parseErr := json.Unmarshal([]byte(dataStr), &resp)
+				if parseErr != nil {
+					utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
+					err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+					return
+				}
 				return
-			}
-			if baseResp.Code != 200 {
+			} else {
+				var baseResp eta_llm_http.RagBaseResponse
+				parseErr := json.Unmarshal([]byte(dataStr), &baseResp)
+				if parseErr != nil {
+					utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
+					err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+					return
+				}
 				if baseResp.Code == 404 {
 					params["PrevId"] = kbId
 					_, putErr := llmService.UploadFileToTemplate([]*os.File{file}, params)
@@ -132,8 +146,8 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 						return
 					}
 				} else {
-					utils.FileLog.Error("内容生成失败,code:%v,msg:%v", baseResp.Code, baseResp.Msg)
-					err = fmt.Errorf("内容生成失败,code:%v,msg:%v", baseResp.Code, baseResp.Msg)
+					utils.FileLog.Error("内容生成失败,code:%v", baseResp.Code)
+					err = fmt.Errorf("内容生成失败,code:%v", baseResp.Code)
 					return
 				}
 			}
@@ -147,17 +161,26 @@ func AIGCBaseOnPromote(aigc AIGC) (resp bus_response.AIGCEtaResponse, err error)
 				utils.FileLog.Error("内容生成失败,code:%v,msg:%v", gcResp.Ret, gcResp.Msg)
 				err = fmt.Errorf("内容生成失败,err:%v", gcResp.Msg)
 			}
-			var steamResp eta_llm_http.ContentResponse
-			parseErr = json.Unmarshal(gcResp.Data, &steamResp)
-			if parseErr != nil {
-				utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
-				err = fmt.Errorf("内容生成失败,err:%v", parseErr)
-				return
-			}
-			parseErr = json.Unmarshal(steamResp.Data, &resp)
-			if parseErr != nil {
-				utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
-				err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+			dataStr = string(gcResp.Data)
+			// 去除 "data: " 前缀
+			if strings.HasPrefix(dataStr, "data: ") {
+				dataStr = strings.TrimPrefix(dataStr, "data: ")
+				parseErr := json.Unmarshal([]byte(dataStr), &resp)
+				if parseErr != nil {
+					utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
+					err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+					return
+				}
+			} else {
+				var baseResp eta_llm_http.RagBaseResponse
+				parseErr := json.Unmarshal([]byte(dataStr), &baseResp)
+				if parseErr != nil {
+					utils.FileLog.Error("内容生成失败,code:%v,msg:%v", parseErr)
+					err = fmt.Errorf("内容生成失败,err:%v", parseErr)
+					return
+				}
+				utils.FileLog.Error("内容生成失败,code:%v", baseResp.Code)
+				err = fmt.Errorf("内容生成失败,code:%v", baseResp.Code)
 				return
 			}
 		}

+ 2 - 12
services/llm/promote_service.go

@@ -7,18 +7,11 @@ import (
 	"os"
 )
 
-func CreateArticleFile(item *rag.WechatArticle) (filePath string, err error) {
+func CreateArticleFile(item *rag.WechatArticle) (tmpFilePath string, err error) {
 	if item.TextContent == `` {
 		err = fmt.Errorf("生成文章原文文本失败,文章内容为空")
 		return
 	}
-	defer func() {
-		if err != nil {
-			utils.FileLog.Error("上传文章原文到知识库失败,err:%v", err)
-			fmt.Println("上传文章原文到知识库失败,err:", err)
-		}
-	}()
-
 	// 生成临时文件
 	uploadDir := utils.STATIC_DIR + "ai/article"
 	err = os.MkdirAll(uploadDir, utils.DIR_MOD)
@@ -27,14 +20,11 @@ func CreateArticleFile(item *rag.WechatArticle) (filePath string, err error) {
 		return
 	}
 	fileName := utils.RemoveSpecialChars(item.Title) + `.md`
-	tmpFilePath := uploadDir + "/" + fileName
+	tmpFilePath = uploadDir + "/" + fileName
 	err = utils.SaveToFile(item.TextContent, tmpFilePath)
 	if err != nil {
 		err = fmt.Errorf("生成临时文件失败,Err:" + err.Error())
 		return
 	}
-	defer func() {
-		_ = os.Remove(tmpFilePath)
-	}()
 	return
 }

+ 1 - 0
static/imgs/ai/article/【功能大盘点辞旧迎新来】中信期货研究邀您共启新程.md

@@ -0,0 +1 @@
+—  END  —来源:中信期货研究所

File diff suppressed because it is too large
+ 0 - 0
static/imgs/ai/article/辑策略震荡时间久的两大变量进入验证阶段负反馈降本空间风险待破位信号AK3月第1周逻辑.md


+ 50 - 6
utils/llm/eta_llm/eta_llm_client.go

@@ -11,6 +11,7 @@ import (
 	"eta/eta_api/utils/llm/eta_llm/eta_llm_http"
 	"fmt"
 	"io"
+	"mime/multipart"
 	"net/http"
 	"os"
 	"strings"
@@ -174,19 +175,21 @@ func (ds *ETALLMClient) FileChat(query string, KnowledgeId string, history []jso
 }
 
 func (ds *ETALLMClient) UploadFileToTemplate(files []*os.File, param map[string]interface{}) (data interface{}, err error) {
-	pervId := param["PrevId"].(string)
+	var pervId string
+	if value, ok := param["PrevId"]; ok {
+		pervId = value.(string)
+	}
 	docReq := eta_llm_http.UploadTempDocsRequest{
-		ChunkOverlap:   750,
-		ChunkSize:      150,
-		Files:          files,
+		ChunkOverlap:   "150",
+		ChunkSize:      "750",
 		PrevId:         pervId,
-		ZhTitleEnhance: false,
+		ZhTitleEnhance: "false",
 	}
 	body, err := json.Marshal(docReq)
 	if err != nil {
 		return
 	}
-	resp, err := ds.DoPost(UPLOAD_TEMP_DOCS_API, body)
+	resp, err := ds.DoFile(UPLOAD_TEMP_DOCS_API, body, files)
 	if !resp.Success {
 		err = errors.New(resp.Msg)
 		return
@@ -259,6 +262,47 @@ func (ds *ETALLMClient) DoPost(apiUrl string, body []byte) (baseResp eta_llm_htt
 	}
 	return parseResponse(response)
 }
+
+func (ds *ETALLMClient) DoFile(apiUrl string, body []byte, files []*os.File) (baseResp eta_llm_http.BaseResponse, err error) {
+	var requestBody bytes.Buffer
+	writer := multipart.NewWriter(&requestBody)
+	// 添加文件到请求体
+	for _, file := range files {
+		filePath, err := writer.CreateFormFile("files", file.Name())
+		if err != nil {
+			return baseResp, fmt.Errorf("创建文件表单字段失败: %w", err)
+		}
+		_, err = io.Copy(filePath, file)
+		if err != nil {
+			return baseResp, fmt.Errorf("写入文件内容失败: %w", err)
+		}
+	}
+	var params = make(map[string]string)
+	err = json.Unmarshal(body, &params)
+	if err != nil {
+		return
+	}
+	// 添加其他参数到请求体
+	for key, value := range params {
+		err := writer.WriteField(key, value)
+		if err != nil {
+			return baseResp, fmt.Errorf("写入表单字段失败: %w", err)
+		}
+	}
+
+	// 关闭 writer,完成请求体的构建
+	err = writer.Close()
+	if err != nil {
+		return baseResp, fmt.Errorf("关闭 multipart writer 失败: %w", err)
+	}
+	request, err := http.NewRequest("POST", ds.BaseURL+apiUrl, &requestBody)
+	request.Header.Set("Content-Type", writer.FormDataContentType())
+	response, err := ds.HttpClient.Do(request)
+	if err != nil {
+		return
+	}
+	return parseResponse(response)
+}
 func (ds *ETALLMClient) DoStreamPost(apiUrl string, body []byte) (baseResp *http.Response, err error) {
 	requestReader := bytes.NewReader(body)
 	return ds.HttpClient.Post(ds.BaseURL+apiUrl, CONTENT_TYPE_JSON, requestReader)

+ 4 - 7
utils/llm/eta_llm/eta_llm_http/request.go

@@ -1,7 +1,5 @@
 package eta_llm_http
 
-import "os"
-
 type KbChatRequest struct {
 	Query          string           `json:"query"`
 	Mode           string           `json:"mode"`
@@ -46,9 +44,8 @@ type KbSearchDocsRequest struct {
 }
 
 type UploadTempDocsRequest struct {
-	Files          []*os.File `json:"files"`
-	PrevId         string     `json:"prev_id"`
-	ChunkSize      int        `json:"chunk_size"`
-	ChunkOverlap   int        `json:"chunk_overlap"`
-	ZhTitleEnhance bool       `json:"zh_title_enhance"`
+	PrevId         string `json:"prev_id"`
+	ChunkSize      string `json:"chunk_size"`
+	ChunkOverlap   string `json:"chunk_overlap"`
+	ZhTitleEnhance string `json:"zh_title_enhance"`
 }

+ 2 - 5
utils/llm/eta_llm/eta_llm_http/response.go

@@ -12,9 +12,6 @@ type SteamResponse struct {
 	Data ChunkResponse `json:"data"`
 }
 
-type ContentResponse struct {
-	Data json.RawMessage `json:"data"`
-}
 
 // ChunkResponse 定义流式响应的结构体
 type ChunkResponse struct {
@@ -72,6 +69,6 @@ type Metadata struct {
 	Id     string `json:"id"`
 }
 type UploadDocsResponse struct {
-	Id         string   `json:"id"`
-	FiledFiles []string `json:"filed_files"`
+	Id         string            `json:"id"`
+	FiledFiles []json.RawMessage `json:"filed_files"`
 }

Some files were not shown because too many files changed in this diff