fix(memory): handle block-list content in remove_code_blocks
A custom LangChain LLM passed to AsyncMemory._create_procedural_memory returns AIMessage.content, which is str | list[str | dict]. Providers that emit content blocks hit content.strip() on a list and raised AttributeError. remove_code_blocks already normalized None, so the list case is handled in the same guard rather than at the single call site. Closes #6150
This commit is contained in:
+37
-2
@@ -1235,9 +1235,10 @@ class TestHybridSearchWarning:
|
||||
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
|
||||
|
||||
from mem0.vector_stores.base import VectorStoreBase
|
||||
|
||||
class StoreWithoutKeywordSearch(VectorStoreBase):
|
||||
def create_col(self, *a, **kw): pass
|
||||
def insert(self, *a, **kw): pass
|
||||
@@ -1271,9 +1272,10 @@ class TestHybridSearchWarning:
|
||||
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
|
||||
|
||||
from mem0.vector_stores.base import VectorStoreBase
|
||||
|
||||
class StoreWithKeywordSearch(VectorStoreBase):
|
||||
def keyword_search(self, query, top_k=5, filters=None):
|
||||
return []
|
||||
@@ -1536,6 +1538,39 @@ async def test_async_procedural_memory_langchain_strips_code_blocks(mock_llm_fac
|
||||
assert "```" not in stored_data
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("mem0.memory.main.VectorStoreFactory")
|
||||
@patch("mem0.memory.main.EmbedderFactory")
|
||||
@patch("mem0.memory.main.LlmFactory")
|
||||
async def test_async_procedural_memory_langchain_block_list_content(mock_llm_factory, mock_emb, mock_vs):
|
||||
"""Regression #6150: block-list message content must not raise AttributeError."""
|
||||
mock_vs.return_value = MagicMock()
|
||||
mock_emb.return_value = MagicMock()
|
||||
mock_emb.return_value.embed.return_value = [0.1] * 1536
|
||||
mock_llm_factory.return_value = MagicMock()
|
||||
|
||||
from mem0.memory.main import AsyncMemory
|
||||
|
||||
config = MemoryConfig()
|
||||
memory = AsyncMemory(config)
|
||||
memory.vector_store = MagicMock()
|
||||
memory.vector_store.insert = MagicMock()
|
||||
|
||||
mock_langchain_llm = MagicMock()
|
||||
mock_response = MagicMock()
|
||||
mock_response.content = [{"type": "text", "text": '```json\n{"key": "value"}\n```'}]
|
||||
mock_langchain_llm.invoke.return_value = mock_response
|
||||
|
||||
messages = [{"role": "user", "content": "test"}]
|
||||
metadata = {"user_id": "test_user"}
|
||||
|
||||
await memory._create_procedural_memory(messages, metadata=metadata, llm=mock_langchain_llm)
|
||||
|
||||
insert_call = memory.vector_store.insert.call_args
|
||||
stored_data = insert_call[1]["payloads"][0]["data"]
|
||||
assert stored_data == '{"key": "value"}'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch("mem0.memory.main.VectorStoreFactory")
|
||||
@patch("mem0.memory.main.EmbedderFactory")
|
||||
|
||||
Reference in New Issue
Block a user