Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

memory-drift

How an AI's memory of you slowly stops being true, and what to do about it.

the thing that bugged me

Everyone talks about model drift. Data drift. Concept drift. There's a whole vocabulary for "the world changed and your model didn't notice."

Nobody really talks about memory drift, which is a slightly different and much weirder problem: an AI remembers something true you told it, and then just... keeps believing it, long after it stops being true, because nothing ever told it to stop.

Say you tell a bank's AI assistant in January that you always travel by train. That's true when you say it. By April you've started driving everywhere. Nobody ever announces this. You just start saying different things, sometimes. By October the AI is still saying "since you normally use rail..." and now it's just wrong, confidently, in a way that's mildly annoying at best and actively unhelpful at worst.

I wanted to know: can you build a memory that fades on its own, the way a person's does, instead of one that either never forgets or forgets everything the moment something new gets said?

what's actually in here

Each memory (say, "customer 41's travel mode") is a Dirichlet distribution over the possible values, train, car, plane, whatever the attribute is. If you haven't run into a Dirichlet before, it's just a distribution over distributions, a clean way to represent "how much belief sits on each option" that updates in a genuinely principled way when new evidence shows up.

The part that makes this feel like memory instead of a running tally is decay. Before any new evidence gets added, the whole belief gets pulled a little bit back toward "I don't really know," based on how long it's been since anyone said anything. Talk about it regularly and the belief stays sharp. Go quiet for a few months and it drifts, on its own, the way an actual memory does.

One thing I like about doing it this way: contradictions don't need a special rule. A single weird statement just nudges the belief a little, it doesn't overwrite it. Enough contradicting statements in a row and the belief genuinely does shift, because that's what real evidence should do. The resistance to noise and the responsiveness to real change come out of the same mechanism, I didn't have to hand-code either one separately.

the honesty bit

There's no real LLM in this build. I didn't have network access while building it, so the "what does this statement actually mean" step runs on TF-IDF and cosine similarity against reference phrases, not sentence embeddings, and definitely not a language model. src/embeddings_upgrade.py is the real, working version using sentence-transformers, same interface, drop it in anywhere the TF-IDF version currently plugs in and it just works.

did it actually work

I built two obvious alternatives to compare against: believe whatever was said most recently, or believe whatever's been said most often overall. Both are things people genuinely build before they think about decay, and both are reasonable, they just fail in opposite directions. "Most recent" panics at every one-off comment. "Most often" barely notices when someone's actually changed.

Memory Health Dashboard, four real examples

Four real memories, picked from the actual run, not staged. The stable one climbs and holds. The decaying one wobbles and slowly gives up. The conflicting one genuinely switches from train to plane, holds for a while, then starts fading again once it stops being reinforced. The hallucinated one is just... one point, one weak statement, nothing to back it up yet.

Method comparison

On customers who genuinely changed their mind, the Bayesian approach reached the correct final belief 79% of the time. "Most recent statement" got there 63% of the time. "Majority vote" managed 40%, it just never fully catches up if there's much history working against it.

On customers who said one inconsistent thing but never actually changed, the Bayesian approach stayed correct 74% of the time, versus 58% for trusting the last thing said.

Worth being honest about one number here: majority vote's average detection delay looks fine on paper (57 days), but that's only counting the 88 out of 219 switchers it ever actually caught up on. It's a survivor's average, not a real comparison, most switchers under majority vote just never got detected at all.

setup

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Run in order:

python src/simulate_conversations.py
python src/extract_evidence.py
python src/memory_engine.py
python src/evaluate.py
python src/make_report.py

what's in the repo

memory_drift/
├── src/
│   ├── simulate_conversations.py   customers talking, irregularly, over a year
│   ├── extract_evidence.py         TF-IDF stand-in for "what did they mean"
│   ├── embeddings_upgrade.py       the real sentence-transformers version
│   ├── memory_engine.py            the actual Dirichlet + decay mechanism
│   ├── baselines.py                the two obvious alternatives
│   ├── evaluate.py                 does it actually beat the obvious alternatives
│   └── make_report.py              the dashboard
├── data/
├── outputs/
├── figures/
└── README.md

what I'd want to try next

A proper NLP model instead of TF-IDF would probably fix a decent chunk of the noise in extraction (62% accuracy right now, which is low enough that some of what looks like "decay" is honestly just extraction being wrong sometimes, not the customer actually being inconsistent). I'd also want to try letting the decay half-life vary per attribute, employment status probably shouldn't fade at the same rate as travel habits, and right now they do.

reflections

88 out of 219 looked perfectly reasonable until I realised what it was counting.

That was how many customers the majority vote model correctly identified as having changed their mind. The average detection delay for those customers was 57 days, which initially looked like a nice result. Faster than the Bayesian model, even.

It took me a while to notice that the average only existed because the other 131 customers never appeared in it.

The model simply never became confident enough to say they'd switched at all.

Once I looked at it that way, the comparison stopped making sense. Reporting how quickly you find something is a bit optimistic when most of the difficult cases are quietly missing from the calculation.


The memory extraction wasn't behaving quite how I imagined either.

I treated the TF-IDF step as temporary scaffolding. It was there so I could spend time on the memory system instead of worrying about language models.

It ended up becoming part of the experiment.

Extraction accuracy settled around 62%, and every now and then I found myself blaming the memory model for forgetting things it had never actually learned correctly in the first place. Some of what looked like memory decay was really just noisy extraction showing up later in the pipeline.

That feels like a much more interesting failure than "TF-IDF isn't as good as an embedding model." The mistake happened upstream and only became visible much further downstream.


I also managed to hide the very thing I wanted to show.

One dashboard panel displayed example memories, but I filtered it to only include customers with at least four observations because the plots looked nicer that way.

Hallucinated memories almost never have four observations.

The dashboard looked perfectly healthy.

It was just missing the entire category I wanted people to inspect.


One thing I'm still unconvinced by is the decay function.

Every memory fades at exactly the same rate because that's what I happened to implement first.

That means changing jobs and changing your favourite way to pay are treated as equally stable facts about a person, which doesn't really survive more than a few seconds of thought. If I revisit this, I'd probably let the decay emerge from the data instead of deciding in advance how forgetful every type of memory should be.

stack

Python, pandas, numpy, scikit-learn (TfidfVectorizer, cosine_similarity), matplotlib

About

A memory system for AI that fades over time instead of either remembering everything forever or panicking at the first inconsistent thing someone says.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages