Files
geo/server/internal/tenant/app/knowledge_prompt_test.go
T
root 63abe403c0 feat(knowledge): broaden context resolution and prompt query
- Walk knowledge group children recursively so selecting a parent group
  pulls snippets from its descendants too.
- Filter knowledge items to status='completed' across the prompt and
  active-snippet queries to avoid leaking in-progress documents.
- Dedupe vector candidates by point id and normalized text, then pick
  rerank+vector results with a per-item cap so prompts stay diverse.
- Tag each rendered snippet with a [Kn] reference id for prompt citing.
- Build the rule knowledge query from task params (title/keywords/etc.)
  before falling back to rule prompt content so retrieval matches the
  user's actual ask.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:02:37 +08:00

165 lines
4.9 KiB
Go

package app
import (
"strings"
"testing"
"github.com/geo-platform/tenant-api/internal/shared/retrieval"
)
func TestExtractKnowledgePreciseFactsKeepsAddressAndContactLines(t *testing.T) {
facts := extractKnowledgePreciseFacts(`
# 合肥门店
地址:合肥市蜀山区望江西路 123 号 A 座 8 层
电话:0551-12345678
官网:https://example.com/store
普通介绍段落
`)
for _, expected := range []string{
"地址:合肥市蜀山区望江西路 123 号 A 座 8 层",
"电话:0551-12345678",
"官网:https://example.com/store",
} {
if !containsExactString(facts, expected) {
t.Fatalf("extractKnowledgePreciseFacts() = %#v, want %q", facts, expected)
}
}
}
func TestRenderPromptSectionIncludesPreciseFactsAndSourceURI(t *testing.T) {
sourceURI := "https://example.com/store"
output := (&KnowledgeService{}).RenderPromptSection(&KnowledgeContext{
Snippets: []KnowledgeSnippet{
{
GroupName: "门店信息",
ItemName: "合肥门店",
SourceURI: &sourceURI,
Text: "这里是一段门店介绍。",
PreciseFacts: []string{"地址:合肥市蜀山区望江西路 123 号", "电话:0551-12345678"},
},
},
})
for _, expected := range []string{
"以下为必须严格按原文保留的高精度事实",
"- 门店信息 / 合肥门店:地址:合肥市蜀山区望江西路 123 号",
"1. [K1] 门店信息 / 合肥门店",
"来源链接: https://example.com/store",
"这里是一段门店介绍。",
} {
if !strings.Contains(output, expected) {
t.Fatalf("RenderPromptSection() = %q, want %q", output, expected)
}
}
}
func TestRenderPromptSectionSupportsPreciseFactsWithoutSnippets(t *testing.T) {
output := (&KnowledgeService{}).RenderPromptSection(&KnowledgeContext{
PreciseFacts: []string{
"公司资料 / 合肥门店:地址:合肥市蜀山区望江西路 123 号",
"公司资料 / 合肥门店:主营业务:全屋定制;橱柜定制",
},
})
for _, expected := range []string{
"以下为必须严格按原文保留的高精度事实",
"- 公司资料 / 合肥门店:地址:合肥市蜀山区望江西路 123 号",
"- 公司资料 / 合肥门店:主营业务:全屋定制;橱柜定制",
} {
if !strings.Contains(output, expected) {
t.Fatalf("RenderPromptSection() = %q, want %q", output, expected)
}
}
}
func TestExtractKnowledgePreciseFactsKeepsBusinessScopeSection(t *testing.T) {
facts := extractKnowledgePreciseFacts(`
# 公司介绍
主营业务
- 全屋定制
- 橱柜定制
- 木门与护墙系统
地址:合肥市蜀山区望江西路 123 号
`)
for _, expected := range []string{
"主营业务:全屋定制;橱柜定制;木门与护墙系统",
"地址:合肥市蜀山区望江西路 123 号",
} {
if !containsExactString(facts, expected) {
t.Fatalf("extractKnowledgePreciseFacts() = %#v, want %q", facts, expected)
}
}
}
func TestKnowledgeSnippetsFromSearchPointsSkipsMissingTextAndDedupes(t *testing.T) {
snippets := dedupeKnowledgeSearchCandidates(knowledgeSnippetsFromSearchPoints([]retrieval.SearchPoint{
{
ID: "point-1",
Score: 0.91,
Payload: map[string]any{
"group_id": int64(10),
"group_name": "产品资料",
"item_id": int64(100),
"item_name": "旗舰款",
"text": " 支持全屋定制方案 ",
},
},
{
ID: "point-2",
Payload: map[string]any{
"text": "支持全屋定制方案",
},
},
{
ID: "point-3",
Payload: map[string]any{},
},
}))
if len(snippets) != 1 {
t.Fatalf("deduped snippets length = %d, want 1: %#v", len(snippets), snippets)
}
if snippets[0].Text != "支持全屋定制方案" {
t.Fatalf("snippet text = %q, want trimmed text", snippets[0].Text)
}
}
func TestSelectKnowledgeRerankedSnippetsFillsAndDiversifiesResults(t *testing.T) {
candidates := []KnowledgeSnippet{
{PointID: "p1", KnowledgeItemID: 1, Text: "同一文档片段 1", Score: 0.90},
{PointID: "p2", KnowledgeItemID: 1, Text: "同一文档片段 2", Score: 0.89},
{PointID: "p3", KnowledgeItemID: 1, Text: "同一文档片段 3", Score: 0.88},
{PointID: "p4", KnowledgeItemID: 2, Text: "第二文档片段", Score: 0.80},
{PointID: "p5", KnowledgeItemID: 3, Text: "第三文档片段", Score: 0.70},
}
selected := selectKnowledgeRerankedSnippets(candidates, []retrieval.RerankResult{
{Index: 2, RelevanceScore: 0.99},
{Index: 99, RelevanceScore: 1},
}, 4)
if len(selected) != 4 {
t.Fatalf("selected length = %d, want 4: %#v", len(selected), selected)
}
if selected[0].PointID != "p3" || selected[0].Score != 0.99 {
t.Fatalf("selected[0] = %#v, want reranked p3 with rerank score", selected[0])
}
if selected[1].PointID != "p1" || selected[2].PointID != "p4" || selected[3].PointID != "p5" {
t.Fatalf("selected order = %#v, want reranked result filled with diverse vector candidates", selected)
}
}
func containsExactString(items []string, target string) bool {
for _, item := range items {
if item == target {
return true
}
}
return false
}