我们给 Imagifly「梦梦」这个 QQ Bot 接了 LLM,让它自然地混进群聊。上线一个月后拉账单:日均 token 消耗 64.5 万、日均费用 $0.80。对一个以闲聊为主的 bot 来说,这个数字明显偏高。这篇文章记录一次完整的优化复盘——不是拍脑袋的”我们优化了性能”,而是把每一分降幅拆到具体措施上的归因分析。
数据来源是 MaiBot 内置的 llm_usage 表,对比优化前(8 月上旬,日本服务器)和优化后(8 月中下旬,icstest 服务器)两个完整时段。
指标 | 优化前 | 优化后 | 变化 |
|---|---|---|---|
日均请求数 | 166 | 153 | -7.8% |
日均 Token 消耗 | 645,157 | 339,042 | -47.4% |
日均费用 | $0.80 | $0.16 | -80.0% |
单次请求平均 Token | 3,879 | 2,209 | -43.1% |
Prompt Cache 命中率 | 59.2% | 59.1% | 持平 |
两个降幅要分开看:token 减了近一半,费用砍了八成——费用降幅大于 token 降幅,是因为模型结构也动了(后面细说)。请求量基本没变,说明优化没有以牺牲响应频次为代价。
3.1 群聊上下文窗口化(-35~40%,最大头)
问题出在初版设计:每次调用 LLM 都把全量群聊历史灌进 prompt。群越活跃、bot 运行越久,上下文就越长,token 消耗像滚雪球。改成窗口化——只保留最近 1 小时、20 条消息、3 张图,再加哈希去重防止重复内容入窗。这一项贡献了绝大部分降幅。
3.2 用户上下文去重(-5~8%)
群里的重复签到、刷屏内容,每次都会触发一遍完整的 LLM 调用。加了 120 秒去重窗口加模板池之后,这类无效调用基本消除。
3.3 输入容错设计(-3~5%)
一个容易被忽略的隐性消耗:用户口误输入(模型名称打错、全角半角混用)触发调用失败,失败后走重试链路,一次失误变成多次计费。在入口做模型简称映射和全角转半角之后,这条重试链路基本消失。
3.4 消息归属区分(-2~3%)
“回复错人”在群聊场景里会导致用户重复提问,每一轮重复提问都是新的 LLM 调用。把消息归属标记做准之后,这类浪费显著减少。
3.5 pro 模型下线(费用侧主要贡献)
初版有 15% 的请求走 deepseek-v4-pro,pro 单价约是 flash 的 5.9 倍。实测下来 bot 的闲聊任务 flash 完全够用,优化后 pro 归零、全量 flash。token 总量没因此下降,但费用直接从 $0.80 掉到 $0.16。
优化措施 | 预估贡献 |
|---|---|
群聊上下文窗口化 | -35~40% |
用户上下文去重 | -5~8% |
输入容错设计 | -3~5% |
消息归属区分 | -2~3% |
pro 模型下线 | 费用侧主要贡献 |
其他(新增 learn 任务等) | +5~8%(抵消项) |
指标 | 优化前 | 优化后 | 降幅 |
|---|---|---|---|
平均 Prompt Token/请求 | 3,503 | 2,120 | -39.5% |
平均 Completion Token/请求 | 376 | 89 | -76.4% |
Completion 降幅比 Prompt 大得多。这不是限制输出长度换来的,而是上下文变准之后,模型不再需要长篇大论地”对齐”灌进来的冗余历史——输入干净了,输出自然收敛。
优化后的总 token 里,planner 任务仍占 71%,learner 类任务占比反而涨了 20 倍(0.4% → 5.8%)——这是我们主动加的:bot 开始从群聊里学习新梗和用户偏好。也就是说,这次优化省下来的预算,一部分被重新投到了”让 bot 变聪明”上。降本的目的从来不是省到极致,而是把算力花在值得的地方。
Prompt Cache 命中率全程稳定在 59% 左右,说明窗口化没有伤害缓存友好性——固定前缀(人设、工具说明)保持不变,被窗口化的只有尾部高频变化的群聊内容,这正是缓存机制喜欢的结构。
全月账单:4,067 次请求、1,065 万 token、总费用 $8.05。对个人开发者来说,这套方法的价值不在绝对金额,而在方法论:先有分任务、分模型的消耗明细,再做归因,最后逐项验证。任何一个 LLM 应用,这套账都值得拉一遍。