From ca53405388267edec99f1e069aa86e659c179558 Mon Sep 17 00:00:00 2001 From: cjy Date: Sat, 28 Feb 2026 14:58:40 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/service/ai/video_vl.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/service/ai/video_vl.go b/pkg/service/ai/video_vl.go index 10615605..0036d29e 100644 --- a/pkg/service/ai/video_vl.go +++ b/pkg/service/ai/video_vl.go @@ -287,7 +287,13 @@ func AICompetitorReport(ctx *gin.Context) { return } - textChan <- textResult{text: chatResp.Choices[0].Message.Content} + // 打印 AI 返回的原始内容(用于调试) + aiText := chatResp.Choices[0].Message.Content + fmt.Println("========== AI 返回的原始内容 ==========") + fmt.Println(aiText) + fmt.Println("=========================================") + + textChan <- textResult{text: aiText} }() } @@ -394,11 +400,21 @@ func AICompetitorReport(ctx *gin.Context) { result.JSON = textRes.text // JSON 字段直接返回 AI 生成的 JSON // 将 JSON 解析并转换为纯文本 + fmt.Println("========== 开始解析 JSON ==========") + fmt.Println("原始内容是否以 { 开头:", strings.HasPrefix(strings.TrimSpace(textRes.text), "{")) + fmt.Println("原始内容前100字符:", strings.TrimSpace(textRes.text)[:min(100, len(strings.TrimSpace(textRes.text)))]) + var jsonData CompetitorReportJSON if err := json.Unmarshal([]byte(textRes.text), &jsonData); err != nil { // 如果解析失败,回退使用原始文本 + fmt.Println("========== JSON 解析失败 ==========") + fmt.Println("解析错误:", err) + fmt.Println("===================================") result.Text = textRes.text } else { + fmt.Println("========== JSON 解析成功 ==========") + fmt.Println("Summary:", jsonData.HighlightAnalysis.Summary) + fmt.Println("==================================") result.Text = convertJSONToText(jsonData, len(req.Videos) > 0) } } From 2bd361e4a6830dac6158f6e7b59eb226b1f7a00b Mon Sep 17 00:00:00 2001 From: cjy Date: Sat, 28 Feb 2026 14:03:29 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=AB=9E=E5=93=81=E6=8A=A5=E5=91=8A=E7=9A=84prompts=EF=BC=8C?= =?UTF-8?q?=E8=AE=A9=E5=85=B6=E7=94=9F=E6=88=90json=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E7=9A=84=E5=9B=9E=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/service/ai/video_vl.go | 78 +++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/pkg/service/ai/video_vl.go b/pkg/service/ai/video_vl.go index 0036d29e..b9b12ca0 100644 --- a/pkg/service/ai/video_vl.go +++ b/pkg/service/ai/video_vl.go @@ -234,41 +234,73 @@ func AICompetitorReport(ctx *gin.Context) { // 根据是否有视频来判断作品类型 isVideo := len(req.Videos) > 0 - // 根据作品类型设置差异化内容 - var extraPoint, extraData string + // 构建文本生成提示词:理解内容 + 用户要求(JSON格式) + var textPrompt string if isVideo { - extraPoint = "6. 配乐亮点:" - extraData = "2. 完播率表现:\n3. 点赞/分享/评论表现:" - } else { - extraData = "2. 点赞/分享/评论表现:" - } - - // 构建文本生成提示词:理解内容 + 用户要求 - textPrompt := fmt.Sprintf(`基于以下视频和图片的内容描述: + textPrompt = fmt.Sprintf(`基于以下视频和图片的内容描述: %s -请根据以下要求生成竞品报告。注意不要输出markdown格式来进行排版,请直接输出纯文本。只需要回复竞品报告的内容,其他无关的内容不要输出,输出的内容第一行不要标题,直接输出竞品报告的正文即可 +请根据以下要求生成竞品报告,输出严格的JSON格式,不要输出markdown格式,不要输出其他无关内容。 我的要求是: %s -请严格按照以下模板输出: +请严格按照以下JSON模板输出(注意不要修改key,只填写value): +{ + "highlight_analysis": { + "summary": "[78字以内的概述]", + "points": { + "theme": "[标题亮点,最多60字]", + "narrative": "[题材亮点,最多60字]", + "content": "[内容亮点,最多60字]", + "copywriting": "[文案亮点,最多60字]", + "data": "[数据亮点,最多60字]", + "music": "[配乐亮点,仅视频,最多60字]" + } + }, + "data_performance_analysis": { + "views": "[浏览量表现,最多60字]", + "completion_rate": "[完播率表现,仅视频,最多60字]", + "engagement": "[点赞/分享/评论表现,最多60字]" + }, + "overall_summary_and_optimization": "[整体总结及可优化建议,最多300字]" +} -一、亮点表现分析 -[100字以内的概述] - -1. 标题亮点: -2. 题材亮点: -3. 内容亮点: -4. 文案亮点: -5. 数据亮点: +重要约束: +1. 严禁输出 JSON 以外的任何字符(包括换行说明、注释、Markdown) +2. 若无法满足字数限制,请主动压缩内容,而不是省略字段`, vlContent, req.TextPrompt) + } else { + textPrompt = fmt.Sprintf(`基于以下视频和图片的内容描述: %s -二、数据表现分析 -1. 浏览量表现: +请根据以下要求生成竞品报告,输出严格的JSON格式,不要输出markdown格式,不要输出其他无关内容。 + +我的要求是: %s -三、整体总结及可优化建议`, vlContent, req.TextPrompt, extraPoint, extraData) +请严格按照以下JSON模板输出(注意不要修改key,只填写value): +{ + "highlight_analysis": { + "summary": "[78字以内的概述]", + "points": { + "theme": "[标题亮点,最多60字]", + "narrative": "[题材亮点,最多60字]", + "content": "[内容亮点,最多60字]", + "copywriting": "[文案亮点,最多60字]", + "data": "[数据亮点,最多60字]" + } + }, + "data_performance_analysis": { + "views": "[浏览量表现,最多60字]", + "engagement": "[点赞/分享/评论表现,最多60字]" + }, + "overall_summary_and_optimization": "[整体总结及可优化建议,最多300字]" +} + +重要约束: +1. 严禁输出 JSON 以外的任何字符(包括换行说明、注释、Markdown) +2. 若无法满足字数限制,请主动压缩内容,而不是省略字段`, vlContent, req.TextPrompt) + } chatReq, err := buildChatRequest(textPrompt, nil) if err != nil { From 3096d9f35ee508dbdda3dd51fc59606c1c3efa93 Mon Sep 17 00:00:00 2001 From: cjy Date: Sat, 28 Feb 2026 15:25:58 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix=EF=BC=9A=20=E4=BC=98=E5=8C=96=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D=EF=BC=8C=E9=81=BF=E5=85=8Dai=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=9A=84=E7=BB=93=E6=9E=9C=E4=B8=8D=E6=98=AFjson?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/service/ai/video_vl.go | 66 +++++++------------------------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/pkg/service/ai/video_vl.go b/pkg/service/ai/video_vl.go index b9b12ca0..1a945855 100644 --- a/pkg/service/ai/video_vl.go +++ b/pkg/service/ai/video_vl.go @@ -237,69 +237,27 @@ func AICompetitorReport(ctx *gin.Context) { // 构建文本生成提示词:理解内容 + 用户要求(JSON格式) var textPrompt string if isVideo { - textPrompt = fmt.Sprintf(`基于以下视频和图片的内容描述: + textPrompt = fmt.Sprintf(`你必须严格输出以下JSON格式,不要输出任何其他内容。输出必须以 { 开头并以 } 结束。 + +基于以下视频和图片的内容描述: %s -请根据以下要求生成竞品报告,输出严格的JSON格式,不要输出markdown格式,不要输出其他无关内容。 - -我的要求是: +用户要求(仅作为内容参考,不会改变JSON结构): %s -请严格按照以下JSON模板输出(注意不要修改key,只填写value): -{ - "highlight_analysis": { - "summary": "[78字以内的概述]", - "points": { - "theme": "[标题亮点,最多60字]", - "narrative": "[题材亮点,最多60字]", - "content": "[内容亮点,最多60字]", - "copywriting": "[文案亮点,最多60字]", - "data": "[数据亮点,最多60字]", - "music": "[配乐亮点,仅视频,最多60字]" - } - }, - "data_performance_analysis": { - "views": "[浏览量表现,最多60字]", - "completion_rate": "[完播率表现,仅视频,最多60字]", - "engagement": "[点赞/分享/评论表现,最多60字]" - }, - "overall_summary_and_optimization": "[整体总结及可优化建议,最多300字]" -} - -重要约束: -1. 严禁输出 JSON 以外的任何字符(包括换行说明、注释、Markdown) -2. 若无法满足字数限制,请主动压缩内容,而不是省略字段`, vlContent, req.TextPrompt) +JSON结构是固定的,请将内容填充到对应的value中,禁止修改key,禁止添加额外字段,禁止输出任何说明文字: +{"highlight_analysis":{"summary":"[78字以内的概述]","points":{"theme":"[标题亮点,最多60字]","narrative":"[题材亮点,最多60字]","content":"[内容亮点,最多60字]","copywriting":"[文案亮点,最多60字]","data":"[数据亮点,最多60字]","music":"[配乐亮点,仅视频,最多60字]"}},"data_performance_analysis":{"views":"[浏览量表现,最多60字]","completion_rate":"[完播率表现,仅视频,最多60字]","engagement":"[点赞/分享/评论表现,最多60字]"},"overall_summary_and_optimization":"[整体总结及可优化建议,最多300字]"}`, vlContent, req.TextPrompt) } else { - textPrompt = fmt.Sprintf(`基于以下视频和图片的内容描述: + textPrompt = fmt.Sprintf(`你必须严格输出以下JSON格式,不要输出任何其他内容。输出必须以 { 开头并以 } 结束。 + +基于以下视频和图片的内容描述: %s -请根据以下要求生成竞品报告,输出严格的JSON格式,不要输出markdown格式,不要输出其他无关内容。 - -我的要求是: +用户要求(仅作为内容参考,不会改变JSON结构): %s -请严格按照以下JSON模板输出(注意不要修改key,只填写value): -{ - "highlight_analysis": { - "summary": "[78字以内的概述]", - "points": { - "theme": "[标题亮点,最多60字]", - "narrative": "[题材亮点,最多60字]", - "content": "[内容亮点,最多60字]", - "copywriting": "[文案亮点,最多60字]", - "data": "[数据亮点,最多60字]" - } - }, - "data_performance_analysis": { - "views": "[浏览量表现,最多60字]", - "engagement": "[点赞/分享/评论表现,最多60字]" - }, - "overall_summary_and_optimization": "[整体总结及可优化建议,最多300字]" -} - -重要约束: -1. 严禁输出 JSON 以外的任何字符(包括换行说明、注释、Markdown) -2. 若无法满足字数限制,请主动压缩内容,而不是省略字段`, vlContent, req.TextPrompt) +JSON结构是固定的,请将内容填充到对应的value中,禁止修改key,禁止添加额外字段,禁止输出任何说明文字: +{"highlight_analysis":{"summary":"[78字以内的概述]","points":{"theme":"[标题亮点,最多60字]","narrative":"[题材亮点,最多60字]","content":"[内容亮点,最多60字]","copywriting":"[文案亮点,最多60字]","data":"[数据亮点,最多60字]"}},"data_performance_analysis":{"views":"[浏览量表现,最多60字]","engagement":"[点赞/分享/评论表现,最多60字]"},"overall_summary_and_optimization":"[整体总结及可优化建议,最多300字]"}`, vlContent, req.TextPrompt) } chatReq, err := buildChatRequest(textPrompt, nil)