通过 L1 scratchpad + L2 vault 双层 SQLite-Vec 架构,实现完全离线的 Agent 记忆系统,47ms 平均召回延迟优于云端向量数据库,且提供了完整的工程实现细节。
上下文危机:为何默认的 Agent 记忆在规模化时失效
现代 AI Agent 面临一个关键瓶颈:上下文窗口限制和 stateless 交互。每次会话都是从空白开始,遗忘之前的洞察、用户偏好和任务相关的学习成果。尽管大语言模型(LLM)已经扩展了上下文,但将不断增长的聊天记录或文档历史附加进去,计算成本高昂且速度缓慢。每次新查询都要重新处理 50,000 个 token 的过往对话,这对生产系统来说是不可持续的。
云端向量数据库"大一统"的趋势提供了一种解决方案,但引入了延迟、成本和根本性的依赖。典型的 Pinecone 语义相似性查询每次请求需要 100-300ms,再加上网络开销。对于一个决策周期内进行 5-10 次记忆检索的 Agent 来说,这会带来明显的滞后。此外,将敏感的 Agent 上下文——其"思考"的原材料——发送到第三方云服务,引发了许多行业无法忽视的合规性和隐私问题。
架构设计:模仿生物模型的 L1 草稿板 + L2 保险库
解决方案在于模仿人类记忆,利用双层架构。这不仅仅是一个软件模式;对于响应式、自包含的 Agent 来说,这是性能上的必需品。
第一层:L1 草稿板(工作记忆)是一个小型、超快、基于内存的数据结构——类似于环形缓冲区或优先级队列——保存着 50-200 条最新、最相关的上下文片段。它的访问时间接近零(微秒级),类似于 CPU 的 L1 缓存。这是 Agent 执行即时推理的地方,使用与当前任务最相关的事实。
第二层:L2 保险库(长期记忆)是一个持久的、可搜索的向量存储,保存着 Agent 的全部历史——可能多达数万条记忆。这里我们使用 sqlite-vec,这是一个为 SQLite 添加向量搜索功能的扩展,将一个单一的、可移植的数据库文件转化为强大的嵌入式向量记忆。L2 的查询仍然很快(个位数毫秒级),但涉及磁盘 I/O,类似于 L2 缓存。它是 L1 草稿板从中抽取的综合知识库。
// Conceptual dual-tier memory structure
struct AgentMemory {
// L1: In-memory, ordered by relevance/timestamp
l1_scratchpad: VecDeque<MemoryEntry>, // Capacity: 200 entries
// L2: Persistent SQLite vector database
l2_vault: sqlite_vec::VectorDB, // Holds 14,726+ entries
}
// The recall function implements the cache lookup logic
fn recall(&mut self, query: &str, k: usize) -> Vec<MemoryEntry> {
// 1. Search L1 first (fast path)
let l1_results = self.l1_scratchpad.search(query, k);
if l1_results.len() >= k {
return l1_results;
}
// 2. On miss, query L2 vector store
let remaining = k - l1_results.len();
let l2_results = self.l2_vault.semantic_search(query, remaining);
// 3. Promote hot L2 results to L1 (cache update)
for mem in &l2_results {
self.promote_to_l1(mem.clone());
}
[l1_results, l2_results].concat()
}
实现深入讲解:sqlite-vec 作为 L2 的引擎
使用 sqlite-vec 构建 L2 保险库提供了性能、简单性和零依赖部署的绝佳组合。整个 14,726 条记忆的数据库是一个单一文件(例如 agent_memory.db),可以版本控制、备份或随 Agent 移动。以下是关键实现片段:
import sqlite_vec
import sqlite3
import numpy as np
# Initialize database with vec extension
db = sqlite3.connect("agent_memory.db")
db.enable_load_extension(True)
sqlite_vec.load(db)
db.enable_load_extension(False)
# Create the vector table
db.execute("""
CREATE VIRTUAL TABLE IF NOT EXISTS memory USING vec0(
id INTEGER PRIMARY KEY,
embedding FLOAT[768], -- Assuming a 768-dimensional model like all-MiniLM
content TEXT,
metadata TEXT
)
""")
# Function to index a new memory
def store_memory(content: str, metadata: dict):
embedding = generate_embedding(content) # Your local embedding function
db.execute(
"INSERT INTO memory (embedding, content, metadata) VALUES (?, ?, ?)",
[embedding.tobytes(), content, json.dumps(metadata)]
)
db.commit()
# The critical search function
def search_vault(query_embedding: np.ndarray, k: int = 5):
results = db.execute(
"""
SELECT id, content, metadata, distance
FROM memory
WHERE embedding MATCH ?
ORDER BY distance
LIMIT ?
""",
[query_embedding.tobytes(), k]
).fetchall()
return results
性能对决:本地 sqlite-vec vs. 云端 Pinecone
我们在标准开发机器(Intel i7-12700H,32GB RAM)上对两种架构进行了基准测试,包含 14,726 条记忆条目。结果表明,对于延迟和成本至关重要的 Agent 工作流,本地双层模型具有明显优势。
L1 草稿板将重复查询的平均检索延迟降低到 5ms 以下。这种速度使 Agent 能够做出流畅的多步骤决策,而不会因网络受限的记忆获取产生"思考停顿"。对于每个任务处理 20 次检索操作的 Agent,本地系统相比云端解决方案每个任务节省了超过 2.8 秒的纯粹等待时间。
构建 Agent 上下文:实际使用场景
这种架构在对历史上下文有持续、快速访问需求的场景中表现出色。例如,一个代码助手 Agent 将 bug 报告、修复代码片段和代码库约定存储在 L2 保险库中。当报告新问题时,它立即从其 14,000+ 条记忆库中检索类似的过往解决方案,而不仅仅是最后五条聊天消息。L1 草稿板保存着当前正在编辑的文件和即时对话,创建了一个专注的工作集。
对于研究 Agent 来说,保险库存放着摘要论文、提取的实体和用户注释。它的双层记忆允许将新查询与数月前存储的相关概念网络连接起来,同时草稿板维持着即时分析管道。关键在于 Agent 的核心智能——其积累的经验——作为本地数据库文件随身携带,创建了一个真正个性化、可移植的 AI 工具。
准备好构建一个拥有持久、高速本地记忆的 AI Agent 了吗?今天就用 sqlite-vec 实现双层架构吧。访问 tormentnexus.site 查看文档和开源模板。
Originally published at tormentnexus.site