Skip to content

Commit a544d60

Browse files
authored
Merge branch 'dev' into feat/demo-product
2 parents 5796475 + 86c999a commit a544d60

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

src/memos/mem_os/core.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,14 @@ def register_mem_cube(
426426
# Check if cube already exists in database
427427
existing_cube = self.user_manager.get_cube(mem_cube_id)
428428

429+
# check the embedder is it consistent with MOSConfig
430+
if self.config.mem_reader.config.embedder != (
431+
cube_embedder := self.mem_cubes[mem_cube_id].text_mem.config.embedder
432+
):
433+
logger.warning(
434+
f"Cube Embedder is not consistent with MOSConfig for cube: {mem_cube_id}, will use Cube Embedder: {cube_embedder}"
435+
)
436+
429437
if existing_cube:
430438
# Cube exists, just add user to cube if not already associated
431439
if not self.user_manager.validate_user_cube_access(target_user_id, mem_cube_id):

tests/mem_os/test_memos_core.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,126 @@ def test_search_memories(
328328
assert result["text_mem"][0]["cube_id"] == "test_cube_1"
329329
mock_mem_cube.text_mem.search.assert_called_once_with("football", top_k=5)
330330

331+
@patch("memos.mem_os.core.UserManager")
332+
@patch("memos.mem_os.core.MemReaderFactory")
333+
@patch("memos.mem_os.core.LLMFactory")
334+
@patch("memos.mem_os.core.logger")
335+
def test_register_mem_cube_embedder_consistency_warning(
336+
self,
337+
mock_logger,
338+
mock_llm_factory,
339+
mock_reader_factory,
340+
mock_user_manager_class,
341+
mock_config,
342+
mock_llm,
343+
mock_mem_reader,
344+
mock_user_manager,
345+
mock_mem_cube,
346+
):
347+
"""Test embedder consistency warning when cube embedder differs from MOS config."""
348+
# Setup mocks
349+
mock_llm_factory.from_config.return_value = mock_llm
350+
mock_reader_factory.from_config.return_value = mock_mem_reader
351+
mock_user_manager_class.return_value = mock_user_manager
352+
mock_user_manager.get_cube.return_value = None # Cube doesn't exist
353+
354+
# Create different embedder configs for MOS and cube
355+
mos_embedder_config = {
356+
"backend": "ollama",
357+
"config": {
358+
"model_name_or_path": "nomic-embed-text:latest",
359+
},
360+
}
361+
362+
cube_embedder_config = {
363+
"backend": "sentence_transformer",
364+
"config": {
365+
"model_name_or_path": "all-MiniLM-L6-v2",
366+
},
367+
}
368+
369+
# Mock the cube's text memory embedder config
370+
mock_mem_cube.text_mem.config.embedder = cube_embedder_config
371+
372+
with patch("memos.mem_os.core.GeneralMemCube") as mock_general_cube:
373+
mock_general_cube.init_from_dir.return_value = mock_mem_cube
374+
375+
mos = MOSCore(MOSConfig(**mock_config))
376+
377+
# Ensure MOS config has different embedder
378+
mos.config.mem_reader.config.embedder = mos_embedder_config
379+
380+
with patch("os.path.exists", return_value=True):
381+
mos.register_mem_cube("test_cube_path", "test_cube_1")
382+
383+
# Verify warning was logged
384+
mock_logger.warning.assert_called_with(
385+
f"Cube Embedder is not consistent with MOSConfig for cube: test_cube_1, will use Cube Embedder: {cube_embedder_config}"
386+
)
387+
388+
# Verify cube was still registered
389+
assert "test_cube_1" in mos.mem_cubes
390+
mock_general_cube.init_from_dir.assert_called_once_with("test_cube_path")
391+
392+
@patch("memos.mem_os.core.UserManager")
393+
@patch("memos.mem_os.core.MemReaderFactory")
394+
@patch("memos.mem_os.core.LLMFactory")
395+
@patch("memos.mem_os.core.logger")
396+
def test_register_mem_cube_embedder_consistency_no_warning(
397+
self,
398+
mock_logger,
399+
mock_llm_factory,
400+
mock_reader_factory,
401+
mock_user_manager_class,
402+
mock_config,
403+
mock_llm,
404+
mock_mem_reader,
405+
mock_user_manager,
406+
mock_mem_cube,
407+
):
408+
"""Test no warning when cube embedder is consistent with MOS config."""
409+
# Setup mocks
410+
mock_llm_factory.from_config.return_value = mock_llm
411+
mock_reader_factory.from_config.return_value = mock_mem_reader
412+
mock_user_manager_class.return_value = mock_user_manager
413+
mock_user_manager.get_cube.return_value = None # Cube doesn't exist
414+
415+
# Create same embedder config for both MOS and cube
416+
embedder_config = {
417+
"backend": "ollama",
418+
"config": {
419+
"model_name_or_path": "nomic-embed-text:latest",
420+
},
421+
}
422+
423+
# Mock the cube's text memory embedder config to be the same
424+
mock_mem_cube.text_mem.config.embedder = embedder_config
425+
426+
with patch("memos.mem_os.core.GeneralMemCube") as mock_general_cube:
427+
mock_general_cube.init_from_dir.return_value = mock_mem_cube
428+
429+
mos = MOSCore(MOSConfig(**mock_config))
430+
431+
# Ensure MOS config has same embedder
432+
mos.config.mem_reader.config.embedder = embedder_config
433+
434+
with patch("os.path.exists", return_value=True):
435+
mos.register_mem_cube("test_cube_path", "test_cube_1")
436+
437+
# Verify no embedder consistency warning was logged
438+
warning_calls = [
439+
call
440+
for call in mock_logger.warning.call_args_list
441+
if "Cube Embedder is not consistent" in str(call)
442+
]
443+
assert len(warning_calls) == 0, (
444+
"No embedder consistency warning should be logged when configs match"
445+
)
446+
447+
# Verify cube was still registered
448+
assert "test_cube_1" in mos.mem_cubes
449+
mock_general_cube.init_from_dir.assert_called_once_with("test_cube_path")
450+
331451
@patch("memos.mem_os.core.UserManager")
332452
@patch("memos.mem_os.core.MemReaderFactory")
333453
@patch("memos.mem_os.core.LLMFactory")

0 commit comments

Comments
 (0)