mirror of
https://github.com/qdrant/fastembed.git
synced 2026-09-23 14:37:51 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
050d80ab51 | ||
|
|
49c2b3e7a9 | ||
|
|
5e2ced87f5 | ||
|
|
ba1a12a0f0 | ||
|
|
983964c432 | ||
|
|
4949158eff | ||
|
|
c68c1029a4 | ||
|
|
dd2a9e9bcc | ||
|
|
71289926c0 | ||
|
|
85a9cc08ec | ||
|
|
589105c84c | ||
|
|
ac6b8c9402 | ||
|
|
b28ff3f8d6 |
@@ -1,22 +1,17 @@
|
||||
# ⚡️ What is FastEmbed?
|
||||
|
||||
FastEmbed is an easy to use -- lightweight, fast, Python library built for retrieval embedding generation.
|
||||
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 embedding supports "query" and "passage" prefixes for the input text. The default model is Flag Embedding, which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval%20with%20FastEmbed/)
|
||||
The default embedding supports "query" and "passage" prefixes for the input text. The default model is Flag Embedding, which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval%20with%20FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/examples/Usage_With_Qdrant/).
|
||||
|
||||
1. Light
|
||||
1. Light & Fast
|
||||
- Quantized model weights
|
||||
- ONNX Runtime for inference
|
||||
- No hidden dependencies on PyTorch or TensorFlow via Huggingface Transformers
|
||||
- ONNX Runtime for inference via [Optimum](github.com/huggingface/optimum)
|
||||
|
||||
2. Accuracy/Recall
|
||||
- Better than OpenAI Ada-002
|
||||
- Default is Flag Embedding, which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard
|
||||
|
||||
3. Fast
|
||||
- About 2x faster than Huggingface (PyTorch) transformers on single queries
|
||||
- Lot faster for batches!
|
||||
- ONNX Runtime allows you to use dedicated runtimes for even higher throughput and lower latency
|
||||
- List of [supported models](https://qdrant.github.io/fastembed/examples/Supported_Models/) - including multilingual models
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
@@ -35,27 +30,50 @@ documents: List[str] = [
|
||||
"passage: Hello, World!",
|
||||
"query: Hello, World!", # these are two different embedding
|
||||
"passage: This is an example passage.",
|
||||
# You can leave out the prefix but it's recommended
|
||||
"fastembed is supported by and maintained by Qdrant."
|
||||
"fastembed is supported by and maintained by Qdrant." # You can leave out the prefix but it's recommended
|
||||
]
|
||||
embedding_model = Embedding(model_name="BAAI/bge-base-en", max_length=512)
|
||||
embeddings: List[np.ndarray] = list(embedding_model.embed(documents))
|
||||
embeddings: List[np.ndarray] = embedding_model.embed(documents) # If you use
|
||||
```
|
||||
|
||||
### Why fast?
|
||||
## Usage with Qdrant
|
||||
|
||||
It's important we justify the "fast" in FastEmbed. FastEmbed is fast because:
|
||||
Installation with Qdrant Client in Python:
|
||||
|
||||
1. Quantized model weights
|
||||
2. ONNX Runtime which allows for fast inference on CPU and other dedicated runtimes
|
||||
```bash
|
||||
pip install qdrant-client[fastembed]
|
||||
```
|
||||
|
||||
### Why light?
|
||||
1. No hidden dependencies on PyTorch or TensorFlow via Huggingface Transformers
|
||||
2. We do use the tokenizer from Huggingface Transformers, but it's a light dependency
|
||||
Might have to use ```pip install 'qdrant-client[fastembed]'``` on zsh.
|
||||
|
||||
### Why accurate?
|
||||
1. Better than OpenAI Ada-002
|
||||
2. Top of the Embedding leaderboards e.g. [MTEB](https://huggingface.co/spaces/mteb/leaderboard)
|
||||
```python
|
||||
from qdrant_client import QdrantClient
|
||||
|
||||
# Initialize the client
|
||||
client = QdrantClient(":memory:") # or QdrantClient(path="path/to/db")
|
||||
|
||||
# Prepare your documents, metadata, and IDs
|
||||
docs = ["Qdrant has Langchain integrations", "Qdrant also has Llama Index integrations"]
|
||||
metadata = [
|
||||
{"source": "Langchain-docs"},
|
||||
{"source": "Linkedin-docs"},
|
||||
]
|
||||
ids = [42, 2]
|
||||
|
||||
# Use the new add method
|
||||
client.add(
|
||||
collection_name="demo_collection",
|
||||
documents=docs,
|
||||
metadata=metadata,
|
||||
ids=ids
|
||||
)
|
||||
|
||||
search_result = client.query(
|
||||
collection_name="demo_collection",
|
||||
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.
|
||||
+44
-18
@@ -16,12 +16,12 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"id": "ada95c6a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install fastembed --upgrade # Install fastembed"
|
||||
"!pip install fastembed --upgrade --quiet # Install fastembed "
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -34,10 +34,25 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 2,
|
||||
"id": "b61c6552",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"torch.Size([384])\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from typing import List\n",
|
||||
"import numpy as np\n",
|
||||
@@ -51,10 +66,7 @@
|
||||
"]\n",
|
||||
"# Initialize the DefaultEmbedding class with the desired parameters\n",
|
||||
"embedding_model = DefaultEmbedding(model_name=\"BAAI/bge-small-en\", max_length=512)\n",
|
||||
"embeddings: List[np.ndarray] = list(\n",
|
||||
" embedding_model.embed(documents)\n",
|
||||
") # notice that we are casting the generator to a list\n",
|
||||
"\n",
|
||||
"embeddings: List[np.ndarray] = embedding_model.embed(documents)\n",
|
||||
"print(embeddings[0].shape)"
|
||||
]
|
||||
},
|
||||
@@ -78,7 +90,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 3,
|
||||
"id": "c0a6f634",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -107,7 +119,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 4,
|
||||
"id": "145a56ce",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -139,7 +151,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 5,
|
||||
"id": "272c8915",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -159,14 +171,20 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 6,
|
||||
"id": "8013eee9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embeddings: List[np.ndarray] = list(\n",
|
||||
" embedding_model.embed(documents)\n",
|
||||
") # notice that we are casting the generator to a list"
|
||||
"embeddings: List[np.ndarray] = embedding_model.embed(documents)"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -179,10 +197,18 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 7,
|
||||
"id": "0d8c8e08",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"torch.Size([384])\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(embeddings[0].shape) # (384,) or similar output"
|
||||
]
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>model</th>\n",
|
||||
" <th>dim</th>\n",
|
||||
" <th>description</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>BAAI/bge-small-en</td>\n",
|
||||
" <td>384</td>\n",
|
||||
" <td>Fast and Default English model</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>BAAI/bge-base-en</td>\n",
|
||||
" <td>768</td>\n",
|
||||
" <td>Base English model</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>sentence-transformers/all-MiniLM-L6-v2</td>\n",
|
||||
" <td>384</td>\n",
|
||||
" <td>Sentence Transformer model, MiniLM-L6-v2</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>intfloat/multilingual-e5-large</td>\n",
|
||||
" <td>1024</td>\n",
|
||||
" <td>Multilingual model, e5-large. Recommend using this model for non-English languages. Recommend using this via Torch implementation of FastEmbed</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" model dim \\\n",
|
||||
"0 BAAI/bge-small-en 384 \n",
|
||||
"1 BAAI/bge-base-en 768 \n",
|
||||
"2 sentence-transformers/all-MiniLM-L6-v2 384 \n",
|
||||
"3 intfloat/multilingual-e5-large 1024 \n",
|
||||
"\n",
|
||||
" description \n",
|
||||
"0 Fast and Default English model \n",
|
||||
"1 Base English model \n",
|
||||
"2 Sentence Transformer model, MiniLM-L6-v2 \n",
|
||||
"3 Multilingual model, e5-large. Recommend using this model for non-English languages. Recommend using this via Torch implementation of FastEmbed "
|
||||
]
|
||||
},
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%load_ext autoreload\n",
|
||||
"%autoreload 2\n",
|
||||
"\n",
|
||||
"from fastembed.embedding import Embedding\n",
|
||||
"import pandas as pd\n",
|
||||
"pd.set_option('display.max_colwidth', None)\n",
|
||||
"pd.DataFrame(Embedding.list_supported_models())"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "fst",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.17"
|
||||
},
|
||||
"orig_nbformat": 4
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -5,9 +5,7 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# [Experimental] Usage With Qdrant\n",
|
||||
"\n",
|
||||
"> **Note:** This notebook is experimental and is subject to change. For working with this, use the dev branch of QdrantClient.\n",
|
||||
"# Usage With Qdrant\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use FastEmbed and Qdrant to perform vector search and retrieval. Qdrant is an open-source vector similarity search engine that is used to store, organize, and query collections of high-dimensional vectors. \n",
|
||||
"\n",
|
||||
@@ -28,13 +26,20 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\u001b[33mDEPRECATION: pytorch-lightning 1.6.5 has a non-standard dependency specifier torch>=1.8.*. pip 23.3 will enforce this behaviour change. A possible replacement is to upgrade to a newer version of pytorch-lightning or contact the author to suggest that they release a version with a conforming dependency specifiers. Discussion can be found at https://github.com/pypa/pip/issues/12063\u001b[0m\u001b[33m\n",
|
||||
"\u001b[0m"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# !pip install fastembed --quiet --upgrade\n",
|
||||
"\n",
|
||||
"# !pip install git+https://github.com/qdrant/qdrant_client.git@dev"
|
||||
"!pip install 'qdrant-client[fastembed]' --quiet --upgrade"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -46,7 +51,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -68,7 +73,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -105,25 +110,32 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Asking to truncate to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no truncation.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['901ff9d7a90a4e56afe655d1de8e7c06',\n",
|
||||
" '7bae5aa894164398a9be68d47d72ff7a',\n",
|
||||
" 'd940bba124e24469ae3166c3110c62f8',\n",
|
||||
" 'c8dcf956a4f444c6bfe69a00cbeb85ce',\n",
|
||||
" 'd2aeb24c51f549c5b21851be05cb4048',\n",
|
||||
" '6d4c672bafef4db68ae72c8986ee8a72',\n",
|
||||
" 'ff198613768a4361a6d8230b40ee7f78',\n",
|
||||
" 'a133ad72876b48d48e716533c2d78cf0',\n",
|
||||
" 'bdf2b016136e4f57b7ac4b65534031b8',\n",
|
||||
" '5f4f279f304c47839e1a74b0f28de136']"
|
||||
"['77e1e4724dd243b08608f57d5692f6aa',\n",
|
||||
" '74841e5dc3594646bda2c6a6d2795dbd',\n",
|
||||
" '6ef39a9445604d0da84d04f760cd7cf7',\n",
|
||||
" 'e659503d3b3748ef90f23c778274835b',\n",
|
||||
" 'b999675068cd413f93faa0cc890c3819',\n",
|
||||
" '8e452f2935cf4e4b80d8eea68c2aad58',\n",
|
||||
" '28ed4fd4592c48c9a0519618d51bb86e',\n",
|
||||
" '59378c784c5f49109bef65fdc4061334',\n",
|
||||
" 'a78c9b598f7942749156334283a6f24f',\n",
|
||||
" 'f72bb24701c64fabb0182c9e757b581b']"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -150,38 +162,57 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[42, 2]"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Prepare your documents, metadata, and IDs\n",
|
||||
"docs = [\"Qdrant has Langchain integrations\", \"Qdrant also has Llama Index integrations\"]\n",
|
||||
"metadata = [\n",
|
||||
" {\"source\": \"Langchain-docs\"},\n",
|
||||
" {\"source\": \"Linkedin-docs\"},\n",
|
||||
"]\n",
|
||||
"ids = [42, 2]\n",
|
||||
"\n",
|
||||
"# Use the new add method\n",
|
||||
"client.add(\n",
|
||||
" collection_name=\"demo_collection\",\n",
|
||||
" documents=docs,\n",
|
||||
" metadata=metadata,\n",
|
||||
" ids=ids\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Top 5 results:\n",
|
||||
"Rank 1: Maharana Pratap was a Rajput warrior king from Mewar. Score: 0.77\n",
|
||||
"Rank 2: Maharana Pratap is considered a symbol of Rajput resistance against foreign rule. Score: 0.77\n",
|
||||
"Rank 3: His legacy is celebrated in Rajasthan through festivals and monuments. Score: 0.69\n",
|
||||
"Rank 4: He had 11 wives and 17 sons, including Amar Singh I who succeeded him as ruler of Mewar. Score: 0.68\n",
|
||||
"Rank 5: He fought against the Mughal Empire led by Akbar. Score: 0.67\n"
|
||||
"[QueryResponse(id='42', embedding=None, metadata={'document': 'Qdrant has Langchain integrations', 'source': 'Langchain-docs'}, document='Qdrant has Langchain integrations', score=0.8496814051311954), QueryResponse(id='2', embedding=None, metadata={'document': 'Qdrant also has Llama Index integrations', 'source': 'Linkedin-docs'}, document='Qdrant also has Llama Index integrations', score=0.8478494193031256)]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from qdrant_client.qdrant_fastembed import QueryResponse\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_top_k_results(results: List[QueryResponse], k: int = 5):\n",
|
||||
" print(f\"Top {k} results:\")\n",
|
||||
" for i, result in enumerate(results[:k]):\n",
|
||||
" print(f\"Rank {i + 1}: {result.document}. Score: {result.score:.2f}\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"query_text = \"Who is Maharana Pratap?\"\n",
|
||||
"results = client.query(\n",
|
||||
" collection_name=\"test_collection\", query_text=query_text, limit=7\n",
|
||||
") # Returns limit most relevant documents\n",
|
||||
"\n",
|
||||
"print_top_k_results(results)"
|
||||
"search_result = client.query(\n",
|
||||
" collection_name=\"demo_collection\",\n",
|
||||
" query_text=[\"This is a query document\"]\n",
|
||||
")\n",
|
||||
"print(search_result)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+49
-18
@@ -1,10 +1,19 @@
|
||||
# ⚡️ What is FastEmbed?
|
||||
|
||||
FastEmbed is an easy to use -- lightweight, fast, Python library built for retrieval embedding generation.
|
||||
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 embedding supports "query" and "passage" prefixes for the input text. The default model is [Flag Embedding](https://github.com/FlagOpen/FlagEmbedding), which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard.
|
||||
The default embedding supports "query" and "passage" prefixes for the input text. The default model is Flag Embedding, which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard. Here is an example for [Retrieval Embedding Generation](https://qdrant.github.io/fastembed/examples/Retrieval%20with%20FastEmbed/) and how to use [FastEmbed with Qdrant](https://qdrant.github.io/fastembed/examples/Usage_With_Qdrant/).
|
||||
|
||||
Advanced user? Skip ahead to [Retrieval with FastEmbed](https://qdrant.github.io/fastembed/examples/Retrieval_with_FastEmbed/)
|
||||
1. Light & Fast
|
||||
- Quantized model weights
|
||||
- ONNX Runtime for inference via [Optimum](github.com/huggingface/optimum)
|
||||
|
||||
2. Accuracy/Recall
|
||||
- Better than OpenAI Ada-002
|
||||
- Default is Flag Embedding, which is top of the [MTEB](https://huggingface.co/spaces/mteb/leaderboard) leaderboard
|
||||
- List of [supported models](https://qdrant.github.io/fastembed/examples/Supported_Models/) - including multilingual models
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
To install the FastEmbed library, pip works:
|
||||
|
||||
@@ -15,31 +24,53 @@ pip install fastembed
|
||||
## 📖 Usage
|
||||
|
||||
```python
|
||||
from fastembed.embedding import DefaultEmbedding
|
||||
from fastembed.embedding import FlagEmbedding as Embedding
|
||||
|
||||
documents: List[str] = [
|
||||
"passage: Hello, World!",
|
||||
"query: Hello, World!", # these are two different embedding
|
||||
"passage: This is an example passage.",
|
||||
# You can leave out the prefix but it's recommended
|
||||
"fastembed is supported by and maintained by Qdrant."
|
||||
"fastembed is supported by and maintained by Qdrant." # You can leave out the prefix but it's recommended
|
||||
]
|
||||
embedding_model = DefaultEmbedding()
|
||||
embeddings: List[np.ndarray] = list(embedding_model.embed(documents))
|
||||
embedding_model = Embedding(model_name="BAAI/bge-base-en", max_length=512)
|
||||
embeddings: List[np.ndarray] = embedding_model.embed(documents) # If you use
|
||||
```
|
||||
|
||||
## 🚒 Under the hood
|
||||
## Usage with Qdrant
|
||||
|
||||
### Why fast?
|
||||
Installation with Qdrant Client in Python:
|
||||
|
||||
It's important we justify the "fast" in FastEmbed. FastEmbed is fast because:
|
||||
```bash
|
||||
pip install qdrant-client[fastembed]
|
||||
```
|
||||
|
||||
1. Quantized model weights
|
||||
2. ONNX Runtime which allows for inference on CPU, GPU, and other dedicated runtimes
|
||||
Might have to use ```pip install 'qdrant-client[fastembed]'``` on zsh.
|
||||
|
||||
### Why light?
|
||||
1. No hidden dependencies on PyTorch or TensorFlow via Huggingface Transformers
|
||||
```python
|
||||
from qdrant_client import QdrantClient
|
||||
|
||||
### Why accurate?
|
||||
1. Better than OpenAI Ada-002
|
||||
2. Top of the Embedding leaderboards e.g. [MTEB](https://huggingface.co/spaces/mteb/leaderboard)
|
||||
# Initialize the client
|
||||
client = QdrantClient(":memory:") # or QdrantClient(path="path/to/db")
|
||||
|
||||
# Prepare your documents, metadata, and IDs
|
||||
docs = ["Qdrant has Langchain integrations", "Qdrant also has Llama Index integrations"]
|
||||
metadata = [
|
||||
{"source": "Langchain-docs"},
|
||||
{"source": "Linkedin-docs"},
|
||||
]
|
||||
ids = [42, 2]
|
||||
|
||||
# Use the new add method
|
||||
client.add(
|
||||
collection_name="demo_collection",
|
||||
documents=docs,
|
||||
metadata=metadata,
|
||||
ids=ids
|
||||
)
|
||||
|
||||
search_result = client.query(
|
||||
collection_name="demo_collection",
|
||||
query_text="This is a query document"
|
||||
)
|
||||
print(search_result)
|
||||
```
|
||||
+32
-1
@@ -3,7 +3,7 @@ import shutil
|
||||
import tarfile
|
||||
from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import Iterable, List
|
||||
from typing import Dict, Iterable, List, Union
|
||||
|
||||
import numpy as np
|
||||
import requests
|
||||
@@ -43,6 +43,35 @@ class Embedding(ABC):
|
||||
def embed(self, texts: List[str]) -> List[np.ndarray]:
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def list_supported_models(cls) -> List[Dict[str, Union[str, int]]]:
|
||||
"""
|
||||
Lists the supported models.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
"model": "BAAI/bge-small-en",
|
||||
"dim": 384,
|
||||
"description": "Fast and Default English model",
|
||||
},
|
||||
{
|
||||
"model": "BAAI/bge-base-en",
|
||||
"dim": 768,
|
||||
"description": "Base English model",
|
||||
},
|
||||
{
|
||||
"model": "sentence-transformers/all-MiniLM-L6-v2",
|
||||
"dim": 384,
|
||||
"description": "Sentence Transformer model, MiniLM-L6-v2",
|
||||
},
|
||||
{
|
||||
"model": "intfloat/multilingual-e5-large",
|
||||
"dim": 1024,
|
||||
"description": "Multilingual model, e5-large. Recommend using this model for non-English languages. Recommend using this via Torch implementation of FastEmbed",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@classmethod
|
||||
def download_file_from_gcs(cls, url: str, output_path: str, show_progress: bool = True) -> str:
|
||||
"""
|
||||
@@ -267,6 +296,8 @@ class FlagEmbedding(Embedding):
|
||||
Returns:
|
||||
List of embeddings, one per document
|
||||
"""
|
||||
if type(documents) == str:
|
||||
documents = [documents]
|
||||
# TODO: Replace loop with parallelized batching
|
||||
if len(documents) >= batch_size:
|
||||
for i in range(0, len(documents), batch_size):
|
||||
|
||||
Generated
+1
-22
@@ -2404,27 +2404,6 @@ packaging = "*"
|
||||
protobuf = "*"
|
||||
sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "onnxruntime-silicon"
|
||||
version = "1.15.0"
|
||||
description = "ONNX Runtime is a runtime accelerator for Machine Learning models"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "onnxruntime_silicon-1.15.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:2ed1fbbe320c8f409d7e72d15c92688da4f947e32e3365893669a2d706666a83"},
|
||||
{file = "onnxruntime_silicon-1.15.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f5c2f9398bb21a6f283b19e96dcfb026c7efb922f3481bfc485f63b67b38ad7b"},
|
||||
{file = "onnxruntime_silicon-1.15.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:0c86a45dc6a5555e3d313cc6e36e3996ec5bd7e816dd0b0177304028e327af85"},
|
||||
{file = "onnxruntime_silicon-1.15.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:3324fa722773447367657b341bc745d0b9e009d501c37504291e9c72bdc3e2a1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
coloredlogs = "*"
|
||||
flatbuffers = "*"
|
||||
numpy = ">=1.22.3"
|
||||
packaging = "*"
|
||||
protobuf = "*"
|
||||
sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "optimum"
|
||||
version = "1.13.2"
|
||||
@@ -4406,4 +4385,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.8.0,<3.12"
|
||||
content-hash = "c2a571c144c399a2f3fc8ebd46e94dbe369c4a1aef56bffc50dbe8c21e0afdfc"
|
||||
content-hash = "e5ffd32f781e2e269cf07d1e53bbb7e8dd685668e877eccbbc1dc9c37bcd0be8"
|
||||
|
||||
+2
-6
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "fastembed"
|
||||
version = "0.0.4"
|
||||
version = "0.0.5a1"
|
||||
description = "Fast, light, accurate library built for retrieval embedding generation"
|
||||
authors = ["NirantK <nirant.bits@gmail.com>"]
|
||||
license = "Apache License"
|
||||
@@ -12,6 +12,7 @@ keywords = ["vector", "embedding", "neural", "search", "qdrant", "sentence-trans
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.8.0,<3.12"
|
||||
onnx = "^1.11.0"
|
||||
onnxruntime = "^1.15.1"
|
||||
torch = ">=2.0.0, !=2.0.1"
|
||||
optimum = ">1.12.0"
|
||||
@@ -23,7 +24,6 @@ tokenizers = "^0.13.3"
|
||||
ruff = "^0.0.277"
|
||||
isort = "^5.12.0"
|
||||
black = "^23.7.0"
|
||||
onnx = "^1.11.0"
|
||||
notebook = ">=7.0.2"
|
||||
mkdocs-material = "^9.1.21"
|
||||
mkdocstrings = "^0.22.0"
|
||||
@@ -32,10 +32,6 @@ cairosvg = "^2.7.1"
|
||||
mknotebooks = "^0.8.0"
|
||||
pytest = "^7.4.0"
|
||||
|
||||
[tool.poetry.dependencies.onnxruntime-silicon]
|
||||
version = "^1.15.0"
|
||||
markers = "sys_platform == 'darwin'" # This makes it macOS specific
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
Reference in New Issue
Block a user