fix: update mem0 and qdrant dependencies#13292
Conversation
WalkthroughThis PR upgrades mem0ai from 0.1.34 to 2.0.2+, updates qdrant-client to 1.12.0–1.x, and migrates ChangesMem0 2.x library upgrade
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 7 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (7 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Test Coverage AdvisorNo source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release-1.10.0 #13292 +/- ##
==================================================
+ Coverage 55.57% 55.61% +0.04%
==================================================
Files 2178 2178
Lines 205682 205657 -25
Branches 31089 29436 -1653
==================================================
+ Hits 114309 114384 +75
+ Misses 90053 89954 -99
+ Partials 1320 1319 -1
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lfx/src/lfx/_assets/component_index.json`:
- Line 92004: In build_search_results, add an early guard that checks if
self.user_id is falsy and avoid calling mem0_memory.search or get_all with
filters containing a null user_id; instead log a warning (using logger.warning)
and return an empty/neutral Data result appropriate for build_search_results (so
callers don’t get null-scoped Mem0 results). Update build_search_results (and
its interaction with ingest_data if needed) to perform this check before
constructing filters or calling mem0_memory.search/get_all.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 19db78ef-e630-4008-9b55-4c3d86760d2c
⛔ Files ignored due to path filters (2)
src/backend/base/uv.lockis excluded by!**/*.lockuv.lockis excluded by!**/*.lock
📒 Files selected for processing (4)
src/backend/base/pyproject.tomlsrc/backend/tests/unit/components/bundles/mem0/test_mem0_component.pysrc/lfx/src/lfx/_assets/component_index.jsonsrc/lfx/src/lfx/components/mem0/mem0_chat_memory.py
| "title_case": false, | ||
| "type": "code", | ||
| "value": "import os\n\nfrom mem0 import Memory, MemoryClient\n\nfrom lfx.base.memory.model import LCChatMemoryComponent\nfrom lfx.inputs.inputs import DictInput, HandleInput, MessageTextInput, NestedDictInput, SecretStrInput\nfrom lfx.io import Output\nfrom lfx.log.logger import logger\nfrom lfx.schema.data import Data\nfrom lfx.utils.validate_cloud import raise_error_if_astra_cloud_disable_component\n\ndisable_component_in_astra_cloud_msg = (\n \"Mem0 chat memory is not supported in Astra cloud environment. Please use local storage mode or mem0 cloud.\"\n)\n\n\nclass Mem0MemoryComponent(LCChatMemoryComponent):\n display_name = \"Mem0 Chat Memory\"\n description = \"Retrieves and stores chat messages using Mem0 memory storage.\"\n name = \"mem0_chat_memory\"\n icon: str = \"Mem0\"\n inputs = [\n NestedDictInput(\n name=\"mem0_config\",\n display_name=\"Mem0 Configuration\",\n info=\"\"\"Configuration dictionary for initializing Mem0 memory instance.\n Example:\n {\n \"graph_store\": {\n \"provider\": \"neo4j\",\n \"config\": {\n \"url\": \"neo4j+s://your-neo4j-url\",\n \"username\": \"neo4j\",\n \"password\": \"your-password\"\n }\n },\n \"version\": \"v1.1\"\n }\"\"\",\n input_types=[\"Data\", \"JSON\"],\n ),\n MessageTextInput(\n name=\"ingest_message\",\n display_name=\"Message to Ingest\",\n info=\"The message content to be ingested into Mem0 memory.\",\n ),\n HandleInput(\n name=\"existing_memory\",\n display_name=\"Existing Memory Instance\",\n input_types=[\"Memory\"],\n info=\"Optional existing Mem0 memory instance. If not provided, a new instance will be created.\",\n ),\n MessageTextInput(\n name=\"user_id\", display_name=\"User ID\", info=\"Identifier for the user associated with the messages.\"\n ),\n MessageTextInput(\n name=\"search_query\", display_name=\"Search Query\", info=\"Input text for searching related memories in Mem0.\"\n ),\n SecretStrInput(\n name=\"mem0_api_key\",\n display_name=\"Mem0 API Key\",\n info=\"API key for Mem0 platform. Leave empty to use the local version.\",\n ),\n DictInput(\n name=\"metadata\",\n display_name=\"Metadata\",\n info=\"Additional metadata to associate with the ingested message.\",\n advanced=True,\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n required=False,\n info=\"API key for OpenAI. Required if using OpenAI Embeddings without a provided configuration.\",\n ),\n ]\n\n outputs = [\n Output(name=\"memory\", display_name=\"Mem0 Memory\", method=\"ingest_data\"),\n Output(\n name=\"search_results\",\n display_name=\"Search Results\",\n method=\"build_search_results\",\n ),\n ]\n\n def build_mem0(self) -> Memory:\n \"\"\"Initializes a Mem0 memory instance based on provided configuration and API keys.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n if self.openai_api_key:\n os.environ[\"OPENAI_API_KEY\"] = self.openai_api_key\n\n try:\n if not self.mem0_api_key:\n return Memory.from_config(config_dict=dict(self.mem0_config)) if self.mem0_config else Memory()\n if self.mem0_config:\n return MemoryClient.from_config(api_key=self.mem0_api_key, config_dict=dict(self.mem0_config))\n return MemoryClient(api_key=self.mem0_api_key)\n except ImportError as e:\n msg = \"Mem0 is not properly installed. Please install it with 'pip install -U mem0ai'.\"\n raise ImportError(msg) from e\n\n def ingest_data(self) -> Memory:\n \"\"\"Ingests a new message into Mem0 memory and returns the updated memory instance.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n mem0_memory = self.existing_memory or self.build_mem0()\n\n if not self.ingest_message or not self.user_id:\n logger.warning(\"Missing 'ingest_message' or 'user_id'; cannot ingest data.\")\n return mem0_memory\n\n metadata = self.metadata or {}\n\n logger.info(\"Ingesting message for user_id: %s\", self.user_id)\n\n try:\n mem0_memory.add(self.ingest_message, user_id=self.user_id, metadata=metadata)\n except Exception:\n logger.exception(\"Failed to add message to Mem0 memory.\")\n raise\n\n return mem0_memory\n\n def build_search_results(self) -> Data:\n \"\"\"Searches the Mem0 memory for related messages based on the search query and returns the results.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n mem0_memory = self.ingest_data()\n search_query = self.search_query\n user_id = self.user_id\n\n logger.info(\"Search query: %s\", search_query)\n\n try:\n if search_query:\n logger.info(\"Performing search with query.\")\n related_memories = mem0_memory.search(query=search_query, user_id=user_id)\n else:\n logger.info(\"Retrieving all memories for user_id: %s\", user_id)\n related_memories = mem0_memory.get_all(user_id=user_id)\n except Exception:\n logger.exception(\"Failed to retrieve related memories from Mem0.\")\n raise\n\n logger.info(\"Related memories retrieved: %s\", related_memories)\n return related_memories\n" | ||
| "value": "import os\n\nfrom mem0 import Memory, MemoryClient\n\nfrom lfx.base.memory.model import LCChatMemoryComponent\nfrom lfx.inputs.inputs import DictInput, HandleInput, MessageTextInput, NestedDictInput, SecretStrInput\nfrom lfx.io import Output\nfrom lfx.log.logger import logger\nfrom lfx.schema.data import Data\nfrom lfx.utils.validate_cloud import raise_error_if_astra_cloud_disable_component\n\ndisable_component_in_astra_cloud_msg = (\n \"Mem0 chat memory is not supported in Astra cloud environment. Please use local storage mode or mem0 cloud.\"\n)\n\n\nclass Mem0MemoryComponent(LCChatMemoryComponent):\n display_name = \"Mem0 Chat Memory\"\n description = \"Retrieves and stores chat messages using Mem0 memory storage.\"\n name = \"mem0_chat_memory\"\n icon: str = \"Mem0\"\n inputs = [\n NestedDictInput(\n name=\"mem0_config\",\n display_name=\"Mem0 Configuration\",\n info=\"\"\"Configuration dictionary for initializing Mem0 memory instance.\n Example:\n {\n \"graph_store\": {\n \"provider\": \"neo4j\",\n \"config\": {\n \"url\": \"neo4j+s://your-neo4j-url\",\n \"username\": \"neo4j\",\n \"password\": \"your-password\"\n }\n },\n \"version\": \"v1.1\"\n }\"\"\",\n input_types=[\"Data\", \"JSON\"],\n ),\n MessageTextInput(\n name=\"ingest_message\",\n display_name=\"Message to Ingest\",\n info=\"The message content to be ingested into Mem0 memory.\",\n ),\n HandleInput(\n name=\"existing_memory\",\n display_name=\"Existing Memory Instance\",\n input_types=[\"Memory\"],\n info=\"Optional existing Mem0 memory instance. If not provided, a new instance will be created.\",\n ),\n MessageTextInput(\n name=\"user_id\", display_name=\"User ID\", info=\"Identifier for the user associated with the messages.\"\n ),\n MessageTextInput(\n name=\"search_query\", display_name=\"Search Query\", info=\"Input text for searching related memories in Mem0.\"\n ),\n SecretStrInput(\n name=\"mem0_api_key\",\n display_name=\"Mem0 API Key\",\n info=\"API key for Mem0 platform. Leave empty to use the local version.\",\n ),\n DictInput(\n name=\"metadata\",\n display_name=\"Metadata\",\n info=\"Additional metadata to associate with the ingested message.\",\n advanced=True,\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n required=False,\n info=\"API key for OpenAI. Required if using OpenAI Embeddings without a provided configuration.\",\n ),\n ]\n\n outputs = [\n Output(name=\"memory\", display_name=\"Mem0 Memory\", method=\"ingest_data\"),\n Output(\n name=\"search_results\",\n display_name=\"Search Results\",\n method=\"build_search_results\",\n ),\n ]\n\n def build_mem0(self) -> Memory:\n \"\"\"Initializes a Mem0 memory instance based on provided configuration and API keys.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n if self.openai_api_key:\n os.environ[\"OPENAI_API_KEY\"] = self.openai_api_key\n\n try:\n if not self.mem0_api_key:\n return Memory.from_config(config_dict=dict(self.mem0_config)) if self.mem0_config else Memory()\n if self.mem0_config:\n return MemoryClient.from_config(api_key=self.mem0_api_key, config_dict=dict(self.mem0_config))\n return MemoryClient(api_key=self.mem0_api_key)\n except ImportError as e:\n msg = \"Mem0 is not properly installed. Please install it with 'pip install -U mem0ai'.\"\n raise ImportError(msg) from e\n\n def ingest_data(self) -> Memory:\n \"\"\"Ingests a new message into Mem0 memory and returns the updated memory instance.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n mem0_memory = self.existing_memory or self.build_mem0()\n\n if not self.ingest_message or not self.user_id:\n logger.warning(\"Missing 'ingest_message' or 'user_id'; cannot ingest data.\")\n return mem0_memory\n\n metadata = self.metadata or {}\n\n logger.info(\"Ingesting message for user_id: %s\", self.user_id)\n\n try:\n mem0_memory.add(self.ingest_message, user_id=self.user_id, metadata=metadata)\n except Exception:\n logger.exception(\"Failed to add message to Mem0 memory.\")\n raise\n\n return mem0_memory\n\n def build_search_results(self) -> Data:\n \"\"\"Searches the Mem0 memory for related messages based on the search query and returns the results.\"\"\"\n # Check if we're in Astra cloud environment and raise an error if we are.\n raise_error_if_astra_cloud_disable_component(disable_component_in_astra_cloud_msg)\n mem0_memory = self.ingest_data()\n search_query = self.search_query\n user_id = self.user_id\n\n logger.info(\"Search query: %s\", search_query)\n\n try:\n if search_query:\n logger.info(\"Performing search with query.\")\n related_memories = mem0_memory.search(query=search_query, filters={\"user_id\": user_id})\n else:\n logger.info(\"Retrieving all memories for user_id: %s\", user_id)\n related_memories = mem0_memory.get_all(filters={\"user_id\": user_id})\n except Exception:\n logger.exception(\"Failed to retrieve related memories from Mem0.\")\n raise\n\n logger.info(\"Related memories retrieved: %s\", related_memories)\n return related_memories\n" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
For mem0ai 2.x, what is the behavior of Memory.search() and Memory.get_all() when filters={"user_id": None} (or when user_id is omitted)? Does it return unscoped/all-user memories?
💡 Result:
In mem0ai 2.x (OSS “Memory” SDK), the documented behavior is that entity scoping is done via the filters object; passing entity IDs as top-level kwargs is rejected, and reads are “scoped by filters”.[1][2][3] 1) If filters={"user_id": None} - The docs state that entity IDs must be passed inside filters and reads return memories “scoped by filters”.[1][2][3] - However, the specific case of filters with user_id=None (or JSON null) is not explicitly documented as returning “all-user/unscoped” memories. The platform feature page instead describes “implicit null scoping”: records where other primary entities are null are treated specially, and wildcards behave differently than null-only values.[3] - Therefore, based on the documented entity-scoping model, filters={"user_id": None} should not be interpreted as “unscoped/all users”; it would target the null-valued user scope (i.e., records created with user_id null / absent), not every user.[3] 2) If user_id is omitted from filters - The docs describe filters-based scoping but do not say that omitting user_id means “return all users”.[2][3] - The entity-scoped-memory feature page explains that records are partitioned by primary entity and that “wildcards” ("") are required to include broader sets; it contrasts wildcard behavior with null-only scoping and gives examples of constructing broader joins using OR and wildcards.[3] - So, omitting user_id is best treated as “use the default scoping behavior for your entity identifiers”, which is not equivalent to all-user retrieval; to retrieve broader sets you’d need explicit wildcard logic (e.g., user_id="") as described by the feature docs.[3] Practical conclusion - No: filters={"user_id": None} is not documented to return unscoped/all-user memories; it aligns with “null scoping” rather than “no scope”.[3] - Also not: omitting user_id is not documented to automatically mean “all-user”; if you want all users, you should use the documented wildcard mechanism in the filters (e.g., "user_id": "*") or an OR-based broadening pattern, rather than relying on null/omitted behavior.[3]
Citations:
- 1: https://docs.mem0.ai/api-reference/memory/search-memories
- 2: https://docs.mem0.ai/api-reference/memory/get-memories
- 3: https://docs.mem0.ai/platform/features/entity-scoped-memory
Avoid querying Mem0 when user_id is missing in build_search_results.
build_search_results always calls mem0_memory.search/get_all with filters={"user_id": user_id}; when self.user_id is empty/None, Mem0’s “entity scoping” via filters will apply “null scoping” (targeting only null/absent user_id records, not all users), leading to incorrect/unexpected results. Add an early guard before calling search()/get_all() when user_id is falsy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/lfx/src/lfx/_assets/component_index.json` at line 92004, In
build_search_results, add an early guard that checks if self.user_id is falsy
and avoid calling mem0_memory.search or get_all with filters containing a null
user_id; instead log a warning (using logger.warning) and return an
empty/neutral Data result appropriate for build_search_results (so callers don’t
get null-scoped Mem0 results). Update build_search_results (and its interaction
with ingest_data if needed) to perform this check before constructing filters or
calling mem0_memory.search/get_all.
Summary
Validation
Summary by CodeRabbit