项目文件夹

文件
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

129 行
3.5 KiB
Go

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
package search
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRRFFuse(t *testing.T) {
textResults := []SearchResult{
{ID: "a", Score: 10},
{ID: "b", Score: 8},
{ID: "c", Score: 5},
}
vecIDs := []string{"b", "d", "a"}
results := rrfFuse(textResults, vecIDs, 60, 10)
require.GreaterOrEqual(t, len(results), 3)
// "a" and "b" appear in both lists → highest RRF scores.
// "b" is rank 1 in text, rank 0 in vec → should score high.
topIDs := make([]string, len(results))
for i, r := range results {
topIDs[i] = r.ID
}
assert.Contains(t, topIDs[:2], "a", "a should be in top 2 (in both lists)")
assert.Contains(t, topIDs[:2], "b", "b should be in top 2 (in both lists)")
// All results should have non-zero scores.
for _, r := range results {
assert.Greater(t, r.Score, float64(0))
}
}
func TestRRFFuse_EmptyVec(t *testing.T) {
textResults := []SearchResult{
{ID: "a", Score: 10},
{ID: "b", Score: 8},
}
results := rrfFuse(textResults, nil, 60, 10)
// With no vec results, only text results contribute.
assert.Len(t, results, 2)
assert.Equal(t, "a", results[0].ID)
}
func TestRRFFuse_Limit(t *testing.T) {
textResults := []SearchResult{
{ID: "a"}, {ID: "b"}, {ID: "c"}, {ID: "d"}, {ID: "e"},
}
vecIDs := []string{"f", "g", "h", "i", "j"}
results := rrfFuse(textResults, vecIDs, 60, 3)
assert.Len(t, results, 3)
}
// --- alphaFuse + auto-α coverage -------------------------------------
func TestAlphaFuse_SmallAlphaFavorsText(t *testing.T) {
// Text-only candidate "t" and vector-only candidate "v" at the
// same rank in their channels. With α=0.1 (BM25-heavy), "t" must
// outrank "v" — symbol queries are supposed to favor text.
textResults := []SearchResult{{ID: "t"}}
vecIDs := []string{"v"}
res := alphaFuse(textResults, vecIDs, 0.1, 60, 10)
require.Len(t, res, 2)
if res[0].ID != "t" {
t.Fatalf("with α=0.1 expected text-only hit first, got %v", res[0].ID)
}
}
func TestAlphaFuse_LargeAlphaFavorsVector(t *testing.T) {
textResults := []SearchResult{{ID: "t"}}
vecIDs := []string{"v"}
res := alphaFuse(textResults, vecIDs, 0.9, 60, 10)
require.Len(t, res, 2)
if res[0].ID != "v" {
t.Fatalf("with α=0.9 expected vector-only hit first, got %v", res[0].ID)
}
}
func TestAlphaFuse_ClampsAlpha(t *testing.T) {
// α below 0 → 0 (text-only); above 1 → 1 (vector-only). Out-of-
// range values must not break sort order.
textResults := []SearchResult{{ID: "t"}}
vecIDs := []string{"v"}
res := alphaFuse(textResults, vecIDs, -5.0, 60, 10)
require.Len(t, res, 2)
if res[0].ID != "t" {
t.Fatalf("α=-5 should clamp to 0 (text wins), got %v", res[0].ID)
}
res = alphaFuse(textResults, vecIDs, 5.0, 60, 10)
require.Len(t, res, 2)
if res[0].ID != "v" {
t.Fatalf("α=5 should clamp to 1 (vector wins), got %v", res[0].ID)
}
}
func TestAlphaFuse_DeterministicTieBreak(t *testing.T) {
textResults := []SearchResult{{ID: "alpha"}, {ID: "beta"}}
vecIDs := []string{"alpha", "gamma"}
for range 5 {
res := alphaFuse(textResults, vecIDs, 0.5, 60, 10)
require.GreaterOrEqual(t, len(res), 3)
if res[0].ID != "alpha" {
t.Fatalf("alphaFuse ordering not stable; got %v", res[0].ID)
}
}
}
func TestNewHybrid_AutoAlphaDefaultOn(t *testing.T) {
h := NewHybrid(nil, nil, nil)
if !h.AutoAlpha() {
t.Errorf("NewHybrid().AutoAlpha() = false, want true (auto-α default)")
}
h.SetAutoAlpha(false)
if h.AutoAlpha() {
t.Errorf("SetAutoAlpha(false) did not take effect")
}
h.SetAutoAlpha(true)
if !h.AutoAlpha() {
t.Errorf("SetAutoAlpha(true) did not take effect")
}
}