MimirDocumentationSign in
Documentation

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

KindWhose keyWhere it is chosen
Language modelEach person’s ownSettings → Providers; a project can pin one provider
Embedding modelThe installation’sAdmin → 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.

PresetDoesDefault modelNotes
DeepSeekChatdeepseek-flashdeepseek-v4-pro is the other option
OpenCode GoChatdeepseek-v4.1-flashThe model list is fetched live from OpenCode
OpenCode ConsoleChatdeepseek-v4.1-flashSame catalogue, different inference path
OllamaChat and embeddingsnomic-embed-textLocal, no key; host.docker.internal on compose
OctenEmbeddingsocten-embedding-4b0.6b and 8b also listed, all truncate to 768
MistralChat and embeddingsmistral-small-latestEmbeddings use codestral-embed
OpenAI-compatibleChat 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

text
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

Providers and embeddings