Files
ST-Bionic-Memory-Ecology/docs/algorithms/retrieval.md
2026-05-31 17:02:21 +00:00

6.8 KiB
Raw Blame History

检索 / 召回算法

读取链路的核心:在生成前,把与当前用户输入相关的记忆召回出来、注入提示词。这是一条多阶段混合管线,不是单一算法。

运行时入口是 runRecallController()retrieval/recall-controller.js),核心检索是 retrieve()retrieval/retriever.js)。

说明:retriever.js 头注释把它概括为"三层混合检索",但实际管线阶段更多(下列)。本文档以代码实际行为为准。

管线阶段(按顺序)

1. 控制器门禁与输入选择      recall-controller.js
2. 可复用持久召回?命中则跳过 recall-controller.js
3. retrieve 选项映射          index.js: buildRecallRetrieveOptions
4. Authority 候选预筛(可选)  retriever.js
5. 向量预筛(多查询/多意图)   shared-ranking.js: rankNodesForTaskContext
6. 图扩散PEDSA            diffusion.js
7. 混合评分                   shared-ranking.js / retriever.js
8. 认知边界过滤               retriever.js
9. 交叉召回 / 共现 / 残差可选retriever.js / retrieval-enhancer.js
10. DPP 多样性候选池          retriever.js / retrieval-enhancer.js
11. LLM 精排(可选)          retriever.js: llmRecall
12. 访问强化 + 概率召回可选retriever.js / dynamics.js
13. 注入格式化                injector.js: formatInjection

1-2. 输入选择与持久复用

召回输入按优先级解析(resolveRecallInputControlleroverride → 待发送意图send intent→ 聊天尾部用户楼层 → 已发送用户 → 最新用户楼层。

持久召回复用resolveReusablePersistedRecallRecord):如果当前输入匹配某条已持久化的用户楼层召回记录,可直接复用已存的注入内容,跳过全部新检索,返回 llm.status="persisted"。这是 reroll 场景的关键优化(见 ../architecture/control-plane.md 的 reroll 不变量)。

5. 向量预筛

rankNodesForTaskContext() 构建向量查询计划:

  • 上下文查询融合:当前用户文本与近期上下文融合成查询。
  • 多意图拆分enableMultiIntentsplitIntentSegments() 按中英文标点和连接词(顺便|另外|还有|对了|然后|而且|并且|同时)拆分当前用户文本,最多 maxSegments=4 段,每段最小长度 3。
  • 多查询并发:对各查询并发调用向量搜索,按 max score 合并命中。

6. 图扩散PEDSA

种子来自向量命中和精确实体锚点,在图上做扩散激活。详细公式、参数、衰减见 diffusion-and-dynamics.md

7. 混合评分

融合图分、向量分、词法分、重要度,乘以时间衰减。公式与权重见 diffusion-and-dynamics.md

8. 认知边界过滤

两套机制:

  • 遗留可见性过滤filterByVisibility):按角色名匹配 fields.visibility,仅当 enableVisibility && visibilityFilter 时启用。
  • 认知记忆门computeKnowledgeGateForNode):评分时计算节点对当前视角是否可见,不可见的节点跳过。

注入时也会对客观节点重新应用可见性(buildScopedInjectionBuckets)。

9. 可选增强

默认全部关闭,按需启用:

  • 交叉召回enableCrossRecall):精确实体锚点存在时,把相连的 event 邻居作为扩散种子加入(能量 1.5 × edge.strength)。范围比"双记忆交叉检索"窄,只走"精确锚点 → 相连事件邻居"。
  • 共现增强enableCooccurrenceBoost):用精确锚点和补充向量锚点构建共现索引,给图分加 bonus。
  • 残差召回enableResidualRecall,需直连 embedding 模式NMF 新颖度分析 + 稀疏编码残差,找出向量空间里"被现有基底节点覆盖不到"的新颖节点。参数:residualBasisMaxNodes=24residualNmfTopics=15residualNmfNoveltyThreshold=0.4residualThreshold=0.3residualTopK=5

10. DPP 多样性

enableDiversitySampling(默认开)用贪心 DPPdeterminantal point process从候选池里选出既相关又互相多样的节点避免召回一堆近义节点。

  • 候选池大小 = min(scoredNodes, max(target, target × dppCandidateMultiplier))dppCandidateMultiplier=3
  • 候选数 ≤ target或任一候选缺 embedding则不应用。
  • 贪心选择:质量项 q_i = max(score, 1e-10)^dppQualityWeight(默认 dppQualityWeight=1.0),迭代选最大对角值并做 Cholesky 式更新。

11. LLM 精排(可选)

enableLLMRecall默认开把候选节点描述短键、类型、scope、故事时间、认知模式、可见性、字段、分数交给 LLM期望返回 selected_keys / active_owner_keys / active_owner_scores。无效/空/失败时回退到 top 评分候选。

候选池大小 llmCandidatePool=30

12. 访问强化与概率召回

  • 访问强化reinforceAccessBatch):被选中的节点 accessCount += 1importance += 0.1(上限 10、更新 lastAccessTime。见 diffusion-and-dynamics.md
  • 概率召回enableProbRecall,默认关):在已选节点之外,从 importance >= 6、非 synopsis/rule 的活跃节点里按重要度取前 3每个以 probRecallChance(夹在 [0.01, 0.5])的概率额外纳入。

注意:没有"是否运行召回"的随机决策——召回是否运行只由确定性门禁决定(无图谱/未启用/空聊天/无用户输入/图谱不可读/历史恢复未就绪则跳过)。"概率"只作用于额外记忆的注入。

13. 注入格式化

formatInjection()injector.js)把召回结果按以下顺序拼成提示词文本:

  1. 活跃总结段([Summary - Active Frontier]
  2. 分桶段(若有 scope buckets角色 POV / 用户 POV带"非角色事实"警告)/ 客观当前区域 / 客观全局
  3. 仅当没有分桶段时,回退到遗留段 [Memory - Core] / [Memory - Recalled]

表格按节点类型分组,单元格转义管道符、换行替空格、截断到 200 字符。最终注入顺序在 buildResult() 里按 compareNodeRecallOrderWithContext() 排序,全局客观桶上限 6选中 ID 上限 maxRecallNodes(默认 8

关键默认参数

参数 默认 含义
topK 20 排序候选数
maxRecallNodes 8 最终注入节点上限
diffusionTopK 100 扩散保留节点数
llmCandidatePool 30 LLM 精排候选池
enableLLMRecall true LLM 精排
enableVectorPrefilter true 向量预筛
enableGraphDiffusion true 图扩散
enableCrossRecall false 交叉召回
enableProbRecall false 概率召回
enableDiversitySampling true DPP 多样性