|
1 | 1 | # meme |
2 | 2 |
|
3 | | -Long term memory for AI agents. |
| 3 | +[![CI][ci-badge]][ci-url] |
| 4 | +[![License][license-badge]][license-url] |
| 5 | +[![Rust][rust-badge]][rust-url] |
| 6 | + |
| 7 | +[ci-badge]: https://github.com/qntx/meme/actions/workflows/rust.yml/badge.svg |
| 8 | +[ci-url]: https://github.com/qntx/meme/actions/workflows/rust.yml |
| 9 | +[license-badge]: https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg |
| 10 | +[license-url]: LICENSE-MIT |
| 11 | +[rust-badge]: https://img.shields.io/badge/rust-edition%202024-orange.svg |
| 12 | +[rust-url]: https://doc.rust-lang.org/edition-guide/ |
| 13 | + |
| 14 | +**High-performance long-term memory for AI agents — three-stage pipeline with semantic compression, hybrid retrieval, and cross-session persistence, written in Rust.** |
| 15 | + |
| 16 | +meme implements the [SimpleMem](3rdparty/SimpleMem/) three-stage memory pipeline with a production-grade Rust core: (1) **Semantic Structured Compression** extracts lossless, disambiguated memory entries from dialogues via LLM, (2) **Online Semantic Synthesis** deduplicates at write time, and (3) **Intent-Aware Retrieval Planning** combines semantic, lexical (FTS), and structured metadata search with LLM-driven reflection. A full cross-session system persists memory across independent conversations. |
| 17 | + |
| 18 | +## Crates |
| 19 | + |
| 20 | +| Crate | | Description | |
| 21 | +| --- | --- | --- | |
| 22 | +| **[`meme`](meme/)** | [![crates.io][meme-crate]][meme-crate-url] [![docs.rs][meme-doc]][meme-doc-url] | Core library — pipeline, vector store, cross-session orchestrator | |
| 23 | +| **[`meme-cli`](meme-cli/)** | [![crates.io][cli-crate]][cli-crate-url] | CLI tool — add dialogues, ask questions, manage sessions | |
| 24 | + |
| 25 | +[meme-crate]: https://img.shields.io/crates/v/meme.svg |
| 26 | +[meme-crate-url]: https://crates.io/crates/meme |
| 27 | +[meme-doc]: https://img.shields.io/docsrs/meme.svg |
| 28 | +[meme-doc-url]: https://docs.rs/meme |
| 29 | +[cli-crate]: https://img.shields.io/crates/v/meme-cli.svg |
| 30 | +[cli-crate-url]: https://crates.io/crates/meme-cli |
| 31 | + |
| 32 | +## Quick Start |
| 33 | + |
| 34 | +### Install the CLI |
| 35 | + |
| 36 | +**Shell** (macOS / Linux): |
| 37 | + |
| 38 | +```sh |
| 39 | +curl -fsSL https://sh.qntx.fun/meme | sh |
| 40 | +``` |
| 41 | + |
| 42 | +**PowerShell** (Windows): |
| 43 | + |
| 44 | +```powershell |
| 45 | +irm https://sh.qntx.fun/meme/ps | iex |
| 46 | +``` |
| 47 | + |
| 48 | +### CLI |
| 49 | + |
| 50 | +```bash |
| 51 | +# Initialize configuration |
| 52 | +meme init |
| 53 | + |
| 54 | +# Add dialogues |
| 55 | +meme add -s Alice "I'll be in Tokyo next Monday for the conference." |
| 56 | +meme add -s Bob "Let's meet at Shibuya station at 3pm." |
| 57 | + |
| 58 | +# Import from JSONL file |
| 59 | +meme add --file conversation.jsonl |
| 60 | + |
| 61 | +# Ask questions |
| 62 | +meme ask "Where will Alice and Bob meet?" |
| 63 | + |
| 64 | +# List stored memories |
| 65 | +meme list |
| 66 | +meme list --json |
| 67 | + |
| 68 | +# Cross-session memory |
| 69 | +meme session start conv-001 -m "Refactor the auth module" |
| 70 | +meme session stop <session-id> |
| 71 | +meme session list |
| 72 | + |
| 73 | +# Memory consolidation (decay/merge/prune) |
| 74 | +meme consolidate |
| 75 | + |
| 76 | +# Export / import |
| 77 | +meme export -o memories.json |
| 78 | +``` |
| 79 | + |
| 80 | +### Library |
| 81 | + |
| 82 | +```rust |
| 83 | +use meme::MemeBuilder; |
| 84 | + |
| 85 | +let meme = MemeBuilder::new() |
| 86 | + .api_key("sk-...") |
| 87 | + .model("gpt-4.1-mini") |
| 88 | + .build() |
| 89 | + .await?; |
| 90 | + |
| 91 | +// Add dialogues — automatically extracted into structured memory entries. |
| 92 | +meme.add_dialogue("Alice", "Let's meet at 2pm tomorrow", None).await?; |
| 93 | +meme.add_dialogue("Bob", "Sure, I'll bring the Q3 report", None).await?; |
| 94 | +meme.finalize().await?; |
| 95 | + |
| 96 | +// Ask questions — hybrid retrieval + LLM answer generation. |
| 97 | +let answer = meme.ask("When will Alice meet?").await?; |
| 98 | +``` |
| 99 | + |
| 100 | +See [`examples/`](meme/examples/) for more: [basic](meme/examples/basic.rs), [cross-session](meme/examples/cross_session.rs), [batch import](meme/examples/batch_import.rs). |
| 101 | + |
| 102 | +## Architecture |
| 103 | + |
| 104 | +```text |
| 105 | +Dialogues ──► MemoryBuilder ──► VectorStore (LanceDB) |
| 106 | + (Stage 1+2) │ |
| 107 | + ├─ Semantic search (dense vectors) |
| 108 | +Query ──► HybridRetriever ────────►├─ Keyword search (FTS / Tantivy) |
| 109 | + (Stage 3) ├─ Structured search (metadata filters) |
| 110 | + │ │ |
| 111 | + ▼ │ |
| 112 | + LLM Planning ◄───────────┘ |
| 113 | + + Reflection |
| 114 | + │ |
| 115 | + ▼ |
| 116 | + Answer Generation |
| 117 | +``` |
| 118 | + |
| 119 | +- **`meme`** — Core library. `Meme` facade wraps the three-stage pipeline behind `add_dialogue()` / `ask()`. `VectorStore` uses LanceDB for embedded vector + FTS indexing. `Embedder` supports API and local ONNX backends via enum dispatch (zero-cost). `LlmClient` is an OpenAI-compatible HTTP client with retry + exponential backoff. |
| 120 | +- **`meme-cli`** — Interactive CLI. TOML + env var configuration, JSONL import, table/JSON output, cross-session management. |
| 121 | +- **Cross-session** — `CrossOrchestrator` manages session lifecycle (start → record events → stop → extract observations → inject context). SQLite stores sessions, events, observations, and summaries. Context injection fills a token-budgeted bundle at session start. |
| 122 | + |
| 123 | +## Three-Stage Pipeline |
| 124 | + |
| 125 | +### Stage 1: Semantic Structured Compression |
| 126 | + |
| 127 | +Dialogues are windowed and sent to an LLM to extract **atomic, self-contained memory entries**. Each entry contains: |
| 128 | + |
| 129 | +- **Lossless restatement** — complete sentence with no pronouns, no relative time |
| 130 | +- **Keywords** — for BM25-style lexical matching |
| 131 | +- **Structured metadata** — timestamp, location, persons, entities, topic |
| 132 | + |
| 133 | +### Stage 2: Online Semantic Synthesis |
| 134 | + |
| 135 | +Previous-window entries are passed as context during extraction to avoid duplicating information across overlapping windows. |
| 136 | + |
| 137 | +### Stage 3: Intent-Aware Retrieval Planning |
| 138 | + |
| 139 | +A single LLM call analyzes the query to produce a **unified plan** containing: |
| 140 | + |
| 141 | +- Extracted keywords, persons, entities, time expressions |
| 142 | +- Targeted search queries for semantic retrieval |
| 143 | +- Required information types for completeness assessment |
| 144 | + |
| 145 | +The plan drives parallel execution of three search views (semantic, keyword, structured), followed by optional **reflection** rounds that assess completeness and issue additional targeted queries. |
| 146 | + |
| 147 | +## Feature Flags |
| 148 | + |
| 149 | +| Feature | Description | |
| 150 | +| --- | --- | |
| 151 | +| `api-embedding` | Remote API-based embedding (enabled by default) | |
| 152 | +| `onnx` | Local ONNX Runtime embedding via `ort` + `tokenizers` | |
| 153 | + |
| 154 | +## Configuration |
| 155 | + |
| 156 | +Configuration is loaded from `~/.meme/config.toml` with environment variable overrides: |
| 157 | + |
| 158 | +| Env Var | Description | |
| 159 | +| --- | --- | |
| 160 | +| `MEME_LLM_API_KEY` | OpenAI-compatible API key | |
| 161 | +| `MEME_LLM_BASE_URL` | API base URL | |
| 162 | +| `MEME_LLM_MODEL` | Model name (default: `gpt-4.1-mini`) | |
| 163 | +| `MEME_EMBEDDING_PROVIDER` | `api` or `onnx` | |
4 | 164 |
|
5 | 165 | ## License |
6 | 166 |
|
|
0 commit comments