Command Palette

Search for a command to run...

ARCANE · Neural memory

Hippocampus

The memory layer for adaptive System 1 models. Hippocampus retrieves past decisions, rather than just text, so a classifier, router, or tool model can learn from new examples immediately without changing its weights.

Similar examples vote alongside the model's own probabilities, and every result lists the memories that influenced it. In our benchmarks, a single example per label lifted accuracy on unseen intents by 24 points, and 5 examples per tool lifted fully correct tool calls by 44 points. See how much it improves.

What it does

  • Any model

    A classifier, an LLM asked for probabilities, a tool-calling model, or no model at all.

  • Learns without training

    Remember or forget an example and the next request uses it. No fine-tuning.

  • Scales

    15,000 examples, 150 labels: 0.13 ms to add one, 3.4 ms per decision.

  • Shows its evidence

    Every decision lists the remembered examples behind it.

Examples are stored in the same document graph as the Grounded Graph of Thought. Search needs only numpy, with no API keys or vector database.

Inspired by the brain

Complementary learning systems theory says the brain keeps two learners. The neocortex learns slowly and holds general knowledge in its connections. The hippocampus stores single episodes at once without rewiring the cortex, and when a similar cue returns it recalls them to steer the cortex's decision. Hippocampus plays that second role next to any model, which plays the first.

In the brainHereWhat it means
Learns one experience at onceremember(text, label)Takes effect on the next request, no training.
A cue brings back similar episodesRetrieval of the 8 most similar examplesBM25 keyword scoring over the stored examples.
Recalled episodes bias the cortexVote mixed with the model's probabilitiesNeither side decides alone; combined they beat both.
Correcting or losing a memoryRe-remember the same text, or forget()A wrong example is overwritten, not baked into weights.
Knowing what you rememberedneighbors returned with each decisionEvery decision lists the examples behind it.

The analogy is loose. The brain consolidates: it replays hippocampal memories during sleep to train the cortex slowly, whereas Hippocampus never moves examples into the model's weights, so the memory keeps growing. Its retrieval matches keywords, not meaning and context. And it stores decided examples and counts votes, closer to exemplar theories of categorization than to full episodic memory.

How much it improves

Hippocampus adds accuracy in proportion to how many examples you give it, and the first few help most. Gains below are percentage points over the same model with no memory, on text and tools the model was never trained on.

+24.0 points
Intent accuracy, 1 example per label
56.5% → 80.5%
+36.8 points
Intent accuracy, 10 examples per label
56.5% → 93.3%
+43.7 points
Fully correct tool calls, 5 examples per tool
42.3% → 86.0%
+43.6 points
Right tool chosen, 10 examples per tool
55.7% → 99.3%
  • Classification: one example per label takes accuracy from 56.5% to 80.5%; ten reach 93.3%. The model and the memory are each weaker alone (56.5% and 64.7% at one example), so the gain comes from combining them.
  • Tool selection: the right tool is chosen 55.7% of the time with no examples, 77.0% with one per tool and 93.7% with five.
  • Tool arguments: storing the arguments raises arguments right from 18.6% to 83.5% with five examples, and fully correct calls from 42.3% to 86.0%.
  • Memory alone: with no model, 15,000 examples across 150 intents decide 80.6% correctly.

These numbers were measured with one base model, the bundled arc1-tiny. How much another model gains depends on how much it already gets right: a model that is weak on your labels gains the most, and one that already scores near 100% has little left to gain. The results section has the full tables and how to reproduce them.

Quick start

Terminal
pip install gpbacay-arcane
hippocampus.py
from gpbacay_arcane import Hippocampus, load_arc1hippocampus = Hippocampus(load_arc1())        # or any model, or Hippocampus() for memory only# Labels: a text and the label it should gethippocampus.remember("I was charged twice this month", "billing")hippocampus.remember("my parcel never arrived", "shipping")out = hippocampus.classify("why is my card charged again?", ["billing", "shipping"])out["label"], out["source"]   # "billing", "model+memory"; out["confidence"] is the mixed probabilityout["neighbors"]              # the remembered examples that voted# Tools: a request, the tool, and the call's argumentshippocampus.remember("rate Dune 4 stars", "rate_movie", {"title": "Dune", "stars": 4})hippocampus.remember("switch bluetooth off", "toggle_bluetooth", {"enabled": False})hippocampus.remember("thanks, that's all", None)   # None = no tool appliesout = hippocampus.run("rate spirited away 5 stars", tools=my_tools)out["function_calls"]     # [{"name": "rate_movie", "arguments": {"title": "spirited away", "stars": 5}}]out["memory_arguments"]   # ["rate_movie"]: these arguments came from a remembered requesthippocampus.react("charged again?")                              # the memory's vote alone, no model callhippocampus.remember("I was charged twice this month", "fraud")  # same text: the label is correctedhippocampus.forget("thanks, that's all")

In JavaScript (the browser, Next.js or Node), Hippocampus runs client-side next to ARC 1's browser build, with no server and no Python. It has the same API and returns the same decisions; only classify and run are async. For memory-only decisions, import it from gpbacay-arcane/hippocampus, which doesn't need onnxruntime-web.

Terminal
npm install gpbacay-arcane onnxruntime-web
Hippocampus.tsx
"use client";  // Next.js: use it in a client componentimport { load, Hippocampus } from "gpbacay-arcane/web";const agent = await load();                    // once, e.g. in useEffectconst hippocampus = new Hippocampus(agent);    // or new Hippocampus() for memory onlyhippocampus.remember("I was charged twice this month", "billing");hippocampus.remember("rate Dune 4 stars", "rate_movie", { title: "Dune", stars: 4 });await hippocampus.classify("why is my card charged again?", ["billing", "shipping"]);await hippocampus.run("rate spirited away 5 stars", myTools);// function_calls -> [{ name: "rate_movie", arguments: { title: "spirited away", stars: 5 } }]localStorage.memory = JSON.stringify(hippocampus);   // save; Python's graph.to_json() loads toonew Hippocampus(agent, { memory: JSON.parse(localStorage.memory) });

How it works

Loading diagram...
  1. Remember. Each example becomes one graph node. Its label is stored beside it, not in the searchable text. The id is a hash of the text, so remembering the same text again replaces the label.
  2. Retrieve. BM25 keyword scoring finds the 8 examples most like the request. For classify, only examples with one of the offered labels count.
  3. Vote. Each label gets its share of the neighbors' total score, so the votes sum to 1. This is the k-nearest-neighbor step of kNN-LM, applied to decisions instead of next words.
  4. Combine. For classify, the vote and the model's distribution are averaged (weight=0.5). For run, the vote is passed to the model as tool_prior; ARC 1, for example, fires a tool when either source is confident (noisy-OR).
  5. Fill arguments. A remembered call becomes a pattern: its argument values turn into typed slots, so "rate Dune 4 stars" becomes rate {title} {stars} stars. The most similar pattern that matches the request supplies the arguments, copied from the request's own words, so a value is never invented. Values that aren't in the text, like enabled: false for "switch bluetooth off", come with the pattern's words. A matching pattern also adds a call the model held back, and drops a model call that copied the same words, since a word belongs to one argument. The call's confidence is then None: the model's calibrated probability no longer describes it.
  6. Fall back. A label with no examples, or a request with no similar example, is decided by the model alone. With no model either, Hippocampus abstains.

For tool calling, every example votes, including examples for tools that aren't offered and examples labeled None. A request that looks like something else therefore takes votes away from the offered tools instead of firing one.

Use it with any model

The memory never calls a model, so Hippocampus works with anything that turns a text and a list of labels into probabilities.

model=What it needs
NoneMemory only. Decides from the vote; returns label=None when nothing similar is stored, instead of guessing.
(text, labels) -> {label: probability}Any function: a scikit-learn classifier, an embedding model, an LLM asked to score the labels.
object with classify(text, labels, **kw)Returns a dict with "distribution". Arc1Agent already does; extra keyword arguments such as task= pass through.
object with run(prompt, tools=, tool_prior=, execute=)For tool calling; returns function_calls. tool_prior maps tool name to the probability it applies, and Arc1Agent.run combines it with its own firing probability. Arguments from a matching remembered request then replace the model's, whatever the model.
any_model.py
from gpbacay_arcane import Hippocampus# A scikit-learn pipeline (vectorizer + classifier) trained on your labelsdef sklearn_model(text, labels):    probs = dict(zip(pipeline.classes_, pipeline.predict_proba([text])[0]))    return {label: probs.get(label, 0.0) for label in labels}hippocampus = Hippocampus(sklearn_model)hippocampus.remember("my card was declined at checkout", "billing")   # fix a blind spot without retraining# Memory only: a router that learns from every confirmed decisionrouter = Hippocampus()for text, label in confirmed_tickets:    router.remember(text, label)router.classify(new_ticket, ["billing", "shipping", "account"])  # label=None when nothing is similar

Results

All results use the bundled ARC 1 (arc1-tiny) as the base model, with the same weights throughout and no fine-tuning. The memory holds a few examples per label; test texts are never in it. Run python examples/benchmark_hippocampus.py --shots 1 2 5 10 to reproduce.

Intents the model never trained on, real text
CLINC150 test utterances, 5 labels (chance 20%), one remembered example per label, n = 600
Model alone56%
Memory alone65%
Hippocampus (model + memory)81%

Neither source is enough on its own with one example. Combined, they beat both, so the model is still doing real work rather than being overruled by a lookup.

Real text, more examples

Examples per labelModel aloneMemory aloneHippocampus
none56.5%––
1–64.7%80.5%
2–74.5%85.3%
5–87.3%90.5%
10–92.0%93.3%

Tools the model never trained on

The held-out tool split, n = 300. Fully correct means the right tools with every argument right. Correct refusals stayed at 100% in every row.

Examples per toolRight toolFully correct, labels onlyFully correct, with argumentsArguments right
none (model alone)55.7%42.3%–18.6%
177.0%50.3%64.0%53.3%
283.7%52.0%70.7%64.1%
593.7%54.7%86.0%83.5%
1099.3%54.7%99.3%100%

Votes alone fix which tool fires, but calls stay near 55% because the base model copies the wrong words for arguments of tools it never trained on. Storing the arguments fixes that: with 5 examples, 86.0% of calls are fully right, the same as the 86.0% it scores on the tools it was trained on (measured on a different test set).

Read the 10-example row with care. These held-out tools are tested with the same sentence patterns the examples were written from, only with new values, so by 10 examples the memory has seen every phrasing. Real requests vary more. A phrasing no example covers falls back to the base model's own argument copying, so store varied examples.

Scale

Memory only, all 150 CLINC150 intents with 100 examples each (15,000 examples), 1,000 test utterances, on a busy laptop CPU:

150-way accuracy
80.6%
to add an example
0.13 ms
median decision
3.4 ms
90th percentile
11 ms

Adding an example never scans the memory, and a search only touches examples that share words with the request. Hippocampus's default graph leaves out the semantic links the document graph normally adds: on CLINC150 they lowered accuracy (0.811 to 0.790 at 15,000 examples) and made each insert take 15 ms instead of 0.09 ms.

Saving the memory

Examples are documents whose ids start with memory-, with the label in the document's description and any tool arguments beside it. Saving the graph saves the memory, and a graph that also holds your documents keeps the two apart: documents never vote.

save.py
import jsonfrom gpbacay_arcane import DocumentGraph, Hippocampusjson.dump(hippocampus.graph.to_json(), open("memory.json", "w"))hippocampus = Hippocampus(model, DocumentGraph.from_json(json.load(open("memory.json"))))hippocampus.labels()   # {"memory-3f2a...": "billing", ...}

Limitations

  • Measured on one model

    Every improvement figure on this page comes from arc1-tiny. Other models were not benchmarked, so treat the gains as an example of the effect, not a guarantee.

  • Keyword retrieval

    A request that shares no words with any example gets no vote and falls back to the model. Using ARC 1's embeddings as DocumentGraph(embed=...) did not meaningfully help on CLINC150.

  • Argument patterns

    A pattern only matches phrasings like a remembered one; others fall back to the model's arguments. A value at the start or end of a pattern stops at punctuation or at and, then, plus or also, so "Tom and Jerry" in that position is cut. English joining words only.

  • Uncalibrated mix

    Even if the model's probabilities are calibrated, the combined confidence has not been re-fitted, so treat it as a ranking.

  • Tested up to 15,000 examples

    Lookups slow down when common words match many examples. Expect that somewhere past about 100,000; it has not been measured.

  • Shared graphs

    If the graph also holds documents, each lookup filters across all stored examples. The default graph holds only examples.

  • Tool calling needs tool_prior

    Any model can classify, but run() needs a model that accepts tool_prior. Arc1Agent does; other tool-calling models need that one argument.

Source: gpbacay_arcane/hippocampus.py. See also the repository README.