Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
MNEMON_DATA_DIR=~/.mnemon
MNEMON_STORE=default

# Optional embeddings through Ollama.
# Enable only when an Ollama service is available.
# Optional embeddings. The defaults below use Ollama.
MNEMON_EMBED_ENDPOINT=http://localhost:11434
MNEMON_EMBED_MODEL=nomic-embed-text

# For an OpenAI-compatible server, replace the endpoint and model above.
# The remaining settings are optional:
# MNEMON_EMBED_ENDPOINT=http://127.0.0.1:18000/v1
# MNEMON_EMBED_MODEL=bge-m3-mlx-8bit
# MNEMON_EMBED_PROTOCOL=openai
# MNEMON_EMBED_API_KEY=sk-...
# MNEMON_EMBED_DIMENSIONS=256
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ memory is useful.
- **Built-in deduplication** — `remember` auto-detects duplicates and conflicts; skips or auto-replaces
- **Retention lifecycle** — importance decay, access-count boosting, and garbage collection
- **Privacy-safe receipts** — export hashed operation receipts for memory-boundary audits without raw memory contents or queries
- **Optional embeddings** — works fully without Ollama; add local [Ollama](https://ollama.ai) for enhanced vector+keyword hybrid search
- **Optional embeddings** — works fully without an embedding provider; add local [Ollama](https://ollama.ai) or an OpenAI-compatible server for enhanced vector+keyword hybrid search

## Vision

Expand Down Expand Up @@ -446,12 +446,27 @@ Mnemon architecture.
| `MNEMON_DATA_DIR` | `~/.mnemon` | Base data directory |
| `MNEMON_STORE` | *(active file or `default`)* | Named memory store for data isolation |

**Ollama-specific** (only relevant if using embeddings):
**Embedding** (only relevant if using embeddings):

| Environment Variable | Default | Description |
|---|---|---|
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | Ollama API endpoint |
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | Embedding API endpoint |
| `MNEMON_EMBED_MODEL` | `nomic-embed-text` | Embedding model name |
| `MNEMON_EMBED_PROTOCOL` | *(auto-detect)* | `ollama` or `openai`; auto-detected from an endpoint ending in `/v1` |
| `MNEMON_EMBED_API_KEY` | *(none)* | Bearer token for OpenAI-compatible servers (oMLX, vLLM, etc.) |
| `MNEMON_EMBED_DIMENSIONS` | *(native)* | Optional Matryoshka dimension truncation |

The embedding client speaks the Ollama API by default and the
OpenAI-compatible embeddings API when the endpoint ends in `/v1` (or when
`MNEMON_EMBED_PROTOCOL=openai` is set). For example, a local server such as
[oMLX](https://omlx.dev) can be configured with:

```bash
export MNEMON_EMBED_ENDPOINT=http://127.0.0.1:18000/v1
export MNEMON_EMBED_MODEL=bge-m3-mlx-8bit
export MNEMON_EMBED_API_KEY=sk-... # omit for keyless local servers
mnemon embed --status
```

## Development

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Mnemon runs locally and stores data in `~/.mnemon/`. Key security considerations

- **SQLite database** — contains all stored insights; protected by filesystem permissions (`0644`).
- **Hook scripts** — shell scripts executed by the LLM CLI at lifecycle events; written with `0755` permissions.
- **Ollama connection** — optional HTTP calls to a local Ollama instance; no TLS by default. If `MNEMON_EMBED_ENDPOINT` is pointed at a remote server, traffic is unencrypted unless the endpoint uses HTTPS.
- **Embedding provider connection** — optional requests send insight or query text to the configured Ollama or OpenAI-compatible server. The default local Ollama endpoint does not use TLS. If `MNEMON_EMBED_ENDPOINT` points outside a trusted local network, use HTTPS to protect content and any `MNEMON_EMBED_API_KEY` bearer token in transit.

## Supported Versions

Expand Down
24 changes: 15 additions & 9 deletions cmd/memory/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ var (

var embedCmd = &cobra.Command{
Use: "embed [id]",
Short: "Generate embeddings for insights via Ollama",
Long: `Generate embedding vectors for insights using a local Ollama model.
Short: "Generate embeddings for insights",
Long: `Generate embedding vectors for insights using the configured provider.

Modes:
mnemon embed --status Show embedding coverage statistics
Expand All @@ -40,19 +40,25 @@ Modes:
if err != nil {
return fmt.Errorf("embedding stats: %w", err)
}
available := ec.Available()
output := map[string]interface{}{
"total_insights": total,
"embedded": embedded,
"coverage": fmt.Sprintf("%.0f%%", float64(embedded)/float64(max(total, 1))*100),
"ollama_available": ec.Available(),
"model": ec.Model(),
"total_insights": total,
"embedded": embedded,
"coverage": fmt.Sprintf("%.0f%%", float64(embedded)/float64(max(total, 1))*100),
"embedding_available": available,
"ollama_available": available, // Backward-compatible alias.
"protocol": ec.Protocol(),
"model": ec.Model(),
}
return enc.Encode(output)
}

// Check Ollama availability
// Check embedding provider availability.
if !ec.Available() {
return fmt.Errorf("Ollama not available at %s — install with: brew install ollama && ollama pull %s", ec.Endpoint(), ec.Model())
if ec.Protocol() == embed.ProtocolOllama {
return fmt.Errorf("Ollama embedding provider not available at %s — install with: brew install ollama && ollama pull %s", ec.Endpoint(), ec.Model())
}
return fmt.Errorf("OpenAI-compatible embedding provider not available at %s", ec.Endpoint())
}

// Single insight mode
Expand Down
2 changes: 1 addition & 1 deletion cmd/memory/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&storeName, "store", "", "named memory store (overrides MNEMON_STORE and active file)")
rootCmd.PersistentFlags().BoolVar(&readOnly, "readonly", false, "open database in read-only mode (no WAL files, safe for read-only mounts)")
rootCmd.PersistentFlags().StringVar(&embedModel, "embed-model", "",
fmt.Sprintf("Ollama embedding model (env: MNEMON_EMBED_MODEL; default: %s)", embed.DefaultModel))
fmt.Sprintf("embedding model (env: MNEMON_EMBED_MODEL; default: %s)", embed.DefaultModel))
}

// resolveEmbedModel returns the embedding model selector that should be
Expand Down
2 changes: 1 addition & 1 deletion cmd/memory/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestOpenDBRejectsInvalidStoreNameFromFlag(t *testing.T) {
// TestResolveEmbedModelChain exercises the full cmd → embed pipeline for the
// --embed-model flag and MNEMON_EMBED_MODEL env var, mirroring how cobra
// will hand the value off at runtime. The test runs against
// embed.NewClientWithModel directly so it does not require a live Ollama.
// embed.NewClientWithModel directly so it does not require a live provider.
func TestResolveEmbedModelChain(t *testing.T) {
oldEmbedModel := embedModel
t.Cleanup(func() { embedModel = oldEmbedModel })
Expand Down
12 changes: 11 additions & 1 deletion docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ make compose-down

## Optional Embeddings

Mnemon works without embeddings. To use Ollama-backed vector search in the Compose environment:
Mnemon works without embeddings. The Compose embeddings profile provides the
default Ollama-backed vector search setup:

```bash
docker compose --profile embeddings up -d ollama
Expand All @@ -87,9 +88,18 @@ The relevant environment variables are:

- `MNEMON_EMBED_ENDPOINT`
- `MNEMON_EMBED_MODEL`
- `MNEMON_EMBED_PROTOCOL`
- `MNEMON_EMBED_API_KEY`
- `MNEMON_EMBED_DIMENSIONS`

For host-based Ollama, set `MNEMON_EMBED_ENDPOINT=http://host.docker.internal:11434` on Docker Desktop, or use the host gateway address for Linux deployments.

An external OpenAI-compatible server can be selected with an endpoint ending
in `/v1`, for example `MNEMON_EMBED_ENDPOINT=http://host.docker.internal:18000/v1`.
Set `MNEMON_EMBED_MODEL` to a model exposed by that server and
`MNEMON_EMBED_API_KEY` when authentication is required. Use HTTPS whenever the
server is not on a trusted local network.

## Release Deployment

Tagged releases are handled by GoReleaser through `.github/workflows/release.yml`.
Expand Down
40 changes: 31 additions & 9 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ These root flags configure Memory commands:
|---|---|---|
| `--store <name>` | (auto) | Named memory store (overrides `MNEMON_STORE` and active file) |
| `--data-dir <path>` | `~/.mnemon` | Base data directory |
| `--embed-model <name>` | `nomic-embed-text` | Ollama embedding model (overrides `MNEMON_EMBED_MODEL`) |
| `--embed-model <name>` | `nomic-embed-text` | Embedding model (overrides `MNEMON_EMBED_MODEL`) |
| `--readonly` | `false` | Open the Memory database read-only, without creating WAL files |
| `--version` | | Print version and exit |

Expand Down Expand Up @@ -242,35 +242,52 @@ Nodes are colored by category (decision, fact, insight, preference, context); ed
|---|---|---|
| `MNEMON_DATA_DIR` | `~/.mnemon` | Base data directory |
| `MNEMON_STORE` | `default` | Active named store |
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | Ollama API endpoint |
| `MNEMON_EMBED_MODEL` | `nomic-embed-text` | Ollama embedding model |
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | Embedding API endpoint |
| `MNEMON_EMBED_MODEL` | `nomic-embed-text` | Embedding model |
| `MNEMON_EMBED_PROTOCOL` | (auto-detect) | `ollama` or `openai`; endpoints ending in `/v1` select `openai` |
| `MNEMON_EMBED_API_KEY` | (none) | Bearer token for OpenAI-compatible servers |
| `MNEMON_EMBED_DIMENSIONS` | (native) | Embedding dimensions; set to truncate (e.g., `256` for Matryoshka models) |
| `MNEMON_MAX_INSIGHTS` | `1000` | Active-insight ceiling before auto-pruning starts; `0` disables auto-pruning |

---

## Embedding Support (Optional)

Mnemon works fully without Ollama — all core features (remember, recall, link, graph traversal) function out of the box. Adding Ollama enhances recall precision through vector similarity, but is never required.
Mnemon works fully without an embedding provider — all core features (remember, recall, link, graph traversal) function out of the box. Configuring Ollama or an OpenAI-compatible server enhances recall precision through vector similarity, but is never required.

### What changes with and without embeddings

| Capability | Without Ollama | With Ollama |
| Capability | Without embeddings | With embeddings |
|---|---|---|
| **Recall anchors** | Keyword + recency | Keyword + vector + recency (RRF hybrid) |
| **Semantic edges** | Token overlap (coarser) | Cosine similarity ≥ 0.50 (precise) |
| **Traversal scoring** | Pure structural | Structural + semantic |
| **Rerank weights** | Keyword 45%, Entity 25%, Graph 30% | Keyword 30%, Entity 15%, Similarity 35%, Graph 20% |

When Ollama is unavailable, the reranking system automatically redistributes similarity weight to keyword and graph signals — no configuration needed, no degraded mode flag. The system detects Ollama availability at runtime with a 2-second timeout.
When the configured provider is unavailable, the reranking system automatically redistributes similarity weight to keyword and graph signals — no configuration or degraded-mode flag is needed. Mnemon checks provider availability at runtime with a 2-second timeout.

### Setup

Ollama remains the default provider:

```bash
brew install ollama # or see https://ollama.ai
ollama pull nomic-embed-text # download the embedding model
```

For an OpenAI-compatible server, point the endpoint at its `/v1` base URL and
select the server's embedding model. The API key is optional for keyless local
servers:

```bash
export MNEMON_EMBED_ENDPOINT=http://127.0.0.1:18000/v1
export MNEMON_EMBED_MODEL=bge-m3-mlx-8bit
export MNEMON_EMBED_API_KEY=sk-... # omit for keyless local servers
```

Set `MNEMON_EMBED_PROTOCOL=openai` explicitly only when the compatible endpoint
does not end in `/v1`.

Verify with:

```bash
Expand All @@ -282,14 +299,19 @@ mnemon embed --status
"total_insights": 87,
"embedded": 87,
"coverage": "100%",
"embedding_available": true,
"ollama_available": true,
"protocol": "ollama",
"model": "nomic-embed-text"
}
```

`ollama_available` is retained as a compatibility alias for existing scripts;
new integrations should use `embedding_available` and `protocol`.

### Backfilling existing insights

If you install Ollama after already using mnemon, existing insights won't have embeddings. Backfill them in one command:
If you configure an embedding provider after already using mnemon, existing insights won't have embeddings. Backfill them in one command:

```bash
mnemon embed --all
Expand All @@ -316,8 +338,8 @@ This generates embeddings for all un-embedded insights and automatically creates
retrieve. │ │ causal │ │
│ │ semantic │ │
┌──────────────────┐ │ ├────────────┤ │
Ollama │ (optional) │ │ Embeddings │ │
nomic-embed-text│ ◄───────────── │ └────────────┘ │
Embedding server │ (optional) │ │ Embeddings │ │
configured model │ ◄───────────── │ └────────────┘ │
└──────────────────┘ └──────────────────┘
```

Expand Down
20 changes: 17 additions & 3 deletions docs/zh/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ store 可见。**Remind** 触发 recall 判断。**Nudge** 触发 writeback 判
- **意图感知召回** — 图遍历 + 可选向量搜索(RRF 融合),所有查询默认启用
- **内置去重** — `remember` 自动检测重复和冲突;跳过或自动替换
- **保留度生命周期** — 重要性衰减、访问计数提升、免疫规则、垃圾回收
- **可选嵌入向量** — 本地 [Ollama](https://ollama.ai) 集成,支持混合向量+关键词搜索
- **可选嵌入向量** — 可使用本地 [Ollama](https://ollama.ai) 或 OpenAI 兼容服务器,支持混合向量+关键词搜索

## 愿景

Expand Down Expand Up @@ -396,8 +396,22 @@ Sub-agent 委派是可选执行策略。当 runtime 支持时,主 agent 可以
|---------|-------|------|
| `MNEMON_DATA_DIR` | `~/.mnemon` | 基础数据目录 |
| `MNEMON_STORE` | *(active 文件或 `default`)* | 命名记忆体,用于数据隔离 |
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | Ollama API 端点 |
| `MNEMON_EMBED_ENDPOINT` | `http://localhost:11434` | 嵌入 API 端点 |
| `MNEMON_EMBED_MODEL` | `nomic-embed-text` | 嵌入模型名称 |
| `MNEMON_EMBED_PROTOCOL` | *(自动探测)* | `ollama` 或 `openai`;端点以 `/v1` 结尾时自动切换 |
| `MNEMON_EMBED_API_KEY` | *(无)* | OpenAI 兼容服务器(oMLX、vLLM 等)的 Bearer 令牌 |
| `MNEMON_EMBED_DIMENSIONS` | *(原生维度)* | 可选的 Matryoshka 维度截断 |

嵌入客户端默认使用 Ollama API;当端点以 `/v1` 结尾(或显式设置
`MNEMON_EMBED_PROTOCOL=openai`)时改用 OpenAI 兼容的 embeddings API。例如,
可通过以下配置对接 [oMLX](https://omlx.dev) 等本地服务器:

```bash
export MNEMON_EMBED_ENDPOINT=http://127.0.0.1:18000/v1
export MNEMON_EMBED_MODEL=bge-m3-mlx-8bit
export MNEMON_EMBED_API_KEY=sk-... # 无需认证的本地服务器可省略
mnemon embed --status
```

也可在命令上使用 `--data-dir` 或 `--store` 标志覆盖。

Expand All @@ -415,7 +429,7 @@ make help # 显示所有目标

**依赖**:Go 1.24+、`modernc.org/sqlite`、`spf13/cobra`、`google/uuid`

**可选**:[Ollama](https://ollama.ai) + `nomic-embed-text` 嵌入支持
**可选**:[Ollama](https://ollama.ai) 或 OpenAI 兼容的嵌入服务器

## 文档

Expand Down
Loading
Loading