4. 工作记忆的实现:滑动窗口、Token限制与注意力机制
好,咱们进入正题。工作记忆,说白了就是智能体的「便签纸」。它能记多少东西,能记多久,直接决定了这个智能体是聪明还是笨。我见过太多项目,模型本身很强,但就是因为上下文管理没做好,结果连简单的多轮对话都搞砸。
这一章,咱们就聊聊怎么实现工作记忆。三个核心手段:滑动窗口、Token限制、注意力机制。一个一个来。
4.1 滑动窗口:最朴素的短期记忆
滑动窗口的思路很简单——只保留最近N条消息。就像你手机里的聊天记录,默认只显示最近100条,再早的就折叠了。
为什么用滑动窗口?因为便宜、快。你想想看,每次对话都把所有历史塞进去,Token消耗不说,模型还会被无关信息干扰。我早期做客服机器人时就踩过这个坑——用户聊了20轮后,模型突然把第3轮提到的「退货」和当前问题混在一起,回答完全跑偏。
滑动窗口的实现,核心就两个参数:
| 参数 | 含义 | 推荐值 |
|---|---|---|
window_size |
保留的消息轮数 | 5-20轮 |
max_tokens |
窗口内总Token上限 | 模型上下文长度的30%-50% |
代码实现其实就几行:
class SlidingWindowMemory:
def __init__(self, window_size=10):
self.window_size = window_size
self.history = []
def add(self, message):
self.history.append(message)
if len(self.history) > self.window_size:
self.history.pop(0) # 丢掉最旧的
def get_context(self):
return self.history[-self.window_size:]
嗯,这里要注意:pop(0) 在Python里是O(n)操作。如果窗口很大(比如1000轮),建议用 collections.deque。我曾经在一个高并发服务里用list做滑动窗口,结果QPS一上来,GC直接爆炸。换成deque后,问题就解决了。
4.2 Token限制下的上下文管理
滑动窗口只是第一步。真正麻烦的是——每个模型的上下文长度是固定的。GPT-3.5是4K,GPT-4是8K/32K,Claude是100K。但你不能真的把100K全塞进去,原因有两个:
- 成本问题:Token就是钱。100K的输入,一次调用可能就要几毛钱。
- 注意力稀释:模型在超长上下文里,反而会「迷失」。中间部分的信息容易被忽略。
我做过一个实验:把一份50页的文档塞进32K模型,让它回答文档第25页的一个细节。结果正确率只有60%左右。但只塞相关的那3页,正确率直接到95%。
所以,Token限制下的上下文管理,核心策略就三个字:「挑着给」。
具体怎么做?我一般用这套流程:
- 优先级排序:系统指令 > 当前用户输入 > 最近3轮对话 > 关键记忆 > 历史摘要
- 动态截断:从优先级最低的开始丢弃,直到总Token数低于上限
- 摘要压缩:对早期对话做摘要,用几句话代替几十轮
看个例子:
def build_context(system_prompt, user_input, history, memory, max_tokens=4000):
context = []
token_count = 0
# 1. 系统指令必须保留
context.append(system_prompt)
token_count += count_tokens(system_prompt)
# 2. 当前输入
context.append(user_input)
token_count += count_tokens(user_input)
# 3. 最近3轮对话
for msg in history[-3:]:
if token_count + count_tokens(msg) > max_tokens:
break
context.append(msg)
token_count += count_tokens(msg)
# 4. 如果还有空间,加关键记忆
for mem in memory[:5]:
if token_count + count_tokens(mem) > max_tokens:
break
context.append(mem)
token_count += count_tokens(mem)
return "\n".join(context)
4.3 注意力机制简介
说到工作记忆,就绕不开注意力机制。你可能听过「Attention Is All You Need」这篇论文。但咱们不聊论文,聊工程。
注意力机制,说白了就是让模型学会「看哪里」。就像你在人群中找朋友,你会自动忽略其他人,只盯着那张脸。模型也一样——在长序列里,它需要知道哪些词更重要。
我画了一张图,帮你理解注意力机制的核心流程:
流程其实就三步:
- 生成QKV:每个输入词都生成三个向量——Query(我要找什么)、Key(我有什么)、Value(我是什么)
- 算分数:用Query和所有Key做点积,再Softmax归一化。分数越高,说明这个词和当前词越相关
- 加权求和:用分数对Value做加权平均。分数高的词,对输出的影响就大
你可能会问:这和工作记忆有什么关系?
关系大了。注意力机制就是工作记忆的「寻址方式」。模型在生成下一个词时,会通过注意力去「回顾」之前的内容。如果注意力分配得好,模型就能记住关键信息。如果分配得不好,就会「失忆」。
我个人的经验是:在工程实现中,不要只依赖模型的注意力机制。你需要在应用层做好上下文裁剪和优先级排序。模型再聪明,也架不住你给它塞一堆垃圾信息。你想想看,让一个天才在垃圾堆里找钻石,他也得找半天。