You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_mem0.py 18 kB

Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
Add mem0 Memory Implementation (#6510) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? These changes are needed to expand AutoGen's memory capabilities with a robust, production-ready integration with Mem0.ai. <!-- Please give a short summary of the change and the problem this solves. --> This PR adds a new memory component for AutoGen that integrates with Mem0.ai, providing a robust memory solution that supports both cloud and local backends. The Mem0Memory class enables agents to store and retrieve information persistently across conversation sessions. ## Key Features - Seamless integration with Mem0.ai memory system - Support for both cloud-based and local storage backends - Robust error handling with detailed logging - Full implementation of AutoGen's Memory interface - Context updating for enhanced agent conversations - Configurable search parameters for memory retrieval ## Related issue number <!-- For example: "Closes #1234" --> ## Checks - [x] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [x] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com> Co-authored-by: Ricky Loynd <riloynd@microsoft.com>
1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. import os
  2. import uuid
  3. from datetime import datetime
  4. from typing import Any, Dict
  5. from unittest.mock import MagicMock, patch
  6. import pytest
  7. from autogen_core.memory import MemoryContent, MemoryMimeType
  8. from autogen_core.model_context import BufferedChatCompletionContext
  9. from autogen_core.models import SystemMessage, UserMessage
  10. from autogen_ext.memory.mem0 import Mem0Memory, Mem0MemoryConfig
  11. from dotenv import load_dotenv
  12. # Load environment variables from .env file
  13. load_dotenv()
  14. # Skip tests if required environment variables are not set
  15. mem0_api_key = os.environ.get("MEM0_API_KEY")
  16. requires_mem0_api = pytest.mark.skipif(mem0_api_key is None, reason="MEM0_API_KEY environment variable not set")
  17. # Skip tests if mem0ai is not installed
  18. mem0 = pytest.importorskip("mem0")
  19. # Define local configuration at the top of the module
  20. FULL_LOCAL_CONFIG: Dict[str, Any] = {
  21. "history_db_path": ":memory:", # Use in-memory DB for tests
  22. "graph_store": {
  23. "provider": "mock_graph",
  24. "config": {"url": "mock://localhost:7687", "username": "mock", "password": "mock_password"},
  25. },
  26. "embedder": {
  27. "provider": "mock_embedder",
  28. "config": {
  29. "model": "mock-embedding-model",
  30. "embedding_dims": 1024,
  31. "api_key": "mock-api-key",
  32. },
  33. },
  34. "vector_store": {"provider": "mock_vector", "config": {"path": ":memory:", "collection_name": "test_memories"}},
  35. "llm": {
  36. "provider": "mock_llm",
  37. "config": {
  38. "model": "mock-chat-model",
  39. "api_key": "mock-api-key",
  40. },
  41. },
  42. }
  43. @pytest.fixture
  44. def full_local_config() -> Dict[str, Any]:
  45. """Return the local configuration for testing."""
  46. return FULL_LOCAL_CONFIG
  47. @pytest.fixture
  48. def cloud_config() -> Mem0MemoryConfig:
  49. """Create cloud configuration with real API key."""
  50. api_key = os.environ.get("MEM0_API_KEY")
  51. return Mem0MemoryConfig(user_id="test-user", limit=3, is_cloud=True, api_key=api_key)
  52. @pytest.fixture
  53. def local_config() -> Mem0MemoryConfig:
  54. """Create local configuration for testing."""
  55. return Mem0MemoryConfig(user_id="test-user", limit=3, is_cloud=False, config={"path": ":memory:"})
  56. @pytest.mark.asyncio
  57. @patch("autogen_ext.memory.mem0._mem0.Memory0")
  58. async def test_basic_workflow(mock_mem0_class: MagicMock, local_config: Mem0MemoryConfig) -> None:
  59. """Test basic memory operations."""
  60. # Setup mock
  61. mock_mem0 = MagicMock()
  62. mock_mem0_class.from_config.return_value = mock_mem0
  63. # Mock search results
  64. mock_mem0.search.return_value = [
  65. {
  66. "memory": "Paris is known for the Eiffel Tower and amazing cuisine.",
  67. "score": 0.95,
  68. "metadata": {"category": "city", "country": "France"},
  69. }
  70. ]
  71. memory = Mem0Memory(
  72. user_id=local_config.user_id,
  73. limit=local_config.limit,
  74. is_cloud=local_config.is_cloud,
  75. api_key=local_config.api_key,
  76. config=local_config.config,
  77. )
  78. # Add content to memory
  79. await memory.add(
  80. MemoryContent(
  81. content="Paris is known for the Eiffel Tower and amazing cuisine.",
  82. mime_type=MemoryMimeType.TEXT,
  83. metadata={"category": "city", "country": "France"},
  84. )
  85. )
  86. # Verify add was called correctly
  87. mock_mem0.add.assert_called_once()
  88. call_args = mock_mem0.add.call_args[0]
  89. # Extract content from the list of dict structure: [{'content': '...', 'role': 'user'}]
  90. actual_content = call_args[0][0]["content"]
  91. assert actual_content == "Paris is known for the Eiffel Tower and amazing cuisine."
  92. call_kwargs = mock_mem0.add.call_args[1]
  93. assert call_kwargs["metadata"] == {"category": "city", "country": "France"}
  94. # Query memory
  95. results = await memory.query("Tell me about Paris")
  96. # Verify search was called correctly
  97. mock_mem0.search.assert_called_once()
  98. search_args = mock_mem0.search.call_args
  99. assert search_args[0][0] == "Tell me about Paris"
  100. assert search_args[1]["user_id"] == "test-user"
  101. assert search_args[1]["limit"] == 3
  102. # Verify results
  103. assert len(results.results) == 1
  104. assert "Paris" in str(results.results[0].content)
  105. res_metadata = results.results[0].metadata
  106. assert res_metadata is not None and res_metadata.get("score") == 0.95
  107. assert res_metadata is not None and res_metadata.get("country") == "France"
  108. # Test clear (only do this once)
  109. await memory.clear()
  110. mock_mem0.delete_all.assert_called_once_with(user_id="test-user")
  111. # Cleanup
  112. await memory.close()
  113. @requires_mem0_api
  114. @pytest.mark.asyncio
  115. @patch("autogen_ext.memory.mem0.MemoryClient") # Patch MemoryClient instead of Memory0
  116. async def test_basic_workflow_with_cloud(mock_memory_client_class: MagicMock, cloud_config: Mem0MemoryConfig) -> None:
  117. """Test basic memory operations with cloud client (mocked instead of real API)."""
  118. # Setup mock
  119. mock_client = MagicMock()
  120. mock_memory_client_class.return_value = mock_client
  121. # Mock search results
  122. mock_client.search.return_value = [
  123. {
  124. "memory": "Test memory content for cloud",
  125. "score": 0.98,
  126. "metadata": {"test": True, "source": "cloud"},
  127. }
  128. ]
  129. memory = Mem0Memory(
  130. user_id=cloud_config.user_id,
  131. limit=cloud_config.limit,
  132. is_cloud=cloud_config.is_cloud,
  133. api_key=cloud_config.api_key,
  134. config=cloud_config.config,
  135. )
  136. # Generate a unique test content string
  137. test_content = f"Test memory content {uuid.uuid4()}"
  138. # Add content to memory
  139. await memory.add(
  140. MemoryContent(
  141. content=test_content,
  142. mime_type=MemoryMimeType.TEXT,
  143. metadata={"test": True, "timestamp": datetime.now().isoformat()},
  144. )
  145. )
  146. # Verify add was called correctly
  147. mock_client.add.assert_called_once()
  148. call_args = mock_client.add.call_args
  149. # Extract content from list of dict structure: [{'content': '...', 'role': 'user'}]
  150. actual_content = call_args[0][0][0]["content"] # call_args[0][0] gets the first positional arg (the list)
  151. assert test_content in actual_content
  152. assert call_args[1]["user_id"] == cloud_config.user_id
  153. assert call_args[1]["metadata"]["test"] is True
  154. # Query memory
  155. results = await memory.query(test_content)
  156. # Verify search was called correctly
  157. mock_client.search.assert_called_once()
  158. search_args = mock_client.search.call_args
  159. assert test_content in search_args[0][0]
  160. assert search_args[1]["user_id"] == cloud_config.user_id
  161. # Verify results
  162. assert len(results.results) == 1
  163. assert "Test memory content for cloud" in str(results.results[0].content)
  164. assert results.results[0].metadata is not None
  165. assert results.results[0].metadata.get("score") == 0.98
  166. # Test clear
  167. await memory.clear()
  168. mock_client.delete_all.assert_called_once_with(user_id=cloud_config.user_id)
  169. # Cleanup
  170. await memory.close()
  171. @pytest.mark.asyncio
  172. @patch("autogen_ext.memory.mem0._mem0.Memory0")
  173. async def test_metadata_handling(mock_mem0_class: MagicMock, local_config: Mem0MemoryConfig) -> None:
  174. """Test metadata handling."""
  175. # Setup mock
  176. mock_mem0 = MagicMock()
  177. mock_mem0_class.from_config.return_value = mock_mem0
  178. # Setup mock search results with rich metadata
  179. mock_mem0.search.return_value = [
  180. {
  181. "memory": "Test content with metadata",
  182. "score": 0.9,
  183. "metadata": {"test_category": "test", "test_priority": 1, "test_weight": 0.5, "test_verified": True},
  184. "created_at": "2023-01-01T12:00:00",
  185. "updated_at": "2023-01-02T12:00:00",
  186. "categories": ["test", "example"],
  187. }
  188. ]
  189. memory = Mem0Memory(
  190. user_id=local_config.user_id,
  191. limit=local_config.limit,
  192. is_cloud=local_config.is_cloud,
  193. api_key=local_config.api_key,
  194. config=local_config.config,
  195. )
  196. # Add content with metadata
  197. test_content = "Test content with specific metadata"
  198. content = MemoryContent(
  199. content=test_content,
  200. mime_type=MemoryMimeType.TEXT,
  201. metadata={"test_category": "test", "test_priority": 1, "test_weight": 0.5, "test_verified": True},
  202. )
  203. await memory.add(content)
  204. # Verify metadata was passed correctly
  205. add_kwargs = mock_mem0.add.call_args[1]
  206. assert add_kwargs["metadata"]["test_category"] == "test"
  207. assert add_kwargs["metadata"]["test_priority"] == 1
  208. assert add_kwargs["metadata"]["test_weight"] == 0.5
  209. assert add_kwargs["metadata"]["test_verified"] is True
  210. # Query and check returned metadata
  211. results = await memory.query(test_content)
  212. assert len(results.results) == 1
  213. result = results.results[0]
  214. # Verify metadata in results
  215. assert result.metadata is not None and result.metadata.get("test_category") == "test"
  216. assert result.metadata is not None and result.metadata.get("test_priority") == 1
  217. assert result.metadata is not None and isinstance(result.metadata.get("test_weight"), float)
  218. assert result.metadata is not None and result.metadata.get("test_verified") is True
  219. assert result.metadata is not None and "created_at" in result.metadata
  220. assert result.metadata is not None and "updated_at" in result.metadata
  221. assert result.metadata is not None and result.metadata.get("categories") == ["test", "example"]
  222. # Cleanup
  223. await memory.close()
  224. @pytest.mark.asyncio
  225. @patch("autogen_ext.memory.mem0._mem0.Memory0")
  226. async def test_update_context(mock_mem0_class: MagicMock, local_config: Mem0MemoryConfig) -> None:
  227. """Test updating model context with retrieved memories."""
  228. # Setup mock
  229. mock_mem0 = MagicMock()
  230. mock_mem0_class.from_config.return_value = mock_mem0
  231. # Setup mock search results
  232. mock_mem0.search.return_value = [
  233. {"memory": "Jupiter is the largest planet in our solar system.", "score": 0.9},
  234. {"memory": "Jupiter has many moons, including Ganymede, Europa, and Io.", "score": 0.8},
  235. ]
  236. memory = Mem0Memory(
  237. user_id=local_config.user_id,
  238. limit=local_config.limit,
  239. is_cloud=local_config.is_cloud,
  240. api_key=local_config.api_key,
  241. config=local_config.config,
  242. )
  243. # Create a model context with a message
  244. context = BufferedChatCompletionContext(buffer_size=5)
  245. await context.add_message(UserMessage(content="Tell me about Jupiter", source="user"))
  246. # Update context with memory
  247. result = await memory.update_context(context)
  248. # Verify results
  249. assert len(result.memories.results) == 2
  250. assert "Jupiter" in str(result.memories.results[0].content)
  251. # Verify search was called with correct query
  252. mock_mem0.search.assert_called_once()
  253. search_args = mock_mem0.search.call_args
  254. assert "Jupiter" in search_args[0][0]
  255. # Verify context was updated with a system message
  256. messages = await context.get_messages()
  257. assert len(messages) == 2 # Original message + system message with memories
  258. # Verify system message content
  259. system_message = messages[1]
  260. assert isinstance(system_message, SystemMessage)
  261. assert "Jupiter is the largest planet" in system_message.content
  262. assert "Jupiter has many moons" in system_message.content
  263. # Cleanup
  264. await memory.close()
  265. @pytest.mark.asyncio
  266. @patch("autogen_ext.memory.mem0._mem0.MemoryClient") # Patch for cloud mode
  267. async def test_component_serialization(mock_memory_client_class: MagicMock) -> None:
  268. """Test serialization and deserialization of the component."""
  269. # Setup mock
  270. mock_client = MagicMock()
  271. mock_memory_client_class.return_value = mock_client
  272. # Create configuration
  273. user_id = str(uuid.uuid4())
  274. config = Mem0MemoryConfig(
  275. user_id=user_id,
  276. limit=5,
  277. is_cloud=True,
  278. )
  279. # Create memory instance
  280. memory = Mem0Memory(
  281. user_id=config.user_id,
  282. limit=config.limit,
  283. is_cloud=config.is_cloud,
  284. api_key=config.api_key,
  285. config=config.config,
  286. )
  287. # Dump config
  288. memory_config = memory.dump_component()
  289. # Verify dumped config
  290. assert memory_config.config["user_id"] == user_id
  291. assert memory_config.config["limit"] == 5
  292. assert memory_config.config["is_cloud"] is True
  293. # Load from config
  294. loaded_memory = Mem0Memory(
  295. user_id=config.user_id,
  296. limit=config.limit,
  297. is_cloud=config.is_cloud,
  298. api_key=config.api_key,
  299. config=config.config,
  300. )
  301. # Verify loaded instance
  302. assert isinstance(loaded_memory, Mem0Memory)
  303. assert loaded_memory.user_id == user_id
  304. assert loaded_memory.limit == 5
  305. assert loaded_memory.is_cloud is True
  306. assert loaded_memory.config is None
  307. # Cleanup
  308. await memory.close()
  309. await loaded_memory.close()
  310. @pytest.mark.asyncio
  311. @patch("autogen_ext.memory.mem0._mem0.Memory0")
  312. async def test_result_format_handling(mock_mem0_class: MagicMock, local_config: Mem0MemoryConfig) -> None:
  313. """Test handling of different result formats."""
  314. # Setup mock
  315. mock_mem0 = MagicMock()
  316. mock_mem0_class.from_config.return_value = mock_mem0
  317. # Test dictionary format with "results" key
  318. mock_mem0.search.return_value = {
  319. "results": [
  320. {"memory": "Dictionary format result 1", "score": 0.9},
  321. {"memory": "Dictionary format result 2", "score": 0.8},
  322. ]
  323. }
  324. memory = Mem0Memory(
  325. user_id=local_config.user_id,
  326. limit=local_config.limit,
  327. is_cloud=local_config.is_cloud,
  328. api_key=local_config.api_key,
  329. config=local_config.config,
  330. )
  331. # Query with dictionary format
  332. results_dict = await memory.query("test query")
  333. # Verify results were extracted correctly
  334. assert len(results_dict.results) == 2
  335. assert "Dictionary format result 1" in str(results_dict.results[0].content)
  336. # Test list format
  337. mock_mem0.search.return_value = [
  338. {"memory": "List format result 1", "score": 0.9},
  339. {"memory": "List format result 2", "score": 0.8},
  340. ]
  341. # Query with list format
  342. results_list = await memory.query("test query")
  343. # Verify results were processed correctly
  344. assert len(results_list.results) == 2
  345. assert "List format result 1" in str(results_list.results[0].content)
  346. # Cleanup
  347. await memory.close()
  348. @pytest.mark.asyncio
  349. @patch("autogen_ext.memory.mem0._mem0.Memory0")
  350. async def test_init_with_local_config(mock_mem0_class: MagicMock, full_local_config: Dict[str, Any]) -> None:
  351. """Test initializing memory with local configuration."""
  352. # Setup mock
  353. mock_mem0 = MagicMock()
  354. mock_mem0_class.from_config.return_value = mock_mem0
  355. # Initialize memory with local config
  356. memory = Mem0Memory(user_id="test-local-config-user", limit=10, is_cloud=False, config=full_local_config)
  357. # Verify configuration was passed correctly
  358. mock_mem0_class.from_config.assert_called_once()
  359. # Verify memory instance properties (use type: ignore or add public properties)
  360. assert memory._user_id == "test-local-config-user" # type: ignore
  361. assert memory._limit == 10 # type: ignore
  362. assert memory._is_cloud is False # type: ignore
  363. assert memory._config == full_local_config # type: ignore
  364. # Test serialization with local config
  365. memory_config = memory.dump_component()
  366. # Verify serialized config
  367. assert memory_config.config["user_id"] == "test-local-config-user"
  368. assert memory_config.config["is_cloud"] is False
  369. # Cleanup
  370. await memory.close()
  371. @pytest.mark.asyncio
  372. @patch("autogen_ext.memory.mem0._mem0.Memory0") # Patches the underlying mem0.Memory class
  373. async def test_local_config_with_memory_operations(
  374. mock_mem0_class: MagicMock,
  375. full_local_config: Dict[str, Any], # full_local_config fixture provides the mock config
  376. ) -> None:
  377. """Test memory operations with local configuration."""
  378. # Setup mock for the instance that will be created by Mem0Memory
  379. mock_mem0_instance = MagicMock()
  380. mock_mem0_class.from_config.return_value = mock_mem0_instance
  381. # Mock search results from the mem0 instance
  382. mock_mem0_instance.search.return_value = [
  383. {
  384. "memory": "Test local config memory content",
  385. "score": 0.92,
  386. "metadata": {"config_type": "local", "test_case": "advanced"},
  387. }
  388. ]
  389. # Initialize Mem0Memory with is_cloud=False and the full_local_config
  390. memory = Mem0Memory(user_id="test-local-config-user", limit=10, is_cloud=False, config=full_local_config)
  391. # Verify that mem0.Memory.from_config was called with the provided config
  392. mock_mem0_class.from_config.assert_called_once_with(config_dict=full_local_config)
  393. # Add memory content
  394. test_content_str = "Testing local configuration memory operations"
  395. await memory.add(
  396. MemoryContent(
  397. content=test_content_str,
  398. mime_type=MemoryMimeType.TEXT,
  399. metadata={"config_type": "local", "test_case": "advanced"},
  400. )
  401. )
  402. # Verify add was called on the mock_mem0_instance
  403. mock_mem0_instance.add.assert_called_once()
  404. # Query memory
  405. results = await memory.query("local configuration test")
  406. # Verify search was called on the mock_mem0_instance
  407. mock_mem0_instance.search.assert_called_once_with(
  408. "local configuration test", user_id="test-local-config-user", limit=10
  409. )
  410. # Verify results
  411. assert len(results.results) == 1
  412. assert "Test local config memory content" in str(results.results[0].content)
  413. res_metadata = results.results[0].metadata
  414. assert res_metadata is not None and res_metadata.get("score") == 0.92
  415. assert res_metadata is not None and res_metadata.get("config_type") == "local"
  416. # Test serialization with local config
  417. memory_config = memory.dump_component()
  418. # Verify serialized config
  419. assert memory_config.config["user_id"] == "test-local-config-user"
  420. assert memory_config.config["is_cloud"] is False
  421. assert "config" in memory_config.config
  422. assert memory_config.config["config"]["history_db_path"] == ":memory:"
  423. # Test clear
  424. await memory.clear()
  425. mock_mem0_instance.delete_all.assert_called_once_with(user_id="test-local-config-user")
  426. # Cleanup
  427. await memory.close()
  428. if __name__ == "__main__":
  429. pytest.main(["-xvs", __file__])