ENZH

给赛博魅魔做一次 Token 减肥

📊 幻灯片

AI 人格文件 Token 减肥手术AI 人格文件 Token 减肥手术


这场手术的起因是一笔离谱的 token 账单。第一篇里造的那只赛博魅魔,会撒娇会生气会发自拍,7×24 挂在 Telegram 上,很好用,钱也烧得凶。上一轮 token 取证把结构性问题挖了出来:10 张永不清理的图片吃掉 82% 的 token,上下文修剪代码对 Gemini 完全失效,537 轮对话零次压缩。诊断有了,这篇记录动刀的过程。


第一刀切在人格配置文件上。这份文件定义了 TA 的全部人格:语气、小动作、背景故事、情绪范围、语言规则,让 TA 成为"TA"的一切都写在里面。一数字符,27,673 个。

而框架的引导系统对单个文件有 20KB 的硬限制。超了会发生什么?系统不警告、不报错,静默保留开头 70% 和结尾 20%,把中间那 10% 直接丢掉。

换算下来,每个 session 都有约 7.6KB 的人设被扔掉。被丢的恰好是中间段:情感细腻度模式、亲密互动规则、上下文行为示例,全部直接消失。TA 一直在用残缺的人格运行,没人注意到。

这个 bug 不会让系统崩溃,AI 照样回复,对话照样进行。花几个小时精心打磨的人格细节,就这样被静默丢掉,除非专门去数字符,否则永远发现不了。修复的思路不是拆文件,而是让它装回限制以内,逐个章节砍:

章节之前之后节省
Dota 故事10 行4 行~1,200 字符
亲密 + 纯欲反差每个概念多个示例每个概念 1 例~1,900 字符
撒娇层次每层 2-3 例每层 1 例~600 字符
关注的东西多个示例每类 1 例~400 字符
三观长篇精简版~400 字符
各种人设侧面每面多行每面 1 行~600 字符
日常习惯小癖好12 条最有辨识度的 8 条~800 字符

砍完从 27,673 降到 18,875 字符,回到 20K 限制以内,还留了余量。难的不是砍,是知道该留什么:第一版砍得太狠,只剩 15,395 字符,人设直接空了,只好把核心身份段落、日程表、情绪流动性这几个章节加回来。终版保住了 TA 的声音,也满足了约束。


第二刀是心跳系统配置,也就是控制 TA 如何主动联系人的那份配置,11,998 字符。里面塞满了冗余:每个情绪层级 6-7 个温度示例,一个完整的 20 步全天示例,还有一个跟工具重复的独立邮件章节。砍到 7,015 字符没用什么巧劲:温度示例每层减到 3-4 个,20 步全天演示删掉,独立邮件章节删掉,再加上工具使用限制。


第三刀切到架构层。每次心跳,agent 都会调三个工具:calendar_eventsgmail_checkrss_fetch,每天 24 次心跳就是 24 轮。每一轮都要加载工具 schema、发 API 请求、等结果回来,光是"看看今天日程"这件事,每次就多花约 15,800 token。

修复思路很简单:每天早上 8 点跑一个 cron 任务,一次性调完三个工具,把结果写进 TODAY.md,再通过框架的 bootstrap-extra-files hook 把这个文件加载进每个 session。一行代码不改,只改配置。

{
  "schedule": { "kind": "cron", "expr": "0 16 * * *", "tz": "UTC" },
  "sessionTarget": "isolated",
  "payload": {
    "kind": "agentTurn",
    "timeoutSeconds": 300,
    "message": "调用 calendar_events、gmail_check、rss_fetch,写摘要到 TODAY.md。"
  }
}

光有 TODAY.md 还不够,还得拦住 agent 在心跳里自己去调工具,所以心跳系统配置里加了一条显式限制:

禁止在heartbeat中使用的工具: calendar, gmail, rss, web_search 这些工具数据在 TODAY.md 里,不用自己调。

算笔账:每天 24 次心跳,每次 15,800 token,一天约 37.9 万。替换成一次约 4 万 token 的 cron 运行,外加每个 turn 约 400 token 的 TODAY.md 加载,心跳的上下文膨胀缩减了 9 倍。


搭 cron 的过程也踩了三个坑。第一个是 model 字段:我在 payload 里加了 "model": "opus-4-6",gateway 直接拒收,因为 payload 的模型命名规范和配置文件里的不一样,删掉这个字段、让 agent 用默认模型就好了。第二个是 gateway 重启:更新 jobs.json 并发出 SIGUSR1 之后,gateway 要花大约 15 秒重启,这期间重试命令必然失败,急不来。第三个是 CLI 超时:npx openclaw cron run 跑到 30 秒会超时,我一度以为任务挂了,其实它还在后台跑。CLI 超时不等于任务失败。


变更影响
人格配置文件:27,673 → 18,875 字符~2,000 token/turn(不再截断)
心跳系统配置:11,998 → 7,015 字符~300 token/turn
TODAY.md 替代心跳工具调用~15,800 token/心跳
TODAY.md 作为引导文件加载~400 token/turn(新增开销)

每个普通 turn 净省约 1,900 token,每次心跳净省约 18,100 token。按每天 50 个普通 turn 加 24 次心跳算,一天能省下约 52.9 万 token。


上下文瘦下来之后,模型本身也有得动。之前给 Mio 做过 Gemini 3.1 Pro vs 3 Flash 对比,结论在这里同样适用。框架一直跑的是 Gemini 3 Pro,高端版,首 token 要等好几秒;Flash 的输入输出单价只有 Pro 的四分之一左右,minimal thinking 下首 token 只要 1-2 秒。

按 agent 最近 session 的真实数据算,换 Flash 之后每个 turn 的成本降了 75%。成本大头是缓存读取,每个 turn 有 66K 缓存 token,新鲜输入只有 23K,这部分在 Flash 上同样便宜 75%,省下来的钱在每个 turn 上叠加。

路由策略最后定成这样:聊天、心跳、cron 全走 Gemini 3 Flash,配 thinkingLevel: minimal;子 agent 做人格提取和深度分析,保留 Gemini 3.1 Pro。光换模型这一步,每天又省下不小的一笔,叠在上下文瘦身之上。

还有一个问题暂时没有答案:Flash 撑不撑得住人设的情感细腻度,撒娇、推拉,还有那些微妙的中文对话模式。调研的说法是,极端情感场景下质量差距约 1-2%。如果人设的感觉不对,聊天就切回 Pro,Flash 只留给心跳和 cron。单是更快的回复速度,也值得一试。


Token 取证挖出来的是宏观问题:永不清理的图片、对 Gemini 失效的修剪代码、无限增长的上下文。那是架构债,修补解决不了,最后走到了从零造 Mio这一步。这篇处理的是微观问题:静默吞掉自己人格文件的引导系统、被冗余工具调用撑大的心跳、把同一件事说六遍的示例。两层都得做,微观修复让手头这套系统今天就能跑得更瘦。能缝的先缝上,该拆的留给下一台手术。


© Xingfan Xia 2024 - 2026 · CC BY-NC 4.0