mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-11 00:58:30 +00:00
Fix #2271: Handle SQLite3 version check gracefully for ChromaDB
Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
@@ -83,6 +83,7 @@ class KnowledgeStorage(BaseKnowledgeStorage):
|
|||||||
raise Exception("Collection not initialized")
|
raise Exception("Collection not initialized")
|
||||||
|
|
||||||
def initialize_knowledge_storage(self):
|
def initialize_knowledge_storage(self):
|
||||||
|
try:
|
||||||
base_path = os.path.join(db_storage_path(), "knowledge")
|
base_path = os.path.join(db_storage_path(), "knowledge")
|
||||||
chroma_client = chromadb.PersistentClient(
|
chroma_client = chromadb.PersistentClient(
|
||||||
path=base_path,
|
path=base_path,
|
||||||
@@ -105,6 +106,14 @@ class KnowledgeStorage(BaseKnowledgeStorage):
|
|||||||
raise Exception("Vector Database Client not initialized")
|
raise Exception("Vector Database Client not initialized")
|
||||||
except Exception:
|
except Exception:
|
||||||
raise Exception("Failed to create or get collection")
|
raise Exception("Failed to create or get collection")
|
||||||
|
except RuntimeError as e:
|
||||||
|
if "unsupported version of sqlite3" in str(e).lower():
|
||||||
|
# Log a warning but continue without ChromaDB
|
||||||
|
logging.warning(f"ChromaDB requires SQLite3 >= 3.35.0. Current version is too old. Some features may be limited. Error: {e}")
|
||||||
|
self.app = None
|
||||||
|
self.collection = None
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
base_path = os.path.join(db_storage_path(), KNOWLEDGE_DIRECTORY)
|
base_path = os.path.join(db_storage_path(), KNOWLEDGE_DIRECTORY)
|
||||||
|
|||||||
@@ -60,10 +60,17 @@ class RAGStorage(BaseRAGStorage):
|
|||||||
self.embedder_config = configurator.configure_embedder(self.embedder_config)
|
self.embedder_config = configurator.configure_embedder(self.embedder_config)
|
||||||
|
|
||||||
def _initialize_app(self):
|
def _initialize_app(self):
|
||||||
|
try:
|
||||||
import chromadb
|
import chromadb
|
||||||
from chromadb.config import Settings
|
from chromadb.config import Settings
|
||||||
|
|
||||||
self._set_embedder_config()
|
self._set_embedder_config()
|
||||||
|
if self.embedder_config is None:
|
||||||
|
# ChromaDB is not available, skip initialization
|
||||||
|
self.app = None
|
||||||
|
self.collection = None
|
||||||
|
return
|
||||||
|
|
||||||
chroma_client = chromadb.PersistentClient(
|
chroma_client = chromadb.PersistentClient(
|
||||||
path=self.path if self.path else self.storage_file_name,
|
path=self.path if self.path else self.storage_file_name,
|
||||||
settings=Settings(allow_reset=self.allow_reset),
|
settings=Settings(allow_reset=self.allow_reset),
|
||||||
@@ -79,6 +86,14 @@ class RAGStorage(BaseRAGStorage):
|
|||||||
self.collection = self.app.create_collection(
|
self.collection = self.app.create_collection(
|
||||||
name=self.type, embedding_function=self.embedder_config
|
name=self.type, embedding_function=self.embedder_config
|
||||||
)
|
)
|
||||||
|
except RuntimeError as e:
|
||||||
|
if "unsupported version of sqlite3" in str(e).lower():
|
||||||
|
# Log a warning but continue without ChromaDB
|
||||||
|
logging.warning(f"ChromaDB requires SQLite3 >= 3.35.0. Current version is too old. Some features may be limited. Error: {e}")
|
||||||
|
self.app = None
|
||||||
|
self.collection = None
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def _sanitize_role(self, role: str) -> str:
|
def _sanitize_role(self, role: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
import os
|
import os
|
||||||
|
import logging
|
||||||
from typing import Any, Dict, Optional, cast
|
from typing import Any, Dict, Optional, cast
|
||||||
|
|
||||||
from chromadb import Documents, EmbeddingFunction, Embeddings
|
# Import chromadb conditionally to handle SQLite3 version errors
|
||||||
from chromadb.api.types import validate_embedding_function
|
try:
|
||||||
|
from chromadb import Documents, EmbeddingFunction, Embeddings
|
||||||
|
from chromadb.api.types import validate_embedding_function
|
||||||
|
CHROMADB_AVAILABLE = True
|
||||||
|
except RuntimeError as e:
|
||||||
|
if "unsupported version of sqlite3" in str(e).lower():
|
||||||
|
logging.warning(f"ChromaDB requires SQLite3 >= 3.35.0. Current version is too old. Some features may be limited. Error: {e}")
|
||||||
|
CHROMADB_AVAILABLE = False
|
||||||
|
# Define placeholder types for type hints
|
||||||
|
Documents = Any
|
||||||
|
EmbeddingFunction = Any
|
||||||
|
Embeddings = Any
|
||||||
|
validate_embedding_function = lambda x: x # noqa: E731
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class EmbeddingConfigurator:
|
class EmbeddingConfigurator:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
if not CHROMADB_AVAILABLE:
|
||||||
|
self.embedding_functions = {}
|
||||||
|
return
|
||||||
|
|
||||||
self.embedding_functions = {
|
self.embedding_functions = {
|
||||||
"openai": self._configure_openai,
|
"openai": self._configure_openai,
|
||||||
"azure": self._configure_azure,
|
"azure": self._configure_azure,
|
||||||
@@ -24,8 +43,11 @@ class EmbeddingConfigurator:
|
|||||||
def configure_embedder(
|
def configure_embedder(
|
||||||
self,
|
self,
|
||||||
embedder_config: Optional[Dict[str, Any]] = None,
|
embedder_config: Optional[Dict[str, Any]] = None,
|
||||||
) -> EmbeddingFunction:
|
) -> Optional[EmbeddingFunction]:
|
||||||
"""Configures and returns an embedding function based on the provided config."""
|
"""Configures and returns an embedding function based on the provided config."""
|
||||||
|
if not CHROMADB_AVAILABLE:
|
||||||
|
return None
|
||||||
|
|
||||||
if embedder_config is None:
|
if embedder_config is None:
|
||||||
return self._create_default_embedding_function()
|
return self._create_default_embedding_function()
|
||||||
|
|
||||||
@@ -47,6 +69,9 @@ class EmbeddingConfigurator:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _create_default_embedding_function():
|
def _create_default_embedding_function():
|
||||||
|
if not CHROMADB_AVAILABLE:
|
||||||
|
return None
|
||||||
|
|
||||||
from chromadb.utils.embedding_functions.openai_embedding_function import (
|
from chromadb.utils.embedding_functions.openai_embedding_function import (
|
||||||
OpenAIEmbeddingFunction,
|
OpenAIEmbeddingFunction,
|
||||||
)
|
)
|
||||||
|
|||||||
32
tests/utilities/test_embedding_configurator.py
Normal file
32
tests/utilities/test_embedding_configurator.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import unittest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
class TestEmbeddingConfigurator(unittest.TestCase):
|
||||||
|
@patch('crewai.utilities.embedding_configurator.CHROMADB_AVAILABLE', False)
|
||||||
|
def test_embedding_configurator_with_chromadb_unavailable(self):
|
||||||
|
from crewai.utilities.embedding_configurator import EmbeddingConfigurator
|
||||||
|
|
||||||
|
# Create an instance of EmbeddingConfigurator
|
||||||
|
configurator = EmbeddingConfigurator()
|
||||||
|
|
||||||
|
# Verify that embedding_functions is empty
|
||||||
|
self.assertEqual(configurator.embedding_functions, {})
|
||||||
|
|
||||||
|
# Verify that configure_embedder returns None
|
||||||
|
self.assertIsNone(configurator.configure_embedder())
|
||||||
|
|
||||||
|
@patch('crewai.utilities.embedding_configurator.CHROMADB_AVAILABLE', True)
|
||||||
|
def test_embedding_configurator_with_chromadb_available(self):
|
||||||
|
from crewai.utilities.embedding_configurator import EmbeddingConfigurator
|
||||||
|
|
||||||
|
# Create an instance of EmbeddingConfigurator
|
||||||
|
configurator = EmbeddingConfigurator()
|
||||||
|
|
||||||
|
# Verify that embedding_functions is not empty
|
||||||
|
self.assertNotEqual(configurator.embedding_functions, {})
|
||||||
|
|
||||||
|
# Mock the _create_default_embedding_function method
|
||||||
|
configurator._create_default_embedding_function = MagicMock(return_value="mock_embedding_function")
|
||||||
|
|
||||||
|
# Verify that configure_embedder returns the mock embedding function
|
||||||
|
self.assertEqual(configurator.configure_embedder(), "mock_embedding_function")
|
||||||
Reference in New Issue
Block a user