refactor: 重构工作流执行逻辑并提取单模型调用
This commit is contained in:
@@ -33,6 +33,66 @@ func GetIsChatModel(ctx context.Context) (res *flowDto.GetIsChatModelRes, err er
|
||||
return
|
||||
}
|
||||
|
||||
func ComposeMessages(ctx context.Context, req *flowDto.ComposeMessagesReq) (res *flowDto.ComposeMessagesRes, err error) {
|
||||
headers := make(map[string]string)
|
||||
if r := g.RequestFromCtx(ctx); r != nil {
|
||||
for k, v := range r.Request.Header {
|
||||
if len(v) > 0 {
|
||||
headers[k] = v[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
res = new(flowDto.ComposeMessagesRes)
|
||||
err = commonHttp.Post(ctx, "prompts-core/prompt/composeMessages", headers, res, &req)
|
||||
return
|
||||
}
|
||||
|
||||
func GetModelResult(ctx context.Context, modelName, skillName string, form, userFrom map[string]any, fileUrl []string, sessionId string, cause string) (mapTaskResult map[string]any, err error) {
|
||||
msgReq := flowDto.ComposeMessagesReq{
|
||||
BuildType: 1,
|
||||
ModelName: modelName,
|
||||
SkillName: skillName,
|
||||
Cause: cause,
|
||||
Form: form,
|
||||
UserForm: userFrom,
|
||||
UserFiles: fileUrl,
|
||||
SessionId: sessionId,
|
||||
}
|
||||
msg, err := ComposeMessages(ctx, &msgReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if g.IsEmpty(msg.Messages) {
|
||||
return nil, fmt.Errorf("msg is empty")
|
||||
}
|
||||
var taskResult any
|
||||
taskResult, err = GatewayTask(ctx, msg.EpicycleId, modelName, msg.Messages)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var getTaskResult *flowDto.TaskCallback
|
||||
getTaskResult, err = GetTaskResult(ctx, taskResult)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mapTaskResult = gconv.Map(getTaskResult.Text)
|
||||
return mapTaskResult, nil
|
||||
}
|
||||
|
||||
func GatewayTask(ctx context.Context, epicycleId int64, model string, content map[string]any) (any, error) {
|
||||
modelTaskId, err := CreateGatewayTask(ctx, &flowDto.CreateTaskReq{
|
||||
ModelName: model,
|
||||
BizName: g.Cfg().MustGet(ctx, "server.name").String(),
|
||||
CallbackUrl: "/flow/execution/modelCallback",
|
||||
RequestPayload: content,
|
||||
EpicycleId: epicycleId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Wait(ctx, modelTaskId)
|
||||
}
|
||||
|
||||
func CreateGatewayTask(ctx context.Context, req *flowDto.CreateTaskReq) (string, error) {
|
||||
headers := make(map[string]string)
|
||||
if r := g.RequestFromCtx(ctx); r != nil {
|
||||
@@ -51,34 +111,6 @@ func CreateGatewayTask(ctx context.Context, req *flowDto.CreateTaskReq) (string,
|
||||
return res.TaskId, nil
|
||||
}
|
||||
|
||||
func ComposeMessages(ctx context.Context, req *flowDto.ComposeMessagesReq) (res *flowDto.ComposeMessagesRes, err error) {
|
||||
headers := make(map[string]string)
|
||||
if r := g.RequestFromCtx(ctx); r != nil {
|
||||
for k, v := range r.Request.Header {
|
||||
if len(v) > 0 {
|
||||
headers[k] = v[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
res = new(flowDto.ComposeMessagesRes)
|
||||
err = commonHttp.Post(ctx, "prompts-core/prompt/composeMessages", headers, res, &req)
|
||||
return
|
||||
}
|
||||
|
||||
func GatewayTask(ctx context.Context, epicycleId int64, model string, content map[string]any) (any, error) {
|
||||
modelTaskId, err := CreateGatewayTask(ctx, &flowDto.CreateTaskReq{
|
||||
ModelName: model,
|
||||
BizName: g.Cfg().MustGet(ctx, "server.name").String(),
|
||||
CallbackUrl: "/flow/execution/modelCallback",
|
||||
RequestPayload: content,
|
||||
EpicycleId: epicycleId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Wait(ctx, modelTaskId)
|
||||
}
|
||||
|
||||
func GetTaskResult(ctx context.Context, result any) (*flowDto.TaskCallback, error) {
|
||||
task := new(flowDto.TaskCallback)
|
||||
if err := gconv.Struct(result, task); err != nil {
|
||||
@@ -116,17 +148,22 @@ func FetchRemoteJsonFile(ctx context.Context, fileUrl string) ([]byte, error) {
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func GetImageBytesFromURL(url string) (all []byte, contentType string, err error) {
|
||||
func GetFileBytesFromURL(url string) (all []byte, err error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Printf("请求失败 %s: %v", url, err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
all, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Printf("请求失败,状态码: %d\n", resp.StatusCode)
|
||||
return
|
||||
}
|
||||
all, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("读取内容失败 %s: %v", url, err)
|
||||
return
|
||||
}
|
||||
contentType = resp.Header.Get("Content-Type")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -197,24 +234,24 @@ func BuildText(text string) string {
|
||||
.item {
|
||||
padding: 30px;
|
||||
}
|
||||
.image-group {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.image-group img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 6px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.image-group img:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.image-group {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.text {
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
line-height: 1.8;
|
||||
line-height: 1.4;
|
||||
color: #555;
|
||||
}
|
||||
.text h2 {
|
||||
@@ -222,7 +259,7 @@ func BuildText(text string) string {
|
||||
font-weight: bold;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.4;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.text h3 {
|
||||
font-size: 20px;
|
||||
@@ -233,7 +270,7 @@ func BuildText(text string) string {
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
.text p {
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 12px;
|
||||
text-align: justify;
|
||||
}
|
||||
.text strong {
|
||||
@@ -243,12 +280,12 @@ func BuildText(text string) string {
|
||||
.text ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 15px 0;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.text ul li {
|
||||
padding: 10px 0 10px 30px;
|
||||
position: relative;
|
||||
line-height: 1.6;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.text ul li:before {
|
||||
content: "●";
|
||||
@@ -262,9 +299,6 @@ func BuildText(text string) string {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
.item {
|
||||
padding: 20px;
|
||||
}
|
||||
.text h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
@@ -278,27 +312,11 @@ func BuildText(text string) string {
|
||||
<div class="container">
|
||||
<div class="item">
|
||||
`)
|
||||
|
||||
//// 写入图片(支持0张、1张、多张)
|
||||
//if len(images) > 0 {
|
||||
// htmlBuilder.WriteString(`<div class="image-group">`)
|
||||
// for _, imgUrl := range images {
|
||||
// htmlBuilder.WriteString(fmt.Sprintf(`<img src="%s" alt="图片"/>`, imgUrl))
|
||||
// }
|
||||
// htmlBuilder.WriteString(`</div>`)
|
||||
//}
|
||||
|
||||
// 🔥 写入文案前:删除 <p class="image-count">需要配图:X 张</p>
|
||||
if text != "" {
|
||||
// 正则删除整行
|
||||
imageTagRegex := regexp.MustCompile(`<p class="image-count">[\s\S]*?</p>`)
|
||||
//re := regexp.MustCompile(`<p class="image-count">需要配图:\d+ 张</p>`)
|
||||
cleanContent := imageTagRegex.ReplaceAllString(text, "")
|
||||
|
||||
// 写入清理后的文案
|
||||
htmlBuilder.WriteString(fmt.Sprintf(`<div class="text">%s</div>`, cleanContent))
|
||||
htmlBuilder.WriteString(fmt.Sprintf(`<div class="text">%s</div>`, ImageTagRegex(text)))
|
||||
}
|
||||
|
||||
htmlBuilder.WriteString(`</div>
|
||||
</div>
|
||||
</body>
|
||||
@@ -336,9 +354,7 @@ func BuildHtml(text string, images []string) string {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
#content {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -352,7 +368,6 @@ func BuildHtml(text string, images []string) string {
|
||||
}
|
||||
htmlBuilder.WriteString(`</div>`)
|
||||
}
|
||||
|
||||
htmlBuilder.WriteString(`
|
||||
<div id="content">加载中...</div>
|
||||
</div>
|
||||
@@ -365,7 +380,7 @@ func BuildHtml(text string, images []string) string {
|
||||
return res.text();
|
||||
})
|
||||
.then(text => {
|
||||
document.getElementById("content").textContent = text;
|
||||
document.getElementById("content").innerHTML = text;
|
||||
})
|
||||
.catch(err => {
|
||||
document.getElementById("content").innerHTML = "加载失败:" + err.message;
|
||||
@@ -377,25 +392,28 @@ func BuildHtml(text string, images []string) string {
|
||||
return htmlBuilder.String()
|
||||
}
|
||||
|
||||
// ExtractImageCount 从 HTML 内容里提取图片数量(例如从 <p class="image-count">需要配图:3 张</p> 拿到 3)
|
||||
// ExtractImageCount 修复:支持单引号/双引号 + 换行 + 空格
|
||||
func ExtractImageCount(content string) int {
|
||||
re := regexp.MustCompile(`<p class="image-count">[^\d]*(\d+)[^\d]*</p>`)
|
||||
// 🔥 关键:支持 class='image-count' (单引号)
|
||||
re := regexp.MustCompile(`<p class=['"]image-count['"][^>]*>.*?(\d+).*?</p>`)
|
||||
match := re.FindStringSubmatch(content)
|
||||
if len(match) >= 2 {
|
||||
num, _ := strconv.Atoi(match[1])
|
||||
return num
|
||||
num, err := strconv.Atoi(match[1])
|
||||
if err == nil {
|
||||
return num
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// StripHtmlTags 去掉所有HTML标签,保留换行和文本结构,并删除配图标记行
|
||||
func StripHtmlTags(html string, delImageCount bool) string {
|
||||
if delImageCount {
|
||||
// 🔥 第一步:直接删除整个 <p class="image-count">...</p> 标签(包含内容)
|
||||
imageTagRegex := regexp.MustCompile(`<p class="image-count">[\s\S]*?</p>`)
|
||||
html = imageTagRegex.ReplaceAllString(html, "")
|
||||
}
|
||||
func ImageTagRegex(html string) string {
|
||||
// 🔥 修复:支持单引号、双引号、空格、换行,100% 删除 <p class='image-count'>
|
||||
imageTagRegex := regexp.MustCompile(`<p class=['"]image-count['"][^>]*>[\s\S]*?</p>`)
|
||||
return imageTagRegex.ReplaceAllString(html, "")
|
||||
}
|
||||
|
||||
// StripHtmlTags 去掉所有HTML标签,保留换行和文本结构,并删除配图标记行
|
||||
func StripHtmlTags(html string) string {
|
||||
// 1. 替换块级标签为换行,保证排版
|
||||
blockTags := regexp.MustCompile(`</?(div|p|h1|h2|h3|h4|h5|h6|li|ul|ol|br|tr|td|th)[^>]*>`)
|
||||
text := blockTags.ReplaceAllString(html, "\n")
|
||||
@@ -434,3 +452,23 @@ func SplitMultiContents(htmlContent string) []string {
|
||||
}
|
||||
return contents
|
||||
}
|
||||
|
||||
// GetAllImgSrcFromHtml 先把提取img src的工具方法放在外面
|
||||
func GetAllImgSrcFromHtml(html string) []string {
|
||||
var imgSrcList []string
|
||||
re := regexp.MustCompile(`<img[^>]*src\s*=\s*["']([^"']+)["']`)
|
||||
matchs := re.FindAllStringSubmatch(html, -1)
|
||||
for _, match := range matchs {
|
||||
if len(match) >= 2 {
|
||||
imgSrcList = append(imgSrcList, match[1])
|
||||
}
|
||||
}
|
||||
return imgSrcList
|
||||
}
|
||||
|
||||
// ReplaceImgSrc 替换img src的方法
|
||||
func ReplaceImgSrc(html string, oldSrc string, newSrc string) string {
|
||||
// 精准替换:找到 <img xxx src="oldSrc" xxx> 并替换
|
||||
re := regexp.MustCompile(`(<img[^>]*src\s*=\s*["'])` + regexp.QuoteMeta(oldSrc) + `(["'])`)
|
||||
return re.ReplaceAllString(html, `${1}`+newSrc+`${2}`)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user