Files
ragflow/internal/ingestion/component/knowledge_compiler/mindmap/mindmap_test.go
Zhichang Yu 29287ef74b refactor(knowledge_compiler): derive variant from template kind via single template id (#17630)
## Summary

Refactor the Go `KnowledgeCompilerComponent` so its parameter is a
**single string template id** instead of a DSL-level `variant` (or
plural group id list). The `variant` is no longer in the DSL — it is now
**derived at runtime from the resolved compilation template's `kind`
field**.

This aligns the Go ingestion port with the frontend Compiler operator,
which emits a singular `compilation_template_group_id` and does not
write `variant` into the generated `compiler.json`.
2026-07-31 18:01:55 +08:00

105 lines
3.1 KiB
Go

package mindmap
import (
"encoding/json"
"strings"
"testing"
"ragflow/internal/utility"
)
func TestRenderPrompt(t *testing.T) {
got := renderPrompt("THE TEXT")
if !strings.Contains(got, "-TEXT-\nTHE TEXT") {
t.Fatalf("input_text not substituted: %q", got)
}
if strings.Contains(got, "{input_text}") {
t.Fatalf("placeholder survived: %q", got)
}
// The verbatim prompt body must be present.
if !strings.Contains(got, "Generate a title for user's 'TEXT'。") {
t.Fatalf("prompt body drifted")
}
}
func TestPackSections_Budget(t *testing.T) {
// budget = max(4096*0.8, 4096-512) = 3584; with the len-based fake
// tokenizer each section of 2000 tokens packs one per batch.
tok := fakeTok{}
sections := []string{strings.Repeat("a", 8000), strings.Repeat("b", 8000), "short"}
got := packSections(sections, tok)
if len(got) != 2 {
t.Fatalf("batches = %d, want 2 (2000+2000 > 3584 splits)", len(got))
}
// An oversized section is never split: it forms its own batch.
big := packSections([]string{strings.Repeat("x", 20000)}, tok)
if len(big) != 1 {
t.Fatalf("oversized section must stay whole: %d batches", len(big))
}
}
type fakeTok struct{}
func (fakeTok) NumTokens(s string) int { return len(s) / 4 }
func TestTreeToProducts_ParentLinks(t *testing.T) {
root := &utility.Node{ID: "root", Children: []*utility.Node{
{ID: "A", Children: []*utility.Node{{ID: "A1"}, {ID: "A2"}}},
{ID: "B"},
}}
products := treeToProducts("t1", "d1", root)
if len(products) != 5 {
t.Fatalf("products = %d, want 5 (root+A+A1+A2+B)", len(products))
}
if products[0].Meta["kind"] != "root" || products[0].ParentID != "" {
t.Errorf("root product malformed: %+v", products[0].Meta)
}
if products[1].ParentID != products[0].ID {
t.Errorf("A parent link = %q, want root id", products[1].ParentID)
}
var aID string
for _, p := range products {
if p.Meta["name"] == "A" {
aID = p.ID
}
}
for _, p := range products {
if n, _ := p.Meta["name"].(string); n == "A1" || n == "A2" {
if p.ParentID != aID {
t.Errorf("%s parent = %q, want A id", n, p.ParentID)
}
}
}
}
func TestSerializeNode_Shape(t *testing.T) {
root := &utility.Node{ID: "Top \"quoted\"", Children: []*utility.Node{{ID: "child"}}}
js := serializeNode(root)
if !strings.HasPrefix(js, `{"id":"Top \"quoted\""`) {
t.Errorf("serializeNode = %q", js)
}
}
// TestSerializeNode_EscapesControlChars locks that serializeNode uses
// encoding/json: control characters such as CR/LF/TAB/FF are escaped (not
// embedded raw), so the output is always valid JSON.
func TestSerializeNode_EscapesControlChars(t *testing.T) {
root := &utility.Node{ID: "a\rb\tc\fd", Children: []*utility.Node{{ID: "x\ny"}}}
js := serializeNode(root)
var dec struct {
ID string `json:"id"`
Children []struct {
ID string `json:"id"`
} `json:"children"`
}
if err := json.Unmarshal([]byte(js), &dec); err != nil {
t.Fatalf("serializeNode produced invalid JSON: %v (%q)", err, js)
}
if dec.ID != "a\rb\tc\fd" {
t.Errorf("root id round-trip = %q, want %q", dec.ID, "a\rb\tc\fd")
}
if len(dec.Children) != 1 || dec.Children[0].ID != "x\ny" {
t.Errorf("child id round-trip = %+v", dec.Children)
}
}