Mem0mem0ai 2.0.20 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
24 small wins to finish your pathNext lesson

What Mem0 asks a model

You cannot write a stand-in for something without knowing what it is asked. Mem0 sends a model one long instruction, and the fastest way to see it is to print it.

A model in Mem0 is any LangChain chat model, which means any class with a _generate method. This one prints what it was given and then says it found nothing.

python
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.messages import AIMessage
from langchain_core.outputs import ChatGeneration, ChatResult
python
class SpyModel(BaseChatModel):
    """Writes down what Mem0 asked, then says it found nothing."""

    @property
    def _llm_type(self):
        return "spy"

    def _generate(self, messages, stop=None, run_manager=None, **kwargs):
        print(str(messages[-1].content))
        return ChatResult(generations=[ChatGeneration(
            message=AIMessage(content='{"memory": []}'))])

Wiring it in needs the configuration from lesson 7, which is shown here in full and explained there. Read it as: use this model, this embedder, and a store in a temporary directory.

Example
import tempfile

from mem0 import Memory
from spy_model import SpyModel
from pretend_mem0 import PretendEmbedder

spy = Memory.from_config({
    "llm": {"provider": "langchain", "config": {"model": SpyModel()}},
    "embedder": {"provider": "langchain", "config": {"model": PretendEmbedder()}},
    "vector_store": {"provider": "qdrant", "config": {
        "path": tempfile.mkdtemp(), "embedding_model_dims": 64, "on_disk": False}},
})
spy.add("I prefer email updates, not SMS.", user_id="ravi")

That is the whole instruction, and it is worth reading properly.

What it is asking for

It sends the conversation, not a question. The block under New Messages is what the customer just said. Everything above it is instructions about how to treat it.

It sends what it already knows. Existing Memories and Recently Extracted Memories are there so the model does not store the same fact twice. On a first call both are empty; on the tenth they are not, and that is how Mem0 avoids a pile of duplicates.

It wants one specific shape back. A JSON object with a memory list, each entry carrying an id, the text to store, and any existing memories it relates to.

json
{"memory": [
  {"id": "0", "text": "User prefers email updates over SMS", "linked_memory_ids": []}
]}
This shape changed in Mem0 2.0, and nearly every tutorial online is wrong about it. Version 1 wanted {"facts": [...]}. Return that to 2.0 and add() returns {'results': []}, with no error and no warning. A silent empty result is the symptom; the wrong key is the cause.
Try it yourself
  • Print messages[0].content as well, to see the system instruction in full.
  • Add a second sentence to the conversation and see how the New Messages block changes.
  • Return {"facts": []} from the spy and confirm that nothing is stored and nothing complains.

This is what real progress feels like.