Fix mem0 search returning nothing, and the OSS extractor on transformers 5.x - #50
Merged
Merged
Conversation
…ers 5.x
Three defects found by calling every public API end to end against a real store
and the real /v1 gateway, rather than the fake gateway the tests use.
mem0 search() returned {"results": []} for EVERY query. _reshape_search_results
reads `selected_refs`, but a ContextPack now serves its refs GROUPED --
groups: [{type, n, items: [{text, ...}]}] -- and emits no `selected_refs` key at
all. mem0's primary read API therefore returned nothing while search_raw plainly
showed content. Both pack shapes are now accepted; a group's `type` is carried
into each item's metadata as `ref_type` so callers keep the event/entity
distinction the flat shape gave them.
mem0 search() results were not addressable. Fixing the above exposed it: group
items carry no id, because `source_ref` is classified as debug-only lineage and
stripped from serving items, so results got synthetic `ref-N-...` ids. Feeding
those back into get/update/delete -- mem0's documented flow -- failed with
found:false, HTTP 500 and deleted:false. Real ids are now recovered from
get_all by exact text match: one extra request, made only when a synthetic id is
actually present. Items that match nothing keep the synthetic id on purpose, as
a derived entity ref ("preference: drink is matcha") is a projection of a memory
rather than an addressable memory.
The OSS causal-LM extractor could not run at all on transformers >= 5.
apply_chat_template(..., return_tensors="pt") now returns a BatchEncoding rather
than a bare tensor, and the result was passed positionally to generate(), which
read .shape off a dict-like and raised a bare AttributeError. Both shapes are
accepted now. Verified with Qwen2.5-7B-Instruct on transformers 5.15.0.
Tests: 8 added. 4 of the mem0 tests and 2 of the extractor tests fail on the
unfixed code with the original errors. The existing mem0 suite exercised the
client against a stub HTTP handler returning hand-written selected_refs, so it
only ever tested request shaping and could not see either search defect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
one_pass_memory_extraction falls back to the deterministic rules when the configured LLM provider raises, which is the right behaviour. But the result it returned still carried understanding_provider: <the configured provider>, so the payload claimed an LLM had produced entities that rules had actually produced. That is not a cosmetic label. The extraction client timeout is 30s by default (MATRIXARK_EXTRACTION_TIMEOUT_SEC) and a 7B model on CPU needs minutes per call, so every call times out, silently falls back, and reports success with the LLM's name on it. Measuring "LLM extraction quality" against such a store measures the deterministic path instead -- which is exactly what happened here before the timeout was traced: a full quality run attributed to Qwen2.5-7B had in fact made zero successful model calls. The fallback now reports understanding_provider: "deterministic" and records what was asked for and why it failed, in understanding_provider_requested and understanding_provider_error. Callers that never inspected those fields are unaffected; callers that trusted understanding_provider now get the truth. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three defects found by calling every public API end to end — all 39 MCP tools and all 11
mem0.Memorymethods — against a real store and the real/v1gateway ASGI app, rather than the stub gateway the existing tests use.1.
mem0.search()returned nothing, for every query_reshape_search_resultsreadsselected_refs. A ContextPack now serves its refs grouped —groups: [{type, n, items: [{text, ...}]}]— and emits noselected_refskey at all. So mem0's primary read API returned{"results": []}on a store that plainly had matching content (search_rawshowed it).Both shapes are accepted now. A group's
typeis carried into each item's metadata asref_type, so callers keep the event/entity distinction the flat shape gave them.2.
mem0.search()results were not addressableFixing (1) exposed this. Group items carry no id —
source_refis deliberately classified as debug-only lineage and stripped from serving items — so results got syntheticref-N-…ids. Feeding those back intoget/update/delete, which is mem0's documented flow, failed withfound: false, HTTP 500, anddeleted: false.Real ids are recovered from
get_allby exact text match: one extra request, made only when a synthetic id is actually present. Items that match nothing keep the synthetic id on purpose — a derived entity ref ("preference: drink is matcha") is a projection of a memory, not an addressable memory, and inventing an id for it would only move the failure downstream.3. The OSS causal-LM extractor could not run on transformers ≥ 5
apply_chat_template(..., return_tensors="pt")returns aBatchEncodingon transformers 5.x where it used to return a bare tensor. The result was passed positionally intogenerate(), which read.shapeoff a dict-like and raised a bareAttributeErrorwith no indication of the cause —segment_provider=osswas simply unusable.Both shapes are accepted now. Verified against
Qwen2.5-7B-Instructon transformers 5.15.0.Why the tests missed all three
test_mem0_complete.pyexercises the mem0 client against a stubBaseHTTPRequestHandlerthat returns hand-writtenselected_refspayloads, so it only ever tested request shaping and never saw a real pack. Nothing at all coveredoss_model_memory_segments.Verification
retrieve/searchbeyond non-emptiness — grounding, per-user scoping in both directions, id resolution,limit, and agreement betweensearchandsearch_raw: 13/13.🤖 Generated with Claude Code