Compare commits

..
Author SHA1 Message Date
George 880a277640 new: gpu package (#224) 2024-05-03 16:35:56 +00:00
George Panchuk e04ac0b335 add eofl 2024-05-03 16:34:16 +00:00
George Panchuk 8991bdc541 sync publih with main 2024-05-03 16:34:16 +00:00
George Panchuk a58ae07017 fix: workflow dispatch can only be triggered from the default branch 2024-05-03 16:34:16 +00:00
George Panchuk 8bd314795d alter workflow 2024-05-03 16:34:16 +00:00
George Panchuk 9f4bc3a475 refactoring: alter workflow names 2024-05-03 16:34:16 +00:00
George Panchuk 7c69436237 fix: do not run windows and mac os tests on gpu branch 2024-05-03 16:34:16 +00:00
George Panchuk e829c89c5c new: gpu package publish workflow 2024-05-03 16:34:16 +00:00
Andrey Vasnetsov 6ecab6d40d bump v0.2.7 2024-05-03 16:33:06 +00:00
d8c592032b new: allow users to override providers (#214)
* new: add gpu support, allow users to override providers

* fix: update poetry.lock

* fix: fix type hint for 3.8

* [readme] Remove similar work

* [README] Add GPU support for FastEmbed library

* [README]  Add device check

* fix: revert changes to pyproject and lock, update readme

* Update poetry.lock

* new: add type alias for providers, add explicit providers to embeddings

---------

Co-authored-by: Nirant Kasliwal <nirant.bits@gmail.com>
Co-authored-by: Nirant <NirantK@users.noreply.github.com>
2024-05-03 18:31:22 +02:00
GeorgeandAndrey Vasnetsov da603b8b7d new: add release instructions (#231)
* new: add release instructions

* review fixes

---------

Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com>
2024-05-03 18:30:54 +02:00
Andrey Vasnetsov 562d604375 Merge pull request #223 from Waffleboy/main
[Bugfix] Allow user to pick local mode only so huggingface does not do a network call and timeout
2024-05-03 18:29:54 +02:00
Andrey Vasnetsov 8b1a98a6a3 Merge pull request #230 from qdrant/update-tokenizers
new: update tokenizers
2024-05-03 18:26:09 +02:00
Andrey Vasnetsov 3c9b147e0a version 2024-05-03 16:21:33 +00:00
George Panchuk 6abd415f4a fix: add local_files_only to sparse, formatting, refactor 2024-05-03 17:49:10 +02:00
George Panchuk 8184acbb39 new: update tokenizers 2024-05-03 16:57:45 +02:00
George 47cf7f9f92 new: add gpu package into workflow (#228)
* new: add gpu package into workflow

* remove gpu tag
2024-05-03 16:30:23 +02:00
generall f7896c81f3 do not ship poetry.lock with the repo, as package users wont have it anyway 2024-05-03 13:00:53 +02:00
Thiru 4a59d09248 Allow user to pick local mode only so huggingface does not do a network call and timeout 2024-05-02 00:25:24 +08:00
Arun 432da42c11 fix links (#215) 2024-04-27 22:24:29 +05:30
16 changed files with 128 additions and 3511 deletions
-1
View File
@@ -15,7 +15,6 @@ on:
tags:
- 'v*' # Push events to every version tag
jobs:
deploy:
+2 -3
View File
@@ -1,8 +1,9 @@
name: Tests
run-name: Tests (gpu)
on:
push:
branches: [ master, main ]
branches: [ master, main, gpu ]
schedule:
- cron: 0 0 * * *
pull_request:
@@ -23,8 +24,6 @@ jobs:
- '3.12.x'
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
+33 -8
View File
@@ -2,7 +2,7 @@
FastEmbed is a lightweight, fast, Python library built for embedding generation. We [support popular text models](https://qdrant.github.io/fastembed/examples/Supported_Models/). Please [open a GitHub issue](https://github.com/qdrant/fastembed/issues/new) if you want us to add a new model.
The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/examples/Usage_With_Qdrant/).
The default text embedding (`TextEmbedding`) model is Flag Embedding, presented in the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. It supports "query" and "passage" prefixes for the input text. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/qdrant/Retrieval_with_FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/qdrant/Usage_With_Qdrant/).
## 📈 Why FastEmbed?
@@ -14,12 +14,18 @@ The default text embedding (`TextEmbedding`) model is Flag Embedding, presented
## 🚀 Installation
To install the FastEmbed library, pip works:
To install the FastEmbed library, pip works best. You can install it with or without GPU support:
```bash
pip install fastembed
```
### ⚡️ With GPU
```bash
pip install fastembed-gpu
```
## 📖 Quickstart
```python
@@ -42,6 +48,23 @@ embeddings_list = list(embedding_model.embed(documents))
len(embeddings_list[0]) # Vector of 384 dimensions
```
### ⚡️ FastEmbed on a GPU
FastEmbed supports running on GPU devices. It requires installation of the `fastembed-gpu` package.
Make sure not to have the `fastembed` package installed, as it might interfere with the `fastembed-gpu` package.
```bash
pip install fastembed-gpu
```
```python
from fastembed import TextEmbedding
embedding_model = TextEmbedding(model_name="BAAI/bge-small-en-v1.5", providers=["CUDAExecutionProvider"])
print("The model BAAI/bge-small-en-v1.5 is ready to use on a GPU.")
```
## Usage with Qdrant
Installation with Qdrant Client in Python:
@@ -50,7 +73,13 @@ Installation with Qdrant Client in Python:
pip install qdrant-client[fastembed]
```
You might have to use ```pip install 'qdrant-client[fastembed]'``` on zsh.
or
```bash
pip install qdrant-client[fastembed-gpu]
```
You might have to use quotes ```pip install 'qdrant-client[fastembed]'``` on zsh.
```python
from qdrant_client import QdrantClient
@@ -85,8 +114,4 @@ search_result = client.query(
query_text="This is a query document"
)
print(search_result)
```
#### Similar Work
Ilyas M. wrote about using [FlagEmbeddings with Optimum](https://twitter.com/IlysMoutawwakil/status/1705215192425288017) over CUDA.
```
+41
View File
@@ -0,0 +1,41 @@
# Releasing FastEmbed
This is a guide how to release `fastembed` and `fastembed-gpu` packages.
## How to
1. Accumulate changes in the `main` branch.
2. Bump the version in `pyproject.toml`
3. Rebase the `gpu` branch on `main` and resolve conflicts if occurred:
```bash
git checkout gpu
git rebase main
git push origin gpu
```
4. Draft release notes
5. Checkout to `main` and create a tag, e.g.:
```bash
git checkout main
git tag -a v0.1.0 -m "Release v0.1.0"
```
6. Checkout `gpu` and create a tag, e.g.:
```bash
git checkout gpu
git tag -a v0.1.0-gpu -m "Release v0.1.0"
```
7. Push tags:
```bash
git push --tags
```
8. Verify that both packages have been published successfully on PyPI. Try installing them and verify imports.
9. Create a release on GitHub with the written release notes.
+6 -1
View File
@@ -3,5 +3,10 @@ import importlib.metadata
from fastembed.text import TextEmbedding
from fastembed.sparse import SparseTextEmbedding, SparseEmbedding
__version__ = importlib.metadata.version("fastembed")
try:
version = importlib.metadata.version("fastembed")
except importlib.metadata.PackageNotFoundError as _:
version = importlib.metadata.version("fastembed-gpu")
__version__ = version
__all__ = ["TextEmbedding", "SparseTextEmbedding", "SparseEmbedding"]
+3
View File
@@ -0,0 +1,3 @@
from fastembed.common.onnx_model import OnnxProvider
__all__ = ["OnnxProvider"]
+7 -2
View File
@@ -91,6 +91,7 @@ class ModelManagement:
hf_source_repo: str,
cache_dir: Optional[str] = None,
extra_patterns: Optional[List[str]] = None,
**kwargs,
) -> str:
"""
Downloads a model from HuggingFace Hub.
@@ -115,6 +116,7 @@ class ModelManagement:
repo_id=hf_source_repo,
allow_patterns=allow_patterns,
cache_dir=cache_dir,
local_files_only=kwargs.get("local_files_only", False),
)
@classmethod
@@ -189,7 +191,7 @@ class ModelManagement:
return model_dir
@classmethod
def download_model(cls, model: Dict[str, Any], cache_dir: Path) -> Path:
def download_model(cls, model: Dict[str, Any], cache_dir: Path, **kwargs) -> Path:
"""
Downloads a model from HuggingFace Hub or Google Cloud Storage.
@@ -224,7 +226,10 @@ class ModelManagement:
try:
return Path(
cls.download_files_from_huggingface(
hf_source, cache_dir=str(cache_dir), extra_patterns=extra_patterns
hf_source,
cache_dir=str(cache_dir),
extra_patterns=extra_patterns,
local_files_only=kwargs.get("local_files_only", False),
)
)
except (EnvironmentError, RepositoryNotFoundError, ValueError) as e:
+3 -1
View File
@@ -26,6 +26,8 @@ from fastembed.parallel_processor import ParallelWorkerPool, Worker
# Holds type of the embedding result
T = TypeVar("T")
OnnxProvider = Union[str, Tuple[str, Dict[Any, Any]]]
class OnnxModel(Generic[T]):
@classmethod
@@ -51,7 +53,7 @@ class OnnxModel(Generic[T]):
model_dir: Path,
model_file: str,
threads: Optional[int],
providers: Optional[Sequence[Union[str, Tuple[str, Dict[Any, Any]]]]] = None,
providers: Optional[Sequence[OnnxProvider]] = None,
) -> None:
model_path = model_dir / model_file
@@ -32,6 +32,7 @@ class SparseTextEmbeddingBase(ModelManagement):
self.model_name = model_name
self.cache_dir = cache_dir
self.threads = threads
self._local_files_only = kwargs.pop("local_files_only", False)
def embed(
self,
+6 -2
View File
@@ -1,5 +1,6 @@
from typing import List, Type, Dict, Any, Union, Iterable, Optional
from typing import List, Type, Dict, Any, Union, Iterable, Optional, Sequence
from fastembed.common import OnnxProvider
from fastembed.sparse.sparse_embedding_base import SparseTextEmbeddingBase, SparseEmbedding
from fastembed.sparse.splade_pp import SpladePP
@@ -42,6 +43,7 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
model_name: str,
cache_dir: Optional[str] = None,
threads: Optional[int] = None,
providers: Optional[Sequence[OnnxProvider]] = None,
**kwargs,
):
super().__init__(model_name, cache_dir, threads, **kwargs)
@@ -49,7 +51,9 @@ class SparseTextEmbedding(SparseTextEmbeddingBase):
for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
if any(model_name.lower() == model["model"].lower() for model in supported_models):
self.model = EMBEDDING_MODEL_TYPE(model_name, cache_dir, threads, **kwargs)
self.model = EMBEDDING_MODEL_TYPE(
model_name, cache_dir, threads, providers=providers, **kwargs
)
return
raise ValueError(
+7 -3
View File
@@ -1,8 +1,8 @@
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Type
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, Type, Sequence
import numpy as np
from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel
from fastembed.common.onnx_model import EmbeddingWorker, OnnxModel, OnnxProvider
from fastembed.common.utils import define_cache_dir
from fastembed.sparse.sparse_embedding_base import SparseEmbedding, SparseTextEmbeddingBase
@@ -63,6 +63,7 @@ class SpladePP(SparseTextEmbeddingBase, OnnxModel[SparseEmbedding]):
model_name: str,
cache_dir: Optional[str] = None,
threads: Optional[int] = None,
providers: Optional[Sequence[OnnxProvider]] = None,
**kwargs,
):
"""
@@ -82,12 +83,15 @@ class SpladePP(SparseTextEmbeddingBase, OnnxModel[SparseEmbedding]):
model_description = self._get_model_description(model_name)
cache_dir = define_cache_dir(cache_dir)
model_dir = self.download_model(model_description, cache_dir)
model_dir = self.download_model(
model_description, cache_dir, local_files_only=self._local_files_only
)
self.load_onnx_model(
model_dir=model_dir,
model_file=model_description["model_file"],
threads=threads,
providers=providers,
)
def embed(
+7 -3
View File
@@ -1,8 +1,8 @@
from typing import Dict, Optional, Tuple, Union, Iterable, Type, List, Any
from typing import Dict, Optional, Tuple, Union, Iterable, Type, List, Any, Sequence
import numpy as np
from fastembed.common.onnx_model import OnnxModel, EmbeddingWorker
from fastembed.common.onnx_model import OnnxModel, EmbeddingWorker, OnnxProvider
from fastembed.common.models import normalize
from fastembed.common.utils import define_cache_dir
from fastembed.text.text_embedding_base import TextEmbeddingBase
@@ -211,6 +211,7 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxModel[np.ndarray]):
model_name: str = "BAAI/bge-small-en-v1.5",
cache_dir: Optional[str] = None,
threads: Optional[int] = None,
providers: Optional[Sequence[OnnxProvider]] = None,
**kwargs,
):
"""
@@ -229,12 +230,15 @@ class OnnxTextEmbedding(TextEmbeddingBase, OnnxModel[np.ndarray]):
model_description = self._get_model_description(model_name)
cache_dir = define_cache_dir(cache_dir)
model_dir = self.download_model(model_description, cache_dir)
model_dir = self.download_model(
model_description, cache_dir, local_files_only=self._local_files_only
)
self.load_onnx_model(
model_dir=model_dir,
model_file=model_description["model_file"],
threads=threads,
providers=providers,
)
def embed(
+6 -2
View File
@@ -1,7 +1,8 @@
from typing import Any, Dict, Iterable, List, Optional, Type, Union
from typing import Any, Dict, Iterable, List, Optional, Type, Union, Sequence
import numpy as np
from fastembed.common import OnnxProvider
from fastembed.text.e5_onnx_embedding import E5OnnxEmbedding
from fastembed.text.jina_onnx_embedding import JinaOnnxEmbedding
from fastembed.text.onnx_embedding import OnnxTextEmbedding
@@ -49,6 +50,7 @@ class TextEmbedding(TextEmbeddingBase):
model_name: str = "BAAI/bge-small-en-v1.5",
cache_dir: Optional[str] = None,
threads: Optional[int] = None,
providers: Optional[Sequence[OnnxProvider]] = None,
**kwargs,
):
super().__init__(model_name, cache_dir, threads, **kwargs)
@@ -56,7 +58,9 @@ class TextEmbedding(TextEmbeddingBase):
for EMBEDDING_MODEL_TYPE in self.EMBEDDINGS_REGISTRY:
supported_models = EMBEDDING_MODEL_TYPE.list_supported_models()
if any(model_name.lower() == model["model"].lower() for model in supported_models):
self.model = EMBEDDING_MODEL_TYPE(model_name, cache_dir, threads, **kwargs)
self.model = EMBEDDING_MODEL_TYPE(
model_name, cache_dir, threads, providers=providers, **kwargs
)
return
raise ValueError(
+1
View File
@@ -16,6 +16,7 @@ class TextEmbeddingBase(ModelManagement):
self.model_name = model_name
self.cache_dir = cache_dir
self.threads = threads
self._local_files_only = kwargs.pop("local_files_only", False)
def embed(
self,
Generated
-3469
View File
File diff suppressed because it is too large Load Diff
+5 -16
View File
@@ -1,8 +1,8 @@
[tool.poetry]
name = "fastembed"
version = "0.2.6"
name = "fastembed-gpu"
version = "0.2.7"
description = "Fast, light, accurate library built for retrieval embedding generation"
authors = ["NirantK <nirant.bits@gmail.com>"]
authors = ["NirantK <nirant.bits@gmail.com>", "Qdrant Team <info@qdrant.tech>"]
license = "Apache License"
readme = "README.md"
packages = [{include = "fastembed"}]
@@ -12,19 +12,10 @@ keywords = ["vector", "embedding", "neural", "search", "qdrant", "sentence-trans
[tool.poetry.dependencies]
python = ">=3.8.0,<3.13"
onnx = [
{version = "^1.15.0", optional = true, markers = "extra != 'gpu'"}
]
onnxruntime = [
{version = "^1.17.0", optional = true, markers = "extra != 'gpu'"}
]
onnxruntime-gpu = [
{ version = "^1.17.0", optional = true, python = "<3.13", markers = "extra == 'gpu'" }
]
onnxruntime-gpu = "^1.17.0"
tqdm = "^4.66"
requests = "^2.31"
tokenizers = "^0.15.1"
tokenizers = "^0.15"
huggingface-hub = "^0.20"
loguru = "^0.7.2"
numpy = [
@@ -45,8 +36,6 @@ pillow = "^10.2.0"
cairosvg = "^2.7.1"
mknotebooks = "^0.8.0"
[tool.poetry.extras]
gpu = ["onnxruntime-gpu"]
[build-system]
requires = ["poetry-core"]