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{ "group_id": int64(10), "group_name": "产品资料", "item_id": int64(100), "item_name": "旗舰款", "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 TestKnowledgeSearchTextIncludesMetadataForRetrieval(t *testing.T) { got := buildKnowledgeSearchText(knowledgeSearchTextInput{ GroupName: "产品资料", ItemName: "旗舰款", SourceType: "website", SourceURI: "https://example.com/product", Text: "支持全屋定制方案", }) for _, expected := range []string{ "目录: 产品资料", "标题: 旗舰款", "来源类型: website", "来源链接: https://example.com/product", "内容:\n支持全屋定制方案", } { if !strings.Contains(got, expected) { t.Fatalf("buildKnowledgeSearchText() = %q, want %q", got, expected) } } } func TestKnowledgeSnippetsFromSearchPointsKeepsSearchTextForRerank(t *testing.T) { snippets := 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": "旗舰款", "source_type": "website", "source_uri": "https://example.com/product", "text": "支持全屋定制方案", "search_text": "目录: 产品资料\n标题: 旗舰款\n内容:\n支持全屋定制方案", }, }, }) if len(snippets) != 1 { t.Fatalf("snippets length = %d, want 1", len(snippets)) } if snippets[0].Text != "支持全屋定制方案" { t.Fatalf("Text = %q, want original chunk text", snippets[0].Text) } if snippets[0].RerankText() != "目录: 产品资料\n标题: 旗舰款\n内容:\n支持全屋定制方案" { t.Fatalf("RerankText() = %q, want search text", snippets[0].RerankText()) } if snippets[0].SourceURI == nil || *snippets[0].SourceURI != "https://example.com/product" { t.Fatalf("SourceURI = %#v, want payload source uri", snippets[0].SourceURI) } } func TestDedupeKnowledgeSearchCandidatesUsesMetadataAwareSearchText(t *testing.T) { candidates := []KnowledgeSnippet{ { PointID: "p1", KnowledgeItemID: 1, ItemName: "A 款", Text: "支持全屋定制方案", SearchText: "标题: A 款\n内容:\n支持全屋定制方案", }, { PointID: "p2", KnowledgeItemID: 2, ItemName: "B 款", Text: "支持全屋定制方案", SearchText: "标题: B 款\n内容:\n支持全屋定制方案", }, } deduped := dedupeKnowledgeSearchCandidates(candidates) if len(deduped) != 2 { t.Fatalf("deduped length = %d, want 2: %#v", len(deduped), deduped) } } 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 TestSelectKnowledgeRerankedSnippetsKeepsOriginalChunkText(t *testing.T) { candidates := []KnowledgeSnippet{ { PointID: "p1", KnowledgeItemID: 1, Text: "原始正文片段", SearchText: "目录: 产品资料\n标题: 旗舰款\n内容:\n原始正文片段", Score: 0.90, }, } selected := selectKnowledgeRerankedSnippets(candidates, []retrieval.RerankResult{ { Index: 0, RelevanceScore: 0.99, Text: "目录: 产品资料\n标题: 旗舰款\n内容:\n原始正文片段", }, }, 1) if len(selected) != 1 { t.Fatalf("selected length = %d, want 1", len(selected)) } if selected[0].Text != "原始正文片段" { t.Fatalf("selected text = %q, want original chunk text", selected[0].Text) } if selected[0].Score != 0.99 { t.Fatalf("selected score = %v, want rerank score", selected[0].Score) } } func containsExactString(items []string, target string) bool { for _, item := range items { if item == target { return true } } return false }