Holographic Memory

io.github.writerslogic由 GitHub 帳號 writerslogic 發布v0.1.2更新於 Nov 2, 2026

Local persistent memory for AI agents with recall, search, forgetting, and encrypted storage.

發布方自己的服務:Memory.fit

已驗證STDIO僅桌面檔案與儲存知識與記憶

概覽

AI 產生的概覽

為 AI 助理提供本機持久記憶:在本機儲存、召回、搜尋、列出、匯出與刪除長期事實和偏好。

可以做什麼
  • 儲存長期事實、決策與偏好,可選擇版本檢查或僅新建寫入
  • 依自然語言問題召回記憶,或以中繼資料篩選與排序控制進行搜尋
  • 依 id 完整讀取單筆記憶,並依 id 前綴或標籤分頁瀏覽
  • 依 id 或 id 前綴刪除記憶,前綴刪除需明確確認
  • 檢視儲存筆數、召回模式、加密狀態與容量,並匯出 JSON、JSONL 或 Markdown 快照
適用情境
適合希望助理跨對話記住事實、決策與偏好,又不願把這些內容交給託管服務的情境。也適合本機優先或離線環境,讓記憶保存在本機目錄中。
執行需求
以本機程序透過 stdio 執行,使用 npx 或 uvx 啟動已發布的 npm 或 PyPI 套件。未宣告需要帳號、API 金鑰或環境變數。語意排序需另行設定嵌入模型;加密與語意召回屬於預設關閉的建置功能。
安裝前請注意
儲存並非匿名:詞頻與向量草圖可與候選文字比對,關閉文字儲存也不構成隱私保護。加密為選用功能,且中繼資料、檔名與大小不加密。刪除只從儲存中移除事實,無法消除模型已推論出的內容。同一儲存同時只允許一個寫入程序。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Holographic Memory,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[WARM logo]

WARM

WritersLogic Adaptive Retention & Memory.

Hybrid search, graph indexing, and vector-symbolic memory.

Local memory for agents and apps: full-text and vector search, a memory API and a vector-symbolic fact store in one embeddable Rust engine that makes no network calls.

[CI] [MSRV 1.89] [OpenSSF Scorecard] [OpenSSF Best Practices] [License: Apache-2.0] [WARM MCP MCP server – quality and maintenance score on Glama]

[Bemula forgetting score, DeepSeek backbone] [LongMemEval dev, gpt-4o reader and judge] [VIBE llama-128-ip max recall@100, one thread]

Website · Docs · Get started · Standards and provenance · Results · Capabilities · Limits · Contribute


What it is

WARM is a Rust library that stores text, vectors and facts in a directory on your machine and finds them again. It ships with Node.js bindings, C, WASM and UniFFI bindings, an HTTP server with a Python client, and an MCP server. There are no service calls, no telemetry and no model downloads unless you turn on a feature that asks for one.

CapabilityWhat you get
Document searchChunking, stemmed BM25 over blocked postings, Boolean and phrase queries, hybrid fusion with embeddings you supply, metadata filters, byte offsets
Vector indexGraph index with a memory-mapped vertex file, an updatable delta for inserts and deletes, optional query-aware routing trained on sample queries
Memory APIremember, recall, forget and explain with time validity and supersession; conversation memory with source provenance
StorageAtomic replace and delete, crash-safe journal and checkpoints, verified compaction, one writer per store
SecurityOptional AES-256-GCM storage encryption with documented coverage and limits, signed audit log, COSE/SCITT provenance
Vector-symbolic layerSparse hypervectors with bind, bundle and permute, triples with multi-hop queries, Hopfield cleanup

Who it's for

You are buildingWhat you get
An agent or assistant that needs memoryA memory API with forgetting that removes facts from the store, and an MCP server for editors and agent hosts
A local-first or offline appEmbedded search and storage in one directory, with no server process and optional encryption
A service that needs vector or text searchwarm-server over HTTP with tenants and scoped keys, or the library in-process
Research on vector-symbolic memoryThe bind/bundle algebra, meaning memory and capacity experiments with their result files

Headline results

Every row links to the committed file it comes from. These are single machines and stated protocols, not a substitute for testing your own data.

ResultConditionsSource file
Bemula forgetting score 0.322; best published row 0.310 (LangMem)Full split: 50 dialogues, 135 forget requests. Agent and judge both deepseek-v4-flash-0731 through OpenRouter pinned to DeepSeek, temperature 0; the judge snapshot is inferred from the authors' run metadata. Recall k=5 hybrid with text-embedding-3-small. Compared with the paper's published DeepSeek rows; a same-day rerun of the suite's naive RAG baseline scored 0.075. One run.bemula_v1.json
LongMemEval dev 89.75 of 100 correct (mean of 4 runs, range 87 to 93)Official generation and judge prompts, gpt-4o-2024-08-06 as reader and judge, top 10 context. Retrieval is the reference turn ranking over cached Qwen3 scores, not native conversation-memory recall. k was chosen on dev; there is no held-out result.longmemeval_official_dev_summary.json
VIBE llama-128-ip strict recall@100 up to 0.99687 at 1,457 QPSOfficial test queries, one thread, query-aware graph (ef=512). Neither frozen RoarGraph configuration reached 0.99. Behind at 0.95 and 0.99 QPS (see below).query_aware_graph_v1/README.md
VIBE yi-128-ip at recall 0.95: 3,214 QPS against 1,953 (MLANN RF80)Same protocol; compared only with the frozen RoarGraph and MLANN configurations measured there. Recall 0.99 was not reached.query_aware_graph_v1/README.md
SIFT-1M QPS at recall@10 0.95: 17,481 against hnswlib 7,630 (2.29x, interval 1.95 to 2.39)Historical observation with unpinned source revision (comparative verdict unverified). Core Ultra 9 185H, queries issued one at a time from one client thread, process not pinned to a core, index built with 8 threads. Timed through the Rust API, hnswlib through its Python binding.heavy-ann-sift-...-185h-22c-27g.json
SciFact nDCG@10 hybrid 0.729, above its own BM25 (0.688) and dense (0.645)5,183 documents, 300 queries, MiniLM embeddings supplied by the harness. NFCorpus: 0.355 against 0.323 and 0.317.public_scifact.json, public_nfcorpus.json

Where it's behind

ResultConditionsSource file
ann-benchmarks at recall 0.95: sift 2,819 QPS against faiss-ivfpqfs 3,788 (0.74x); glove 1,019 against ScaNN 1,535 (0.66x)Official ann-benchmarks runner, each run pinned to one CPU, AVX2 hostann_benchmarks_harness_wl02_v1.json
VIBE llama-128-ip QPS: 24.6% behind RoarGraph at recall 0.95, 54.8% behind MLANN RF80 at 0.99One thread, official test queriesquery_aware_graph_v1/README.md
SIFT-1M build time 0.58x and serving RSS 0.46x of hnswlibSame run as the QPS row abovedocs/benchmarks/GAPS.md
Text search ingest time, serving RSS and cold start behind SQLite FTS5 and tantivy on most corporaBEIR and memory corpora, two hostsdocs/benchmarks/GAPS.md
glove-100-angular with the sparse vector path: recall@10 0.252 at 33.7 QPS against FAISS HNSW 0.832 at 4,111 QPSOne thread, Apple M4; the sparse path is experimentalpublic_glove-100-angular.json

Method, intervals and every loss: docs/benchmarks and the benchmarks pages.

Generated from benchmarks/results/competitive/ by warm-bench table; method and caveats in docs/benchmarks/COMPARISON.md. W = WARM ahead (95% interval excludes parity), T = tie, L = a comparator is ahead.

DatasetMetricWARMBest otherAdvantage
sift-128-euclideanQPS @ recall@10 >= 0.95 (QPS)17,481hnswlib 7,630n/v-
sift-128-euclideanp99 latency @ 0.95 (us)105hnswlib 220n/v-
sift-128-euclideanBuild time (s)312.60hnswlib 182.49n/v-
sift-128-euclideanRSS, serving (MiB)2,204hnswlib 1,019n/v-
sift-128-euclideanIndex size (MiB)446.3hnswlib 873.8n/v-
beir:fiqanDCG@100.2654SQLite FTS5 0.2678n/v-
beir:fiqaQPS (single thread) (QPS)3,612tantivy 1,617n/v-
beir:fiqap99 latency (us)509tantivy 1,269n/v-
beir:fiqaIngest/build time (s)2.16SQLite FTS5 1.18n/v-
beir:fiqaPeak RSS, serving (MiB)n/mn/mn/m-
beir:fiqaOn-disk size (MiB)20.6Apache Lucene 9.12.3 (JVM) 12.2n/v-
memorynDCG@100.4561Apache Lucene 9.12.3 (JVM) 0.46270.99xT
memoryQPS (single thread) (QPS)2,289tantivy 2,5040.91xT
memoryp99 latency (us)775tantivy 7200.93xT
memoryIngest/build time (s)2.52SQLite FTS5 2.060.82xL
memoryPeak RSS, serving (MiB)66SQLite FTS5 260.39xL
memoryOn-disk size (MiB)9.8Apache Lucene 9.12.3 (JVM) 10.31.05xW
memorynDCG@100.4561Apache Lucene 9.12.3 (JVM) 0.4627n/v-
memoryQPS (single thread) (QPS)12,629tantivy 4,850n/v-
memoryp99 latency (us)145tantivy 396n/v-
memoryIngest/build time (s)1.21SQLite FTS5 0.88n/v-
memoryPeak RSS, serving (MiB)n/mn/mn/m-
memoryOn-disk size (MiB)9.8Apache Lucene 9.12.3 (JVM) 10.3n/v-
beir:nfcorpusnDCG@100.2916SQLite FTS5 0.2914n/v-
beir:nfcorpusQPS (single thread) (QPS)40,784tantivy 15,413n/v-
beir:nfcorpusp99 latency (us)57tantivy 150n/v-
beir:nfcorpusIngest/build time (s)0.23SQLite FTS5 0.14n/v-
beir:nfcorpusPeak RSS, serving (MiB)n/mn/mn/m-
beir:nfcorpusOn-disk size (MiB)2.1Apache Lucene 9.12.3 (JVM) 1.5n/v-
beir:nfcorpusnDCG@100.2916SQLite FTS5 0.29141.00xT
beir:nfcorpusQPS (single thread) (QPS)10,572tantivy 7,1511.48xW
beir:nfcorpusp99 latency (us)279tantivy 2941.05xT
beir:nfcorpusIngest/build time (s)0.59SQLite FTS5 0.290.48xL
beir:nfcorpusPeak RSS, serving (MiB)57SQLite FTS5 300.53xL
beir:nfcorpusOn-disk size (MiB)2.1Apache Lucene 9.12.3 (JVM) 1.50.72xL
beir:scifactnDCG@100.7027Apache Lucene 9.12.3 (JVM) 0.7022n/v-
beir:scifactQPS (single thread) (QPS)17,782tantivy 6,450n/v-
beir:scifactp99 latency (us)95tantivy 287n/v-
beir:scifactIngest/build time (s)0.31SQLite FTS5 0.20n/v-
beir:scifactPeak RSS, serving (MiB)196tantivy 174n/v-
beir:scifactOn-disk size (MiB)2.9Apache Lucene 9.12.3 (JVM) 2.0n/v-
beir:scifactnDCG@100.7027Apache Lucene 9.12.3 (JVM) 0.70221.00xT
beir:scifactQPS (single thread) (QPS)2,733tantivy 2,9650.92xL
beir:scifactp99 latency (us)518tantivy 5080.98xT
beir:scifactIngest/build time (s)1.42SQLite FTS5 0.430.30xL
beir:scifactPeak RSS, serving (MiB)160SQLite FTS5 540.34xL
beir:scifactOn-disk size (MiB)2.9Apache Lucene 9.12.3 (JVM) 2.00.68xL

Get started

Clone once: git clone https://github.com/writerslogic/warm && cd warm. Run the offline agent-memory demo with cargo run --release --example demo-offline-agent.

Rust

From your own Rust project, add the current Apache-2.0 source:

sh
cargo add warm-rust

The published crate 0.6.1 remains AGPL-3.0-or-later.

rust
use writerslogic_warm::{DocumentInput, WarmCore, SearchOptions};
let dir = tempfile::tempdir()?;let warm = WarmCore::new(4096, Some(dir.path().display().to_string()), None)?;warm.memorize_document(DocumentInput {    id: "backups".into(),    text: "Restore deleted documents from verified backups.".into(),    source_uri: Some("operations.md".into()),    version: Some("1".into()),    metadata: Some(serde_json::json!({ "project": "alpha" })),    chunk_words: None, overlap_words: None, store_text: None, embeddings: None, title_weight: None,})?;let hits = warm.search_documents("restore backups", &SearchOptions::default())?;println!("{} {:?}", hits[0].document_id, hits[0].source_uri);

Unreleased Rust API change: WarmCore::query, query_batch, and analyze_components return Result. Handle the result with ? or an explicit error branch; deferred-encoding failures no longer become successful partial query results. get_document, list_documents, get_document_info, and list_document_info also return Result; retained-text and checkpoint decoding failures propagate instead of panicking, and reads no longer hydrate the entire checkpoint or hold store locks during text I/O.

Node.js

Install the Node.js package and its platform-specific native binary:

sh
npm install writerslogic-warm

To build from source, run npm ci --omit=optional && npm run build with Rust installed. The WARM release includes listDocuments for scoped pruning. See the integration guide for source provenance, namespace isolation, dry runs and deletion limits.

js
const { WarmMemorySystem } = require('writerslogic-warm')const { DocumentMemory } = require('writerslogic-warm/semantic')
async function main() {  const dir = require('node:fs').mkdtempSync(require('node:path').join(require('node:os').tmpdir(), 'warm-readme-'))  const memory = new DocumentMemory(new WarmMemorySystem(4096, dir))  await memory.memorize({    id: 'backups', text: 'Restore deleted documents from verified backups.',    sourceUri: 'operations.md', version: '1', metadata: { project: 'alpha' },  })  const [hit] = await memory.search('restore backups', { filter: { project: 'alpha' } })  console.log(hit.documentId, hit.sourceUri, hit.text)  await memory.flush()}main().catch(error => { console.error(error); process.exit(1) })
Server and Python

The Python package warm-sdk is an HTTP client for warm-server, which stores vectors you supply. (warm-python provides native vector search and phase vectors, but no document search.)

sh
cargo build --release --features server --bin warm-serverWARM_API_KEY=change-me target/release/warm-server --input-dim 384 &uv pip install warm-sdk
python
from writerslogic_warm_sdk import WarmClient
client = WarmClient(url="http://127.0.0.1:8080", api_key="change-me", tenant_id="demo")client.add_documents([{"id": "a", "vector": [0.1] * 384, "text": "hello", "metadata": {}}])print(client.query([0.1] * 384, top_k=1)["matches"][0]["id"])

Endpoints, flags, tenants and limits are in the server docs. A runnable Python quickstart with a toy embedder is in examples/quickstart/python.

MCP

warm-mcp serves a store to any Model Context Protocol client over stdio or HTTP:

sh
npx -y writerslogic-warm-mcp                                # stdio; downloads a verified binary on first runnpx -y writerslogic-warm-mcp --transport http               # http://127.0.0.1:8765/mcp

The MCP package is a separate launcher. To build the server from source:

sh
cargo build --release --features mcp,security --bin warm-mcp   # add local-models for semantic recall./target/release/warm-mcp                                       # stdio./target/release/warm-mcp --transport http                      # http://127.0.0.1:8765/mcp

Client setup, data directory and the one-writer rule: MCP integration.

For normalized content from multiple applications, see the organizational knowledge adapter.

The five-minute quickstart walks through ingest, search, a SQLite FTS5 comparison and encryption in Rust, Python and Node, and CI runs that code on every pull request. For a whole agent memory with no embeddings and no network, run cargo run --example demo-offline-agent.

What ships today

CapabilityStatusDocumented limit
Hybrid document search (BM25 + exact cosine, filters, byte offsets)ShipsExact scan of eligible chunks; benchmark your corpus before assuming capacity (guide)
Boolean lexical search (+required, -excluded, quoted phrases)ShipsFlat queries only, no nesting; an empty or only-excluded query matches nothing (design)
Atomic replace/delete, crash-safe journal, verified compaction, process lockShipsOne writer per store; compaction is not secure erasure
Vector index (qgraph vertex graph, memory-mapped)ShipsBuild time and serving RSS behind hnswlib on SIFT-1M (gaps)
Updatable vector index (durable delta for inserts and deletes)ShipsSingle writer; format in VECTOR-UPDATES.md
Query-aware graph routing (trained on sample queries)Ships (opt-in)Needs representative training queries; tested on VIBE llama and yi (report)
Memory API: remember, recall, forget, explainShipsForgetting removes a fact from the store; it does not cover what a model inferred (docs)
Conversation memory (conversation-memory)ShipsBounded context with exact source provenance; native recall not yet benchmarked on LongMemEval end to end
Meaning memory: triples, multi-hop, Hopfield cleanupShips (runtime opt-in)Tested on synthetic and 2,120-fact sets (research_bench_16384_256.json)
Union-bundle membership (experimental)ResearchAt D = 16,384: positive gap to N = 500 (4% false positives), tested to 2,500 (benchmark_scaling_results.json)
Sparse vector index (memorize_vector)ExperimentalNot competitive with HNSW (results)
Encrypted stores (security)ShipsAES-256-GCM, Argon2id; covers the log, index caches and the text segment. Metadata, file names and sizes are not encrypted
Signed audit log, credential-gated access, COSE/SCITT/C2PA (provenance)ShipsHost must authenticate DIDs; PoSME, RATS, did:web not implemented
On-device models (local-models: Qwen3 embed/rerank/LLM)ShipsLocal weights only; never downloads
warm-server HTTP API, multi-tenant (server)ShipsSingle node; TLS, per-tenant scoped keys (guide)
MCP server (mcp: warm-mcp, stdio and HTTP)ShipsEncryption needs security; semantic recall needs local-models
Node.js bindingsShips on npm and from sourceNative binaries are selected by platform at install time
C, Go, .NET, Java, Kotlin, Swift and WebAssembly bindingsSource availableRequire local builds; the language packages and native bundles are not yet published (runtime guides)
PythonClient + phase substrateNo in-process document search
Query-private search (private-search)ExperimentalFor searching an index someone else holds; hides the query vector from the scorer only (notes)

Every capability above except document search and the vector index is behind a Cargo feature or runtime option that is off by default; Cargo features lists them all.

Architecture

mermaid
flowchart TB  subgraph bindings["Bindings and servers"]    rust["Rust crate"]    node["Node.js (napi)"]    ffi["C, WASM, UniFFI"]    python["Python: warm-sdk"]    server["warm-server (HTTP)"]    mcp["warm-mcp (stdio, HTTP)"]  end  subgraph engine["Engine API"]    core["WarmCore: documents, vectors, facts, mutation gate"]    prov["Security and provenance: signed audit log, COSE/SCITT"]  end  subgraph indexes["Indexes and memory"]    text["Text index: blocked postings, BM25, Boolean and phrase"]    vector["Vector index (qgraph): vertex file, updatable delta, query-aware projection"]    memory["Memory API: remember, recall, forget, conversation memory"]    vsa["Vector-symbolic layer: bind, bundle, Hopfield cleanup"]  end  subgraph storage["Storage"]    journal["Journal and checkpoints"]    segments["Append-only segments (CRC32, LZ4)"]    mapped["Memory-mapped files"]    crypto["AES-256-GCM encryption (optional)"]  end  python --> server  rust --> core  node --> core  ffi --> core  server --> core  mcp --> core  core --> text  core --> vector  core --> memory  core --> vsa  core --> prov  memory --> text  text --> journal  vector --> journal  memory --> journal  journal --> segments  segments --> mapped  segments --> crypto

Module map: docs/ARCHITECTURE.md.

Limits

  • Not anonymous. Hypervector sketches and term counts are not encryption; anyone with a store can encode candidate text and compare. storeText: false keeps term counts, IDs and embeddings, so it is not a privacy control.
  • Document search is conventional. It does not use the hypervectors; the holographic parts are the algebra and the meaning memory.
  • One writer per store. A second writing process fails at open with a lock error.
  • Capacity numbers are points, not guarantees, and are stated only over the tested range (capacity).
  • Benchmark results are single machines. Conditions are in each results file; the single-core ann-benchmarks run and the VIBE high-recall points are losses (see Where it's behind).
  • Masking is obfuscation. Client-side vector masking preserves every pairwise similarity.
  • A store is a directory and WarmCore::new(.., None, ..) uses the current directory.

Full statement: docs/PRIVACY.md. Report vulnerabilities privately via SECURITY.md.

Contributing

CONTRIBUTING.md: setup, the checks CI runs, DCO sign-off (git commit -s, no CLA). Start with a good first issue or Discussions. See the Code of Conduct. Benchmark changes regenerate the results file they touch; the README cites files, not remembered figures.

License

Apache-2.0. See LICENSE. Use, modify and embed it in open-source or proprietary software, including network services, with no copyleft obligation. Releases up to and including crate 0.6.1 were published under AGPL-3.0-or-later and stay available under those terms.

來源:README.md,提交 ba980ff

工具

8

remember

Store memory

Store a durable fact, decision or preference; use `recall` to find one instead. A supplied `id` replaces that memory, while an omitted `id` creates a new one. Use `if_version` to reject concurrent changes or `create_only` to reject overwrites.

輸入參數idtagstext必填titlemetadataif_versionallow_emptycreate_only

recall

Recall matching memories

Retrieve full memories ranked for a natural-language question. Use this for ordinary recall; use `search` when you need metadata filters, ranking controls or score details. Read-only; default builds rank lexically, and a configured model adds semantic ranking.

輸入參數ktagsquery必填min_score

get

Get memory

Read one known memory id in full, including tags, metadata and version. Use an id from `list` or `search`; use `recall` when only a natural-language question is known. Read-only; an unknown id returns an error.

輸入參數id必填

forget

Delete memories

Delete memories from the active store by id, ids or id prefix; use `remember` to update content instead. Inspect prefix matches with `list` first: prefix deletion requires `confirm: true`. Returns the deletion count and ids that were absent.

輸入參數ididsprefixconfirm

list

List memories

Browse memories in id order, optionally limited by id prefix or tag; use `search` for relevance ranking. Read-only. Returns text previews unless `full` is true; pass `next_cursor` as `cursor` to continue.

輸入參數tagfulllimitcursorprefix

stats

Store statistics

Inspect store counts, recall mode, encryption status, storage size and active limits without reading memory contents. Read-only; use `list` to inspect stored memories.

無需輸入參數。

export

Export memory contents

Read a portable snapshot of memory contents as JSON, JSONL or Markdown; use `list` for short previews instead. Read-only. The payload is returned as text and capped by the server's export byte limit; pass `next_cursor` as `cursor` to continue.

輸入參數taglimitcursorformatprefix

版本歷史

1
  1. v0.1.2最新Oct 26, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Memory 整合