feat: warn when hybrid search silently degrades to semantic-only (#5444)

This commit is contained in:
Hrushikesh Yadav
2026-06-10 16:26:48 +05:30
committed by GitHub
parent 652193d599
commit e769502baa
2 changed files with 96 additions and 0 deletions
+77
View File
@@ -970,3 +970,80 @@ async def test_async_create_memory_stores_text_lemmatized(mock_sqlite, mock_llm_
"AsyncMemory._create_memory must store text_lemmatized for BM25 keyword search"
)
assert payload[0]["text_lemmatized"] != "", "text_lemmatized must not be empty"
class TestHybridSearchWarning:
"""Warn at init when vector store does not support keyword_search."""
@patch("mem0.memory.telemetry.capture_event")
@patch("mem0.memory.main.SQLiteManager")
@patch("mem0.utils.factory.LlmFactory.create")
@patch("mem0.utils.factory.EmbedderFactory.create")
@patch("mem0.utils.factory.VectorStoreFactory.create")
def test_warning_for_store_without_keyword_search(
self, mock_vs_factory, mock_emb, mock_llm, mock_sqlite, _cap, caplog
):
from mem0.vector_stores.base import VectorStoreBase
import logging
class StoreWithoutKeywordSearch(VectorStoreBase):
def create_col(self, *a, **kw): pass
def insert(self, *a, **kw): pass
def search(self, *a, **kw): return []
def delete(self, *a, **kw): pass
def update(self, *a, **kw): pass
def get(self, *a, **kw): pass
def list_cols(self): return []
def delete_col(self): pass
def col_info(self): return {}
def list(self, *a, **kw): return []
def reset(self): pass
mock_vs_factory.return_value = StoreWithoutKeywordSearch()
mock_emb.return_value = MagicMock()
mock_llm.return_value = MagicMock()
config = MemoryConfig()
config.vector_store.provider = "chroma"
with caplog.at_level(logging.WARNING, logger="mem0.memory.main"):
Memory(config)
assert any("does not support keyword search" in r.message for r in caplog.records)
@patch("mem0.memory.telemetry.capture_event")
@patch("mem0.memory.main.SQLiteManager")
@patch("mem0.utils.factory.LlmFactory.create")
@patch("mem0.utils.factory.EmbedderFactory.create")
@patch("mem0.utils.factory.VectorStoreFactory.create")
def test_no_warning_for_store_with_keyword_search(
self, mock_vs_factory, mock_emb, mock_llm, mock_sqlite, _cap, caplog
):
from mem0.vector_stores.base import VectorStoreBase
import logging
class StoreWithKeywordSearch(VectorStoreBase):
def keyword_search(self, query, top_k=5, filters=None):
return []
def create_col(self, *a, **kw): pass
def insert(self, *a, **kw): pass
def search(self, *a, **kw): return []
def delete(self, *a, **kw): pass
def update(self, *a, **kw): pass
def get(self, *a, **kw): pass
def list_cols(self): return []
def delete_col(self): pass
def col_info(self): return {}
def list(self, *a, **kw): return []
def reset(self): pass
mock_vs_factory.return_value = StoreWithKeywordSearch()
mock_emb.return_value = MagicMock()
mock_llm.return_value = MagicMock()
config = MemoryConfig()
with caplog.at_level(logging.WARNING, logger="mem0.memory.main"):
Memory(config)
assert not any("does not support keyword search" in r.message for r in caplog.records)