feat: simplify SOP to immediate-effect configuration
This commit is contained in:
88
internal/run/knowledge_graph_test.go
Normal file
88
internal/run/knowledge_graph_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package run
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
|
||||
)
|
||||
|
||||
func TestRenderKnowledgeContent(t *testing.T) {
|
||||
got := string(renderKnowledgeContent([]byte(`{"template":"您好{{input.name}},标签:{{derived.tags}}"}`), map[string]interface{}{"name": "王女士", "tags": []interface{}{"高意向", "复购"}}))
|
||||
want := `{"template":"您好王女士,标签:高意向、复购"}`
|
||||
if got != want {
|
||||
t.Fatalf("got %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderKnowledgeContentSupportsFormNamespace(t *testing.T) {
|
||||
got := string(renderKnowledgeContent([]byte(`{"template":"结果:{{form.call_result}}"}`), runtimeContext(nil, nil, map[string]interface{}{"call_result": "已接受"})))
|
||||
if got != `{"template":"结果:已接受"}` {
|
||||
t.Fatalf("got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTemplateNamespacesDoNotOverwriteEachOther(t *testing.T) {
|
||||
context := runtimeContext(map[string]interface{}{"status": "input"}, map[string]interface{}{"status": "derived"}, map[string]interface{}{"status": "form"})
|
||||
got := string(renderKnowledgeContent([]byte(`{"template":"{{input.status}}/{{derived.status}}/{{form.status}}"}`), context))
|
||||
if got != `{"template":"input/derived/form"}` {
|
||||
t.Fatalf("got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledgeRelationCondition(t *testing.T) {
|
||||
condition := json.RawMessage(`{"field":"derived.segment","operator":"equals","value":"vip"}`)
|
||||
matched, err := matchCondition(condition, map[string]interface{}{"segment": "vip"})
|
||||
if err != nil || !matched {
|
||||
t.Fatalf("matched=%v err=%v", matched, err)
|
||||
}
|
||||
matched, err = matchCondition(condition, map[string]interface{}{"segment": "normal"})
|
||||
if err != nil || matched {
|
||||
t.Fatalf("matched=%v err=%v", matched, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSnapshotRelationsHonorSelector(t *testing.T) {
|
||||
snapshot := knowledgeSnapshot{Relations: []model.KnowledgeRelation{
|
||||
{FromKnowledgeID: 1, ToKnowledgeID: 2, RelationType: "recommended_copy"},
|
||||
{FromKnowledgeID: 1, ToKnowledgeID: 3, RelationType: "internal_note"},
|
||||
}}
|
||||
raw, err := json.Marshal(snapshot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parsed, err := parseKnowledgeSnapshot(raw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
selector := knowledgeSelector{RelationTypes: []string{"recommended_copy"}}
|
||||
filtered := make([]model.KnowledgeRelation, 0)
|
||||
for _, relation := range parsed.Relations {
|
||||
if len(selector.RelationTypes) == 0 || containsString(selector.RelationTypes, relation.RelationType) {
|
||||
filtered = append(filtered, relation)
|
||||
}
|
||||
}
|
||||
if len(filtered) != 1 || filtered[0].RelationType != "recommended_copy" {
|
||||
t.Fatalf("filtered relations = %#v", filtered)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledgeSelectorWithoutCandidateKeysReturnsEmpty(t *testing.T) {
|
||||
outputs, err := loadKnowledgeOutputsForScenario(nil, 1, 1, map[string]interface{}{}, knowledgeSelector{DerivedField: "matched", KnowledgeTypes: []string{"symptom"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(outputs) != 0 {
|
||||
t.Fatalf("outputs = %#v", outputs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnowledgeCandidateMatchesKeyOrDisplayName(t *testing.T) {
|
||||
item := model.KnowledgeItem{ItemKey: "xlsx_symptom_123", Name: "腹泻"}
|
||||
if !knowledgeCandidateMatches(map[string]bool{"腹泻": true}, item) {
|
||||
t.Fatal("display name should match an external symptom tag")
|
||||
}
|
||||
if !knowledgeCandidateMatches(map[string]bool{"xlsx_symptom_123": true}, item) {
|
||||
t.Fatal("item key should remain supported")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user