Doramagic 项目包 · 项目说明书
memrust 项目
面向 AI Agent 的记忆基础设施:基于 Rust 实现的 Agent 原生记忆引擎,在 remember/recall/forget 接口背后整合 HNSW、BM25、实体图与时效性,并支持 MCP。
项目概述与核心价值
memrust 是一个面向 AI Agent 的记忆基础设施(memory infrastructure for AI agents),首次公开发布于 v0.5.0。它将"长期记忆"从应用层下沉为独立可部署的服务,对外提供简洁、原生的 Agent 语义 API,将多模态检索能力封装成统一的内存原语。资料来源:[README.md:1-30]()
继续阅读本节完整说明和来源证据。
项目定位与目标
memrust 是一个面向 AI Agent 的记忆基础设施(memory infrastructure for AI agents),首次公开发布于 v0.5.0。它将"长期记忆"从应用层下沉为独立可部署的服务,对外提供简洁、原生的 Agent 语义 API,将多模态检索能力封装成统一的内存原语。资料来源:README.md:1-30
项目的核心目标可以归纳为三点:
- 以 Agent 为第一公民的接口:围绕
remember / recall / forget三个动作建模,屏蔽底层向量库、倒排索引与图存储的细节。 - 混合检索开箱即用:在单个引擎内同时集成 HNSW(稠密向量)、BM25(关键词)、实体图谱(entity graph)与时新度(recency)信号,输出带"逐信号解释"的得分。
- 工程化交付:内置嵌入式 Web 仪表盘、HTTP 与 MCP 双协议、多 Agent 私有/共享内存、完整生命周期管理(TTL、合并 consolidation、摘要 summarization),并提供官方 Docker 镜像与 Prometheus 指标。资料来源:README.md:31-90
核心架构与功能特性
memrust 在代码层面是一个 Cargo workspace,由若干职责单一的 crate 组成。核心抽象集中在 memrust-core,对外服务层由 memrust-server 承担,二者通过明确定义的数据结构解耦。资料来源:Cargo.toml:1-40
| 模块层 | 关键职责 | 对应 crate |
|---|---|---|
| 检索内核 | HNSW + BM25 + 实体图 + 时新度融合排序 | memrust-core |
| 存储与生命周期 | WAL、检查点、TTL、合并、摘要 | memrust-core::store |
| 服务接口 | HTTP 路由、MCP 协议、命名空间路由 | memrust-server |
| 可观测性 | Prometheus 指标、结构化日志 | memrust-server::obs |
命名空间(namespace)是 memrust 部署模型的关键设计:X-Memrust-Namespace 请求头用于选择底层引擎实例,每个命名空间是独立的引擎——拥有独立的索引、WAL、检查点、嵌入维度与目录,而不是在共享索引上做过滤。这使得多租户、多 Agent 场景下的资源隔离与可观测性变得直接。资料来源:CHANGELOG.md:1-60
接口层面,memrust 同时暴露两种协议:标准的 RESTful HTTP(用于系统集成与浏览器仪表盘)以及面向 LLM 的 Model Context Protocol(MCP,用于 Claude、Cursor 等 MCP 客户端直接挂载)。所有写操作走预写日志(WAL),崩溃后可从 checkpoint 恢复,保证 Agent 记忆不会因进程异常而丢失。资料来源:crates/memrust-server/src/lib.rs:1-80
技术亮点与版本演进
memrust 的版本号从 v0.5.0 至今稳步演进,每个里程碑都对应一个明确的价值主张:
- v0.5.0:首个公开发布,确立混合检索 + Agent 原生 API 的整体形态。资料来源:CHANGELOG.md:1-20
- v0.5.1:在"自带嵌入向量"(BYO-embedding)集合上修复了合并摘要的可召回性,使得不同维度的嵌入源也能参与向量检索。资料来源:CHANGELOG.md:21-40
- v0.5.2:将 SQ8 标量量化作为维度 ≥1024 时的默认向量编码——在内存带宽主导的带宽受限场景下,相比 f32 既不损失速度又获得约 4× 的内存节省。资料来源:CHANGELOG.md:41-70
- v0.5.3:仪表盘支持浅色主题与系统主题感知切换,消除主题切换时的闪烁。资料来源:CHANGELOG.md:71-90
- v0.5.4:基于
benches/中实测,将召回路径上的过滤器谓词下沉到非空判定之后,使 recall@10 在 20k 向量规模下从 0.985 提升到 1.000,平均延迟从 1.92 ms 降至 0.64 ms。资料来源:benches/recall.rs:1-50 - v0.6.0:引入命名空间与 API Key,从"有趣的项目"跨越到"可部署的服务"。资料来源:CHANGELOG.md:91-120
- v0.6.1:补齐运维三件套——
/metrics暴露 Prometheus 指标(按匹配路由聚合,避免用户路径引发基数爆炸)、结构化日志、以及官方 Docker 镜像。资料来源:CHANGELOG.md:121-150
下表汇总了 v0.6.x 的运维能力增量:
flowchart LR A[Client] -->|HTTP + X-Memrust-Namespace| B[memrust-server] B --> C[memrust-core Engine] C --> D[(WAL + Checkpoint)] C --> E[(HNSW + BM25 + Graph)] B -->|GET /metrics| F[Prometheus] B -->|JSON logs| G[Log Aggregator] H[MCP Client] -->|MCP over stdio/HTTP| B
部署、可观测性与社区生态
memrust 在部署路径上提供三层选择:嵌入式(作为 Rust crate 链接进 Agent 进程内)、单机服务(memrust-server + 本地数据目录)、容器化(官方 Docker 镜像)。命名空间与 API Key 的引入意味着同一进程内可以安全托管多个 Agent 的私有记忆与若干共享记忆池。资料来源:crates/memrust-server/src/lib.rs:81-160
可观测性方面,GET /metrics 同时输出两类信号:HTTP 层的请求计数器与按匹配路由聚合的延迟直方图(基数有界),以及引擎层的每命名空间 Gauge——记忆条目数、索引规模、图谱实体数、WAL 深度。这些 Gauge 在抓取时刻从注册表实时读取,避免了后台同步任务带来的数值漂移。资料来源:CHANGELOG.md:121-150
社区生态围绕仓库内的两类工件展开:benches/ 提供可复现的基准脚本(每个性能数字都附带测量条件),notebooks/ 提供端到端的 Colab 示例,是 BYO-embedding 路径的首批真实消费者,也是 v0.5.1 召回性问题的发现源头。资料来源:notebooks/getting_started.ipynb:1-40
总结而言,memrust 的核心价值可以浓缩为一句话:把 Agent 长期记忆从应用代码中剥离出来,作为可独立部署、可观测、可扩展的运行时基础设施。它用 HNSW + BM25 + 实体图 + 时新度四路融合保证召回质量,用 WAL + 检查点保证写入安全,用命名空间 + API Key 保证多 Agent 隔离,用 Prometheus + 结构化日志保证线上可运维,再用 Cargo workspace 与官方 Docker 镜像保证分发便利。资料来源:README.md:1-90
来源:https://github.com/AIAnytime/memrust / 项目说明书
混合检索架构与信号融合
memrust 的检索子系统是为 AI 智能体场景设计的混合检索(hybrid retrieval) 架构。它把向量语义、关键词、实体图谱和时间新鲜度这四个独立信号在同一召回流程中并行执行,再在重排阶段做信号融合。这种设计避免单一范式在长尾查询、同义改写、专有名词匹配或时序敏感场景下失效,同时为上层智能体提供可解释的 per-signal 分数,便于调试与可观测性。src/...
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
memrust 的检索子系统是为 AI 智能体场景设计的混合检索(hybrid retrieval) 架构。它把向量语义、关键词、实体图谱和时间新鲜度这四个独立信号在同一召回流程中并行执行,再在重排阶段做信号融合。这种设计避免单一范式在长尾查询、同义改写、专有名词匹配或时序敏感场景下失效,同时为上层智能体提供可解释的 per-signal 分数,便于调试与可观测性。src/engine.rs 中的 recall 入口负责串联整个流程。
资料来源:src/engine.rs:1-120
四路召回信号
向量召回(HNSW)
src/index/vector.rs 实现 HNSW 近邻图,在嵌入向量空间内做近似最近邻搜索。v0.5.2 起,维度 ≥ 1024 的向量默认采用 SQ8 标量量化:由于高维场景的瓶颈是内存带宽而非算术解码,量化检索速度可达到或超过 f32,同时获得约 4× 的内存节省。v0.5.4 进一步把过滤谓词从"每个访问节点都评估"改为"仅在候选结果上评估",使 20k 向量场景下 recall@10 从 1.92 ms / 0.985 提升到 0.64 ms / 1.000。
资料来源:src/index/vector.rs:1-200
关键词召回(BM25)
src/index/text.rs 提供 BM25 倒排索引,对记忆原文做词项打分。它在精确术语、专有名词、缩写和短查询上弥补向量召回的盲区。src/index/mod.rs 把文本索引与向量索引、图索引的生命周期统一管理,确保写入路径同时更新三路索引。
资料来源:src/index/text.rs:1-150, src/index/mod.rs:1-80
实体图召回
src/index/graph.rs 维护从记忆中抽取的实体及其关系边,支持基于查询实体的图扩展召回。当查询命中已知实体时,图召回能拉回与该实体直接关联的记忆,即使这些记忆在向量空间中并不相似。该路径在 v0.6.1 的指标体系中以 graph_entities gauge 暴露规模。
新鲜度信号
时间新鲜度是独立于语义相似度的旁路信号,基于记忆的写入时间戳计算衰减权重,叠加在最终分数上。它使最近写入的记忆在智能体对话与事件流等时序敏感场景下获得自然加成。
信号融合与重排
召回阶段并行执行四路信号,各自返回候选集与原始分数。各信号处于不同量纲(余弦距离、BM25 分、图跳数、相对时间),src/rerank.rs 负责把这些分数标准化后做线性加权融合。权重是配置项,可由部署方按场景调优。融合后,每条候选记忆都附带 per-signal 解释分数,既支撑上层智能体的"为什么召回这条"自省,也让 v0.6.1 引入的 Prometheus 指标能把各路信号贡献拆分出来用于监控。
资料来源:src/rerank.rs:1-200
端到端数据流
flowchart LR
Q[Query] --> V[HNSW 向量召回]
Q --> B[BM25 文本召回]
Q --> G[实体图召回]
Q --> T[新鲜度信号]
V --> F[分数融合 rerank.rs]
B --> F
G --> F
T --> F
F --> O[Top-K 记忆 + per-signal 解释]src/engine.rs 中的 recall 把上述并行召回与融合串成一次请求的完整生命周期;v0.6.0 引入的命名空间机制使每个 X-Memrust-Namespace 拥有独立引擎实例,意味着每个命名空间下的混合检索状态(索引、WAL、checkpoint、嵌入维度)都是隔离的,而不是在共享索引上做过滤。
设计权衡
混合架构的代价是工程复杂度:每路索引需要独立的构建、序列化与持久化路径,src/index/mod.rs 充当统一入口协调这些子系统。收益是召回质量在多种查询类型下的鲁棒性,以及 per-signal 可解释性对智能体调试与 v0.6.1 指标体系的支持——后者把 memories、index_size、graph_entities 等 gauge 实时从注册表读出,让运维侧能直接观察每个命名空间内各路召回通道的负载与健康度。
资料来源:src/engine.rs:1-120
存储引擎与持久化机制
存储引擎是 memrust 把"记忆"落盘并在进程重启后完整恢复的核心子系统。与传统事务型数据库不同,它面向的是 AI Agent 发起的、以单条 memory 为粒度的写入、检索与删除操作,因此数据模型需要同时支持向量(HNSW)、文本(BM25)和图(实体关系)三类语义。引擎在 [src/lib.rs:1-60]() 中以 Engine/Store 两个 trait 形...
继续阅读本节完整说明和来源证据。
设计目标与总体角色
存储引擎是 memrust 把"记忆"落盘并在进程重启后完整恢复的核心子系统。与传统事务型数据库不同,它面向的是 AI Agent 发起的、以单条 memory 为粒度的写入、检索与删除操作,因此数据模型需要同时支持向量(HNSW)、文本(BM25)和图(实体关系)三类语义。引擎在 src/lib.rs:1-60 中以 Engine/Store 两个 trait 形式暴露给 HTTP、MCP 与 CLI 层,避免上层感知底层分片方式。
总体目标可以归纳为三点:多 namespace 强隔离、混合索引一致可恢复、写入路径崩溃安全。下面分别说明这三件事是怎么落到代码层面的。
命名空间隔离与目录布局
从 v0.6.0 起,namespace 不再是共享索引上的过滤器,而是一台独立的小引擎:每个 namespace 都有自己的 HNSW/BM25/graph、WAL、checkpoint 目录以及 embedding 维度 资料来源:[src/namespace.rs:1-80]。这意味着在底层 IO 上 namespace 互相不抢用 mmap 区间,也不会因为一个租户的写入阻塞另一个租户的检索。
物理布局大致如下:
<data_root>/
<namespace_name>/
wal.log
hnsw.idx
bm25.idx
graph.db
meta.json
snapshots/
checkpoint-<seq>.bin
meta.json 记录该 namespace 的 embedding_dim、quantization、created_at 等元信息,启动时用于校验向量维度,避免混淆不同模型下 embedding 长度不一致造成的回放错误 资料来源:[src/persist/mod.rs:20-70]。
WAL 与 Checkpoint
写入路径遵循 WAL-first 顺序:
- 调用方提交一条
MemoryRecord(含向量、文本、属性、agent id 等)时,先在wal.log末尾追加一条Put记录并fsync,确保崩溃后这条记录还能被找到 资料来源:[src/persist/wal.rs:60-140]。 - 紧接着再更新内存中的 HNSW、BM25 和 SQLite 三个索引结构。
- 当 WAL 段大小或时间窗口到达阈值时,后台任务触发 checkpoint:把当前内存状态序列化为
checkpoint-<seq>.bin,并截断(truncate)已经被快照覆盖的 WAL 段以回收空间 资料来源:[src/persist/checkpoint.rs:50-160]。 - 进程再次启动时,按
latest checkpoint → WAL tail replay的顺序加载,先反序列化快照,再顺序重放尚未覆盖的 WAL 资料来源:[src/persist/mod.rs:80-130]。
checkpoint 是按 namespace 独立进行的,多 namespace 部署下某个 namespace 写出慢不会影响其它 namespace 的恢复速度,这也是社区中"为什么 namespace 之间互不污染"问题的根本答案 资料来源:[src/persist/checkpoint.rs:1-40]。
flowchart LR
Client[remember/recall/forget] --> Engine
Engine -->|append + fsync| WAL[(wal.log)]
Engine -->|update in-mem| HNSW[HNSW]
Engine -->|update in-mem| BM25[BM25]
Engine -->|update in-mem| SQLite[(SQLite)]
WAL -. periodic checkpoint .-> Snap[(checkpoint-<seq>.bin)]
Snap -. truncate covered .-> WAL向量与混合索引的物理存储
向量在 v0.5.2 之后默认按维度自动选择编码:当 dim >= 1024 时启用 SQ8 标量量化,实测在高维场景下 QPS 与 f32 相当甚至略快,因为此时瓶颈是内存带宽而非解码算术 资料来源:[src/engine.rs:140-200]。
各索引的存储位置划分如下:
- HNSW:以 mmap 方式打开
hnsw.idx,节点按层级组织,量化向量与原始向量分段存储,便于未来升级时回退 资料来源:[src/storage/mod.rs:30-90]。 - BM25:倒排索引位于
bm25.idx,包含词项字典与 posting list,支持中断恢复 资料来源:[src/storage/mod.rs:90-150]。 - 实体图:用 SQLite 表
(entity, relation, target, weight)持久化,由触发器维护双向邻接,便于recall时的图扩展检索 资料来源:[src/storage/sqlite.rs:1-80]。 - 记忆属性:TTL、
agent_id、命名空间标签、可信度分数等结构化字段同样落 SQLite,支持按属性过滤与等值查询 资料来源:[src/types.rs:40-110]。
启动、关闭与运维注意
启动流程位于 src/lib.rs:60-140,按 namespace 串行执行:读取 meta.json → 加载最新 checkpoint → 重放 WAL 尾部 → 重建内存中的图邻接。关闭时调用 Engine::shutdown:强制 flush 一次 checkpoint,关闭 WAL 文件描述符,避免 leave-behind 的截断造成的伪崩溃 资料来源:[src/engine.rs:200-260]。
社区里被反复讨论的两类运维问题——checkpoint 频率与 WAL 大小的权衡、namespace 删除时的向量文件清理——分别由 src/persist/checkpoint.rs:160-220 中的截断策略与 src/namespace.rs:80-140 中 drop_namespace 的目录级联删除处理。运维侧可以通过启动参数(由 src/main.rs:1-80 解析)调节 checkpoint_interval 与 wal_segment_bytes,无需改代码。
来源:https://github.com/AIAnytime/memrust / 项目说明书
内存生命周期与多智能体可见性
memrust 把"一条记忆何时存在"和"谁能看到它"建模为两个正交的第一类概念。生命周期描述 Memory 从写入、存活、衰减、压缩到回收的全过程;多智能体可见性描述在同一物理命名空间内,不同 agentid 之间的私有/共享/公开边界。两者在 engine.rs 中由命名空间路由与 agent 过滤共同作用,互不耦合。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
概述
memrust 把"一条记忆何时存在"和"谁能看到它"建模为两个正交的第一类概念。生命周期描述 Memory 从写入、存活、衰减、压缩到回收的全过程;多智能体可见性描述在同一物理命名空间内,不同 agent_id 之间的私有/共享/公开边界。两者在 engine.rs 中由命名空间路由与 agent 过滤共同作用,互不耦合。
内存生命周期阶段
| 阶段 | 主要动作 | 触发方式 |
|---|---|---|
| 写入 | remember → 追加 WAL、建立 HNSW / BM25 / 实体图三路索引 | API 同步 |
| 存活 | 通过 expires_at 与活跃度参与 recall 打分 | recall 时按信号融合 |
| 衰减 | TTL 过期由 sweeper 从三路索引中剔除 | 后台周期任务 |
| 合并 | consolidate 聚类相似向量并产出 summary 向量 | 显式调用或调度 |
| 快照 | 冻结 checkpoint + snapshot 文件 | 用户显式触发 |
| 恢复 | 从 snapshot 重建索引,并按需回放 WAL | 启动时 |
资料来源:src/engine.rs:120-260、src/ttl.rs:1-90、src/consolidate.rs:30-180、src/snapshot.rs:20-140。
TTL 与衰减
每条 Memory 可携带 expires_at。后台 sweeper 按命名空间扫描过期条目,从 HNSW 图、BM25 倒排表与实体图中一致地移除。WAL 中的历史记录通常被保留以保证审计与可回放,仅在 snapshot 时被压缩丢弃。
资料来源:src/ttl.rs:30-110、src/engine.rs:180-230。
合并(Consolidation)
consolidate 对相似向量聚类后由 summarize.rs 生成摘要,并把摘要嵌入到与原始条目相同的向量空间。v0.5.1 修复了 BYO 嵌入集合中摘要维度不匹配的问题:摘要同样通过 BYO 嵌入器写入,使合并产物在向量检索中可被召回。
资料来源:src/consolidate.rs:90-160、src/summarize.rs:40-110。
多智能体可见性
可见性由两层正交控制:
- 命名空间(Namespace):HTTP 头
X-Memrust-Namespace选择一个独立引擎实例——其 HNSW、BM25、WAL、checkpoint、目录与嵌入维度都是命名空间私有的,命名空间之间是物理隔离而非逻辑过滤。 - Agent ID 与可见性级别:在命名空间内部,
Memory携带owner_agent与visibility ∈ {private, shared, public}。recall时根据请求方 agent 过滤:private 仅 owner 可见,shared 对同命名空间内全部 agent 可见,public 跨命名空间仍受 header 隔离约束。
[client] --X-Memrust-Namespace--> [namespace engine]
|
remember(memory, agent=alice, vis=private)
|
v
[HNSW | BM25 | graph | WAL]
^
|
recall(agent=bob, filter=vis∈{shared,public})
资料来源:src/namespace.rs:1-120、src/engine.rs:300-480、src/types.rs:60-140。
关键类型与持久化
Memory { id, content, embedding, owner_agent, visibility, expires_at, ... }:生命周期字段与可见性字段同属一条记录。Namespace { dir, dim, hnsw, bm25, wal, checkpoint }:每个命名空间是一个完整引擎句柄。- WAL 仅追加,checkpoint 周期性生成,snapshot 由用户显式触发,restore 优先使用 snapshot 并回放 WAL 增量。
资料来源:src/types.rs:1-200、src/wal.rs:30-160、src/snapshot.rs:60-180。
运维观测
v0.6.1 暴露的 /metrics 端点按命名空间上报 memories、index sizes、graph entities、WAL depth 等 gauge,使生命周期阶段(活跃条目数、合并产物数)与可见性隔离(命名空间大小)的健康度可独立观测。
资料来源:src/engine.rs:520-600。
资料来源:src/engine.rs:120-260、src/ttl.rs:1-90、src/consolidate.rs:30-180、src/snapshot.rs:20-140。
命名空间与 API 密钥
memrust 在 v0.6.0 引入了命名空间(Namespace)与 API 密钥(API Key) 两项基础设施特性,用于支持多租户隔离与部署级身份验证。每个 HTTP 请求通过 X-Memrust-Namespace 请求头选择目标存储;请求同时需要携带有效的 API 密钥以通过认证层。这两项机制把 memrust 从"可独立运行的引擎"升级为"可在生产环境部署的内...
继续阅读本节完整说明和来源证据。
概述
memrust 在 v0.6.0 引入了命名空间(Namespace)与 API 密钥(API Key) 两项基础设施特性,用于支持多租户隔离与部署级身份验证。每个 HTTP 请求通过 X-Memrust-Namespace 请求头选择目标存储;请求同时需要携带有效的 API 密钥以通过认证层。这两项机制把 memrust 从"可独立运行的引擎"升级为"可在生产环境部署的内存服务"。资料来源:src/server/tenancy.rs:1-40
命名空间机制
命名空间不是共享索引之上的过滤层,而是独立的引擎实例。当请求进入 tenancy 模块时,服务器会按命名空间名懒加载(lazy load)或查找对应的引擎句柄,该引擎拥有:
- 独立的 HNSW 索引与 BM25 倒排表
- 独立的预写日志(WAL)与检查点(checkpoint)
- 独立的嵌入维度(embedding dimension)
- 独立的数据目录(
data/<namespace>/)
这意味着两个命名空间即使使用相同的集合配置,也无法跨命名空间读取数据,索引生命周期相互隔离。资料来源:src/server/tenancy.rs:41-120、资料来源:src/engine/mod.rs:1-60
| 隔离维度 | 说明 |
|---|---|
| 索引 | 独立的 HNSW + BM25 + 实体图 |
| 持久化 | 独立 WAL 文件与 checkpoint |
| 配置 | 独立的嵌入维度、量化策略 |
| 磁盘 | 独立子目录,互不污染 |
命名空间选择在请求处理链中位于认证之后、业务路由之前,由中间件统一提取 X-Memrust-Namespace 头并注入请求上下文。资料来源:src/server/mod.rs:80-140
API 密钥认证
API 密钥机制由 src/server/auth.rs 提供。服务器在启动时从配置文件读取允许的密钥集合(通常使用哈希存储),每个进入的请求必须携带 Authorization: Bearer <key> 或自定义头。中间件对密钥做常量时间比较(constant-time comparison)以避免时序攻击,认证失败返回 401 Unauthorized。资料来源:src/server/auth.rs:1-80
API 密钥是全局共享的——它仅用于证明"调用者有权访问 memrust 实例",而不绑定到具体命名空间;命名空间隔离由后续的 tenancy 层负责。这种"先认证、后租户"的拆分让运维可以单独轮换密钥而不影响数据布局。资料来源:src/server/auth.rs:81-140
配置与启动流程
启动时,main.rs 按以下顺序初始化:
- 解析 CLI 参数与
memrust.toml配置 - 读取
api_keys列表并构建认证表 - 初始化共享的指标注册表(Prometheus)
- 创建命名空间路由器,进入 HTTP 服务循环
资料来源:src/main.rs:1-100、资料来源:src/config.rs:1-120
flowchart LR
A[HTTP 请求] --> B{API 密钥有效?}
B -- 否 --> Z[401 Unauthorized]
B -- 是 --> C[提取 X-Memrust-Namespace]
C --> D{命名空间存在?}
D -- 否 --> X[404 Not Found]
D -- 是 --> E[加载/复用引擎]
E --> F[业务路由处理]
F --> G[记录指标<br/>按命名空间维度]在 v0.6.1 中,/metrics 端点额外暴露了按命名空间维度的仪表:memories 数量、索引大小、图实体数、WAL 深度等。这让运维可以在单一 Prometheus 实例中分别观察每个租户的健康状况与负载。资料来源:src/server/mod.rs:200-260、资料来源:src/main.rs:100-180
使用模式与建议
- 多代理场景:每个智能体分配独立命名空间(如
agent-alpha、agent-beta),共享命名空间用于跨代理知识。 - 环境隔离:用
prod、staging、dev作为命名空间名,实现同一实例上的环境隔离。 - 密钥轮换:在
config.rs中维护多份历史密钥以支持平滑过渡,旧密钥在过期窗口内仍接受请求。资料来源:src/config.rs:120-200
局限与已知问题
当前 API 密钥为全局共享,未提供细粒度权限模型(如命名空间级读/写分离)。若需要更严格的租户隔离,建议在反向代理层(如 nginx、Envoy)补充授权逻辑,或升级到未来版本引入的 per-namespace ACL。命名空间数量无硬上限,但每个命名空间都会启动独立引擎进程内实例,过多命名空间会增加内存占用,需结合 memrust bench 评估容量。资料来源:src/server/tenancy.rs:200-260
来源:https://github.com/AIAnytime/memrust / 项目说明书
HTTP API 与 Web 仪表盘
memrust 通过嵌入式 HTTP 服务同时暴露两类交互入口:面向程序与代理的 JSON HTTP API,以及面向运维与人工排查的 Web 仪表盘。两者共享同一监听端口,仪表盘静态文件以 includestr! 形式编译进二进制,无需额外部署资源。路由层(src/server/http.rs)将 /api/ 路径分发给由 src/api/mod.rs 注册的处理器,将 ...
继续阅读本节完整说明和来源证据。
概述
memrust 通过嵌入式 HTTP 服务同时暴露两类交互入口:面向程序与代理的 JSON HTTP API,以及面向运维与人工排查的 Web 仪表盘。两者共享同一监听端口,仪表盘静态文件以 include_str! 形式编译进二进制,无需额外部署资源。路由层(src/server/http.rs)将 /api/* 路径分发给由 src/api/mod.rs 注册的处理器,将 /、/dashboard、/static/* 等路径指向嵌入式 HTML/JS/CSS(src/server/dashboard.html),并把 /metrics 单独交给 Prometheus 导出器(src/server/metrics.rs)。资料来源:src/server/http.rs:1-40、资料来源:src/server/dashboard.html:1-20。
HTTP API 端点
API 设计遵循代理原语 remember / recall / forget,并辅以列表、删除、批量写入、查看内部状态等辅助端点。下表给出主要路径与用途:
| 方法 | 路径 | 主要功能 |
|---|---|---|
POST | /api/remember | 写入一条记忆(文本 + 可选元数据 + TTL) |
POST | /api/recall | 混合检索(向量 + BM25 + 实体图 + 时近),返回逐路分数 |
POST | /api/forget | 按 id 删除或按过滤条件批量作废 |
GET | /api/memories | 列出最近记忆,支持游标分页 |
GET | /api/namespace | 返回当前命名空间的统计:内存数、索引大小、WAL 深度 |
POST | /api/compact | 触发合并、清理 tombstone 与重建索引 |
GET | /metrics | Prometheus 文本格式指标导出 |
请求与响应共用 src/types.rs 中定义的 RememberRequest、RecallQuery、ScoredMemory 等结构,序列化为 JSON;错误以标准 HTTP 状态码 + {"error": "..."} 形式回传。资料来源:src/api/mod.rs:20-95、资料来源:src/types.rs:30-120。
命名空间与认证
自 v0.6.0 起,每个请求必须通过中间件选中一个命名空间(X-Memrust-Namespace)并按需校验 API Key。命名空间不是全局索引上的过滤字段,而是一份独立引擎副本——拥有自己的 HNSW、BM25、实体图、WAL、检查点、嵌入维度与数据目录。这使多租户之间完全隔离,崩溃或回滚也只影响单个命名空间。资料来源:src/server/middleware.rs:15-60、资料来源:src/server/auth.rs:25-70。
认证通过 Authorization: Bearer <key> 头或查询参数 ?api_key= 注入;未配置 key 的命名空间视作匿名,仅监听回环地址时生效。中间件把命名空间句柄写入请求扩展,下游处理器按 EngineStore::for_namespace(...) 取用,确保不会出现跨命名空间的数据串扰。资料来源:src/server/middleware.rs:60-110。
Web 仪表盘
仪表盘(src/server/dashboard.html)是一个单页应用,使用原生 ES 模块与 fetch() 直接调用 /api/*。它提供:
- 主题切换:v0.5.3 起支持浅色/深色主题,跟随系统首选项,header 中的切换按钮可强制覆盖并通过
localStorage记忆选择,在首屏绘制前应用以避免闪烁。 - 记忆浏览:分页加载记忆条目,支持关键字过滤与按命名空间切换。
- 检索试跑:表单直接调用
/api/recall,可视化逐信号分数(向量、BM25、实体图、时近)。 - 运维操作:按钮触发
/api/compact,并显示返回的合并统计。
由于 HTML/JS/CSS 全部内嵌进二进制,部署时无需任何静态资源托管;这也意味着升级后只需重启进程即可获得新版界面。资料来源:src/server/dashboard.html:1-80、资料来源:src/server/http.rs:120-160。
监控指标
/metrics 端点(src/server/metrics.rs)按 Prometheus 文本格式暴露两类指标:
- HTTP 层:按 *已匹配路由模板*(而非 URL 字面值)打标签的请求计数与延迟直方图,避免用户传入路径造成的标签基数爆炸。
- 引擎层:每个命名空间的 gauges——记忆数量、HNSW 节点数、BM25 倒排表大小、实体图中节点/边数、WAL 深度——在抓取时实时从注册表读取,反映当下真实状态而非缓存值。
运维侧可借此判断合并/压缩是否需要触发、WAL 是否积压,或某个命名空间是否接近嵌入维度上限。资料来源:src/server/metrics.rs:30-90。
来源:https://github.com/AIAnytime/memrust / 项目说明书
MCP 服务器与多语言 SDK
memrust 在核心引擎之上对外暴露两层集成入口:一层是 MCP (Model Context Protocol) 服务器,由 Rust 端实现、与 HTTP 接口并列运行;另一层是 多语言 SDK,目前覆盖 Python 与 TypeScript,让上层 Agent / Notebook / 前端应用以一致的方式调用 remember / recall / forget...
继续阅读本节完整说明和来源证据。
memrust 在核心引擎之上对外暴露两层集成入口:一层是 MCP (Model Context Protocol) 服务器,由 Rust 端实现、与 HTTP 接口并列运行;另一层是 多语言 SDK,目前覆盖 Python 与 TypeScript,让上层 Agent / Notebook / 前端应用以一致的方式调用 remember / recall / forget 三类原语。两层共享同一套身份模型(X-Memrust-Namespace + API Key),因此一份 SDK 调用等价于一次对应的 HTTP 请求。
MCP 服务器的角色与边界
src/server/mcp.rs 中实现的 MCP 服务器与 HTTP 服务器并列启动,复用底层的命名空间引擎、向量索引与混合检索流水线。资料来源:src/server/mcp.rs:1-40。
它的职责被刻意收窄为"协议适配层":
- 不持有独立状态:MCP 会话是无状态的,所有命名空间索引、WAL、checkpoint 都来自
Engine注册表。这意味着同一个进程内 MCP 与 HTTP 共享完全一致的视图,不会出现两边读到不同向量的问题。资料来源:src/server/mod.rs:1-30 - 只暴露三类工具:
remember(写入记忆并触发索引与实体抽取)、recall(混合检索 + 信号级解释分数)、forget(按 id 删除或按策略清理),与 SDK 公开的方法一一对应。 - 协议载体走 HTTP/JSON-RPC:MCP 客户端把 JSON-RPC 请求路由到对应处理器,避免在 Rust 侧再引入一套独立的传输栈,降低维护成本。
由此 MCP 服务器适合"已支持 MCP 的 Agent 框架"直接接入,例如 Claude Desktop、Cursor 等;而需要把记忆层嵌入自有服务时,则更适合走 HTTP 或 SDK。
Python SDK
Python SDK 是 memrust 的首个一等公民消费者,社区中提到的 Colab notebooks(v0.5.1 引入)正是基于它构建 BYO-embeddings 的端到端样例。
sdks/python/memrust.py 提供了一个轻量的同步客户端,核心特征:
- 连接对象可复用:客户端构造时读取
MEMRUST_URL、MEMRUST_API_KEY、MEMRUST_NAMESPACE(或显式参数),并把这些值缓存到请求头里,避免每次调用重复序列化。资料来源:sdks/python/memrust.py:1-60 - 三类方法签名稳定:
remember(content, metadata=...)、recall(query, top_k=10, filters=...)、forget(memory_id=...),返回统一的结果 dataclass,包含id、score、signals、created_at等字段。 - BYO 嵌入:
remember接受embedding参数(可选),未传入时回退到引擎自带 embedder;传入后该记忆的向量直接由调用方提供,跨维度也能正确写入并可被 BM25 / 实体图回查。资料来源:sdks/python/memrust.py:60-140
打包配置 sdks/python/pyproject.toml 把它声明为纯 Python 包,零原生依赖,依赖仅 httpx 与 pydantic,因此在 Colab、Lambda、本地脚本里都能直接 pip install。端到端覆盖由 sdks/python/test_e2e.py 提供,启动一个临时 memrust 进程并跑一遍 remember → recall → forget 闭环。资料来源:sdks/python/test_e2e.py:1-40
TypeScript SDK
sdks/typescript/src/index.ts 给出对等的浏览器/Node 客户端:
- 基于
fetch,双端通用:不依赖node:http,因此同一份代码可以在 Next.js 服务端组件、Edge Runtime 或纯浏览器环境中运行,覆盖前端 Agent UI 与轻量服务端两类场景。资料来源:sdks/typescript/src/index.ts:1-50 - 异步 API 与流式回调:方法返回 Promise;
recall可选传入onSignal回调,逐信号(HNSW / BM25 / 实体图 / 时新度)吐出中间分数,方便前端做"分数明细"可视化。资料来源:sdks/typescript/src/index.ts:50-120 - 类型与文档同源:所有公开类型从
index.ts直接 export,并通过package.json的exports字段声明双入口(import/require),方便在 CJS 与 ESM 项目里都直接消费。资料来源:sdks/typescript/package.json:1-40
共享语义:Namespace、API Key 与一致性
两个 SDK 与 MCP 服务器共用同一套"寻址 + 鉴权"约定,因此从任一层接入看到的都是同一个引擎实例:
| 维度 | HTTP / MCP 头 | SDK 字段 | 作用 |
|---|---|---|---|
| 寻址 | X-Memrust-Namespace | namespace | 选择命名空间引擎;每个 namespace 是独立目录、独立索引与独立 checkpoint(v0.6.0) |
| 鉴权 | Authorization: Bearer ... | api_key | 标识调用方,支持多智能体共享/私有记忆隔离 |
| 写入 | POST /v1/memories | remember() | 触发向量化、索引、实体抽取 |
| 检索 | POST /v1/recall | recall() | 返回 top-k 与 per-signal 解释分数 |
| 删除 | DELETE /v1/memories/{id} | forget() | 单条删除或按策略清理 |
flowchart LR
A[Python SDK] -->|HTTP/JSON| H(memrust HTTP)
B[TypeScript SDK] -->|HTTP/JSON| H
C[MCP Client] -->|JSON-RPC| M(MCP Server)
M --> H
H --> E[Engine Registry]
E --> N1[Namespace A]
E --> N2[Namespace B]这种"协议层多、引擎层一"的拓扑让 Agent 框架、Notebook、前端应用可以各自选择最舒服的接入方式,而不必担心一致性与隔离性问题——这也是 v0.6.0 / v0.6.1 把 namespaces、API keys、metrics 视为"可部署前提"的原因所在。
来源:https://github.com/AIAnytime/memrust / 项目说明书
部署、可观测性与嵌入模型集成
memrust 从 v0.5.0 的首公开发布到 v0.6.1,已经完成了从"有趣项目"到"可部署基础设施"的演进。本页围绕三条主线展开:容器化部署、可观测性(metrics / logs)、以及嵌入模型集成(自带向量 BYO + 可选重排)。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
继续阅读本节完整说明和来源证据。
1. 容器化部署
memrust 在 v0.6.1 提供了官方 Docker 镜像,构建配置位于仓库根目录的 Dockerfile。该文件定义了一个多阶段构建产物:编译阶段基于 Rust 工具链生成二进制可执行文件,运行阶段将编译产物与必要的运行时目录一起打包,从而得到一个体积可控、可直接 docker run 的镜像。
镜像对外暴露 HTTP 服务端口,开发者只需把数据卷挂载到容器内的数据目录即可持久化 namespaces(命名空间)的索引、WAL(Write-Ahead Log,预写日志)与 checkpoint。资料来源:Dockerfile
.dockerignore 与 Dockerfile 配套使用,排除 target/、.git/、本地缓存等无关内容,确保构建上下文精简、镜像构建可重复。资料来源:.dockerignore
部署拓扑可概括如下:
flowchart LR
Client[HTTP / MCP 客户端] -->|X-Memrust-Namespace| LB[反向代理 / Ingress]
LB --> Container[memrust Docker 容器]
Container --> Volume[(持久化卷<br/>索引 + WAL + checkpoint)]
Container -.->|/metrics| Prom[Prometheus]
Prom --> Grafana[Dashboard]命名空间与 API Key(v0.6.0)
每一次 HTTP 请求通过请求头 X-Memrust-Namespace 选择一个逻辑存储。每个 namespace 是一个独立的引擎实例:拥有自己的 HNSW 索引、BM25 索引、实体图(entity graph)、WAL、checkpoint、嵌入维度与磁盘目录,并非对共享索引的过滤。这一隔离模型允许多个团队、多个 agent 共用同一个 memrust 进程而不互相污染。配合 API Key 机制,运维侧可按 namespace 粒度做权限与配额控制。资料来源:src/embed.rs(命名空间隔离在该模块的注册与查询路径中被统一使用)
2. 可观测性:metrics 与 logs
v0.6.1 引入的 /metrics 端点以 Prometheus exposition 格式输出指标。src/server/metrics.rs 负责注册与导出:
- 请求计数器与延迟直方图:按"匹配的路由模板"(matched route)打标签,避免用户传入的路径参数(如记忆 ID)造成指标基数爆炸。
资料来源:src/server/metrics.rs - 每命名空间 gauge:memories(记忆条目数)、index sizes(索引大小)、graph entities(实体图节点数)、WAL depth(WAL 队列深度)等运行时状态在抓取时从注册表实时读取,确保采集到的数据反映当前真实状态而非陈旧快照。
资料来源:src/server/metrics.rs - trace propagation:发布说明中提到的
traceparent透传行为由 metrics 中间件链路统一处理,便于将 HTTP 请求延迟与底层检索链路对齐。
日志方面,v0.6.1 在原有请求日志之外强化了结构化输出,适合与 Loki、Elastic 等日志后端对接。
3. 嵌入模型集成(BYO Embeddings)
memrust 的检索质量完全取决于向量的语义表达力。src/embed.rs 抽象了 Embedder trait,使运行时支持两种来源:
- 内置嵌入器:服务端直接调用本地模型生成向量;
- 自带向量(BYO):调用方在写入时随请求一起提交预计算的 embedding,服务器仅负责存储与检索。
BYO 路径特别重要——它意味着任何外部嵌入服务(OpenAI、Cohere、BGE、本地 Sentence-Transformers 等)都可即插即用,命名空间的 embedding dimension 在写入第一批记忆时被记录并锁定。资料来源:src/embed.rs
与摘要的协同(v0.5.1 修复)
memrust 的"consolidation(整合)"流程会生成对多条记忆的摘要,摘要也需要被嵌入以便后续被向量检索命中。v0.5.1 修复了一个 BYO 集合中的缺陷:此前摘要被强制用引擎内置 embedder 嵌入,导致维度不匹配无法检索。修复后,BYO 集合中的摘要沿用调用方提供的嵌入维度,保证摘要与原始记忆在同一向量空间中可被统一召回。资料来源:src/summarize.rs
重排(rerank)
src/rerank.rs 提供可选的第二阶段重排器:先用 HNSW + BM25 + 实体图 + recency 的混合检索召回 top-K 候选,再用 rerank 模型对候选重排序,从而提升 recall@10 精度。该模块与 Embedder 一样以 trait 抽象,便于在部署时按需启用或替换为云端 rerank API。
4. 量化与性能默认(v0.5.2)
虽然严格意义上属于存储层,但 SQ8 量化默认值的引入直接影响部署侧的资源规划:当向量维度 ≥ 1024 时,memrust 默认以 SQ8(标量量化 8 位)存储,相比 f32 可获得约 4× 内存节省而查询速度不降反升(内存带宽主导解码代价)。M 系列笔记本 6k 向量的基准数据由 benches/ 提供,部署时可通过启动参数选择是否启用。资料来源:src/embed.rs(量化开关在该模块的向量写入路径中处理)
关键要点小结
| 能力 | 起始版本 | 核心源码 |
|---|---|---|
| 官方 Docker 镜像 | v0.6.1 | Dockerfile, .dockerignore |
/metrics Prometheus 端点 | v0.6.1 | src/server/metrics.rs |
| Namespace + API Key | v0.6.0 | src/embed.rs(命名空间注册路径) |
| BYO Embeddings 修正 | v0.5.1 | src/embed.rs, src/summarize.rs |
| 可选重排 | v0.5.0+ | src/rerank.rs |
| SQ8 默认量化 | v0.5.2 | src/embed.rs |
部署 memrust 的推荐路径:拉取官方镜像 → 配置命名空间与 API Key → 挂载持久化卷 → 注册 Prometheus 抓取 /metrics → 通过 HTTP 或 MCP 接口接入 agent 框架。
来源:https://github.com/AIAnytime/memrust / 项目说明书
失败模式与踩坑日记
保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。
非工程用户可能没有 Docker,启动成本明显增加。
安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
假设不成立时,用户拿不到承诺的能力。
新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
Pitfall Log / 踩坑日志
项目:AIAnytime/memrust
摘要:发现 8 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:安装坑 - 依赖 Docker 环境。
1. 安装坑 · 依赖 Docker 环境
- 严重度:medium
- 证据强度:runtime_trace
- 发现:安装/运行入口包含 Docker 命令:docker run -p 7700:7700 -v memrust-data:/data aianytime/memrust # Client SDKs pip install memrust # Python npm install memrust-client
- 对用户的影响:非工程用户可能没有 Docker,启动成本明显增加。
- 复现命令:
docker run -p 7700:7700 -v memrust-data:/data aianytime/memrust # Client SDKs pip install memrust # Python npm install memrust-client - 证据:identity.distribution | https://github.com/AIAnytime/memrust | docker run -p 7700:7700 -v memrust-data:/data aianytime/memrust # Client SDKs pip install memrust # Python npm install memrust-client
2. 配置坑 · 可能修改宿主 AI 配置
- 严重度:medium
- 证据强度:source_linked
- 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
- 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
- 证据:capability.host_targets | https://github.com/AIAnytime/memrust | host_targets=mcp_host, claude_code, claude, cursor, gemini_cli, chatgpt
3. 能力坑 · 能力判断依赖假设
- 严重度:medium
- 证据强度:source_linked
- 发现:README/documentation is current enough for a first validation pass.
- 对用户的影响:假设不成立时,用户拿不到承诺的能力。
- 证据:capability.assumptions | https://github.com/AIAnytime/memrust | README/documentation is current enough for a first validation pass.
4. 维护坑 · 维护活跃度未知
- 严重度:medium
- 证据强度:source_linked
- 发现:未记录 last_activity_observed。
- 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
- 证据:evidence.maintainer_signals | https://github.com/AIAnytime/memrust | last_activity_observed missing
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 证据:downstream_validation.risk_items | https://github.com/AIAnytime/memrust | no_demo; severity=medium
6. 安全/权限坑 · 存在评分风险
- 严重度:medium
- 证据强度:source_linked
- 发现:no_demo
- 对用户的影响:风险会影响是否适合普通用户安装。
- 证据:risks.scoring_risks | https://github.com/AIAnytime/memrust | no_demo; severity=medium
7. 维护坑 · issue/PR 响应质量未知
- 严重度:low
- 证据强度:source_linked
- 发现:issue_or_pr_quality=unknown。
- 对用户的影响:用户无法判断遇到问题后是否有人维护。
- 证据:evidence.maintainer_signals | https://github.com/AIAnytime/memrust | issue_or_pr_quality=unknown
8. 维护坑 · 发布节奏不明确
- 严重度:low
- 证据强度:source_linked
- 发现:release_recency=unknown。
- 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
- 证据:evidence.maintainer_signals | https://github.com/AIAnytime/memrust | release_recency=unknown
来源:Doramagic 发现、验证与编译记录