每周一早晨,我的LangChain代理都在重复同一件事:为三家固定客户生成安全周报。同样的上下文,同样的推理结构,同样的输出格式。而我每次都要付完整的Anthropic API费用。
查完日志后,数字触目惊心。45次运行,三类重复工作流——安全审计、发票处理、周报——生成的计划结构几乎完全一致。大模型每次都在重新推导同一个骨架。93%的token开销是冗余的。
这不是提示工程能解决的问题。是结构性问题。
主流代理框架——LangChain、LangGraph、CrewAI、AutoGen——默认都是无状态的。每次调用从零开始,没有上一次执行的记忆。一次性查询没问题,但重复工作流意味着永远付全款。
提示缓存(Anthropic和OpenAI的内置功能)能帮上忙,但只针对完全相同的输入提示。输入稍有变化就失效,而且不消除API调用,对下游的推理和计划生成毫无作用。
真正需要的是执行缓存——在计划层面缓存,而非提示层面。
核心思路:首次运行时,为执行计划生成指纹并存储为片段。后续遇到相同或语义相似的目标,直接从缓存调取计划,跳过LLM。
两种模式并行:
System 1——精确匹配。对目标+上下文+输入做SHA-256指纹。匹配成功则在约2.66毫秒内从本地SQLite重建。零API调用,零token。
System 2——语义匹配。目标相似但不完全相同——同一工作流,不同客户名或日期。通过嵌入相似度匹配存储计划,比对片段差异,只重生成变化部分。只为增量付费,而非完整计划。
后台有个叫Retrospector的进程,会把失败的片段隔离,确保错误模式不会被复用。信号总线追踪每类工作流的延迟基线和失败率,反馈回来强化或弱化缓存模式。缓存会随时间变聪明,不只是变大。
接入方式极简:
import mnemon
mnemon.init()
# 以下代码完全不变
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")
response = llm.invoke("Generate weekly security report for Acme Corp")
mnemon.init()在导入时即修补BaseChatModel.invoke和ainvoke。首次调用走LLM并缓存,后续相同或语义等效的目标直接从本地SQLite响应。
如需显式控制缓存范围,可传入自定义函数和缓存键策略。框架保持对底层客户端的零侵入,不破坏原有代码结构。
作者实测:三类重复工作流的token成本下降93%,延迟从数百毫秒降至个位数毫秒。代价是首次运行的缓存建立开销,以及约15MB的本地SQLite存储。
这个方案指向一个被忽视的优化空间——代理框架的"计划层"长期被当作黑盒,默认每次重新推理。但当工作流呈现明显周期性时,推理结果本身就是可缓存的资产。
代价也有:缓存失效策略需要精细设计,语义匹配的阈值调参需要迭代,失败片段的隔离机制增加了系统复杂度。但对于高频重复场景,收益远超成本。
更深的问题在于,为什么主流框架默认无状态?可能源于通用性与场景优化的张力——框架设计者优先保证任意查询的灵活性,而非特定模式的效率。这留下了垂直优化的窗口。
mnemon的解法不是替代LangChain等框架,而是寄生式增强:一行导入,透明拦截,原有代码无需改动。这种"非侵入式补丁"的架构选择,降低了采纳门槛,也限制了深度整合的可能性。
作者最后提到,Retrospector的反馈机制让缓存具备有限的学习能力——这不是静态的查询结果缓存,而是带质量评估的执行计划复用系统。方向有趣,但长期效果仍需观察。
热门跟贴