在多代理 AI 系统中,代理间的交互频繁产生海量记忆日志,如对话上下文、决策记录和知识更新。这些日志写入密集、顺序性强,传统 SQL 或向量存储难以高效持久化。LSM 树(Log-Structured Merge-Tree)作为日志结构合并树,正适合此类场景:通过内存 MemTable 缓冲顺序追加、后台分层 compaction 合并,实现高吞吐写入与可控读取放大。
LSM 核心架构适配多代理记忆
多代理记忆引擎以代理 ID + 会话 ID 为键前缀(e.g., "agent1:session123:entity"),将记忆条目(包含时间戳、类别如 facts/preferences、内容嵌入)追加为日志。核心组件:
-
WAL + MemTable:每代理独立 MemTable(跳表或红黑树有序),容量阈值 64MB。先追加 WAL(SQLite/PostgreSQL append-only),再入 MemTable。崩溃恢复从 WAL 重建,确保零丢失。
-
Flush 到 L0 SSTable:MemTable 满时冻结为 Immutable MemTable,后台异步 flush 为 L0 SSTable(有序键值文件,含数据块 + 索引块)。每个 SSTable 附 Bloom 过滤器(false positive 率 <0.1%,位数约 10 * 键数 /log2 (1/FP))。
-
Leveled Compaction:L0(最多 12 文件,重叠键)→L1+(每层键范围不重叠,L1 总量 10L0,Ln=10L (n-1))。触发:Ln 文件 > 4 个或总大小超阈值。合并时,逐层归并排序,删除 tombstone(逻辑删),保留最新值。参数:L0→L1 阈值 4 文件,L1 + 重叠文件最多 10 个 / 层。
-
跨代理隔离与召回:命名空间前缀隔离(e.g., "/agent1/"),全局索引层(稀疏 B 树)跨会话查询。优先级 eviction:热度分数 = 访问频 * 新鲜度(exp (-age/τ),τ=7 天),低优先级移至冷层(L7+)。
证据显示,此设计在 LevelDB/RocksDB 中经工业验证:写入 QPS>10 万,P99 延迟 < 5ms。"LSM-Tree 通过牺牲部分写入放大换取极高的写入吞吐,是 LevelDB、RocksDB 等知名存储引擎的基础架构。"
Bloom 去重与召回优化
Bloom 过滤器每 SSTable 独立,k=7 哈希函数(murmur3+fnv1a)。查询前查 Bloom:不存在即 miss,存在概率 > 99.9% 命中则二分索引 + 数据块读。去重:compaction 中 Bloom 辅助检测冗余键,节省空间 20-30%。
跨会话召回:Retrieval Agent 动态查询。流程:
- 输入嵌入→语义 / 全文 / 类别混合搜索(MemTable 优先)。
- 逐层 SSTable:Bloom 预滤 + L1 二分(O (log N / 层))。
- Top-K 融合(热度 + 相似度),注入 LLM 上下文(限 4K token)。
参数清单:
| 组件 | 参数 | 推荐值 | 说明 |
|---|---|---|---|
| MemTable | 容量 | 64MB | 平衡内存 /flush 频 |
| WAL | 缓冲 | 16MB | 顺序写批次 |
| Bloom | FP 率 | 0.1% | 位 / 键≈14 |
| Compaction | L0 阈值 | 4 文件 | 读放大控制 |
| Levels | 总数 | 7 | 写放大 < 10x |
| Eviction | τ | 7 天 | 新鲜度衰减 |
监控要点:compaction 队列 > 10、写放大 > 15x、L0 文件 > 8→扩容 / 调阈值。回滚:暂停 compaction,切换 readonly MemTable。
工程落地参数与伪代码
伪实现(Python+RocksDB):
import rocksdb # 或自定义LSM
db = rocksdb.DB("multi_agent_mem.db", rocksdb.Options(create_if_missing=True))
db.put(b"agent1:session1:fact:user_pref", b"FastAPI") # WAL+MemTable
# 召回
def retrieve(agent_id, query_emb):
bloom_cache = {} # LRU
candidates = []
for level in range(7):
for sst in level_ssts(level):
if bloom_might_contain(sst.bloom, key_prefix(agent_id, query_emb)):
val = db.get(key_prefix(agent_id, query_emb))
if val: candidates.append((score(val), val))
return top_k(candidates, 5)
风险缓解:
- 写放大:Leveled 策略 < 10x,限 compaction CPU<20%。
- 读放大:Bloom + 块缓存(LRU 256MB),最坏 7 层 < 50ms。
- 一致性:MVCC 序列号,snapshot 读跨会话。
Memori 项目启发此设计:"Memori enables any LLM to remember conversations, learn from interactions, and maintain context across sessions with a single line: memori.enable ()." 结合 LSM,实现高效多代理记忆。
来源:
- GitHub: GibsonAI/Memori
- LSM 参考:LevelDB 源码、RocksDB 文档