Merge branch 'feat/v3-pipeline' of https://github.com/mem0ai/mem0 into feat/v3-pipeline
This commit is contained in:
+10
-2
@@ -144,6 +144,7 @@ def create_mocked_memory():
|
|||||||
|
|
||||||
mock_embedder = MagicMock()
|
mock_embedder = MagicMock()
|
||||||
mock_embedder.embed.return_value = [0.1, 0.2, 0.3]
|
mock_embedder.embed.return_value = [0.1, 0.2, 0.3]
|
||||||
|
mock_embedder.embed_batch.return_value = [[0.1, 0.2, 0.3]]
|
||||||
mock_embedder_factory.return_value = mock_embedder
|
mock_embedder_factory.return_value = mock_embedder
|
||||||
|
|
||||||
mock_vector_store = MagicMock()
|
mock_vector_store = MagicMock()
|
||||||
@@ -151,9 +152,12 @@ def create_mocked_memory():
|
|||||||
mock_vector_store.add.return_value = None
|
mock_vector_store.add.return_value = None
|
||||||
mock_vector_factory.return_value = mock_vector_store
|
mock_vector_factory.return_value = mock_vector_store
|
||||||
|
|
||||||
mock_sqlite.return_value = MagicMock()
|
mock_db = MagicMock()
|
||||||
|
mock_db.get_last_messages.return_value = []
|
||||||
|
mock_sqlite.return_value = mock_db
|
||||||
|
|
||||||
memory = Memory()
|
memory = Memory()
|
||||||
|
memory.custom_instructions = None
|
||||||
memory.api_version = "v1.0"
|
memory.api_version = "v1.0"
|
||||||
return memory, mock_llm, mock_vector_store
|
return memory, mock_llm, mock_vector_store
|
||||||
|
|
||||||
@@ -170,6 +174,7 @@ def create_mocked_async_memory():
|
|||||||
|
|
||||||
mock_embedder = MagicMock()
|
mock_embedder = MagicMock()
|
||||||
mock_embedder.embed.return_value = [0.1, 0.2, 0.3]
|
mock_embedder.embed.return_value = [0.1, 0.2, 0.3]
|
||||||
|
mock_embedder.embed_batch.return_value = [[0.1, 0.2, 0.3]]
|
||||||
mock_embedder_factory.return_value = mock_embedder
|
mock_embedder_factory.return_value = mock_embedder
|
||||||
|
|
||||||
mock_vector_store = MagicMock()
|
mock_vector_store = MagicMock()
|
||||||
@@ -177,9 +182,12 @@ def create_mocked_async_memory():
|
|||||||
mock_vector_store.add.return_value = None
|
mock_vector_store.add.return_value = None
|
||||||
mock_vector_factory.return_value = mock_vector_store
|
mock_vector_factory.return_value = mock_vector_store
|
||||||
|
|
||||||
mock_sqlite.return_value = MagicMock()
|
mock_db = MagicMock()
|
||||||
|
mock_db.get_last_messages.return_value = []
|
||||||
|
mock_sqlite.return_value = mock_db
|
||||||
|
|
||||||
memory = AsyncMemory()
|
memory = AsyncMemory()
|
||||||
|
memory.custom_instructions = None
|
||||||
memory.api_version = "v1.0"
|
memory.api_version = "v1.0"
|
||||||
return memory, mock_llm, mock_vector_store
|
return memory, mock_llm, mock_vector_store
|
||||||
|
|
||||||
|
|||||||
+20
-18
@@ -37,16 +37,19 @@ class TestAddToVectorStoreErrors:
|
|||||||
memory.config = mocker.MagicMock()
|
memory.config = mocker.MagicMock()
|
||||||
memory.config.custom_instructions = None
|
memory.config.custom_instructions = None
|
||||||
memory.config.custom_update_memory_prompt = None
|
memory.config.custom_update_memory_prompt = None
|
||||||
|
memory.custom_instructions = None
|
||||||
memory.api_version = "v1.1"
|
memory.api_version = "v1.1"
|
||||||
|
# v3 pipeline needs db.get_last_messages to return a list
|
||||||
|
memory.db.get_last_messages = MagicMock(return_value=[])
|
||||||
|
memory.db.save_messages = MagicMock()
|
||||||
|
|
||||||
return memory
|
return memory
|
||||||
|
|
||||||
def test_empty_llm_response_fact_extraction(self, mocker, mock_memory, caplog):
|
def test_empty_llm_response_fact_extraction(self, mocker, mock_memory, caplog):
|
||||||
"""Test empty response from LLM during fact extraction"""
|
"""Test invalid JSON response from LLM during extraction"""
|
||||||
# Setup
|
# Setup
|
||||||
mock_memory.llm.generate_response.return_value = "invalid json" # This will trigger a JSON decode error
|
mock_memory.llm.generate_response.return_value = "invalid json"
|
||||||
mock_capture_event = mocker.MagicMock()
|
mocker.patch("mem0.memory.main.capture_event")
|
||||||
mocker.patch("mem0.memory.main.capture_event", mock_capture_event)
|
|
||||||
|
|
||||||
# Execute
|
# Execute
|
||||||
with caplog.at_level(logging.ERROR):
|
with caplog.at_level(logging.ERROR):
|
||||||
@@ -54,12 +57,10 @@ class TestAddToVectorStoreErrors:
|
|||||||
messages=[{"role": "user", "content": "test"}], metadata={}, filters={}, infer=True
|
messages=[{"role": "user", "content": "test"}], metadata={}, filters={}, infer=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# Verify
|
# Verify — v3 single-pass pipeline makes 1 LLM call, returns [] on parse error
|
||||||
assert mock_memory.llm.generate_response.call_count == 1
|
assert mock_memory.llm.generate_response.call_count == 1
|
||||||
assert result == [] # Should return empty list when no memories processed
|
assert result == []
|
||||||
# Check for error message in any of the log records
|
assert any("Error parsing extraction response" in record.message for record in caplog.records), "Expected error message not found in logs"
|
||||||
assert any("Error parsing extraction response:" in record.msg for record in caplog.records), "Expected error message not found in logs"
|
|
||||||
assert mock_capture_event.call_count == 1
|
|
||||||
|
|
||||||
def test_empty_llm_response_memory_actions(self, mock_memory, caplog):
|
def test_empty_llm_response_memory_actions(self, mock_memory, caplog):
|
||||||
"""Test empty response from LLM during memory actions (v3: single-pass, 1 LLM call)"""
|
"""Test empty response from LLM during memory actions (v3: single-pass, 1 LLM call)"""
|
||||||
@@ -139,17 +140,20 @@ class TestAsyncAddToVectorStoreErrors:
|
|||||||
memory.config = mocker.MagicMock()
|
memory.config = mocker.MagicMock()
|
||||||
memory.config.custom_instructions = None
|
memory.config.custom_instructions = None
|
||||||
memory.config.custom_update_memory_prompt = None
|
memory.config.custom_update_memory_prompt = None
|
||||||
|
memory.custom_instructions = None
|
||||||
memory.api_version = "v1.1"
|
memory.api_version = "v1.1"
|
||||||
|
# v3 pipeline needs db.get_last_messages to return a list
|
||||||
|
memory.db.get_last_messages = MagicMock(return_value=[])
|
||||||
|
memory.db.save_messages = MagicMock()
|
||||||
|
|
||||||
return memory
|
return memory
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_async_empty_llm_response_fact_extraction(self, mock_async_memory, caplog, mocker):
|
async def test_async_empty_llm_response_fact_extraction(self, mock_async_memory, caplog, mocker):
|
||||||
"""Test empty response in AsyncMemory._add_to_vector_store"""
|
"""Test invalid JSON response from LLM during extraction (async)"""
|
||||||
mocker.patch("mem0.utils.factory.EmbedderFactory.create", return_value=MagicMock())
|
mocker.patch("mem0.utils.factory.EmbedderFactory.create", return_value=MagicMock())
|
||||||
mock_async_memory.llm.generate_response.return_value = "invalid json" # This will trigger a JSON decode error
|
mock_async_memory.llm.generate_response.return_value = "invalid json"
|
||||||
mock_capture_event = mocker.MagicMock()
|
mocker.patch("mem0.memory.main.capture_event")
|
||||||
mocker.patch("mem0.memory.main.capture_event", mock_capture_event)
|
|
||||||
|
|
||||||
with caplog.at_level(logging.ERROR):
|
with caplog.at_level(logging.ERROR):
|
||||||
result = await mock_async_memory._add_to_vector_store(
|
result = await mock_async_memory._add_to_vector_store(
|
||||||
@@ -157,9 +161,7 @@ class TestAsyncAddToVectorStoreErrors:
|
|||||||
)
|
)
|
||||||
assert mock_async_memory.llm.generate_response.call_count == 1
|
assert mock_async_memory.llm.generate_response.call_count == 1
|
||||||
assert result == []
|
assert result == []
|
||||||
# Check for error message in any of the log records
|
assert any("Error parsing extraction response" in record.message for record in caplog.records), "Expected error message not found in logs"
|
||||||
assert any("Error parsing extraction response:" in record.msg for record in caplog.records), "Expected error message not found in logs"
|
|
||||||
assert mock_capture_event.call_count == 1
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_async_empty_llm_response_memory_actions(self, mock_async_memory, caplog, mocker):
|
async def test_async_empty_llm_response_memory_actions(self, mock_async_memory, caplog, mocker):
|
||||||
@@ -307,7 +309,7 @@ def test_create_then_search_and_get_all_return_same_timestamps(mocker):
|
|||||||
|
|
||||||
# Step 3: Call search and get_all, compare timestamps
|
# Step 3: Call search and get_all, compare timestamps
|
||||||
search_results = memory._search_vector_store("pizza", filters={"user_id": "alice"}, limit=10)
|
search_results = memory._search_vector_store("pizza", filters={"user_id": "alice"}, limit=10)
|
||||||
get_all_results = memory._get_all_from_vector_store(filters={"user_id": "alice"}, top_k=100)
|
get_all_results = memory._get_all_from_vector_store(filters={"user_id": "alice"}, limit=100)
|
||||||
|
|
||||||
search_item = search_results[0]
|
search_item = search_results[0]
|
||||||
get_all_item = get_all_results[0]
|
get_all_item = get_all_results[0]
|
||||||
@@ -374,7 +376,7 @@ def test_search_and_get_all_consistent_after_update(mocker):
|
|||||||
memory.vector_store.list.return_value = [[mem_result]]
|
memory.vector_store.list.return_value = [[mem_result]]
|
||||||
|
|
||||||
search_results = memory._search_vector_store("pizza", filters={"user_id": "alice"}, limit=10)
|
search_results = memory._search_vector_store("pizza", filters={"user_id": "alice"}, limit=10)
|
||||||
get_all_results = memory._get_all_from_vector_store(filters={"user_id": "alice"}, top_k=100)
|
get_all_results = memory._get_all_from_vector_store(filters={"user_id": "alice"}, limit=100)
|
||||||
|
|
||||||
assert search_results[0]["created_at"] == get_all_results[0]["created_at"]
|
assert search_results[0]["created_at"] == get_all_results[0]["created_at"]
|
||||||
assert search_results[0]["updated_at"] == get_all_results[0]["updated_at"]
|
assert search_results[0]["updated_at"] == get_all_results[0]["updated_at"]
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import asyncio
|
|
||||||
import threading
|
import threading
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user