mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-06 17:27:31 +00:00
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:
@ -391,6 +391,7 @@ func (g *GraphDB) RecallByScene(scenes []string, limit int) (*SceneRecall, error
|
||||
relQuery := `SELECT e.id, sb.id, tb.id, sb.text_content, tb.text_content,
|
||||
e.edge_type, e.confidence, COALESCE(e.status, ''), e.session_id,
|
||||
e.turn_id, e.created_at, COALESCE(srt.text, ''),
|
||||
COALESCE(sb.vector, ''), COALESCE(tb.vector, ''), COALESCE(srt.vector, ''),
|
||||
MAX(sr.weight) AS w
|
||||
FROM scene_refs sr
|
||||
JOIN scenes s ON sr.scene_id = s.id
|
||||
@ -398,7 +399,7 @@ func (g *GraphDB) RecallByScene(scenes []string, limit int) (*SceneRecall, error
|
||||
JOIN memory_blocks sb ON sb.id = e.source_id
|
||||
JOIN memory_blocks tb ON tb.id = e.target_id
|
||||
LEFT JOIN (
|
||||
SELECT c.target_id AS edge_id, MIN(b.text_content) AS text
|
||||
SELECT c.target_id AS edge_id, MIN(b.text_content) AS text, MIN(b.vector) AS vector
|
||||
FROM memory_block_edges c
|
||||
JOIN memory_blocks b ON b.id = c.source_id
|
||||
WHERE c.edge_type = 'contains' AND c.target_kind = 'edge'
|
||||
@ -420,13 +421,25 @@ func (g *GraphDB) RecallByScene(scenes []string, limit int) (*SceneRecall, error
|
||||
// relations 行号,块体系下无意义)。
|
||||
// ★ DateBucket / SentenceID 不再有来源:旧表退场后边表不存这两列,
|
||||
// 日期可从 created_at 推,原句 ID 由 contains 边回溯得到。
|
||||
var srcVecRaw, tgtVecRaw, senVecRaw string
|
||||
if err := rows.Scan(&rel.ID, &rel.SourceBlockID, &rel.TargetBlockID,
|
||||
&rel.SourceName, &rel.TargetName,
|
||||
&rel.RelationType, &rel.Confidence, &rel.Status, &rel.SessionID,
|
||||
&rel.TurnID, &rel.CreatedAt, &rel.SentenceText, &w); err != nil {
|
||||
&rel.TurnID, &rel.CreatedAt, &rel.SentenceText,
|
||||
&srcVecRaw, &tgtVecRaw, &senVecRaw, &w); err != nil {
|
||||
rows.Close()
|
||||
return nil, err
|
||||
}
|
||||
// 块向量(算场景相关度用):解码失败就当没有,不影响召回本身。
|
||||
if v, err := decodeVector(srcVecRaw); err == nil {
|
||||
rel.SourceVec = v
|
||||
}
|
||||
if v, err := decodeVector(tgtVecRaw); err == nil {
|
||||
rel.TargetVec = v
|
||||
}
|
||||
if v, err := decodeVector(senVecRaw); err == nil {
|
||||
rel.SentenceVec = v
|
||||
}
|
||||
// 旧表退场后边表不存 date_bucket,从 created_at 推日期桶。
|
||||
if rel.DateBucket == "" && !rel.CreatedAt.IsZero() {
|
||||
rel.DateBucket = rel.CreatedAt.Format("2006-01-02")
|
||||
|
||||
Reference in New Issue
Block a user