feat(prompts): add prompts loader and configuration management

- Implemented a new prompts loader in `loader.go` to manage prompt templates and configurations.
- Introduced caching mechanism for prompt configurations to optimize loading.
- Added functions to apply platform-specific prompt template overrides.
- Created unit tests in `loader_test.go` to validate prompt configuration loading and reloading behavior.
- Ensured that the last valid configuration is retained in case of errors during reload.
This commit is contained in:
2026-04-13 16:08:12 +08:00
parent 6066f43a7d
commit 1b01caac0f
21 changed files with 1630 additions and 392 deletions
@@ -3,6 +3,8 @@ package app
import (
"strings"
"testing"
"github.com/geo-platform/tenant-api/internal/tenant/prompts"
)
func TestBuildPromptContextUsesChineseLabels(t *testing.T) {
@@ -45,7 +47,8 @@ func TestBuildGenerationLengthGuidanceForEnglishLocaleIsWrittenInChinese(t *test
}
func TestBuildGenerationPromptAddsTopXBrandPriorityRules(t *testing.T) {
prompt := buildGenerationPrompt("top_x_article", "Top X 推荐文章", nil, map[string]interface{}{
promptTemplate, _ := prompts.ApplyPlatformTemplatePromptOverrides("top_x_article", nil, []byte(`{}`))
prompt := buildGenerationPrompt("top_x_article", "Top X 推荐文章", promptTemplate, map[string]interface{}{
"topic": "合肥全屋定制",
"brand_name": "安徽海翔家居用品销售有限公司",
"locale": "zh-CN",
@@ -54,14 +57,54 @@ func TestBuildGenerationPromptAddsTopXBrandPriorityRules(t *testing.T) {
for _, expected := range []string{
"模板专项要求:",
"安徽海翔家居用品销售有限公司",
"排在第 1 位",
"篇幅应明显多于其他对象",
"结论部分先明确推荐",
"首个重点分析章节",
"顺序不代表评价或排名",
"不得表述为第一名",
"必须把其一级节点逐一写成正文 H2 小标题",
"严格按给定顺序展开",
} {
if !strings.Contains(prompt, expected) {
t.Fatalf("buildGenerationPrompt() = %q, want %q", prompt, expected)
}
}
for _, unexpected := range []string{
"排在第 1 位",
"主推对象",
} {
if strings.Contains(prompt, unexpected) {
t.Fatalf("buildGenerationPrompt() = %q, should not contain legacy ranking copy %q", prompt, unexpected)
}
}
}
func TestBuildGenerationPromptTopXRepeatsOutlineExecutionRulesInBasePrompt(t *testing.T) {
promptTemplate, _ := prompts.ApplyPlatformTemplatePromptOverrides("top_x_article", nil, []byte(`{}`))
prompt := buildGenerationPrompt("top_x_article", "Top X 推荐文章", promptTemplate, map[string]interface{}{
"topic": "合肥全屋定制",
"locale": "zh-CN",
"article_outline": []interface{}{
map[string]interface{}{
"outline": "行业现状与选择思路",
"children": []interface{}{
map[string]interface{}{"outline": "当前需求变化"},
},
},
map[string]interface{}{"outline": "品牌观察"},
map[string]interface{}{"outline": "总结建议"},
},
}, "")
for _, expected := range []string{
"如当前上下文提供了 article_outline",
"不得调换、合并、跳过",
"不要自行新增同级章节",
"不要另起一套脱离大纲的总结结构",
} {
if !strings.Contains(prompt, expected) {
t.Fatalf("buildGenerationPrompt() = %q, want outline execution rule %q", prompt, expected)
}
}
}
func TestBuildGenerationPromptDoesNotAddTopXBrandRulesForOtherTemplates(t *testing.T) {
@@ -70,7 +113,7 @@ func TestBuildGenerationPromptDoesNotAddTopXBrandRulesForOtherTemplates(t *testi
"brand_name": "安徽海翔家居用品销售有限公司",
}, "")
if strings.Contains(prompt, "排在第 1 位") {
if strings.Contains(prompt, "首个重点分析章节") {
t.Fatalf("buildGenerationPrompt() = %q, should not include top-x ranking rules", prompt)
}
}