feat(wxpa): 配图提示词规则从 Go 硬编码迁移到 JSON 配置驱动
- 新增 spec/06-image_prompt_generation/rule.json 定义配图分布规则(500 字间隔、封面图、正文图尺寸)
- 新增 prompt_template、bracket_format 等 JSON 配置,支持中文提示词模板
- 修改 buildCoverImagePrompt/buildContentImagePrompt 使用 strings.ReplaceAll 替换 {index}/{section_summary} 占位符
- 修改 executeWeixinPublicAccountImagePromptStep 调用 buildWeixinPublicAccountImagePromptsV2
- 新增 buildWeixinPublicAccountContentWithPromptsFromJSON 包装 renderWeixinPublicAccountImagePromptFromJSON
- 前端产物 Tab 新增配图缩略图行展示
This commit is contained in:
+9
-4
@@ -27,8 +27,8 @@ type weixinPublicAccountSection struct {
|
||||
}
|
||||
|
||||
func executeWeixinPublicAccountImagePromptStep(workflow *weixinPublicAccountWorkflowState, article *weixinpublicaccountmodel.WeixinPublicAccountArticle, user *model.User, now time.Time) weixinPublicAccountStepExecution {
|
||||
prompts := buildWeixinPublicAccountImagePrompts(workflow)
|
||||
contentWithPrompts := buildWeixinPublicAccountContentWithPrompts(workflow.Shared.Content, prompts)
|
||||
prompts := buildWeixinPublicAccountImagePromptsV2(workflow)
|
||||
contentWithPrompts := buildWeixinPublicAccountContentWithPromptsFromJSON(workflow.Shared.Content, prompts)
|
||||
workflow.Shared.ContentWithPrompts = contentWithPrompts
|
||||
workflow.Shared.ImagePrompts = prompts
|
||||
|
||||
@@ -55,9 +55,9 @@ func executeWeixinPublicAccountImagePromptStep(workflow *weixinPublicAccountWork
|
||||
func executeWeixinPublicAccountImageGenerationStep(workflow *weixinPublicAccountWorkflowState, article *weixinpublicaccountmodel.WeixinPublicAccountArticle, user *model.User, now time.Time) (weixinPublicAccountStepExecution, *web.AppError) {
|
||||
prompts := workflow.Shared.ImagePrompts
|
||||
if len(prompts) == 0 {
|
||||
prompts = buildWeixinPublicAccountImagePrompts(workflow)
|
||||
prompts = buildWeixinPublicAccountImagePromptsV2(workflow)
|
||||
workflow.Shared.ImagePrompts = prompts
|
||||
workflow.Shared.ContentWithPrompts = buildWeixinPublicAccountContentWithPrompts(workflow.Shared.Content, prompts)
|
||||
workflow.Shared.ContentWithPrompts = buildWeixinPublicAccountContentWithPromptsFromJSON(workflow.Shared.Content, prompts)
|
||||
}
|
||||
aiRoute, refs, appErr := generateWeixinPublicAccountImages(article.TaskID, workflow, prompts, user)
|
||||
if appErr != nil {
|
||||
@@ -181,6 +181,11 @@ func buildWeixinPublicAccountContentWithPrompts(content string, prompts []weixin
|
||||
return strings.Join(blocks, "\n")
|
||||
}
|
||||
|
||||
// buildWeixinPublicAccountContentWithPromptsFromJSON 基于 JSON 配置渲染带括号标记的正文。
|
||||
func buildWeixinPublicAccountContentWithPromptsFromJSON(content string, prompts []weixinPublicAccountImagePrompt) string {
|
||||
return renderWeixinPublicAccountImagePromptFromJSON(content, prompts)
|
||||
}
|
||||
|
||||
func buildWeixinPublicAccountVisualPrompt(workflow *weixinPublicAccountWorkflowState, sectionTitle, context string) string {
|
||||
keyword := firstNonEmpty(workflow.Form.Keyword, "业务主题")
|
||||
tone := firstNonEmpty(workflow.Form.Tone, "专业但好懂")
|
||||
|
||||
+23
-19
@@ -217,18 +217,20 @@ func buildWeixinPublicAccountImagePromptsV2(workflow *weixinPublicAccountWorkflo
|
||||
func buildCoverImagePrompt(workflow *weixinPublicAccountWorkflowState, rule *imagePromptRule) string {
|
||||
title := firstNonEmpty(workflow.Shared.SelectedTitle, workflow.Form.Keyword, "公众号文章")
|
||||
|
||||
// 从 JSON 模板构建(当前回退到硬编码模板)
|
||||
// 从 JSON 模板构建
|
||||
template := rule.Template.Template
|
||||
if template == "" {
|
||||
// 回退到当前硬编码的英文模板
|
||||
return fmt.Sprintf("realistic editorial illustration, Chinese business article cover, %s, focus on %s, %s, clean composition, natural lighting, brand-safe, no text, no watermark",
|
||||
weixinPublicAccountBusinessDomainLabel(workflow.Form.BusinessDomain),
|
||||
title,
|
||||
"公众号封面主视觉",
|
||||
)
|
||||
if template != "" {
|
||||
// 使用字符串替换,而非 fmt.Sprintf
|
||||
prompt := strings.ReplaceAll(template, "{index}", "1")
|
||||
prompt = strings.ReplaceAll(prompt, "{section_summary}", fmt.Sprintf("%s(截断至120字)", title))
|
||||
return prompt
|
||||
}
|
||||
|
||||
return fmt.Sprintf(template, 1, title, fmt.Sprintf("%s(截断至120字)", title))
|
||||
// 回退到硬编码模板
|
||||
return fmt.Sprintf("realistic editorial illustration, Chinese business article cover, %s, focus on %s, %s, clean composition, natural lighting, brand-safe, no text, no watermark",
|
||||
weixinPublicAccountBusinessDomainLabel(workflow.Form.BusinessDomain),
|
||||
title,
|
||||
"公众号封面主视觉",
|
||||
)
|
||||
}
|
||||
|
||||
// buildContentImagePrompt 生成正文配图提示词。
|
||||
@@ -237,16 +239,18 @@ func buildContentImagePrompt(workflow *weixinPublicAccountWorkflowState, section
|
||||
|
||||
// 从 JSON 模板构建
|
||||
template := rule.Template.Template
|
||||
if template == "" {
|
||||
// 回退到当前硬编码的英文模板
|
||||
return fmt.Sprintf("realistic editorial illustration, Chinese business article cover, %s, focus on %s, %s, clean composition, natural lighting, brand-safe, no text, no watermark",
|
||||
weixinPublicAccountBusinessDomainLabel(workflow.Form.BusinessDomain),
|
||||
firstNonEmpty(section.Title, workflow.Form.Keyword),
|
||||
firstNonEmpty(summary, workflow.Form.Tone),
|
||||
)
|
||||
if template != "" {
|
||||
// 使用字符串替换,而非 fmt.Sprintf
|
||||
prompt := strings.ReplaceAll(template, "{index}", fmt.Sprintf("%d", index))
|
||||
prompt = strings.ReplaceAll(prompt, "{section_summary}", summary)
|
||||
return prompt
|
||||
}
|
||||
|
||||
return fmt.Sprintf(template, index, firstNonEmpty(section.Title, workflow.Form.Keyword), summary)
|
||||
// 回退到硬编码模板
|
||||
return fmt.Sprintf("realistic editorial illustration, Chinese business article cover, %s, focus on %s, %s, clean composition, natural lighting, brand-safe, no text, no watermark",
|
||||
weixinPublicAccountBusinessDomainLabel(workflow.Form.BusinessDomain),
|
||||
firstNonEmpty(section.Title, workflow.Form.Keyword),
|
||||
firstNonEmpty(summary, workflow.Form.Tone),
|
||||
)
|
||||
}
|
||||
|
||||
// countChineseWords 计算内容的中文字数。
|
||||
|
||||
+1
-1
@@ -792,7 +792,7 @@ func respondWeixinPublicAccountWorkflow(c *gin.Context, task model.TaskRecord) {
|
||||
func findWeixinPublicAccountImagePrompt(workflow weixinPublicAccountWorkflowState, imageKey string) (weixinPublicAccountImagePrompt, int, bool) {
|
||||
prompts := workflow.Shared.ImagePrompts
|
||||
if len(prompts) == 0 {
|
||||
prompts = buildWeixinPublicAccountImagePrompts(&workflow)
|
||||
prompts = buildWeixinPublicAccountImagePromptsV2(&workflow)
|
||||
workflow.Shared.ImagePrompts = prompts
|
||||
}
|
||||
for idx, item := range prompts {
|
||||
|
||||
Reference in New Issue
Block a user