mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-03 15:53:56 +00:00
fix(memory): 记忆层启动接线/并发/落盘一致性整备
按设计方案整顿记忆系统,收敛一批"单测照不出、只在长跑生产里暴露"的缺陷: - 启动接线:initMemoryStack 残留 `defer distiller.Stop()`,规则蒸馏 10min 心跳启动即死。改为由调用点 cleanup 停机,并补 Stopped() 探针 + TestInitMemoryStackKeepsDistillerRunning / TestStartKeepsLoopRunningUntilStop。 - L0 相关性上下文:SetDenseSpace 注入稠密空间时回填已有事件的稠密向量, 否则旧事件走稀疏余弦、新事件走稠密余弦,同一次 Prune 里两种尺度混排。 - 文档检索:QueryScored 访问计数从读锁内写移出(-race 竞争),更新后置脏, 优雅关停可落盘、FindColdDocs 冷度判据跨重启不再失真。 - 蒸馏管线:只 flush 未落盘记录(persisted 标记)、蒸馏成功后从 raw 文件 删除对应行、原子写文件,修重启重复蒸馏导致 mention_count 膨胀。 - 图库:全量 Recall 加实体上限(内部整备路径,防大图整表进内存); ClearSentenceID 补写锁;Commit/upsertEntity 计数语义注释澄清。 - 索引器:recalled 去重集加 FIFO 上限,防长跑进程自动注入越来越沉默。 - 文档/媒体注释修正;README 记忆层流程对齐跨模态召回。 验证:go build ./...、go vet、go test -race ./internal/memory/... ./internal/agent/core/... ./cmd/homed/... 全绿。
This commit is contained in:
@ -2,6 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -237,6 +238,41 @@ func containsStr(s, substr string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TestSetDenseSpaceBackfillsExistingEvents 锁死 L0 稠密回填:
|
||||
//
|
||||
// NewRelevanceContext 先 load()(此时 denseSpace 仍为 nil,旧事件只算了稀疏
|
||||
// 向量),SetDenseSpace 才注入稠密空间。若不回填已有事件,它们的 DenseFP
|
||||
// 为空、DenseVec 长度不符,Prune 里旧事件走稀疏余弦、新事件走稠密余弦——
|
||||
// 同一次排序里混排两种尺度,谁留下只取决于事件新旧。
|
||||
func TestSetDenseSpaceBackfillsExistingEvents(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "context.json")
|
||||
|
||||
// run1:写入事件并落盘(不注入稠密空间)。
|
||||
c1 := NewRelevanceContext(path, memory.NewStaticEmbedder(""))
|
||||
c1.Append(ContextEvent{Timestamp: time.Now(), Source: "user", Input: "昨天的决定"})
|
||||
c1.Append(ContextEvent{Timestamp: time.Now(), Source: "agent", Response: "记为待办"})
|
||||
if err := c1.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// run2:模拟重启——load() 发生在 SetDenseSpace 之前。
|
||||
c2 := NewRelevanceContext(path, memory.NewStaticEmbedder(""))
|
||||
if c2.Len() == 0 {
|
||||
t.Fatal("重启后未读回任何事件")
|
||||
}
|
||||
c2.SetDenseSpace(fakeSpace{})
|
||||
|
||||
events := c2.Recent(c2.Len())
|
||||
if len(events) == 0 {
|
||||
t.Fatal("no events")
|
||||
}
|
||||
for i, e := range events {
|
||||
if e.DenseFP != "fake-space" || len(e.DenseVec) != 2 {
|
||||
t.Errorf("event %d 未回填稠密向量: fp=%q len=%d", i, e.DenseFP, len(e.DenseVec))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func splitLines(s string) []string {
|
||||
var lines []string
|
||||
start := 0
|
||||
|
||||
Reference in New Issue
Block a user