mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-05 07:10:29 +08:00
Port Python rag/advanced_rag agentic search to Go: ES-backed dataset-nav service, agentic-search harness, and agent tools. Includes agentic-search port plan and self-review docs.
103 lines
3.5 KiB
Go
103 lines
3.5 KiB
Go
package harness
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"ragflow/internal/service/nav"
|
|
)
|
|
|
|
// TestAskNavSelect_IndexBased asserts the model's index-based selection maps
|
|
// back to the item subset.
|
|
func TestAskNavSelect_IndexBased(t *testing.T) {
|
|
installChat(t, `{"relevant":[0,2]}`)
|
|
items := []navSelectItem{
|
|
{Name: "Alpha", Description: "aaa"},
|
|
{Name: "Beta", Description: "bbb"},
|
|
{Name: "Gamma", Description: "ggg"},
|
|
}
|
|
out := askNavSelect(context.Background(), nil, "query", "clusters", items, 10)
|
|
if len(out) != 2 {
|
|
t.Fatalf("selected = %d, want 2", len(out))
|
|
}
|
|
if out[0].Name != "Alpha" || out[1].Name != "Gamma" {
|
|
t.Errorf("selected names = %q, %q; want Alpha, Gamma", out[0].Name, out[1].Name)
|
|
}
|
|
}
|
|
|
|
// TestAskNavSelect_Empty asserts an empty "relevant" list yields nothing.
|
|
func TestAskNavSelect_Empty(t *testing.T) {
|
|
installChat(t, `{"relevant":[]}`)
|
|
if out := askNavSelect(context.Background(), nil, "q", "clusters", []navSelectItem{{Name: "A"}}, 10); len(out) != 0 {
|
|
t.Errorf("expected no selection, got %d", len(out))
|
|
}
|
|
}
|
|
|
|
// TestAskNavSelect_OutOfRange asserts invalid indices are skipped.
|
|
func TestAskNavSelect_OutOfRange(t *testing.T) {
|
|
installChat(t, `{"relevant":[0,99,-1]}`)
|
|
out := askNavSelect(context.Background(), nil, "q", "clusters", []navSelectItem{{Name: "A"}, {Name: "B"}}, 10)
|
|
if len(out) != 1 || out[0].Name != "A" {
|
|
t.Errorf("out-of-range selection = %+v, want [A]", out)
|
|
}
|
|
}
|
|
|
|
// TestNavigateDatasetByTree_NoQuery asserts empty query returns nil without
|
|
// calling anything.
|
|
func TestNavigateDatasetByTree_NoQuery(t *testing.T) {
|
|
if out := NavigateDatasetByTree(context.Background(), nil, nil, "t1", "kb1", " "); out != nil {
|
|
t.Errorf("expected nil for empty query, got %v", out)
|
|
}
|
|
}
|
|
|
|
// fakeNavSvcHarness is an in-memory nav.NavService for the BFS test.
|
|
type fakeNavSvcHarness struct {
|
|
clusters []nav.NavNode
|
|
children map[string][]nav.NavNode
|
|
}
|
|
|
|
func (f *fakeNavSvcHarness) UpsertDoc(context.Context, nav.UpsertDocInput) error { return nil }
|
|
func (f *fakeNavSvcHarness) RemoveDoc(context.Context, string, string, string) error {
|
|
return nil
|
|
}
|
|
func (f *fakeNavSvcHarness) Search(context.Context, string, string, string, []float32, int) ([]nav.NavHit, error) {
|
|
return nil, nil
|
|
}
|
|
func (f *fakeNavSvcHarness) ListClusters(context.Context, string, string, int, int) ([]nav.NavNode, int64, error) {
|
|
return f.clusters, int64(len(f.clusters)), nil
|
|
}
|
|
func (f *fakeNavSvcHarness) ListChildren(_ context.Context, _, _, name string, _, _ int) ([]nav.NavNode, int64, error) {
|
|
return f.children[name], int64(len(f.children[name])), nil
|
|
}
|
|
|
|
// TestCollectNavLeaves_BFS asserts document leaves are collected, sub-clusters
|
|
// descended, and leaves deduped by doc_id.
|
|
func TestCollectNavLeaves_BFS(t *testing.T) {
|
|
ns := &fakeNavSvcHarness{
|
|
clusters: []nav.NavNode{{Name: "C1", Description: "cluster 1"}},
|
|
children: map[string][]nav.NavNode{
|
|
"C1": {
|
|
{Name: "Sub", Type: "cluster"},
|
|
{Name: "DocA", Type: "doc", DocID: "d1"},
|
|
{Name: "DocB", Type: "doc", DocID: "d2"},
|
|
},
|
|
"Sub": {{Name: "DocC", Type: "doc", DocID: "d3"}},
|
|
},
|
|
}
|
|
selected := []navSelectItem{{Name: "C1", Description: "cluster 1"}}
|
|
leaves := collectNavLeaves(context.Background(), ns, "t1", "kb1", selected)
|
|
if len(leaves) != 3 {
|
|
t.Fatalf("leaves = %d, want 3 (d1,d2 from C1 + d3 from Sub)", len(leaves))
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, l := range leaves {
|
|
if l.DocID == "" {
|
|
t.Errorf("leaf %q has empty doc_id", l.Name)
|
|
}
|
|
seen[l.DocID] = true
|
|
}
|
|
if !seen["d1"] || !seen["d2"] || !seen["d3"] {
|
|
t.Errorf("collected doc_ids = %v, want d1,d2,d3", seen)
|
|
}
|
|
}
|