召回预算:条数 / 字符 / 超时上限


文档摘要

召回预算:条数 / 字符 / 超时上限 本节摘要:第 6 章的收束节。召回引擎产出了一堆相关记忆,但不能全塞进上下文——上下文窗口有限,记忆太多会挤掉真正重要的内容,还可能拖慢响应。本节讲清三道召回预算闸门:条数上限(防稀释)、字符上限(防撑爆)、超时上限(防拖慢),它们的执行顺序与裁剪策略,以及为什么优先级是「超时>字符>条数」。这是「记忆不喧宾夺主」的最后一道工程保障。 一、为什么需要预算:上下文窗口是稀缺资源 先理解一个硬约束:上下文窗口有限。在这个约束下,记忆不是「越多越好」: 预算闸门的存在,就是让「相关记忆」变成「既相关又适量的记忆」——在有限的窗口里,只放最有价值的那些。

召回预算:条数 / 字符 / 超时上限

本节摘要:第 6 章的收束节。召回引擎产出了一堆相关记忆,但不能全塞进上下文——上下文窗口有限,记忆太多会挤掉真正重要的内容,还可能拖慢响应。本节讲清三道召回预算闸门:条数上限(防稀释)、字符上限(防撑爆)、超时上限(防拖慢),它们的执行顺序与裁剪策略,以及为什么优先级是「超时>字符>条数」。这是「记忆不喧宾夺主」的最后一道工程保障。

一、为什么需要预算:上下文窗口是稀缺资源

先理解一个硬约束:上下文窗口有限。在这个约束下,记忆不是「越多越好」:

没有预算的问题 召回 100 条相关记忆 → 全塞进上下文 ├─ 占满窗口,真正的用户问题/代码被挤出 ├─ 记忆之间互相稀释,重要的反而不突出 └─ 注入耗时,响应变慢 → 记忆反而让 Agent 变笨、变慢

预算闸门的存在,就是让「相关记忆」变成「既相关又适量的记忆」——在有限的窗口里,只放最有价值的那些。

闸门 防的问题 直观理解
条数上限 条数过多稀释重点 「贪多嚼不烂」
字符上限 单条/总量过长撑爆窗口 「一条太长也受不了」
超时上限 召回耗时拖慢响应 「用户在等,及时更重要」

二、三道闸门的执行顺序

三道闸门不是平等并列,而是有优先级和顺序:

三道闸门执行顺序 召回原始结果(BM25+向量+RRF 融合后,按相关度排序) │ ├─ 闸门1: 条数上限(N 条) │ 超过 N 条? → 已按相关度排序,只取前 N 条 │ (防稀释:宁缺毋滥,留最相关的) │ ├─ 闸门2: 字符上限(M 字符) │ 累计字符超 M? → 从尾部裁剪 │ (防撑爆:保证不超窗口) │ └─ 闸门3: 超时上限(T 毫秒) 召回总耗时超 T? → 立即返回已收集的,停止等待 (防拖慢:响应优先) ▼ 最终注入的记忆(适量、相关、及时)

执行顺序的设计逻辑:条数先裁(粗筛,留最相关的)→ 字符再裁(细裁,防单条过长)→ 超时兜底(任何环节超时立即止)。

关键概念:注意「条数裁剪是基于相关度排序的」——不是随机丢,而是丢相关度最低的尾部。所以召回引擎的排序质量(上一节的 RRF)直接影响裁剪后留下的是不是最好的。排序越准,裁剪后质量越高。

三、优先级:超时 > 字符 > 条数

三道闸门里,超时的优先级最高——它是一个「硬中断」:

优先级逻辑 超时(最高):用户在等,无论条数/字符是否满意,超时立即返回 → 响应优先于完整 字符(中):硬窗口约束,超了必裁 → 不能让记忆撑爆上下文 条数(相对软):N 是经验值,可略调 → 主要防稀释,边界没那么硬
闸门 优先级 触发后的动作
超时 最高(硬中断) 立即返回已有结果,不等
字符 中(硬约束) 从尾部裁剪到不超
条数 相对软(经验值) 留前 N 条

⚠️ 注意:超时优先级最高意味着——极端情况下,召回可能返回「不完整」的结果(比如只跑了 BM25 没等向量)。这是刻意的取舍:「及时但不全」好过「全但让用户等」。这也是为什么召回引擎设计成「两路可独立返回」——一路超时不拖累另一路。

四、裁剪策略:留什么、丢什么

裁剪不是「随机丢」,而是「留最有价值的」。具体策略:

裁剪的优先级(留什么) ① 高相关度(RRF 分数高)的优先留 ② 高使用计数的优先留(常用记忆,第3章元数据) ③ 高置信度的优先留(L1 抽取/合并时累积) ④ 来自高层(L2/L3)的优先留(快速进入语境价值高) → 被裁的:相关度低、少用、低置信、冗余的
高相关度 低相关度
高使用计数 少用
高置信度 低置信度
L2/L3(高层) 冗余 L1

这种「多维优先级」的裁剪,让有限的预算装下「最该装」的记忆。值得注意的是「使用计数」参与裁剪——常用的记忆更容易留下,这让系统有「越用越顺手」的特性:常用记忆被反复召回强化,不用的逐渐淡出。

五、预算与代理层 injection 的衔接

召回预算裁剪后的「最终记忆」,会交给代理层(第 8 章)做 injection。预算与 injection 有个重要衔接:

预算与 injection 的衔接 召回预算裁剪后:最终记忆(适量) │ ├─ 代理层 injection 分流: │ 稳定的(L2/L3/Skill)→ inject(拼进 system prompt) │ 易变的(L0/L1)→ toolize(作为工具按需调用) │ └─ inject 的部分会算进「注入大小控制」 → 召回预算 + injection 大小控制 = 双重保障

也就是说,召回预算是「第一道控量」,代理层的「注入大小控制」是「第二道控量」——前者控召回总量,后者控实际进 system prompt 的量(toolize 的不占 system prompt)。两道结合,确保上下文既不被召回撑爆,也不被注入撑爆。第 8 章会详解这个双道控制。

💡 技巧:调试「上下文太满/响应太慢」时,分两层查:① 召回预算(条数/字符/超时阈值是否合理),② injection 策略(该 toolize 的有没有误 inject)。两层都可能出问题,排查方向不同。第 9 章 SDK 接入的性能建议也基于这两层。

本节要点回顾

  1. 预算必要性:上下文有限,记忆越多反而越笨越慢——预算让记忆「适量」。
  2. 三道闸门:条数(防稀释)、字符(防撑爆)、超时(防拖慢),执行顺序条数→字符→超时兜底。
  3. 优先级:超时最高(硬中断,响应优先于完整)> 字符(硬约束)> 条数(相对软)。
  4. 裁剪策略:留高相关/高使用/高置信/高层,丢低相关/少用/低置信/冗余——越用越顺手。
  5. 双道控量:召回预算(第一道)+ injection 注入大小控制(第二道),第 8 章详解后者。

第 6 章到此完成——从 L0 录制、L1 抽取去重、L2/L3 沉淀、混合检索、到召回预算,整条 Pipeline 的源码级机制都讲透了。下一章转向另一类记忆——知识引擎 Wiki 与 CodeGraph。


发布者: 作者: 灏天文库 转发
评论区 (0)
U