内容
# SMRITI
<p align="center">
<img src="assets/smriti-hero.svg" alt="SMRITI — 记忆知道何时" width="920">
</p>
**结构化记忆,具备反射索引和时间推理**
*smriti* (स्मृति): 梵文,意为“被记住的事物”。
一个零基础设施、本地优先、Apache-2.0许可的AI智能体内存层。一个SQLite文件。不需要Neo4j、Postgres、Docker、云账户或付费层。标准库HTTP + numpy是整个依赖面。
```python
from smriti import Smriti, LLM, OllamaEmbedder
mem = Smriti(path="memory.db",
embedder=OllamaEmbedder("nomic-embed-text"),
llm=LLM("qwen3:14b", provider="ollama"))
mem.add([{"role": "user", "content": "我于6月1日搬到了班加罗尔。"}],
timestamp="2026-06-02T10:00:00Z")
print(mem.context("我住在哪里?"))
# 已知事实:
# - [2026-01-15 | 已被2026-06-01取代] 用户住在海得拉巴。
# - [2026-06-01 | 当前] 用户住在班加罗尔。
```
## 您获得的是
一个今天就能运行、在您自己的机器上、并能在您自己的数据上验证的内存层 —— 无需基础设施、无需云账户、无需依赖排行榜。以下所有内容都是我们测试过的,而不是营销文案。
**1. 一行命令即可运行。无需搭建任何环境。** `pip install -e .` 为您提供了一个工作内存层,存储在一个单独的SQLite文件中 —— 无需Postgres、Neo4j、Qdrant、Redis、Docker或云账户。依赖面仅为Python标准库加上numpy。完整的离线测试套件和快速入门在无需网络和API密钥的情况下运行;lite模式完全离线。
**2. 无需外部服务即可运行 —— 且针对实际运行进行了强化。** 内存是一个文件:无需集群维护或版本匹配。它是提供者无关的 —— 可以指向任何OpenAI兼容的端点(Ollama、DeepSeek、Groq、OpenAI、vLLM...)和任何嵌入器。它在生产环境中生存:自动重试暂态网络错误、容错摄入(一次失败的尝试永远不会中止运行)、以及进度检查点 —— 所有这些都在实际网络故障后添加并测试过。
**3. 设计上成本低廉。** lite模式在写入时不进行任何LLM调用;完整模式在每个会话中只进行一次提取调用。检索打包了一个固定、预算上限的上下文(在我们的运行中,每个答案约1600个令牌),因此每个查询的成本保持在几分之一美分内 —— 即使是前沿的阅读器+裁判在500个问题上的成本也约为2.50美元。它在小型、廉价的模型上运行良好。Apache-2.0许可,所有功能都包含在内 —— 无需付费层即可使用图、时间或扩展功能。
**4. 可预测地扩展,您历史记录不会丢失。** 在包含的扩展测试框架上测量:约42,000行/秒的摄入速度、单数字毫秒级别的查询速度,最高可达约12k个记忆,并且在测试的每个扩展级别(300k+行)都能正确检索针头。更新*取代*而不是删除旧事实 —— 旧事实被标记为过去并保留,永远不会被销毁 —— 因此准确性不会随着会话的积累而悄悄衰退(这是删除写入系统随着时间推移而降低的故障模式)。您始终可以回答“现在什么正确”和“那时是什么正确”。
**5. 足够小,足够透明,您可以自己验证。** 约1.5k可读行,Apache-2.0许可。基准测试框架与代码一起提供,因此您可以用*您自己的*数据、*您自己的*裁判、*您自己的*硬件来衡量SMRITI —— `bench/ab.sh`运行一个固定裁判的A/B测试并打印增量变化。我们更愿意为您提供证明工具,而不是要求您相信我们自己评判的数字。
## 它与其他框架的比较
每个最近的开放框架都有一个赌注,每个赌注都会带来实际的运营成本:
| 框架 | 优势 | SMRITI填补的空白 |
|---|---|---|
| **GBrain** (Garry Tan,2026年4月) | 自我连接的带类型知识图谱,无需LLM调用进行提取;生产环境中已证明可处理146k+页面 | 需要Postgres + pgvector;需要手动编写markdown技能;无*截止日期*有效性模型;与OpenClaw / Hermes耦合 |
| **Supermemory** (本地构建) | 声称在LongMemEval / LoCoMo / ConvoMem中排名第一;二进制本地模式,RAG + 连接器 + 嵌入式代理;成熟的全栈选项 | 一个大型系统您需要信任而不是阅读;“遗忘”和时间处理是内部的 —— 您无法审计*为什么*一个事实被删除或应用了哪个窗口 |
| mem0 | 成熟的提取管道、广泛的SDK、90k+开发者 | 平面事实存储失去时间;图功能位于$249/mo Pro层后面;本地自托管需要Docker + Postgres + Qdrant;知识更新留下过时的事实相互竞争 |
| Zep / Graphiti | 双时间知识图谱 —— 适合“何时正确”的正确模型 | 重型图数据库基础设施;社区版已弃用;高级功能仅限云端 |
| Letta / MemGPT | 自我管理的内存层 | 您采用一个完整的代理运行时,而不是一个库;每个内存操作都花费LLM推理 |
SMRITI的综合:**保留Zep的时间模型和GBrain的实体图谱,去除数据库负担;保留mem0的提取规则,增加取代;与Supermemory竞争透明度,而不是排行榜。** 一个SQLite文件,约1.5k行您可以坐下来阅读,有效性窗口打印到模型看到的上下文中。
### 使用您自己的基准测试
SMRITI的立场是**发布并验证**。与其发布自我评判的标题,不如发布测试框架,并邀请您生成唯一重要的数字 —— 在您自己的对话中,使用您实际使用的模型和裁判。托管的领导者发布强大的排行榜分数;这些分数是使用前沿的阅读器评判他们自己的系统产生的,并且(通过他们自己的生产数据)其中一些分数在积累过时数据和矛盾时急剧下降。SMRITI的赌注是生产环境的现实:任何地方都可运行,值得信赖,保留完整的历史,几乎不花钱 —— 而且您可以通过一个命令自己验证准确性。在我们自己的系统内A/B测试中,每个类型的路由器在多会话聚合中提升约10个点(p<0.05),而在知识更新方面没有回归;这是否适用于您的工作负载,是您确认的,而不是我们要求您相信的。
## 架构
每个阶段都带有梵文名称 —— 不是品牌,而是借用的精度。Nyaya的记忆账户(**anubhava → samskara → smriti**:体验留下印象,回忆从印象中产生)*是*写入路径;Vedanta的**badha**(覆灭:后来的认知使早期的认知无效,但不抹去它曾经发生过)*是*取代。完整的词典和每个术语背后的推理: [`NOMENCLATURE.md`](NOMENCLATURE.md)。
```
写入路径(写入时合并)
会话 ──► 事件日志 · anubhava अनुभव (仅追加,嵌入式,FTS索引)
└─► 事实提取 · grahana ग्रहण (1个LLM调用/会话)
└─► 冲突解决 · badha बाध :
层级1:(主题,谓词)键冲突 → 取代,0令牌
层级2:语义冲突 → 1个微小仲裁调用
事实从不被删除 — invalid_at + superseded_by
保留完整的双时间历史(有效性窗口 = avadhi अवधि)
事实存储 · samskara संस्कार
读取路径(读取时反射) · smarana स्मरण
查询 ──► 4个通道并行:
1. shabda शब्द BM25(SQLite FTS5) 事实 + 事件
2. artha अर्थ 向量 事实 + 事件
3. sambandha सम्बन्ध 实体跳跃(图谱-lite,padartha物质链接)
4. kala काल 距离查询最近的事件日期
──► 互惠排名融合 · sangama संगम
──► 有效性注释(当前 / 已取代-在-日期)
──► 打包,带有出处信息的上下文 · prasanga प्रसंग
```
两个值得辩护的设计决策:
1. **事实和原始事件在检索时都是首要的。** 仅提取的系统会丢失提取器错过的任何内容;仅事件的系统在处理知识更新时很困难。融合两者可以获得精炼事实的精度和原始证据的召回安全性。
2. **取代,而不是突变。** “我住在哪里?”读取当前事实。“我之前住在哪里?”读取有效性窗口。相同的存储,没有额外的机制,完整的审计轨迹。
### 模式
- **`lite`** (别名`laghu`, लघु — “轻”) — 写入时不进行任何LLM调用。事件摄入 + 4通道混合检索。近乎零成本,完全离线能力,检索仅限混合模式已知可恢复大部分基准价值。适合高容量代理的默认模式。
- **`full`** (别名`purna`, पूर्ण — “完整”) — 添加事实提取 + 写入时合并。每个会话一个提取调用,仅在语义冲突时进行仲裁调用。这是知识更新和时间推理准确性的来源。
## 安装并在60秒内尝试
```bash
pip install -e . # 从此存储库
python -m pytest tests/ # 33个离线测试 — 无网络,无API密钥
python examples/quickstart.py # 现场查看取代
```
快速入门在**离线**(lite模式)下运行。对于LLM支持的提取和取代,将SMRITI指向任何OpenAI兼容的端点(Ollama,vLLM,LM Studio,Groq,DeepSeek,OpenRouter,托管)和任何嵌入器 — 无需额外安装。
### 放入您的代理(MCP)
SMRITI提供了一个一键MCP服务器,因此任何MCP兼容的代理(Claude Code,Cursor,...)都具有持久、可审计的内存:
```bash
smriti-mcp --db memory.db # 或:python -m smriti.mcp_server --db memory.db
```
将其添加到您的代理的MCP配置中:
```json
{ "mcpServers": { "smriti": { "command": "smriti-mcp", "args": ["--db", "memory.db"] } } }
```
它公开了六种类型的工具,返回结构化的JSON — `remember`, `recall`, `search`, `facts_about`, `add_fact`, `stats`. 默认情况下离线(无密钥);设置`SMRITI_LLM_MODEL` / `SMRITI_LLM_PROVIDER` / `SMRITI_API_KEY`以启用完整提取模式。
### 在您的数据上进行基准测试
不要听我们说 — 在您自己的对话中,使用您自己的裁判,运行随附的测试框架:
```bash
bash bench/ab.sh # 固定裁判的A/B,打印准确性变化
```
## 基准测试
测试框架位于`bench/`中,用于**LongMemEval**(ICLR 2025 — 实际标准:500个问题,约115k令牌历史,测试提取,多会话推理,时间推理,知识更新,放弃)和**LoCoMo**(mem0发布数字背后的基准)。
```bash
# 1. 获取数据集(LongMemEval来自HuggingFace,LoCoMo来自GitHub)
python -m bench.download # 神谕 + locomo(小,快速)
python -m bench.download --all # 每个分割,或命名一个:longmemeval_s
# 2. 在神谕分割上进行快速本地验证
python -m bench.run --bench longmemeval --data data/longmemeval_oracle.json \
--mode lite --limit 50 --answer-model qwen3:14b --judge-model qwen3:14b
# 3. 可比较的数字:full模式下的longmemeval_s
python -m bench.run --bench longmemeval --data data/longmemeval_s_cleaned.json \
--mode full --provider groq --api-key $GROQ_API_KEY \
--memory-model llama-3.3-70b-versatile \
--answer-model llama-3.3-70b-versatile --judge-model llama-3.3-70b-versatile
# 4. LoCoMo
python -m bench.run --bench locomo --data data/locomo10.json --mode full --limit 200
```
输出:整体准确性,**每个问题类型的准确性**(诚实视图 — 时间推理和知识更新是扁平存储死亡的地方),摄入/答案延迟和令牌计数,以及用于错误分析的完整每个问题JSONL。
**诚实部分。** SMRITI尚未在完整的基准测试中运行 — 测试框架存在正是为了让数字来自您的硬件,而不是来自营销。发布的参考点可击败或匹配:Zep ~63.8% 和 Hindsight ~91.4% 在 LongMemEval vs. mem0的 ~49%; mem0 在 LoCoMo 上报告 J≈66.9。供应商数字使用不同的裁判,答案模型和分割,因此唯一的比较是您使用固定裁判自己运行的比较。运行lite和full模式并行;报告两者。
## 仓库布局
```
smriti/ 核心库
store.py SQLite双时间存储 — anubhava + samskara(FTS5 + 向量)
extraction.py grahana:单次传递会话 → 原子事实
consolidation.py badha:ADD / SUPERSEDE / SKIP冲突解决
retrieval.py smarana:4通道检索 + sangama(RRF)+ prasanga打包
memory.py 公共Smriti API(模式:lite/laghu,full/purna)
embedder.py Ollama / OpenAI兼容的 / 离线哈希
llm.py OpenAI兼容的客户端 + 模拟
mcp_server.py 仅限标准库的MCP服务器(6种类型工具,stdio JSON-RPC)
bench/ pariksha:LongMemEval + LoCoMo运行者,nyaya裁判,CLI,A/B
tests/ 离线测试套件(模拟LLM,哈希嵌入器)— 33个测试
examples/ 可运行的快速入门
NOMENCLATURE.md 完整的词典以及每个术语为何重要
smriti-dashboard.html 功能级比较仪表盘(在任何浏览器中打开)
smriti-landing.html three.js登录页面 — 四条河流的sangama(供应商/three.min.js备用,离线工作)
smriti-teaser.html 36秒自包含启动预告 — 打开,它播放并循环;以1080p屏幕录制或分享链接
```
## 路线图
### 已发货
基于研究的(Hindsight观察范式;StructMem / MemGAS多粒度;mem0实体链接;多跳RAG文献),每个都通过固定的裁判A/B验证:
- [x] 观察/总结层 + 添加注入 + 枚举-不-断言
- [x] 多粒度摘要(每个实体和每个`(subject, predicate)` + 数值/总计
- [x] 召回跟踪 — 事实增强的关键扩展 + 聚合计数路径
- [x] **每类型路由器** — 召回配置文件聚合,精度配置文件当前状态。提升多会话 **+10点(p<0.05)** 且 **无** 知识更新回归
- [x] mem0启发的杠杆 — FTS Porter stemmer,语义实体链接(两者可选)
- [x] 2跳实体遍历 · 交叉编码器重排名 · 迭代检索
- [x] **MCP服务器** — `smriti-mcp`: 仅限标准库stdio JSON-RPC,6种类型工具,默认lite,安全强化(ATTACH/DETACH授权器,固定DB路径,输入上限,防崩溃循环)
- [x] 基准测试框架 — 分层 `--sample`, `--question-type`,一键A/B(`bench/ab.sh`)
### 下一步(发布后)
按影响顺序递延:
1. **实体规范化** — 写入时置信度评分的别名合并(“Rachel” / “我的表弟Rachel” / “Rachel Smith” → 一个实体)。关闭跨实体聚合后的碎片。(Codebase-Memory解析级联 + mem0实体链接)
2. **sqlite-vec** ANN后端 — 可选向量索引以提升 ~100k行后的O(N)扫描;回落到numpy,保持单个文件零基础设施默认值。(测量的扩展上限)
3. **完整的`longmemeval_s` + LoCoMo数字** — 在硬(完整干草堆)分割上发布,使用固定的裁判;可选的前沿阅读器用于leaderboard可比性(〜$2.50/运行,见BENCHMARKS.md)。
4. **递归-CTE N跳遍历** — 任意深度实体遍历,使用纯SQL。(Codebase-Memory技术)
5. **增量观察刷新** — 内容哈希,以便仅更改的实体/谓词重新总结。(XXH3模式)
6. **生产强化** — 嵌入维度保护,异步摄入队列 + 批处理嵌入,多用户(`user_id`)命名空间,并发安全的存储库)。