第十七节 历史折叠(Compact)
当上下文接近模型上限时,AVL Code 会自动把历史折叠为摘要,确保对话可以无限延续。
17.1 触发方式
- 手动:会话标签栏右键 → 折叠当前会话。
- 自动:助手在自身上下文接近上限时自动触发,不打断当前回合。
17.2 折叠后的可见性
折叠是只追加的:原消息物理保留,只是被标记为"对当前回合不可见"。你可以在消息流上点击折叠摘要展开查看原始内容。
17.3 保留的结构化信息
折叠摘要中至少保留:
- 当前计划与待办的最新状态
- 关键的工具执行结论
- 用户已确认的关键决策
- 上下文必需的事实(路径、版本号等)
17.4 多次折叠
长会话可能经历多次折叠;每次折叠都是叠加而非替换,最早的内容总能逐层回溯回去。
17.4.1 自动折叠被中止时显示真实原因
自动折叠(自动 compact)历史被中止时,聊天区会显示具体原因而不是笼统提示,方便你判断是配置、上下文还是其它情况导致;优雅中止 / 保留会话的既有行为不变。
17.4.2 上下文超限根治
某些场景下对话可能突然报错断流(上游返回 400),且自动压缩也救不回来。真因往往不是 token 统计低估,而是 单条工具结果太大 — 例如安全扫描 sec.* 一次吐出近 300 KB 的 strings 提取,几乎占满整个上下文窗口,两条背靠背就把下一次请求顶过窗口被上游直接拒绝(这种拒绝不返回用量,反应式压缩看不到、来不及触发)。
两层根治:
- 工具结果钳制:每条工具结果先钳到一个安全大小(约为上下文窗口的 6%,按 UTF-8 字符边界安全截断并留「继续读取」标记),从源头消除「一步顶爆窗口」。
- 发送前预估式护栏:以上一轮真实用量为锚 + 本地估算本轮新增;预判会超窗就提前走"压缩后继续",不再白发一个注定被拒的请求。
17.4.3 自动压缩后可靠续跑
自动压缩历史后,AI 有时会停下来只回一句寒暄 / 报当前时间 / 反问「请问需要我做什么」,而不接着完成手里的活。本版做了一组改进让它可靠续跑:
- 续跑指令改为明确的指令式:直接要求依据压缩摘要里未完成 / 进行中 / 受阻的任务从下一步继续自主执行,不要只回寒暄或当前时间。
- 续跑那一轮不再在末尾注入时钟提示,避免弱模型把「当前时间」当成最新重点而忽略待办。
- 万一续跑还是停在反问上,自动补一记「继续」(复刻你手动敲「继续」的效果)把后续工作推完。
- 进度条复用手动
/compact同款(带百分比 / 预计时间 / 实时字数),不再只有一个模糊的「处理中」指示。
17.4.4 思考型模型的压缩不再被误判超时
之前自动压缩对所有模型用同一个固定总时限,遇到 reasoning / extended-thinking 型模型时,模型在思考阶段没立刻吐 token 就被错杀,于是续跑前的摘要直接失败。本版把等待改为空闲看门狗:只要服务端还在持续产出(包括 thinking 段落),就继续等;只有真正一段时间无任何动静才超时。结果:思考型模型也能正常完成压缩摘要,对话不再被中途掐断。
17.4.5 纯空白回复不再被误判为"结束"
推理型模型有时会在思考中间态吐出只有换行 / 空格的片段。之前终止判定是「输出非空就算还在干活」,这种纯空白片段会被反向解读为"已结束",整轮被提前掐断。本版把判定改为「按去空白后是否为空」 — 思考中间态的空白段不再误停,整段推理完整保留。
17.5 KV Cache 前缀缓存治理(性能)
上游模型服务按「前缀缓存」工作:系统提示 → 工具列表 → 对话历史 这一长串,只要靠前的字节没变就能命中缓存、跳过重算;一旦靠前位置有任何一字节变化,从该处往后的缓存全部作废、整段重算。
为让缓存在整段对话里持续保温,AVL Code 在三个"每轮都在变"的源头做了治理:
| 源头 | 治理 |
|---|---|
| 工具列表顺序 | 按工具名排序钉成确定顺序(之前 Go map 遍历是随机的,每轮顺序抖;治理收益最大、无条件每轮生效) |
| 目标(goal)块 + 记忆召回 | 从系统提示前缀剥离,改为行尾瞬态注入(界面不可见、不落盘),只花当轮增量 token,不再牵连前缀缓存 |
| 项目指令(AGENTS.md) | 特意保留在前缀 — 一次会话内稳定,留在前缀同字节重读不失效;编辑时才失效(正是期望行为) |
TUI 模式同步治理 — 命令行界面也把目标块改为行尾瞬态注入,桌面 / 终端两种使用方式的缓存表现一致。
效果:长对话、多轮工具调用场景下,命中缓存的比例显著提升 — 响应更快、token 成本更低。这条优化对用户透明,无需任何配置。
17.6 记忆宫殿(长期记忆)
AVL Code 内置「记忆宫殿」作为跨会话的长期记忆库。一段对话结束后,HookStop 会触发记忆候选抽取,落到当前宫殿的草稿盒(_pending/ 子目录)由你审阅;批准后才正式入库进入相应「房间」(Room)。命令面板里 /memorize <text> 直写一条、/memory 打开宫殿面板。
17.6.1 越用越聪明:召回加权与负反馈
记忆不再只按时间或匹配度排序:
- 召回 / 成效双计:每条记忆带
recall_count(被翻出来次数)与success_count(用了之后这一轮顺利完成的次数),加权后常被命中又确实帮上忙的排得更靠前;老被翻出却没派上用场的慢慢沉底,不再干扰判断。 - 罕见词加权:检索时偏冷门 / 特征更强的词命中权重更高 — 更容易把真正相关的那一条翻出来,而不是被通用词淹没。
- 无关时少塞:与当前提问相关性弱的记忆不再一股脑注入,只保留你置顶(pinned)的几条 — 既省 token 又减少干扰。
- AI 自审的教训自动沉淀:自检门禁的
judge检查器发现的问题(见 §10.11.1)会自动沉淀成记忆草稿进入待审区,下次遇到同类问题能直接复用。
17.6.2 冲突放「待审」,不硬覆盖
新记的内容与旧记忆矛盾(同 Subject + Predicate 但 Object 不同 — 典型如偏好 / 决策翻转)时,不直接覆盖,而是落到草稿盒并标 ConflictHint = 旧记忆 ID:
- 前端
MemoryReviewPanel在该条上高亮显示「与旧记忆冲突」。 - 你可一键取代(旧记忆置过期)/ 保留旧的 / 驳回新的。
- 与
MergeHint(与旧记忆三元组高度重合 → 疑似重复、建议合并)互补:merge = 该合并,conflict = 该取代。
17.6.3 记忆健康看板
设置 → 记忆宫殿 → 健康看板 把每座宫殿的状况一屏摊开:
| 指标 | 含义 |
|---|---|
| 总数 / 已过期 / 从未召回 | 概览 |
| 房间数 / 每房间记忆数 | 容量分布 |
| 热度榜(Top 10) | 召回最多的 — 经常派上用场的记忆 |
| 冷门清单(≤ 20) | 从未被召回的 — 可考虑清理 |
| 低效清单(≤ 20) | 召回够多(≥ 5)但成功率 ≤ 20% 的 — 负反馈正在压制,建议人工复核 |
| 疑似重复簇(≤ 20) | 同房间三元组高度重合(≥ 2/3 命中)的记忆簇 — 建议合并 |
| 草稿盒待审计数 | pending_duplicates(疑似重复)+ pending_conflicts(疑似冲突) |
每一条都能直接跳到正式条目做置顶 / 编辑 / 删除;簇可一键合并。
17.6.4 自动反省(复盘学习,GRAI+KISS)
打开 *设置 → 智能体 → 自省 → 「自动反省(复盘学习)」*(默认关,因为会有一次 LLM 调用成本)后,多步任务收尾时会自动跑一次复盘:按 GRAI 框架回顾这一轮——目标(Goal)、结果(Result,读本次轨迹摘要 + 自愈统计)、归因(Analysis,5-WHY,优先看自己可控的原因)、洞察(Insight)——再把可行动的经验教训按 KISS 分类(保持 / 改进 / 停止 / 开始)沉淀下来,下次遇到类似情况能直接用上。
- 只在做过多步工作的任务收尾时触发:单轮问答不会触发;异步进行、不阻塞你继续用。
- 教训落到记忆宫殿的「待审草稿盒」(
_pending,房间scratch、类型 decision、不衰减),需你人工审批后才进入正式记忆库参与检索(每次最多 8 条,按标题去重)。 - 全程 fail-safe:记忆关闭 / 无 LLM / 解析失败都会静默跳过,绝不影响任务本身。
自动反省读取的「自愈统计」正是 §8.5.1 里那套自愈成败历史,二者共同构成经验学习闭环:自愈从历史学着调整尝试次数,复盘把教训沉淀供你审阅。
