Files
geo/server/internal/tenant/app/knowledge_query_test.go
T

142 lines
5.5 KiB
Go
Raw Normal View History

package app
import (
"context"
"errors"
"strings"
"testing"
"github.com/geo-platform/tenant-api/internal/shared/llm"
)
func TestBuildGenerationKnowledgeQueryIncludesContextAndFallbackQuestions(t *testing.T) {
query := buildGenerationKnowledgeQuery("top_x_article", "Top X 推荐文章", map[string]interface{}{
"topic": "合肥全屋定制",
"brand_name": "安徽海翔家居",
"region": "合肥",
"primary_keyword": "合肥定制家具",
"supplemental_questions": []string{"合肥家具品牌怎么选", "全屋定制避坑"},
"key_points": "突出门店与服务能力",
})
for _, expected := range []string{
"文章类型:推荐榜文章",
"模板名称:Top X 推荐文章",
"主题:合肥全屋定制",
"品牌:安徽海翔家居",
"地域:合肥",
"主关键词:合肥定制家具",
"兜底检索问题:",
} {
if !strings.Contains(query, expected) {
t.Fatalf("buildGenerationKnowledgeQuery() = %q, want %q", query, expected)
}
}
questions := normalizeKnowledgeResolveQueries(query)
if len(questions) != maxKnowledgeQueryQuestions {
t.Fatalf("normalizeKnowledgeResolveQueries() len = %d, want %d: %#v", len(questions), maxKnowledgeQueryQuestions, questions)
}
for _, question := range questions {
if !strings.HasSuffix(question, "") {
t.Fatalf("question = %q, want Chinese question mark", question)
}
}
}
func TestParseKnowledgeQueryRewriteOutputAcceptsObjectAndArray(t *testing.T) {
objectQuestions := parseKnowledgeQueryRewriteOutput(`{"questions":["安徽海翔家居在合肥有哪些门店和联系方式?","安徽海翔家居主营哪些全屋定制产品和服务?","合肥全屋定制用户选择时关注哪些案例和售后?"]}`)
if len(objectQuestions) != maxKnowledgeQueryQuestions {
t.Fatalf("object questions len = %d, want %d: %#v", len(objectQuestions), maxKnowledgeQueryQuestions, objectQuestions)
}
if objectQuestions[0] != "安徽海翔家居在合肥有哪些门店和联系方式?" {
t.Fatalf("first object question = %q", objectQuestions[0])
}
arrayQuestions := parseKnowledgeQueryRewriteOutput(`["安徽海翔家居有什么品牌优势?","合肥全屋定制有哪些案例可引用?","全屋定制选型需要哪些避坑信息?"]`)
if len(arrayQuestions) != maxKnowledgeQueryQuestions {
t.Fatalf("array questions len = %d, want %d: %#v", len(arrayQuestions), maxKnowledgeQueryQuestions, arrayQuestions)
}
}
func TestNormalizeKnowledgeResolveQueriesPrefersFallbackQuestionBlock(t *testing.T) {
query := strings.Join([]string{
"文章类型:推荐榜文章",
"主题:合肥全屋定制",
"品牌:安徽海翔家居",
"重点要求:",
"请突出本地服务",
"不要写成硬广",
"兜底检索问题:",
"- 安徽海翔家居在合肥有哪些门店和联系方式?",
"- 安徽海翔家居主营哪些全屋定制产品和服务?",
"- 合肥全屋定制用户选择时关注哪些案例和售后?",
}, "\n")
got := normalizeKnowledgeResolveQueries(query)
want := []string{
"安徽海翔家居在合肥有哪些门店和联系方式?",
"安徽海翔家居主营哪些全屋定制产品和服务?",
"合肥全屋定制用户选择时关注哪些案例和售后?",
}
if len(got) != len(want) {
t.Fatalf("normalizeKnowledgeResolveQueries() = %#v, want %#v", got, want)
}
for index := range want {
if got[index] != want[index] {
t.Fatalf("normalizeKnowledgeResolveQueries()[%d] = %q, want %q", index, got[index], want[index])
}
}
}
func TestRewriteKnowledgeResolveQueriesUsesKnowledgeURLModelAndJSONObject(t *testing.T) {
client := &fakeKnowledgeQueryLLM{
content: `{"questions":["安徽海翔家居在合肥有哪些门店和联系方式?","安徽海翔家居主营哪些全屋定制产品和服务?","合肥全屋定制用户选择时关注哪些案例和售后?"]}`,
}
svc := &KnowledgeService{
llmClient: client,
cfg: knowledgeRuntimeConfig{URLMarkdownModel: "knowledge-url-fast"},
}
questions, err := svc.rewriteKnowledgeResolveQueries(context.Background(), "品牌:安徽海翔家居\n地域:合肥")
if err != nil {
t.Fatalf("rewriteKnowledgeResolveQueries() error = %v", err)
}
if len(questions) != maxKnowledgeQueryQuestions {
t.Fatalf("questions len = %d, want %d: %#v", len(questions), maxKnowledgeQueryQuestions, questions)
}
if client.request.Model != "knowledge-url-fast" {
t.Fatalf("Generate model = %q, want knowledge-url-fast", client.request.Model)
}
if client.request.ResponseFormat == nil || client.request.ResponseFormat.Type != llm.ResponseFormatTypeJSONObject {
t.Fatalf("ResponseFormat = %#v, want json_object", client.request.ResponseFormat)
}
if !strings.Contains(client.request.Prompt, "品牌:安徽海翔家居") || !strings.Contains(client.request.Prompt, "必须输出 3 个问题") {
t.Fatalf("Prompt = %q, want raw user input and three-question instruction", client.request.Prompt)
}
}
type fakeKnowledgeQueryLLM struct {
request llm.GenerateRequest
content string
err error
}
func (f *fakeKnowledgeQueryLLM) Validate() error {
if f.err != nil {
return f.err
}
return nil
}
func (f *fakeKnowledgeQueryLLM) Generate(_ context.Context, req llm.GenerateRequest, _ func(string)) (*llm.GenerateResult, error) {
f.request = req
if f.err != nil {
return nil, f.err
}
if strings.TrimSpace(f.content) == "" {
return nil, errors.New("empty fake content")
}
return &llm.GenerateResult{Content: f.content, Model: req.Model}, nil
}