add() stops reporting memories the vector store never saved

2 days ago

If you run mem0 open source, the first fix in 2.2.1 is in add. Say add extracts three memories, and the vector store rejects the one about a penicillin allergy. Version 2.2.0 still returned all three as added, and wrote all three to history. Now only records that were actually inserted get a history entry, entity links, and a place in the results.

Ask about this presentation

Chapters

  1. 0:00add() reports only stored memories
  2. 0:24with Memory() works again
  3. 0:41Bedrock reads the text block
  4. 1:00Turbopuffer applies every filter operator
  5. 1:21Euclidean scores stay between 0 and 1
  6. 1:45Two calls can now raise
  7. 2:07Upgrade to 2.2.1
Show transcript
  1. If you run mem0 open source, the first fix in 2.2.1 is in add. Say add extracts three memories, and the vector store rejects the one about a penicillin allergy. Version 2.2.0 still returned all three as added, and wrote all three to history. Now only records that were actually inserted get a history entry, entity links, and a place in the results.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    add() stops reporting memories the vector store never saved

    2.2.0 add() returned
    User's name is Aryan ADD
    User is allergic to penicillin ADD
    User works as an engineer ADD
    2.2.1 add() returns
    User's name is Aryan ADD
    User is allergic to penicillin not stored
    User works as an engineer ADD
  2. The second core fix brings back a pattern some of you were already using. You can open a Memory in a with block again, and an AsyncMemory in an async with block. When the block ends, the instance is closed for you. Errors raised inside the block still reach your code.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Memory and AsyncMemory work as context managers again

    mem0/memory/main.py
    Python Node JS
    with Memory() as m:
        ...
    
    async with AsyncMemory() as m:
        ...
    On exit, the instance closes. __exit__ calls self.close() and returns False, so an exception inside the block still propagates.
  3. On AWS Bedrock, a Claude reasoning model can answer with a reasoning block first and the text block second. The Anthropic path always read the first block, so these calls failed with a KeyError. It now returns the first block that carries text. An empty content list returns an empty string.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Claude reasoning models on AWS Bedrock stop failing with KeyError

    Converse response
    Python Node JS
    "content": [
      {"reasoningContent": {
          "reasoningText": {"text": "step by step..."}}},
      {"text": "final answer"}
    ]
    2.2.0
    content[0]["text"]
    KeyError
    2.2.1
    first block with "text"
    "final answer"
  4. Turbopuffer users get two fixes. The first is filters. The store only read greater than or equal, and less than or equal. Every other operator was dropped silently, so a not equal or an in filter came back unfiltered. Now all eight apply: equal, not equal, greater than, less than, the two inclusive ones, in, and not in.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Turbopuffer filters now apply all eight operators

    2.2.0
    eq ne gt gte lt lte in nin
    Dropped without an error, so the query returned unfiltered results.
    2.2.1
    eq ne gt gte lt lte in nin
    Mapped to Turbopuffer's Eq, NotEq, Gt, Gte, Lt, Lte, In and NotIn.
  5. The second fix is search scores. Turbopuffer and S3 Vectors both turned a distance into a score as one minus the distance, which only works for cosine. With euclidean distances, Turbopuffer scores went negative past a distance of 1 and inverted ranking, and S3 Vectors collapsed most scores to zero. Both now use one over one plus the distance, which stays between zero and one.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Euclidean search scores on Turbopuffer and S3 Vectors stay between 0 and 1

    DistanceTurbopuffer 2.2.01 − dS3 Vectors 2.2.0max(0, 1 − d)Both in 2.2.11 / (1 + d)
    0.50.50.50.67
    2−100.33
    4−300.2

    Worked example from the formulas. Applies to euclidean_squared on Turbopuffer and euclidean on S3 Vectors; cosine scores are unchanged.

  6. Two of these fixes can raise an error where your code used to carry on. If the vector store rejects every extracted memory, add now raises a VectorStoreError instead of returning memories that were never stored. Your messages are still saved for a retry. And a Turbopuffer filter with an unsupported operator raises a value error.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Two calls now raise errors instead of carrying on

    VectorStoreError
    Memory.add() and AsyncMemory.add()
    When none of the extracted memories could be inserted. The raw messages are still saved, so a later retry can re-extract them.
    ValueError
    Turbopuffer filters
    When a filter uses an operator outside the eight. 2.2.0 dropped it and returned unfiltered results.
  7. Upgrading is one command. Install mem0ai 2.2.1 from pip. Before you upgrade, check any code that assumes add always returns, and wrap it to catch the new error. After that, add stops reporting memories the vector store never saved.

    Slide text
    mem0
    Core LLMs Vector stores Upgrade

    Upgrade to mem0ai 2.2.1, and catch VectorStoreError around add()

    $pip install --upgrade mem0ai==2.2.1
    Hold off only if your code needs to handle a failed write in add() first, since it now raises instead of returning.
    Imported from mem0.exceptions, the same module as LLMError.

What happened in AI today, in your inbox

One short email each evening. Read it and you’re caught up.

Built in New York with ❤️