From d48b1832c727f59d39c4f0de71ad42e081d5ebd7 Mon Sep 17 00:00:00 2001 From: Parshva Daftari <89991302+parshvadaftari@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:39:39 +0530 Subject: [PATCH] Fixes ollama and updates openai dependency (#3452) --- mem0/llms/ollama.py | 8 ++++++++ mem0/memory/main.py | 20 ++++++++++++++++---- mem0/vector_stores/faiss.py | 6 ++++++ pyproject.toml | 4 ++-- tests/memory/test_main.py | 8 ++++---- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/mem0/llms/ollama.py b/mem0/llms/ollama.py index b19342143..9c5b0f36f 100644 --- a/mem0/llms/ollama.py +++ b/mem0/llms/ollama.py @@ -91,6 +91,14 @@ class OllamaLLM(LLMBase): "messages": messages, } + # Handle JSON response format by modifying the system prompt + if response_format and response_format.get("type") == "json_object": + # Add JSON format instruction to the last message or create a system message + if messages and messages[-1]["role"] == "user": + messages[-1]["content"] += "\n\nPlease respond with valid JSON only." + else: + messages.append({"role": "user", "content": "Please respond with valid JSON only."}) + # Add options for Ollama (temperature, num_predict, top_p) options = { "temperature": self.config.temperature, diff --git a/mem0/memory/main.py b/mem0/memory/main.py index 35c59ab4c..c997983ff 100644 --- a/mem0/memory/main.py +++ b/mem0/memory/main.py @@ -7,6 +7,7 @@ import logging import os import uuid import warnings + from copy import deepcopy from datetime import datetime from typing import Any, Dict, Optional @@ -38,6 +39,9 @@ from mem0.utils.factory import ( VectorStoreFactory, ) +# Suppress SWIG deprecation warnings globally +warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*SwigPy.*") +warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*swigvarlink.*") def _build_filters_and_metadata( *, # Enforce keyword-only arguments @@ -386,8 +390,12 @@ class Memory(MemoryBase): response = "" try: - response = remove_code_blocks(response) - new_memories_with_actions = json.loads(response) + if not response or not response.strip(): + logger.warning("Empty response from LLM, no memories to extract") + new_memories_with_actions = {} + else: + response = remove_code_blocks(response) + new_memories_with_actions = json.loads(response) except Exception as e: logger.error(f"Invalid JSON response: {e}") new_memories_with_actions = {} @@ -1229,8 +1237,12 @@ class AsyncMemory(MemoryBase): logger.error(f"Error in new memory actions response: {e}") response = "" try: - response = remove_code_blocks(response) - new_memories_with_actions = json.loads(response) + if not response or not response.strip(): + logger.warning("Empty response from LLM, no memories to extract") + new_memories_with_actions = {} + else: + response = remove_code_blocks(response) + new_memories_with_actions = json.loads(response) except Exception as e: logger.error(f"Invalid JSON response: {e}") new_memories_with_actions = {} diff --git a/mem0/vector_stores/faiss.py b/mem0/vector_stores/faiss.py index cb2cd2254..141df5eae 100644 --- a/mem0/vector_stores/faiss.py +++ b/mem0/vector_stores/faiss.py @@ -8,7 +8,13 @@ from typing import Dict, List, Optional import numpy as np from pydantic import BaseModel +import warnings + try: + # Suppress SWIG deprecation warnings from FAISS + warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*SwigPy.*") + warnings.filterwarnings("ignore", category=DeprecationWarning, message=".*swigvarlink.*") + logging.getLogger("faiss").setLevel(logging.WARNING) logging.getLogger("faiss.loader").setLevel(logging.WARNING) diff --git a/pyproject.toml b/pyproject.toml index 537c24105..4127345e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ requires-python = ">=3.9,<4.0" dependencies = [ "qdrant-client>=1.9.1", "pydantic>=2.7.3", - "openai>=1.90.0,<1.100.0", + "openai>=1.90.0,<1.110.0", "posthog>=3.5.0", "pytz>=2024.1", "sqlalchemy>=2.0.31", @@ -54,7 +54,7 @@ llms = [ "groq>=0.3.0", "together>=0.2.10", "litellm>=1.74.0", - "openai>=1.90.0,<1.100.0", + "openai>=1.90.0,<1.110.0", "ollama>=0.1.0", "vertexai>=0.1.0", "google-generativeai>=0.3.0", diff --git a/tests/memory/test_main.py b/tests/memory/test_main.py index 90ceff17d..0290fc677 100644 --- a/tests/memory/test_main.py +++ b/tests/memory/test_main.py @@ -66,7 +66,7 @@ class TestAddToVectorStoreErrors: mock_memory.llm.generate_response.side_effect = ['{"facts": ["test fact"]}', ""] # Execute - with caplog.at_level(logging.ERROR): + with caplog.at_level(logging.WARNING): result = mock_memory._add_to_vector_store( messages=[{"role": "user", "content": "test"}], metadata={}, filters={}, infer=True ) @@ -74,7 +74,7 @@ class TestAddToVectorStoreErrors: # Verify assert mock_memory.llm.generate_response.call_count == 2 assert result == [] # Should return empty list when no memories processed - assert "Invalid JSON response" in caplog.text + assert "Empty response from LLM, no memories to extract" in caplog.text @pytest.mark.asyncio @@ -117,11 +117,11 @@ class TestAsyncAddToVectorStoreErrors: mock_capture_event = mocker.MagicMock() mocker.patch("mem0.memory.main.capture_event", mock_capture_event) - with caplog.at_level(logging.ERROR): + with caplog.at_level(logging.WARNING): result = await mock_async_memory._add_to_vector_store( messages=[{"role": "user", "content": "test"}], metadata={}, effective_filters={}, infer=True ) assert result == [] - assert "Invalid JSON response" in caplog.text + assert "Empty response from LLM, no memories to extract" in caplog.text assert mock_capture_event.call_count == 1