Providers and embeddings
Mimir talks to two kinds of model, and they do different jobs. A language model reads a memory after it is written and answers with a title and a one-line summary. An embedding model turns a memory into a vector so search can find it by meaning. Without either one Mimir still works — you lose summaries and the vector half of search, not the store.
Who owns a key
| Kind | Whose key | Where it is chosen |
|---|---|---|
| Language model | Each person’s own | Settings → Providers; a project can pin one provider |
| Embedding model | The installation’s | Admin → Embeddings, chosen once by an admin from their own rows |
Summaries are per person because a summary is generated with the key of the person whose memory it is. Vectors are install-wide because one column holds one vector space: two embedding models with different dimensions cannot share a column, so the choice has to be made once for everybody.
Presets
Adding a provider means picking a preset, which supplies the base URL and a sensible default model. Anything that speaks the OpenAI API can be added with the last row.
| Preset | Does | Default model | Notes |
|---|---|---|---|
| DeepSeek | Chat | deepseek-flash | deepseek-v4-pro is the other option |
| OpenCode Go | Chat | deepseek-v4.1-flash | The model list is fetched live from OpenCode |
| OpenCode Console | Chat | deepseek-v4.1-flash | Same catalogue, different inference path |
| Ollama | Chat and embeddings | nomic-embed-text | Local, no key; host.docker.internal on compose |
| Octen | Embeddings | octen-embedding-4b | 0.6b and 8b also listed, all truncate to 768 |
| Mistral | Chat and embeddings | mistral-small-latest | Embeddings use codestral-embed |
| OpenAI-compatible | Chat and embeddings | — | Your own base URL and model name |
The 768-dimension rule
The vector column is vector(768). An embedding provider must be able to answer at exactly 768 dimensions, or its vectors are discarded and search quietly falls back to keywords. Octen takes a dimension field, Mistral’s codestral-embed takes output_dimension, and both truncate to the first N values — so both fit. Mistral’s other embedding model, mistral-embed, is fixed at 1024 and is deliberately not offered.
Adding one
Settings → Providers
Provider [ Ollama ▾ ]
Used for [ Embeddings ▾ ] one kind per saved row
Label [ homelab ]
Model [ nomic-embed-text ▾ ]
Base URL [ http://host.docker.internal:11434 ]
API key [ optional — a local model has none ]
[x] Use as the default for this type- Test probes the provider. For embeddings it asks for one vector and reports its length; for chat it lists models. The result is stored on the row and shows in the list.
- Set default makes the row the one used when nothing else is pinned. One default per kind per person.
- Price is per million tokens, input and output, and only seeds what a call will cost from now on. Editing it never rewrites the calls already recorded.
What a call costs
Every call to a provider leaves a row: tokens in, tokens out, status, and the cost at the price the provider carried when the call was made. Admin → Usage shows the month split between language and embedding spend, an unpriced count, thirty days of daily spend, twenty-four hours of call counts, a breakdown by model, a breakdown by person, and the latest failures.
A call made by a provider with no price is still counted and appears under Unpriced; fill the price in on the provider row to price everything from then on. When a provider answers without token usage, Mimir estimates from the text length and marks the row as estimated rather than guessing silently.
The spike pill
Admins see a pill in the header and above the admin pages when the current hour has at least 20 calls and more than five times the median hourly count of the past week. It is aimed at a loop nobody meant to start. Press × and it stays quiet for you until a new hour crosses the line; another admin still sees it.
Pruning the usage log
provider_calls has no automatic expiry. At the bottom of Admin → Usage, enter a number of days and prune; the run is audited with how many rows it removed. The audit log prunes itself on a schedule (memory reads after 30 days, the rest after 365), so this control exists only for the usage table.
When no model is configured
- Writes always succeed. The memory is stored with no summary and no vector.
- Search is keyword-only: still fused, still path-scoped, just one arm.
- The tree and the digest are unaffected — they read titles and paths, which do not need a model.
- A backfill can fill missing vectors later, and Admin → Embeddings can re-embed everything after a model change.
Where to go next
- How Mimir works — paths, versions, digest and search.
- How search works — what the vector arm adds and when to trust it.