fix(memory): 场景召回按块向量余弦排序 + 召回 query 可见性 + 对话回执放宽

① 场景召回是每轮常驻注入,此前按「场景权重→时间倒序」排,与 query 无关:
   老图库的 rt/rtchild/inputch 等历史事实常年霸榜,实测 1833 字符里九成是它们,
   刚聊的群聊内容一句没有 —— 这就是"忘事"的机制。
   块里本来就存着向量,相关性就是一次余弦比较:RecallByScene 带出端点/原句块
   向量,Indexer 按 max(cos) 排序并设 0.20 下限,取前 8。
   无稠密空间时保持原顺序(不能用字面匹配冒充语义 —— 既有判据要求
   「措辞与记忆零字面重合时场景路必须兜住」)。

② recall query 可见性:cleaner 缺失/生效/回空三种情况都打日志。此前静默回退
   原文,"召回 query 其实是工具原始回执"这件事在日志里完全看不到。
   实测 qq_get_message: 199 -> 27 bytes(cleaner 生效)。

③ 对话正文类工具(get_message/get_history/list_chats)时间线渲染放宽到 400 字
   (160 字会把群聊上下文切成碎片)。

判据:internal/memory/scene_relevance_test.go
This commit is contained in:
JianFeeeee
2026-10-27 13:25:25 +08:00
parent bd066a627a
commit b2938ed4a7
6 changed files with 249 additions and 5 deletions

View File

@ -115,6 +115,17 @@ type Relation struct {
SentenceText string `json:"sentence_text,omitempty"` // 原句全文(走原句块回溯)
// SentenceBlockID 是原句块的 ID(blk_src_<hash>),供场景引用与去重。
SentenceBlockID string `json:"sentence_block_id,omitempty"`
// SourceVec / TargetVec / SentenceVec 是端点块与原句块的**稠密向量**。
//
// 为什么带在关系上:场景召回是"每轮都要跑的常驻注入",排序必须与本轮
// query 相关(块里本来就存着向量,相关性就是一次余弦比较)。
// 此前 RecallByScene 只按「场景权重 → 时间倒序」排,老图库里的历史高频
// 三元组常年霸榜,每轮灌同一批无关内容(实测 90% token 是这些)。
//
// 不落 JSON / 不入库:它们只用于本次比较,块向量本身仍在 memory_blocks 里。
SourceVec []float64 `json:"-"`
TargetVec []float64 `json:"-"`
SentenceVec []float64 `json:"-"`
}
type Triple struct {