-
Notifications
You must be signed in to change notification settings - Fork 2
fix: defer fastembed import errors to use time instead of import time #280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |
| import logging | ||
|
|
||
| from collections.abc import Callable, Iterable, Sequence | ||
| from typing import Any, ClassVar, Literal, cast, override | ||
| from typing import TYPE_CHECKING, Any, ClassVar, Literal, cast, override | ||
|
|
||
| import numpy as np | ||
|
|
||
|
|
@@ -26,10 +26,10 @@ | |
| from codeweaver.core import ( | ||
| CodeChunk, | ||
| CodeWeaverSparseEmbedding, | ||
| ConfigurationError, | ||
| Provider, | ||
| rpartial, | ||
| ) | ||
| from codeweaver.core.utils import has_package | ||
| from codeweaver.providers.embedding.capabilities.base import SparseEmbeddingModelCapabilities | ||
| from codeweaver.providers.embedding.providers.base import ( | ||
| EmbeddingCustomDeps, | ||
|
|
@@ -38,22 +38,49 @@ | |
| SparseEmbeddingProvider, | ||
| ) | ||
|
|
||
| _FASTEMBED_AVAILABLE = has_package("fastembed") or has_package("fastembed-gpu") | ||
|
|
||
| try: | ||
| if TYPE_CHECKING: | ||
| from fastembed.sparse import SparseTextEmbedding | ||
| from fastembed.text import TextEmbedding | ||
|
|
||
|
Comment on lines
+41
to
46
|
||
| from codeweaver.providers.embedding.fastembed_extensions import ( | ||
| get_sparse_embedder, | ||
| get_text_embedder, | ||
| ) | ||
| except ImportError as e: | ||
| raise ConfigurationError( | ||
| r"FastEmbed is not installed. Please install it with `pip install code-weaver\[fastembed]` or `code-weaver\[fastembed-gpu]`." | ||
| ) from e | ||
| elif _FASTEMBED_AVAILABLE: | ||
| try: | ||
| from fastembed.sparse import SparseTextEmbedding | ||
| from fastembed.text import TextEmbedding | ||
|
|
||
| from codeweaver.providers.embedding.fastembed_extensions import ( | ||
| get_sparse_embedder, | ||
| get_text_embedder, | ||
| ) | ||
| except ImportError: | ||
| _FASTEMBED_AVAILABLE = False | ||
|
|
||
| if not (TYPE_CHECKING or _FASTEMBED_AVAILABLE): | ||
| TextEmbedding = Any | ||
| SparseTextEmbedding = Any | ||
|
|
||
| if _FASTEMBED_AVAILABLE: | ||
| _TextEmbedding = get_text_embedder() | ||
sourcery-ai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _SparseTextEmbedding = get_sparse_embedder() | ||
| else: | ||
| _TextEmbedding = None | ||
| _SparseTextEmbedding = None | ||
|
|
||
| _TextEmbedding = get_text_embedder() | ||
| _SparseTextEmbedding = get_sparse_embedder() | ||
|
|
||
| def _require_fastembed() -> None: | ||
| """Raise ConfigurationError if fastembed is not installed.""" | ||
| if not _FASTEMBED_AVAILABLE: | ||
| from codeweaver.core import ConfigurationError | ||
|
|
||
| raise ConfigurationError( | ||
| "fastembed is not installed. Please install it with " | ||
| "`pip install code-weaver[fastembed]` or `pip install code-weaver[fastembed-gpu]`." | ||
| ) | ||
|
|
||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
@@ -109,6 +136,7 @@ def _initialize( | |
| **kwargs: Any, | ||
| ) -> None: | ||
| """Initialize the FastEmbed client.""" | ||
| _require_fastembed() | ||
|
|
||
| @property | ||
| def base_url(self) -> str | None: | ||
|
|
@@ -176,6 +204,7 @@ def _initialize( | |
| **kwargs: Any, | ||
| ) -> None: | ||
| """Initialize the FastEmbed sparse client.""" | ||
| _require_fastembed() | ||
| # impl_deps and custom_deps are ignored for FastEmbed sparse provider; | ||
| # caps may be passed as a keyword argument via **kwargs from the base class. | ||
| # 1. Set caps using object.__setattr__ because pydantic model isn't fully initialized yet | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,29 +11,41 @@ | |
|
|
||
| from collections.abc import Callable, Sequence | ||
| from functools import partial | ||
| from typing import Any, ClassVar, cast | ||
| from typing import TYPE_CHECKING, Any, ClassVar, cast | ||
|
|
||
| import numpy as np | ||
|
|
||
| from codeweaver.core import Provider, ProviderError | ||
| from codeweaver.core.constants import DEFAULT_RERANKING_MAX_RESULTS | ||
| from codeweaver.core.utils import has_package | ||
| from codeweaver.providers.reranking.providers.base import RerankingProvider | ||
|
|
||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| try: | ||
| _FASTEMBED_AVAILABLE = has_package("fastembed") or has_package("fastembed-gpu") | ||
|
|
||
| if TYPE_CHECKING: | ||
| from fastembed.rerank.cross_encoder import TextCrossEncoder | ||
| elif _FASTEMBED_AVAILABLE: | ||
| try: | ||
| from fastembed.rerank.cross_encoder import TextCrossEncoder | ||
| except ImportError: | ||
| _FASTEMBED_AVAILABLE = False | ||
|
|
||
| if not (TYPE_CHECKING or _FASTEMBED_AVAILABLE): | ||
| TextCrossEncoder = Any | ||
sourcery-ai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+26
to
+37
|
||
|
|
||
|
|
||
| except ImportError as e: | ||
| logger.warning( | ||
| "Failed to import TextCrossEncoder from fastembed.rerank.cross_encoder", exc_info=True | ||
| ) | ||
| from codeweaver.core import ConfigurationError | ||
| def _require_fastembed() -> None: | ||
| """Raise ConfigurationError if fastembed is not installed.""" | ||
| if not _FASTEMBED_AVAILABLE: | ||
| from codeweaver.core import ConfigurationError | ||
|
|
||
| raise ConfigurationError( | ||
| r"FastEmbed is not installed. Please install it with `pip install code-weaver\[fastembed]` or `codeweaver\[fastembed-gpu]`." | ||
| ) from e | ||
| raise ConfigurationError( | ||
| "fastembed is not installed. Please install it with " | ||
| "`pip install code-weaver[fastembed]` or `pip install code-weaver[fastembed-gpu]`." | ||
| ) | ||
|
|
||
|
|
||
| class FastEmbedRerankingProvider(RerankingProvider[TextCrossEncoder]): | ||
|
|
@@ -55,6 +67,7 @@ async def _execute_rerank( | |
| **kwargs: Any, | ||
| ) -> Any: | ||
| """Execute the reranking process.""" | ||
| _require_fastembed() | ||
| try: | ||
| # our batch_size needs to be the number of documents because we only get back the scores. | ||
| # If we set it to a lower number, we wouldn't know what documents the scores correspond to without some extra setup. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_FASTEMBED_AVAILABLEis based on package presence, but the fastembed imports in the next block are not guarded. If fastembed (or fastembed-gpu) is installed but fails to import (missing binary deps, incompatible Python, etc.), this module will still raise at import time. To actually defer import errors to use-time, wrap these imports intry/except ImportErrorand fall back to theAnyplaceholders +_require_fastembed()raisingConfigurationErrorwhen the exported helpers are called.