返回 DeepSeek-Reasonix
keywords_recall_test.go
根目录 / internal / memory / keywords_recall_test.go
1 package memory
2
3 import (
4 "strings"
5 "testing"
6 )
7
8 // CJK bigram selectivity: a query phrase must match a real two-character
9 // subsequence, not scattered common characters (the retired per-rune scorer
10 // matched the latter).
11 func TestAutoRecallCJKBigramsRequireRealSubsequence(t *testing.T) {
12 store := recallTestStore(t)
13 recallTestWrite(t, store.Dir, Memory{
14 ID: "mem-migration", Name: "db-migration-compat", Title: "数据库迁移兼容性",
15 Description: "数据库迁移必须保持向后兼容", Type: TypeProject,
16 Scope: FactScopeProject, Body: "所有 schema 变更先加列后删列。",
17 })
18 recallTestWrite(t, store.Dir, Memory{
19 ID: "mem-scattered", Name: "warehouse-stats", Title: "仓库统计口径",
20 Description: "数值统计以据点仓库的库存为准", Type: TypeProject,
21 Scope: FactScopeProject, Body: "库存数字每周核对一次。",
22 })
23
24 result := AutoRecall(store, "数据库迁移怎么保证兼容", RecallOptions{})
25 if len(result.Hits) == 0 {
26 t.Fatalf("AutoRecall missed the real 数据库迁移 fact: %+v", result)
27 }
28 for _, hit := range result.Hits {
29 if hit.Memory.ID == "mem-scattered" {
30 t.Fatalf("scattered common characters must not match: %+v", result.Hits)
31 }
32 }
33 }
34
35 // Keywords bridge the lexical gap AutoRecall cannot cross: the fact's own
36 // words never appear in the query, its saved aliases do.
37 func TestAutoRecallMatchesThroughSavedKeywords(t *testing.T) {
38 store := recallTestStore(t)
39 recallTestWrite(t, store.Dir, Memory{
40 ID: "mem-pnpm", Name: "package-manager", Title: "Package manager is pnpm",
41 Description: "The project migrated from npm to pnpm", Type: TypeProject,
42 Scope: FactScopeProject, Keywords: "依赖 安装 包管理 install dependencies",
43 Body: "Use pnpm for every workspace task; npm and yarn lockfiles are gone.",
44 })
45
46 result := AutoRecall(store, "依赖应该用什么工具安装", RecallOptions{})
47 if len(result.Hits) != 1 || result.Hits[0].Memory.ID != "mem-pnpm" {
48 t.Fatalf("keywords should carry the paraphrased query to the fact, got %+v", result.Hits)
49 }
50 if !strings.Contains(result.Hits[0].Reason, "依赖") && !strings.Contains(result.Hits[0].Reason, "安装") {
51 t.Fatalf("reason should surface the matched alias, got %q", result.Hits[0].Reason)
52 }
53 }
54
55 func TestSaveRoundTripsKeywordsAndPreservesThemOnUpdate(t *testing.T) {
56 store := recallTestStore(t)
57 saved, err := store.SaveWithOptions(Memory{
58 Name: "package-manager", Description: "The project uses pnpm",
59 Keywords: "依赖 包管理", Body: "pnpm everywhere.",
60 }, SaveOptions{})
61 if err != nil {
62 t.Fatal(err)
63 }
64 loaded, ok := store.Read(saved.Memory.ID)
65 if !ok || loaded.Keywords != "依赖 包管理" {
66 t.Fatalf("keywords lost in round trip: ok=%v %+v", ok, loaded)
67 }
68
69 if _, err := store.SaveWithOptions(Memory{
70 ID: saved.Memory.ID, Description: "The project uses pnpm 9",
71 Body: "pnpm 9 everywhere.",
72 }, SaveOptions{}); err != nil {
73 t.Fatal(err)
74 }
75 updated, ok := store.Read(saved.Memory.ID)
76 if !ok || updated.Keywords != "依赖 包管理" {
77 t.Fatalf("an update omitting keywords must preserve them, got %+v", updated)
78 }
79 if updated.Revision != 2 || !strings.Contains(updated.Body, "pnpm 9") {
80 t.Fatalf("update did not land: %+v", updated)
81 }
82 }
83
83 lines GO