关于 Orma Memory
Orma 是面向本地 LLM 和编码 Agent 的长期记忆系统,可通过 Python SDK、兼容 OpenAI 的代理或 MCP 服务使用。它在本地 SQLite 中保存对话片段,并以混合搜索进行无需 LLM 调用的召回。
主要功能
- 01按追加日志保存对话片段
- 02SQLite 混合向量与全文搜索
- 03后台异步整理记忆
- 04提供 Python SDK 和兼容代理
- 05支持交互式记忆图可视化
适用场景
- 01为本地编码 Agent 提供跨会话记忆
- 02将长期记忆接入兼容 OpenAI 的客户端
- 03查询并可视化已保存的对话信息
MCP 相关
MCP 服务向编码 Agent 提供 `orma_recall` 工具。工具调用连接本地记忆系统,以检索保存的信息。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
4收录的工具列表 · 更新于 5 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| query | string | 是 | 要搜索的内容(例如:'project architecture'、'database configuration'、'user preferences')。 |
| space | string | 否 | 可选的隔离记忆空间(默认为 'default')。 |
详细介绍
Orma (ഓർമ്മ)
Orma (德拉威语/马拉雅拉姆语,意为“记忆”或“回忆”) 是一个以情节为先、零延迟的长期记忆层,专为本地开放权重的大模型打造(适用于消费级 8–16 GB 笔记本上的 3B–8B 模型)。
Orma 有两种使用方式:
- 作为原生 Python SDK(
from orma import Memory),直接集成到你的 Agent、聊天机器人和应用中(类似 Mem0 和 Cognee)。 - 作为兼容 OpenAI 的代理(
orma proxy或orma up),无需修改代码,即可为任何大模型工具、客户端或框架透明地添加长期记忆。
所有内容都通过 SQLite 和 sqlite-vec 在本地运行,并使用快速的设备端嵌入——无需外部服务、无需云端 API 密钥,也不会丢失数据。
快速导航
- 为什么选择 Orma?(与 Mem0 和 Cognee 对比)
- 真实基准测试:延迟、Token 和准确率
- 架构与数据流
- 安装与快速入门
- 使用方式
- 抑制控制与反模式预防(负面记忆)
- 多用户与多租户隔离
- CLI 参考
- 认知与数学架构
- 配置开关
为什么选择 Orma,而非 Mem0 和 Cognee?
大多数 Agent 记忆框架(如 Mem0 或 Cognee)都是为大型云端模型(GPT-4o、Claude 3.5 Sonnet)和企业级图数据库设计的:
- 它们会冻结对话轮次: 每次调用
add()都同步调用大模型,会导致本地机器卡顿 5–15 秒。 - 它们会产生幻觉图谱: 3B 模型难以完成复杂的实体关系提取,还会输出格式错误的 JSON 或颠倒关系。
- 它们会永久破坏事实: 向小模型提供破坏性
DELETE / UPDATE指令,容易导致意外数据丢失。
Orma 方法
- 片段就是记忆: 每轮对话、文档或工具日志都会完整保存在只追加日志中,并立即按句子建立索引。
- 回忆时不调用 LLM: 回忆通过混合向量搜索(sqlite-vec)和 BM25 全文搜索(FTS5),结合有界的近期性加权(ACT-R),在
< 25ms内完成。 - 睡眠会异步整合状态: 机器空闲时,后台工作进程会使用本地模型提取单值当前状态(
now true)和带日期的事件,并引用精确行号。 - 确定性代码防护: 时间解析、代词承接(anuvṛtti)和矛盾消解均由经过验证的 Python 代码处理,而不是依赖小型模型进行运算。
| 特性 | Mem0 | Cognee | Orma |
|---|---|---|---|
| 目标 LLM | 云端(GPT-4o) | 云端(GPT-4o) | 本地 3B–8B(Ollama / llama.cpp) |
| Python SDK | Memory() | cognee.add() | from orma import Memory |
| 零代码代理模式 | 付费云端 / 自定义 | 否 | 是(orma proxy / orma up) |
| 写入开销 | 同步调用 LLM(延迟 5–15s) | 多阶段图管线 | 即时(SQLite 追加耗时 < 5ms) |
| 回忆开销 | 向量 + LLM 合成 | 图遍历 + LLM | 即时(混合搜索耗时 < 25ms,调用 0 次 LLM) |
| 数据安全性 | 破坏性 DELETE / UPDATE | 有损图提取 | 无损只追加日志(可随时 rebuild) |
| 存储架构 | 外部向量数据库 | Neo4j / NetworkX + 向量 | 单个嵌入式 SQLite 文件(~/.orma/memory.db) |
| 幻觉防护 | 依赖 LLM 准确性 | 依赖 Pydantic 输出 | 行号引用 + 确定性 Python 防护 |
真实基准测试:延迟、令牌与准确性
没有编造的数据,也没有合成的营销图表。以下是 Orma 与 Mem0(arXiv:2504.19413,LOCOMO 的表 2)和 Cognee(BEAM 基准测试)已发布数据的实际对比,以及 Orma 测试套件(scripts/latency_smoke.py 和 eval/run.py)中的本地测量结果。
1. 检索延迟(端到端 p95)
大多数记忆系统会在回复前阻塞聊天轮次,以调用 LLM 或遍历实体图。Orma 在回忆期间从不调用 LLM,而是直接在 SQLite 中运行混合搜索(BM25 + sqlite-vec),将检索时间控制在 20ms 以内。
| 架构 | 检索机制 | p95 延迟 | 相对加速比 | 数据来源 |
|---|---|---|---|---|
| 完整上下文基线 | 暴力填充历史提示词 | 17,120 ms(17.1s) | 1.0x(基线) | arXiv:2504.19413,表 2 |
| Mem0g(图变体) | 向量搜索 + 图遍历 | 2,600 ms(2.6s) | 快 6.5x | arXiv:2504.19413,表 2 |
| Cognee(Graph-RAG) | 多信号向量 + 实体图 | ~1,950 ms(2.0s) | 快 8.8x | Cognee BEAM 基准测试 |
| Mem0(基础变体) | 向量语义查找 + LLM 合成 | 1,440 ms(1.4s) | 快 11.9x | arXiv:2504.19413,表 2 |
| Orma(认知引擎) | 零 LLM 混合 SQLite(FTS5 + sqlite-vec) | 18 ms(0.018s) | 快 951x | scripts/latency_smoke.py(2,000 条笔记) |
xychart-beta
title "p95 Retrieval Latency in Milliseconds (Lower is Better)"
x-axis ["Full-Context (Raw)", "Mem0g (Graph)", "Cognee (Graph-RAG)", "Mem0 (Base)", "Orma (Hybrid SQLite)"]
y-axis "Latency in ms (Log Scale Ratios)" 0 --> 18000
bar [17120, 2600, 1950, 1440, 18]
2. 上下文令牌占用
在本地运行 3B–8B 模型时,令牌会直接影响速度和注意力跨度。向提示词中塞入数千个记忆令牌,会让小模型变慢、难以跟上上下文。Orma 的 Sutra 打包会将事实压缩为紧凑的括号格式([user.city: Pune]),以极低的令牌成本提供完全相同的上下文。
| 记忆系统 | 记忆载荷格式 | 平均上下文令牌数 | 相较于完整上下文的令牌缩减比例 |
|---|---|---|---|
| 完整上下文基准 | 原始的多会话对话历史 | 约 26,031 个令牌 | 0%(上下文爆满) |
| Cognee | 图上下文树和实体关系 | 约 3,650–7,000 个令牌 | 约 73%–86% |
| Mem0g(图) | 图关系和语义条目 | 约 3,600 个令牌 | 86.2% |
| Mem0(基础版) | 提取的语义要点 | 约 1,764 个令牌 | 93.2% |
| Orma Classic | 按优先级排列的 Markdown 分节 | 约 240 个令牌(10 条事实) | 99.1% |
| Orma Sutra Packing | 紧凑的符号括号:[user.attr: val] | 135 个令牌(10 条事实) | 99.5%(比 Mem0 基础版少 68%) |
xychart-beta
title "Context Token Footprint in Prompt Window (Lower is Better)"
x-axis ["Full Context", "Mem0g", "Mem0 Base", "Orma Classic", "Orma Sutra"]
y-axis "Tokens Consumed per Query" 0 --> 30000
bar [26031, 3600, 1764, 240, 135]
3. 小模型上的准确性(Qwen 2.5 3B)
在 Qwen 2.5 3B 上使用 30 个多会话评估场景进行测试(eval/run.py 和 eval/cases.json):事实回忆、个人资料更新(替换旧的城市/工作)、避免将事实错误归于家庭成员,以及时间依据判断:
Scenario Without Memory (Raw Model) With Orma Cognitive Memory
---------------------------------------------------------------------------------------
Current Fact Accuracy (12 cases) 1 / 10 (10.0%) 12 / 12 (100.0%)
State Update Supersession (Pune->BLR) 0 / 1 (0.0%) 1 / 1 (100.0%)
Misattributions Avoided (Sister Asha) 2 / 7 (28.6%) 7 / 7 (100.0%)
Temporal Event Grounding (Trek date) 1 / 3 (33.3%) 3 / 3 (100.0%)
---------------------------------------------------------------------------------------
Total Evaluation Correctness: 1 / 10 (10.0%) 29 / 30 (96.7%)
4. 抑制控制(停止重复犯错)
小模型很容易做你告诉它不要做的事。如果你写下 “绝不要用分号串联 PowerShell 命令”,自回归注意力就会盯上 “分号”,然后照样输出分号。
Orma 会将负面规则提取为提示词顶部的抑制指令([FORBIDDEN: ...]),并采用负向表述语义,无需微调即可让小模型达到 100% 遵循率:
| 方法 | 负面提示词策略 | Qwen 2.5 3B 遵循率 | 观察到的行为 |
|---|---|---|---|
| 标准用户轮次 | “请不要使用分号” | 28%(10 次中失败 7 次) | 生成 git add . ; git commit |
| 系统记忆要点 | - user · forbidden: semicolon | 45%(10 次中失败 5 次) | 模型将要点视为被动知识 |
| Orma 抑制指令前置 | 提示词顶部添加 [FORBIDDEN: ...] + 框定语义 | 100%(10 次全部通过) | 生成整洁的多行命令;不含分号 |
架构与数据流
1. 在线回忆与认知检索流水线(< 25ms,零大模型调用)
flowchart TD
User["User / App / Chatbot"] -->|"1a. Chat Request"| Proxy["Orma Proxy / SDK"]
CodingAgent["Coding Agent (Claude Code / Cursor / Windsurf)"] -->|"1b. MCP Tool Call (orma_recall)"| MCPServer["Orma MCP Server"]
MCPServer --> Proxy
subgraph MultiSearch ["Multi-Channel Hybrid Search (SQLite)"]
Proxy -->|"2a. BM25 Query"| FTS["FTS5 BM25 Exact Text Index"]
Proxy -->|"2b. Vector Query"| Vec["sqlite-vec (bge-small-en-v1.5)"]
FTS --> RRF["Reciprocal Rank Fusion (RRF)"]
Vec --> RRF
RRF --> NoiseFloor["Adaptive Space Noise Floor Calibration"]
end
subgraph SpreadingGraph ["ACT-R Spreading Activation (SQLite Entity Graph)"]
NoiseFloor --> ExtractEntities["Extract Seed Entities from Query & States"]
ExtractEntities --> Adjacency["Traverse Bi-directional Entity Links"]
Adjacency --> FanEffect["Anderson's Fan Effect: Weight / Fan(Entity)"]
FanEffect --> AssociateStates["Boost Associated Context (Dr. Rao -> Clinic -> Toothache)"]
end
subgraph CognitiveRanker ["Stochastic & Cognitive Scoring Suite"]
AssociateStates --> Hawkes["Hawkes Temporal Burst: alpha * exp(-beta * dt)"]
Hawkes --> Ebbinghaus["Ebbinghaus Spaced Stability: S = S0 * (1 + gain * (n - 1))"]
Ebbinghaus --> BaseLevel["ACT-R Base-Level Decay: sum (age_days + 1)^(-d)"]
end
subgraph BudgetPacker ["Budget Allocation, Inhibitory Hoisting & Sutra Packing"]
BaseLevel --> Novelty["Novelty Gate: Drop duplicates (cosine >= 0.97)"]
Novelty --> Partition["Partition Budget: States | Events | Passages"]
Partition --> InhibitoryCheck{"Is Inhibitory? (forbidden_*, avoid_*)"}
InhibitoryCheck -->|"Yes (Anti-Pattern)"| TopHoist["Hoist to Top of Prompt: [FORBIDDEN: rule]"]
InhibitoryCheck -->|"No (Positive Fact)"| SutraFormat["Sutra Format: [user.attr: val] (-45% tokens)"]
TopHoist --> DynamicFraming["Inject Dynamic Negative Framing Semantics"]
SutraFormat --> DynamicFraming
DynamicFraming --> MemoryBlock["Construct Prioritized System Memory Block"]
end
MemoryBlock -->|"3. Injected Prompt"| Upstream["Local LLM (Ollama / llama.cpp / vLLM)"]
Upstream -->|"4. Streaming Response"| Proxy
Proxy -->|"5. Return to User / Agent"| User
Proxy -.->|"6. Async Non-Blocking Append"| EpisodicLog[("SQLite Append-Only Episodes")]
2. 后台休眠整合与可废止认识逻辑
flowchart TD
EpisodicLog[("Pending SQLite Episodes")] -->|"Idle (120s) or Batch Threshold"| Batcher["Episode Batcher (Line IDs [s1, s2, ...])"]
Batcher --> SleepLLM["Local Sleep Model (Qwen2.5-3B / Llama-3.2-3B)"]
SleepLLM -->|"Constrained JSON Schema Output"| RawExtraction["Raw States & Events with Line Citations"]
subgraph DeterministicVerification ["Deterministic Neuro-Symbolic Verification"]
RawExtraction --> V1["Line Citation Check (Cited sentence exists?)"]
V1 --> V2["Grounding Engine (Value matches / paraphrases line?)"]
V2 --> V3["Pronoun & Anaphora Resolution (Anuvṛtti tracking)"]
V3 --> V4["Calendar & Timezone Anchoring (clock.py)"]
end
subgraph InhibitoryAndDefeasibleGate ["Inhibitory & Defeasible Logic Gate"]
V4 --> ProhibCheck{"Declared Prohibited? (prohibited: true, orma_forbid)"}
ProhibCheck -->|"Yes (Anti-Pattern / Rule to Avoid)"| ForbiddenPrefix["Namespace Attribute: forbidden_<attr>"]
ProhibCheck -->|"No (Standard Fact)"| FrameCheck{"Has Schema Condition? (item.condition non-empty)"}
FrameCheck -->|"No (Categorical Fact)"| Categorical["Supersedes Contradictory Prior State"]
Categorical --> CloseOld["Mark Old State: active = 0, superseded_by_id = new_id"]
FrameCheck -->|"Yes (Defeasible Exception)"| Defeasible["Preserve Baseline Truth + Record Conditional Override"]
end
CloseOld --> Store[("SQLite State Store & Entity Adjacency Graph")]
Defeasible --> Store
ForbiddenPrefix --> Store
安装
pip install orma-ai
也可以从源代码安装以进行开发:
git clone https://github.com/wizardwithcodehazard/orma.git
cd orma
pip install -e ".[dev]"
python -m pytest -q # 213 tests pass locally
用法选项 1:Python SDK(直接集成到代码中)
使用 Python SDK,将 Orma 直接嵌入 Agent、流水线或 Web 应用:
from orma import Memory
# 1. Initialize memory (defaults to ~/.orma/memory.db)
mem = Memory(
upstream="http://localhost:11434/v1", # Ollama or llama.cpp endpoint
model="llama3.2:3b" # Model for background sleep consolidation
)
# 2. Add memories, documents, or ongoing chat turns
mem.add("I work as a backend engineer and I live in Pune.")
mem.add_file("project_notes.md")
# Record chat interactions
mem.observe(role="user", text="I moved from Pune to Bangalore last week.")
mem.observe(role="assistant", text="Congratulations on the move to Bangalore!")
# 3. Retrieve formatted context for prompt injection
messages = [{"role": "user", "content": "Where do I currently live?"}]
prompt_messages = mem.build_context(messages)
# prompt_messages contains a system prompt with current facts, outdated facts marked, and relevant quotes!
# 4. Search memory directly
results = mem.search("Where is my home?")
for state in results.states:
print(state.text) # "user · home city: Bangalore"
# 5. Background consolidation (extracts facts and closes outdated ones)
report = mem.sleep()
print(report)
mem.close()
用法选项 2:零代码代理(OpenAI SDK、LangChain、Cursor、Open WebUI)
将 Orma 作为本地代理启动:
# With Ollama
orma proxy --model llama3.2:3b
# Or with llama.cpp
orma proxy --upstream http://127.0.0.1:9931 --model "Qwen/Qwen2.5-3B-Instruct-GGUF:Q4_K_M"
然后将任意客户端指向 http://localhost:8080/v1:
使用官方 OpenAI Python 客户端:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="none"
)
response = client.chat.completions.create(
model="llama3.2:3b",
messages=[{"role": "user", "content": "What is my job and where do I live?"}]
)
print(response.choices[0].message.content)
使用 LangChain:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
base_url="http://localhost:8080/v1",
api_key="none",
model="llama3.2:3b"
)
使用 Open WebUI、AnythingLLM 或 Cursor:
- 将 OpenAI Base URL 设置为:
http://localhost:8080/v1 - 将 API Key 设置为:
none
用法选项 3:交互式 3D 连接组可视化工具(orma viz)
通过实时 WebGL 可视化模型的认知记忆图:
orma viz
这会启动记忆可视化工具,并直接在浏览器中打开 http://127.0.0.1:8080/_orma/viz:
- 新皮层连接组: 交互式 3D WebGL 神经网络,显示活跃状态(绿色)、硬性反模式(深红色)、可撤销规则(琥珀色)和实体枢纽(青色)。
- 动作电位脉冲: 突触边会根据近期程度和 Hawkes 突发频率,以定向光子粒子的形式动态呈现。
- 扩散激活: 搜索任意主题,即可让 3D 摄像机移动到对应节点,并观察激活沿相连邻居传播。
- 突触检查器: 点击任意节点,即可查看其精确的句子出处引用(
[s14])和历史时间线。 - 海马缓冲区: 实时抽屉,显示近期情景轮次流和待处理的睡眠巩固内容。
用法选项 4:一键启动 Web UI(orma up)
如果你使用 llama.cpp 或 Ollama 搭配浏览器 Web UI,请运行:
orma up --upstream http://127.0.0.1:9931 --model "Qwen/Qwen2.5-3B-Instruct-GGUF:Q4_K_M"
这会立即:
- 在端口 8080 上启动 Orma 记忆代理。
- 自动在默认 Web 浏览器中打开
http://127.0.0.1:8080/#/。 - 将 Web UI 前端请求透传,同时透明地通过 Orma 记忆层路由所有聊天补全请求。
用法选项 5:面向编码助手的 Model Context Protocol(MCP)服务
Orma 原生支持通过标准 stdio 使用 Model Context Protocol(MCP)。这样,编码 Agent(Claude Code、Cursor、Antigravity IDE、Windsurf、Roo Code、Hermes)就能在不同编辑会话间使用持久、零延迟的记忆,不再受会话遗忘困扰。
flowchart LR
subgraph Clients ["AI Coding Assistants & IDEs"]
ClaudeCode["Claude Code"]
Cursor["Cursor IDE"]
Windsurf["Windsurf"]
Antigravity["Antigravity / Roo / Hermes"]
end
subgraph Transport ["Standard stdio JSON-RPC 2.0"]
RPC["JSON-RPC Channel (orma mcp)"]
end
subgraph MCPServer ["Orma MCP Server Layer"]
RecallTool["orma_recall"]
RememberTool["orma_remember"]
ForbidTool["orma_forbid"]
FactsTool["orma_facts"]
ForgetTool["orma_forget"]
end
subgraph OrmaEngine ["Orma Local Cognitive Engine"]
Hybrid["Hybrid BM25 + sqlite-vec Search"]
InhibitoryEngine["Inhibitory Hoisting & Sutra Packing"]
SleepDaemon["Background Sleep Consolidation Worker"]
DB[("Embedded SQLite: ~/.orma/memory.db")]
end
Clients <-->|"stdio"| RPC
RPC --> MCPServer
MCPServer <--> OrmaEngine
OrmaEngine <--> DB
在 Claude Code 中:
claude mcp add orma -- orma mcp
在 Cursor 中(.cursor/mcp.json 或“设置” > MCP):
{
"mcpServers": {
"orma": {
"command": "orma",
"args": ["mcp"]
}
}
}
在 Windsurf / Antigravity IDE / Roo Code 中(mcp.json):
{
"mcpServers": {
"orma": {
"command": "orma",
"args": ["mcp"]
}
}
}
通过 Smithery.ai 一键安装:
npx -y @smithery/cli install orma-ai --client cursor
向 Agent 提供的工具:
orma_recall(query, space):返回经过令牌预算控制并以 Sutra 打包的活跃事实、反模式和过往决策(< 20ms)。orma_remember(text, kind, role, space):永久记录项目决策、架构规则或用户约束。将kind="anti_pattern"设为反模式,标记需要避免的错误。orma_forbid(rule, space):直接注册硬性反模式或禁止行为(例如,“绝不使用分号串联 PowerShell 命令”)。orma_facts(space, include_history):检查所有活跃的规范事实,无需执行搜索。orma_forget(state_id, space):关闭已过时或被取代的约束。
抑制控制与反模式防护(负面记忆)
使用编码助手的人都熟悉这种烦恼:你告诉模型 “停止使用分号串联 PowerShell 命令”,两轮之后它又这么做了。自回归注意力会紧盯着被禁止的令牌,并重复你要求它避免的错误。
flowchart TD
subgraph Problem ["Traditional LLM Attention Failure"]
UserWarning["User: 'Never use semicolon to chain commands in PowerShell'"] --> StandardLLM["Standard LLM Attention Mechanism"]
StandardLLM --> AttentionBias["Attention Activates on Forbidden Token: 'semicolon'"]
AttentionBias --> RecurrenceError["Forbidden Mistake Repeated: git add . ; git commit"]
end
subgraph Solution ["Orma Inhibitory Control Architecture"]
ForbidRule["Inhibitory Rule: orma_forbid / sleep extraction"] --> SchemaAttr["Schema Attribution (prohibited: true)"]
SchemaAttr --> NamespaceAttr["Attribute Namespacing (forbidden_powershell_chain)"]
NamespaceAttr --> HoistTop["Top-of-Prompt Hoisting: [FORBIDDEN: never use semicolon]"]
HoistTop --> DynamicFraming["Dynamic Negative Framing Semantics"]
DynamicFraming --> CleanOutput["Strict Negative Compliance: git add . \n git commit"]
end
Orma 引入了抑制控制:
- 架构层级归因: 睡眠提取期间会通过
prohibited: true识别负面规则,也可通过orma_forbid(rule)直接注册。 - Sutra 抑制前置: 禁止状态会呈现为
[FORBIDDEN: <rule>],并提升至系统提示词的最顶部(位于所有正面事实和对话历史之前)。 - 动态负面框定: 存在反模式时,Orma 会动态地将明确的负面约束语义注入系统提示词:
## Memory ... Lines marked [FORBIDDEN: ...] or under Forbidden are strict negative constraints: you must NEVER suggest, mention, or take what is forbidden. [FORBIDDEN: chaining terminal commands using semicolons or commas] [user.editor: neovim] - 普遍适用: 对开发者的痛点(终端语法、禁止的依赖、已弃用的 API 调用)和个人约束(严重过敏、语气边界、禁止使用的流行语)同样有效。
多用户与多租户隔离
Orma 开箱即用地支持隔离的记忆空间,因此多个用户或 Agent 会话不会相互污染记忆:
- 在 Python SDK 中:
mem.add("Alice likes green tea.", space="user_alice") context = mem.build_context(messages, space="user_alice") - 在 HTTP 请求/代理中:
传入
x-orma-space请求头或"user"字段:curl http://localhost:8080/v1/chat/completions \ -H "x-orma-space: user_123" \ -H "Content-Type: application/json" \ -d '{"messages": [{"role": "user", "content": "Who am I?"}]}'
CLI 参考
Orma 提供了用于管理记忆的命令行工具:
# Add a note or document
orma add "My dentist is Dr. Rao in Kothrud."
orma add docs/handbook.md
# Search memory
orma search "dentist"
# Inspect active facts and outdated history
orma facts --history
# Preview the exact prompt block that would be injected
orma recall "Who is my dentist?"
# Manually trigger sleep consolidation
orma sleep --model llama3.2:3b
# Forget a specific fact
orma forget 12
# Database statistics
orma stats
# Launch interactive 3D Cognitive Connectome WebGL visualizer
orma viz
# Run as an MCP server for Claude Code / Cursor / Windsurf
orma mcp
记忆提示词输出格式(Sutra 密集打包)
Orma 回忆记忆时,会将其打包成一种明确无歧义的高密度符号括号表示(相比对话式散文可节省 35–45% 的上下文令牌):
## Memory
What you remember about the person you are talking to, from earlier conversations, notes and documents. Answer directly using these facts and statements without asking the user to re-confirm details already provided here; do not mention this list. A line marked [outdated] was true when it was said and has changed since. Today is 2026-11-01.
[user.home city: Bangalore (since 2026-10-17)]
[user.morning drink: black coffee]
[user.morning drink | cond: sore throat -> warm ginger tea with raw honey]
[user.role: systems engineer @ Zerodha]
[EVENT: 2026-11-01: user received a gift from manager: Swiss knife]
[LOG: 2026-10-10 user: I'm Sahil and I live in Pune. [outdated: now Bangalore]]
(注意:可通过 enable_sutra_packing = False 切换回经典的自然语言分段格式)
认知与数学架构
Orma 将认知科学、随机点过程和非单调逻辑中的成熟原理直接集成到其零延迟检索引擎中:
+---------------------------------------------------------------------------------------------------+
| ORMA COGNITIVE RETRIEVAL PIPELINE |
+------------------------------------+--------------------------------------------------------------+
| Hybrid Search (BM25 + sqlite-vec) | Multi-channel fusion calibrated against dynamic noise floor |
| Spreading Activation (ACT-R) | Associative entity graph traversal with Fan Effect damping |
| Hawkes Temporal Burst Process | Self-exciting exponential kernel for conversational momentum |
| Ebbinghaus Retention & Stability | Dynamic stability scaling per spaced repetition & rehearsal |
| Defeasible Epistemic Logic | Conditional exception handling preventing false overwrites |
| Sutra Context Packing | Dense declarative bracket encoding saving 35-45% tokens |
+------------------------------------+--------------------------------------------------------------+
1. Hawkes 自激时间过程(enable_hawkes)
认知原理: 人类对话具有自然的聚类和时间突发性(Hawkes 1971,Kleinberg 2002)。当用户提起某个话题(例如正在进行的项目或身体症状)时,后续交流会围绕这一话题簇展开。标准的近期性衰减机制要么过快遗忘过去的话题,要么让它们保持活跃过久。
数学公式:
Intensity(t) = alpha * exp(-beta * dt)
beta = ln(2) / half_life_seconds
- 突发幅度(
alpha = 0.4): 提升活跃对话突发期间访问过的项目。 - 衰减常数(
beta = ln(2) / 1800): 30 分钟的半衰期可确保会话早些时候讨论的话题仍保持较强的对话惯性,同时不会无限期地延续到未来几天。 - 有界排序: 在 orma/recall/rank.py 中实现为有界加性加权,因此时间突发永远不会凌驾于精确事实匹配之上。
2. 艾宾浩斯间隔重复稳定性(enable_ebbinghaus)
认知原理: 人类遗忘曲线(Ebbinghaus 1885,Cepeda 等人,2008)表明,记忆保持会呈指数衰减,但每次间隔检索都会提升记忆的基础稳定性(半衰期)。随口提到一次的事实应逐渐淡去,而在 4 个不同日期得到确认的事实则应始终可访问。
数学公式:
Retention R(dt) = exp(-dt / S)
Stability S(n) = S0 * (1 + gain * (n - 1))
- 基线稳定性(
S0 = 2.0天): 单次提及时的初始稳定性。 - 复习增益(
gain = 0.5): 对于每次后续引用或间隔复习n,记忆稳定性都会线性增长,从而延长衰减前的半衰期。 - 双重保护: 单次出现的噪声会从回忆候选池中消失,而重复提及的偏好则能抵抗数月的衰减。
3. ACT-R 扩散激活与 Anderson 扇效应(enable_spreading_activation)
认知原理: 人类会通过联想回忆信息(Anderson 1983)。当被问到 “我牙痛时应该去哪里?” 时,查询中可能不包含医生的姓名,但“牙痛”这一概念会与“牙医”和“Rao 医生”产生联想。传统图数据库(例如 Neo4j)会增加 50–150ms 的网络开销。Orma 直接在 SQLite 中使用带索引的邻接表执行联想图遍历。
数学公式:
Activation A_i = B_i + sum_j (W_j * S_ji)
Association S_ji = Base_Weight / Fan(Entity_j)
- 源种子提取: 根据混合文本匹配和活跃状态识别种子实体。
- 扇效应: John R. Anderson 的扇效应证明,从某个概念扩散的联想激活与其关联事实的数量成反比:
- 具体实体(例如
Fan = 2的"Dr. Rao")会将 50% 的联想能量直接传递到目标诊所状态。 - 通用枢纽(例如
Fan = 60的"Pune")会将能量分散到数十种状态中,从而避免通用概念抢占回忆预算。
- 具体实体(例如
4. 可废止认识逻辑(enable_defeasible_logic)
认知原理: 现实世界中的信念具有非单调性。当用户先说:
“我每天早上都喝黑咖啡。” 后来说: “喉咙痛时,我会喝加蜂蜜的姜茶。”
朴素的记忆系统(如 Mem0 或基础图谱提取)会在实体属性 (user, drink) 上检测到矛盾,并破坏性地覆盖原有习惯。
认识规则引擎:
- Orma 通过模式归因检查断言(模型在休眠期间提取
item.condition),而非依赖脆弱的关键词匹配。 - 分类断言(
condition: "",例如"I moved to Bangalore"):触发状态取代(active = 0, superseded_by_id = new_state_id)。 - 可废止覆盖(
condition: "sore throat",例如"When sick, drink tea"):将其注册为条件例外,不会关闭或破坏基准分类事实。两条事实都会保留在上下文中。
5. 自适应噪声底校准与倒数排名融合
算法原理: 小型嵌入模型(例如 384 维的 bge-small-en-v1.5)会受到高维单位超球面上的几何集中效应影响——无关句子仅凭随机巧合就经常获得 0.45–0.55 的余弦相似度。
- 噪声底估算:Orma 动态抽样成对距离,计算嵌入空间的第 50 百分位噪声底。
- 相似度底截断:低于空间噪声底的分数不具有任何证据效力。
- 倒数排名融合(RRF):
无需调整超参数,即可融合精确关键词召回(FTS5 BM25)与语义向量搜索(sqlite-vec)。RRF Score = (1 / (60 + Rank_BM25)) + (1 / (60 + Rank_Vector))
6. Sutra 上下文编码(enable_sutra_packing)
认知与大模型原理: 小型 3B 模型主要接受代码和结构化 JSON 训练。自然语言叙事记忆块(“现为真:”“此前提及:”)会浪费宝贵的上下文预算来处理格式模板,还可能导致模型重复提出澄清问题。
- 紧凑声明式语法:将状态、条件、事件和过时的谱系压缩为原子化的方括号形式(
[user.attribute: value (metadata)])。 - 节省 Token:将提示词记忆开销降低 35% 至 45%,从而提升生成速度,并为用户指令留出更多空间。
- 零语法泄漏:格式经过设计,可确保经过指令调优的模型将知识吸收为背景系统事实,而不会向用户输出方括号。
7. 抑制控制与注意力前置
认知与神经符号原理: 在人类认知神经科学中,执行性抑制控制(前额叶皮层)会抑制占优的运动或言语冲动。在自回归 Transformer 中,否定式表述(“不要使用 X”)反而会提高生成 X 的概率,因为 Token 注意力会激活所提及词语的语义表征。
- 前置优先级:Orma 不会将否定规则交织在叙事事实中,而是将否定边界单独提取为
[FORBIDDEN: <rule>]Token,并放在系统提示词的最前面。 - 指令调优对齐:在任务上下文之前定义顶层边界时,现代指令调优模型(例如 Qwen 2.5、Llama 3.2、Claude 3.5)会将其视为硬性系统约束。
- 双通道注册:
- 声明式提取: 异步休眠会将 “never use semicolon in terminal” 映射为
prohibited = True和命名空间属性forbidden_<name>。 - 即时 MCP 工具: 编码助手可直接调用
orma_forbid(rule),立即建立防护规则,无需等待后台整合。
- 声明式提取: 异步休眠会将 “never use semicolon in terminal” 映射为
存储与数据持久性(100% 本地且持久)
- 单文件 SQLite 存储:所有记忆都存储在
~/.orma/memory.db中,并启用了预写日志(WAL)。 - 重启与电源循环后仍可保留:你可以随时关闭
orma up、重启机器或关闭终端;完整的记忆状态、情景历史和整合后的事实都会永久保存。 - 无损追加,不覆盖:模型产生幻觉时,情景记录不会被破坏性覆盖或清除。你可以随时使用
orma facts --history检查或重新整合历史记录。
配置与消融开关
Orma 中的每种机制都可以在 orma/config.py 中单独配置或消融,也可以通过 OrmaConfig 传入:
| 参数 | 默认值 | 描述 |
|---|---|---|
enable_semantic | True | 后台将记忆整合为状态和事件(关闭时 = 纯情景句子搜索基线) |
enable_novelty_gate | True | 丢弃重复句子(余弦相似度 >= 0.97) |
enable_similarity_weighting | True | 根据自适应空间噪声下限校准向量相似度 |
enable_base_level | True | ACT-R 基于近因性和频率的幂律衰减 |
enable_hawkes | True | 用于对话突发情况的 Hawkes 自激时间过程 |
enable_ebbinghaus | True | 艾宾浩斯间隔重复稳定性缩放 |
enable_spreading_activation | True | 带有扇出效应的关联扩散激活 |
enable_defeasible_logic | True | 非单调条件例外保护 |
enable_sutra_packing | False | 密集声明式括号编码(减少 40% 的 token 用量;默认 False,切换为 True 即可启用) |
budget_tokens | 4096 | 注入记忆块的 token 预算上限 |
search_k | 30 | 每个混合搜索通道检索的前 k 个候选项 |
rrf_k | 60 | 用于合并 BM25 和向量分数的倒数排名融合常数 |
许可证
本项目根据 Apache-2.0 License 发布。更多信息请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。