Files
AskaEth 61cf80d5ee
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
docs(comments): 注释中文化 · internal/runtime/memory(31 文件,纯替换)
- 只翻注释/文档字符串:820 增 / 820 删 严格 1:1;剥掉整行注释与行尾注释尾巴后,
  逐文件与 HEAD 比对「代码部分差异 = 0」;裁决/design 编号计数逐项与 HEAD 一致
- 保留可执行 SQL 样例、SQLite 报错原文、pgvector/HNSW/ANN/BLOB 等技术词原文
- 复核:go build 绿 + memory/projectindex/vector 三包测试绿;gofmt 仅剩 2 个既有未格式化文件(改动前即如此,未顺手修)
2026-10-04 13:32:54 +08:00

80 lines
2.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package memory
import (
"context"
"math"
"testing"
"time"
)
func TestRetriever_DecayFactor_久未使用降权(t *testing.T) {
t.Parallel()
r := NewRetriever(newTestStore(t))
now := time.Now().UTC()
tests := []struct {
name string
updatedAt time.Time
decayWeight float64
want float64
}{
{name: "fresh keeps full weight", updatedAt: now, decayWeight: 1.0, want: 1.0},
// 默认半衰期为 30 天:60 天前 = 2 个半衰期 = 2^-2。
{name: "two half-lives halves twice", updatedAt: now.Add(-60 * 24 * time.Hour), decayWeight: 1.0, want: 0.25},
// 较低的基础 decay_weight 会整体压低曲线。
{name: "low decay_weight scales down", updatedAt: now, decayWeight: 0.5, want: 0.5},
{name: "low weight plus age compounds", updatedAt: now.Add(-60 * 24 * time.Hour), decayWeight: 0.5, want: 0.125},
// 未来时间戳不得把得分抬到基础权重以上。
{name: "future timestamp clamps to zero", updatedAt: now.Add(time.Hour), decayWeight: 1.0, want: 1.0},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := r.decayFactor(MemoryItem{
DecayWeight: tt.decayWeight,
UpdatedAt: tt.updatedAt,
}, now)
if math.Abs(got-tt.want) > 1e-9 {
t.Fatalf("decayFactor = %v, want %v", got, tt.want)
}
})
}
}
func TestRetriever_Retrieve_DecayWeight_降权(t *testing.T) {
t.Parallel()
ctx := context.Background()
s := newTestStore(t)
now := time.Now().UTC()
// 一条新鲜但 decay_weight 近乎零的条目(design:用户可削弱某记忆)。
addItem(t, s, MemoryItem{
PersonaID: "persona.a", Content: "低权重但新鲜", UpdatedAt: now,
DecayWeight: 0.1, Scope: ScopePersona, Kind: KindWorldEvent,
})
// 稍有历史、但 decay_weight 满额的条目。
addItem(t, s, MemoryItem{
PersonaID: "persona.a", Content: "权重高稍旧", UpdatedAt: now.Add(-time.Hour),
DecayWeight: 1.0, Scope: ScopePersona, Kind: KindWorldEvent,
})
r := NewRetriever(s)
// query 为空时无任何命中,因此排序完全由衰减因子
// (decay_weight × 时间衰减)驱动:低权重的新条目必须
// 排在满权重、稍旧的条目之后。
results, err := r.Retrieve(ctx, "persona.a", "", 10)
if err != nil {
t.Fatalf("Retrieve: %v", err)
}
if len(results) != 2 {
t.Fatalf("got %d results, want 2", len(results))
}
if got := results[0].Item.Content; got != "权重高稍旧" {
t.Fatalf("top result = %q, want the full-decay-weight item", got)
}
if got := results[1].Item.Content; got != "低权重但新鲜" {
t.Fatalf("second result = %q, want the low-decay-weight item", got)
}
}