Files
ragflow/internal/agent/component/retrieval_params_test.go
Hz_ a55a438b42 fix(go-agent): finish retrieval component (#17845)
- Prefer canonical `dataset_ids` over legacy `kb_ids` in Canvas
retrieval components.
- Cover selected and explicitly cleared dataset IDs with regression
tests.
- Add cross-language retrieval with dataset-specific embedding and
rerank models.
- Support vector and keyword similarity controls, metadata filtering,
TOC enhancement, and child-chunk expansion.
- Route Canvas retrieval across datasets and memories with compatible
embedding validation.
2026-08-05 15:48:54 +08:00

150 lines
5.1 KiB
Go

//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package component
import (
"context"
"reflect"
"testing"
agenttool "ragflow/internal/agent/tool"
"gorm.io/gorm"
)
type retrievalRequestRecorder struct {
request agenttool.RetrievalRequest
}
func (r *retrievalRequestRecorder) Search(_ context.Context, _ *gorm.DB, request agenttool.RetrievalRequest) ([]agenttool.RetrievalChunk, error) {
r.request = request
return []agenttool.RetrievalChunk{}, nil
}
func TestRetrievalComponentAppliesAdvancedNodeParams(t *testing.T) {
component, err := newRetrievalComponent(map[string]any{
"dataset_ids": []any{"dataset-1"},
"memory_ids": []any{"memory-1", "memory-2"},
"cross_languages": []any{"English", "Chinese", "Spanish"},
"toc_enhance": true,
"use_kg": true,
"meta_data_filter": map[string]any{"method": "manual"},
"retrieval_from": "memory",
})
if err != nil {
t.Fatalf("newRetrievalComponent: %v", err)
}
merged := component.(*retrievalComponent).applyDefaults(nil)
if got := merged["memory_ids"]; !reflect.DeepEqual(got, []string{"memory-1", "memory-2"}) {
t.Errorf("memory_ids = %#v", got)
}
if got := merged["cross_languages"]; !reflect.DeepEqual(got, []string{"English", "Chinese", "Spanish"}) {
t.Errorf("cross_languages = %#v", got)
}
if got := merged["toc_enhance"]; got != true {
t.Errorf("toc_enhance = %#v", got)
}
if got := merged["use_kg"]; got != true {
t.Errorf("use_kg = %#v", got)
}
if got := merged["meta_data_filter"]; !reflect.DeepEqual(got, map[string]any{"method": "manual"}) {
t.Errorf("meta_data_filter = %#v", got)
}
if got := merged["retrieval_from"]; got != "memory" {
t.Errorf("retrieval_from = %#v", got)
}
}
func TestRetrievalComponentForwardsAdvancedNodeParams(t *testing.T) {
previous := agenttool.GetRetrievalService()
recorder := &retrievalRequestRecorder{}
agenttool.SetRetrievalService(recorder)
t.Cleanup(func() { agenttool.SetRetrievalService(previous) })
component, err := newRetrievalComponent(map[string]any{
"dataset_ids": []any{"dataset-1"},
"memory_ids": []any{"memory-1"},
"cross_languages": []any{"English", "Chinese", "Spanish"},
"toc_enhance": true,
"use_kg": false,
"meta_data_filter": map[string]any{"method": "manual"},
"retrieval_from": "dataset",
})
if err != nil {
t.Fatalf("newRetrievalComponent: %v", err)
}
if _, err := component.Invoke(context.Background(), nil, map[string]any{"query": "爱"}); err != nil {
t.Fatalf("Invoke: %v", err)
}
request := recorder.request
if !reflect.DeepEqual(request.MemoryIDs, []string{"memory-1"}) {
t.Errorf("MemoryIDs = %#v", request.MemoryIDs)
}
if !reflect.DeepEqual(request.CrossLanguages, []string{"English", "Chinese", "Spanish"}) {
t.Errorf("CrossLanguages = %#v", request.CrossLanguages)
}
if !request.TOCEnhance {
t.Error("TOCEnhance = false")
}
if request.UseKG {
t.Error("UseKG = true")
}
if !reflect.DeepEqual(request.MetaDataFilter, map[string]any{"method": "manual"}) {
t.Errorf("MetaDataFilter = %#v", request.MetaDataFilter)
}
if request.RetrievalFrom != "dataset" {
t.Errorf("RetrievalFrom = %q", request.RetrievalFrom)
}
}
func TestRetrievalComponentForwardsExplicitZeroSimilarityParams(t *testing.T) {
previous := agenttool.GetRetrievalService()
recorder := &retrievalRequestRecorder{}
agenttool.SetRetrievalService(recorder)
t.Cleanup(func() { agenttool.SetRetrievalService(previous) })
component, err := newRetrievalComponent(map[string]any{
"dataset_ids": []any{"dataset-1"},
"similarity_threshold": 0,
"keywords_similarity_weight": 0,
})
if err != nil {
t.Fatalf("newRetrievalComponent: %v", err)
}
merged := component.(*retrievalComponent).applyDefaults(nil)
if value, ok := merged["similarity_threshold"]; !ok || value != float64(0) {
t.Fatalf("similarity_threshold = %#v, present = %v; want explicit zero", value, ok)
}
if value, ok := merged["keywords_similarity_weight"]; !ok || value != float64(0) {
t.Fatalf("keywords_similarity_weight = %#v, present = %v; want explicit zero", value, ok)
}
if _, err := component.Invoke(context.Background(), nil, map[string]any{"query": "zero"}); err != nil {
t.Fatalf("Invoke: %v", err)
}
if recorder.request.SimilarityThreshold == nil || *recorder.request.SimilarityThreshold != 0 {
t.Fatalf("SimilarityThreshold = %v; want explicit zero", recorder.request.SimilarityThreshold)
}
if recorder.request.KeywordsSimilarityWeight == nil || *recorder.request.KeywordsSimilarityWeight != 0 {
t.Fatalf("KeywordsSimilarityWeight = %v; want explicit zero", recorder.request.KeywordsSimilarityWeight)
}
}