2.1 优先级与驱逐顺序


2.1 优先级与驱逐顺序

本节摘要:预算恒等式给了科目,本节给分配算法。第一步是写预算分配表:以一个 128k 窗口的客服 Agent 为例(示意数字),常驻层(指令 4% + 工具 10%)与输出预留(20%)先扣,剩余在记忆与素材之间倾斜分配——素材是主战场,因为它是总量最大、增长最快的成分。第二步是"不可动的三块":常驻层(刚性税)、输出预留、pinned 清单(任务原文、当前计划、红线约束、关键引用——丢了它们后面全白干)。第三步把"优先级"翻译成工程上可执行的驱逐顺序:超限时依次丢陈旧工具结果 → 已完成子任务的历史 → 早期探索对话 → 可重取的环境快照,每层内部"丢大块保线索"(截断优于整条删除,尾部比头部值钱)。最后给出 ce_budget.py 预算核算示意,并交代重新分配的三个触发时机。

学习目标

阅读完本节,你应当能够:

  1. 为自己的任务写出一张预算分配表(含常驻税与输出预留)。
  2. 默写驱逐顺序的四个顺位与 pinned 最小集,并解释排位理由。
  3. 读懂并改造 ce_budget.py,把四成分账本接到自己的应用上。

一、预算分配表:先扣,再分

以"128k 窗口的客服 Agent,带知识库检索与 15 个工具"为例(全部为示意数字):

科目 内容 占比(示意) 性质
指令 系统提示(角色 / 边界 / 契约) 4% 常驻税
工具 15 个工具 schema 10% 常驻税
记忆 长期记忆召回(用户偏好) 3% 动态
记忆 会话历史 16% 动态(线性增长)
素材 检索片段 + 工具结果 42% 动态(最大头)
输出预留 本轮生成空间 20% 不可动
机动 未分配缓冲 5% 应对突发长输出

两条读表结论:其一,常驻税 + 输出预留 ≈ 1/3——供料策略真正能调配的只有 2/3 窗口,这是很多人配预算时漏掉的前提;其二,素材拿最大份额是常态——它单条就可达数千 token,且质量上限最高(一条精准片段顶十轮寒暄)。

💡 分配表是"设计期预算",不是"运行期事实"。运行时每轮的实际占用会偏离它——偏离的校正机制就是下面第三节的驱逐顺序。

二、不可动的三块

  1. 常驻层:指令与工具每轮都在。它是刚性的:动态层再挤也省不出这笔钱,想"减税"只能回设计期(3.1 节精简系统提示、3.2 节收缩工具集)——所以本章的驱逐策略从不碰它。
  2. 输出预留:1.1 节立过的规矩,15%~25%(示意)。它被吃掉的第一个症状是模型回复变短、JSON 截断——看到这个症状先查预算表,别急着改 prompt。
  3. pinned 清单:动态层里"永不驱逐"的条目,最小集四项——任务原文(用户到底要什么)、当前计划(多步任务的进度状态)、红线约束("不许做 X"的约定)、关键引用(关键文件的路径 + 一行摘要)。第四项最容易被忽略:红线只在第 3 轮说过一次,驱逐器第 30 轮把它丢了,模型转个圈又把 X 做了。

⚠️ pinned 不是"越多越安全":pinned 条目本身也占预算,全 pin 等于没有驱逐空间。工程纪律是只 pin 上述四类,其余一切皆可驱逐。

三、驱逐顺序:优先级的工程形态

说"素材的优先级低于记忆"太空洞,工程上直接写谁先丢

顺位 被驱逐的内容 为什么它最先丢 丢了之后的补偿
1 陈旧工具结果(旧日志、已读过的文件原文) 时效最差:文件还在盘上、日志可重查 引用化——留"路径 + 一行摘要"占位
2 已完成子任务的历史 结论已沉淀进当前计划,过程无价值 结论并入 pinned 的计划条目
3 早期探索对话(试错讨论) 信息密度低 关键发现并入任务简报(第 6 章,后半)
4 可重取的环境快照(文件树、状态查询) 下一步需要时可再取 按需再查
pinned 四项 + 最近 K 轮(K 取 3~5,示意) 不驱逐:任务丢了等于失忆;最近轮丢了模型接不上话

排位的统一逻辑是重取成本:越容易重新获取的内容越先丢。文件可以重读、快照可以重查、结论已经沉淀——丢它们的代价最小;而任务原文与最近对话不可重取,丢一次就永久失忆。

每层内部还有一条细则——丢大块保线索:一条 3,000 token 的测试输出,整条删除不如截成"首 200 + [中间截断] + 尾 200"。尾部尤其值钱:编译器与测试的结论(成败、错误摘要)几乎总在末尾。

四、ce_budget.py:预算核算示意

# ce_budget.py —— 四成分预算核算与驱逐建议(写法示意,以实际工程为准) # 成分口径与 1.2 节四成分表一致;后半各章(压缩 / 框架)请沿用此口径 WINDOW = 128_000 # 总窗口 token(示意) RESERVE = 0.20 # 输出预留比例(示意) PINNED_TAGS = ("task", "plan", "redline", "keyref") # pinned 最小集四类 RECENT_K = 4 # 最近 K 轮不驱逐(示意) # 驱逐顺序:重取成本从低到高;pinned 与最近 K 轮不在序列内 EVICT_ORDER = ["stale_tool_output", "done_subtask_history", "early_chat", "env_snapshot"] def est_tokens(text: str) -> int: """粗估 token(示意):中文约 1 字 ≈ 1 token,其余约 4 字符 ≈ 1 token。 生产应换所用模型的分词器,或用 API 返回的用量回填校准。""" cn = sum(1 for ch in text if "\u4e00" <= ch <= "\u9fff") return cn + (len(text) - cn) // 4 def audit(entries: list[dict]) -> dict: """entries 每条形如 {"kind": 指令/工具/记忆/素材, "tag": 具体标记, "text": 内容, "turn": 所在轮次}。返回成分账本与总占用。""" cap = int(WINDOW * (1 - RESERVE)) # 输出预留先扣 ledger: dict[str, int] = {} for e in entries: ledger[e["kind"]] = ledger.get(e["kind"], 0) + est_tokens(e["text"]) return {"cap": cap, "ledger": ledger, "used": sum(ledger.values())} def evict_until_fits(entries: list[dict], max_turn: int) -> list[dict]: """超预算时按 EVICT_ORDER 逐层驱逐;pinned 与最近 K 轮永不丢。""" out = [dict(e) for e in entries] def protected(e): # 保护判定:pinned 标记或最近 K 轮 return e["tag"] in PINNED_TAGS or e["turn"] > max_turn - RECENT_K for layer in EVICT_ORDER: if audit(out)["used"] <= audit(out)["cap"]: break out = [e for e in out if e["tag"] != layer or protected(e)] for e in out: # 还超:丢大块保线索(尾部敏感,首尾各留 200 字符) if e["tag"] == "stale_tool_output" and not protected(e) and len(e["text"]) > 800: e["text"] = e["text"][:200] + "\n…[中间截断]…\n" + e["text"][-200:] if audit(out)["used"] > audit(out)["cap"]: raise RuntimeError("驱逐后仍超预算:该触发压缩了(第 6 章,后半)") return out

三个实现要点:tag 在写入时打——工具结果落进消息列表的那一刻就标 stale_tool_output(随年龄升级,如 10 轮后 fresh 转 stale),驱逐器只做机械筛选;每轮审计——audit() 的输出顺手就是第 6 章(后半)可观测的账本;抛错的含义——驱逐是日常超支的止血带,抛错说明结构性不够用,出路是压缩或按需检索,不是更狠的截断。

五、什么时候重新分配

预算分配表不是一次写死的:任务阶段切换(检索期素材占比高、写码期工具结果占比高)时要换表;水位逼近上限(如用量达 80%,示意)时触发压缩(第 6 章,后半);成分结构变化(新增 10 个工具 = 常驻税上涨)时全表重算。

本节要点回顾

  1. 分配表先扣三块:常驻税、输出预留、pinned——可调配的只有约 2/3 窗口;素材通常是最大科目。
  2. pinned 最小集:任务原文、当前计划、红线约束、关键引用;只 pin 这四类,其余皆可驱逐。
  3. 驱逐四顺位:陈旧工具结果 → 完成子任务历史 → 早期对话 → 环境快照;统一逻辑是重取成本,不可重取的永不丢。
  4. 丢大块保线索:截断优于删除,尾部比头部值钱;tag 在写入时打。
  5. 驱逐救不了结构性超支ce_budget.py 抛错的那一行,就是压缩的入口。

量的问题解决了——每个科目给多少、超了砍谁。但同样的内容按不同顺序摆,命中率可以差出一截:模型对窗口的开头、结尾与中部并不一视同仁。下一节讲位置效应。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U