100 lines
3.1 KiB
Go
100 lines
3.1 KiB
Go
package io
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
|
|
)
|
|
|
|
// stubRetriever is a fake KnowledgeRetriever for testing knowledge responses.
|
|
type stubRetriever struct {
|
|
results []memory.Result
|
|
err error
|
|
}
|
|
|
|
func (s *stubRetriever) Retrieve(ctx context.Context, personaID, query string, topK int) ([]memory.Result, error) {
|
|
_ = ctx
|
|
return s.results, s.err
|
|
}
|
|
|
|
// knowledgeToolForTest builds a tools set with opts and returns the knowledge
|
|
// tool.
|
|
func knowledgeToolForTest(t *testing.T, opts ...Option) *knowledgeTool {
|
|
t.Helper()
|
|
return findTool(t, buildTools(t, &config.Config{}, opts...), "knowledge").(*knowledgeTool)
|
|
}
|
|
|
|
func TestKnowledge_NoKnowledgeBase(t *testing.T) {
|
|
t.Parallel()
|
|
kt := knowledgeToolForTest(t) // no retriever wired
|
|
_, err := kt.Execute(context.Background(), map[string]any{"query": "cyrene"})
|
|
if err == nil || !strings.Contains(err.Error(), "no knowledge base") {
|
|
t.Fatalf("expected no-knowledge-base error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestKnowledge_ReturnsResults(t *testing.T) {
|
|
t.Parallel()
|
|
sr := &stubRetriever{results: []memory.Result{
|
|
{Item: memory.MemoryItem{ID: "1", Content: "Cyrene 是主人", Kind: memory.KindWorldEvent, Scope: memory.ScopeProject}, Score: 0.9},
|
|
}}
|
|
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(sr))
|
|
|
|
got, err := kt.Execute(context.Background(), map[string]any{"query": "cyrene", "persona": "p1", "top_k": 5})
|
|
if err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
m := got.(map[string]any)
|
|
if m["count"].(int) != 1 {
|
|
t.Fatalf("count = %v", m["count"])
|
|
}
|
|
results := m["results"].([]map[string]any)
|
|
if results[0]["content"] != "Cyrene 是主人" {
|
|
t.Fatalf("content = %v", results[0]["content"])
|
|
}
|
|
if results[0]["kind"] != "world_event" {
|
|
t.Fatalf("kind = %v", results[0]["kind"])
|
|
}
|
|
}
|
|
|
|
func TestKnowledge_EmptyResults(t *testing.T) {
|
|
t.Parallel()
|
|
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{}))
|
|
got, err := kt.Execute(context.Background(), map[string]any{"query": "nothing"})
|
|
if err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
m := got.(map[string]any)
|
|
if m["count"].(int) != 0 {
|
|
t.Fatalf("count = %v", m["count"])
|
|
}
|
|
if m["note"] != "no relevant knowledge found" {
|
|
t.Fatalf("note = %v", m["note"])
|
|
}
|
|
if _, ok := m["results"].([]map[string]any); !ok {
|
|
t.Fatalf("results absent or wrong type: %T", m["results"])
|
|
}
|
|
}
|
|
|
|
func TestKnowledge_RetrieverError(t *testing.T) {
|
|
t.Parallel()
|
|
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{err: errors.New("boom")}))
|
|
_, err := kt.Execute(context.Background(), map[string]any{"query": "x"})
|
|
if err == nil || !strings.Contains(err.Error(), "retrieve") {
|
|
t.Fatalf("expected retrieve error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestKnowledge_MissingQuery(t *testing.T) {
|
|
t.Parallel()
|
|
kt := knowledgeToolForTest(t, WithKnowledgeRetriever(&stubRetriever{}))
|
|
_, err := kt.Execute(context.Background(), map[string]any{})
|
|
if err == nil || !strings.Contains(err.Error(), "query is required") {
|
|
t.Fatalf("expected query-required error, got %v", err)
|
|
}
|
|
}
|