Repository navigation
What's new
-
An optional classifier for the small decisions — off by default. Alongside
its real work, muninn asks a language model a stream of narrow questions: is
this recalled memory relevant to what you just typed, are these two entities
the same thing, does this new lesson replace an older one, was that short
message a correction. A new[jev]section points those questions at
TypeSafe's Jev instead — a model that answers yes/no, pick-one and score
questions with a typed value and a calibrated probability rather than prose.
Turn it on with your own API key:[jev] enabled = true api_key = "env:TYPESAFE_API_KEY"Nothing else is required, and nothing changes until you do it. The questions
it takes over are: filtering and ranking recalled memories, deciding whether
two entities or two schema types are the same, choosing a parent type,
judging which older lessons a new one supersedes, spotting a corrective
message, and settling confident duplicate merges during background curation. -
Every classifier path falls back to whatever decided it before. On an
error, a timeout, or a probability that lands in the undecided band, the
previous decision runs instead: your language model in most cases, and for
correction detection the pattern list muninn has always used, which never
involved a model. A missing key, an expired key or a provider outage degrades
to the behaviour you had rather than to a wrong answer. An undecided answer is
never read as a "no" — that distinction is what stops a slow reply from
quietly minting a duplicate of an entity that already exists. -
Recall is now ranked before it is trimmed. See Fixed below; it is the
one change that lands whether or not you enable the classifier. -
Two operator commands for a whole-graph pass.
muninn jev auditsweeps the
entire graph and writes a report of what the classifier thinks should change:
duplicate entities found both by name and by vector neighbour, synonym schema
types, types with no parent, lessons whose meaning depends on a missing
referent, and lessons that supersede an older one. It writes nothing to the
graph.muninn jev applyreplays that report back through the same guarded
merge paths the background curator already uses, with a dry run as the default
and a probability floor you choose. On a graph of 32,500 entities the sweep
took about four minutes and eleven cents; applying its verdicts merged 101
duplicate entity pairs. -
Health and spend are visible.
muninn healthreports
jev: up | down | disabled, and the server's health endpoint carries ajev
key once it is configured. A classifier that is down never flips the overall
ok, because every path it serves has a working fallback — it is an
accelerator, not a dependency. Its tokens are metered per tenant alongside
model calls and keyed by its own model id, so you can see what it costs
separately. -
Where your data goes. While the classifier is off, which is the default,
nothing new leaves the machine. With it on, the text behind each judgement is
sent to a third-party API: the memories being ranked for a prompt, entity names
and summaries, schema type names and descriptions, and lesson text. The
whole-graph sweep is the deliberate exception — one run sends most of your
entity names and summaries, every schema type and every lesson. If that trade
is not one you want, leave the classifier off; everything works as it did.
Fixed
- A highly relevant memory could be dropped from the injected context while a
weaker one survived. Each section of the injected memory has a byte budget,
and it trimmed from the end of the section — where "the end" was decided by
retrieval order, not by the relevance grade the recall filter had just
assigned. The most relevant item in a section could therefore be the one cut.
Ordering now follows the grade, so the budget removes what was judged weakest.
This applies whichever backend did the grading, so it improves recall with the
classifier off as well as on.
Upgrading
Nothing to do. There is no schema migration, no change to any existing setting,
and no change in behaviour until you add a [jev] section and enable it.
Replace the binary and restart muninn serve (or nothing at all, if you only
use the detached worker).
If you do enable it: the decision bands have defaults that were measured rather
than guessed, and the one worth knowing is same_yes (0.75). The classifier's
"these are the same thing" probability tops out near 0.85 even for two records
that are obviously identical, so a higher band silently stops merging anything.
A project-level config file may tune the per-area switches and the bands, but
cannot set the key, the endpoint or the model.
Install
curl -fsSL https://muninnai.dev/install.sh | bashOr take a platform archive from this release directly:
curl -fsSL -o muninn.tar.gz \
"https://github.com/scottlarkin/muninn-release/releases/download/v0.2.2/muninn_v0.2.2_darwin_arm64.tar.gz"
tar -xzf muninn.tar.gz && sudo mv muninn /usr/local/bin/Checksums for every artifact are in checksums.txt on the release. A tarball
downloaded through a browser is quarantined by macOS; clear it with
xattr -dr com.apple.quarantine ./muninn.