mirror of
https://github.com/qdrant/fastembed.git
synced 2026-08-06 18:11:01 -05:00
308 lines
43 KiB
Plaintext
308 lines
43 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# 🤗 Huggingface vs ⚡ FastEmbed️\n",
|
||
"\n",
|
||
"Comparing the performance of Huggingface's 🤗 Transformers and ⚡ FastEmbed️ on a simple task on the following machine: Apple M2 Max, 32 GB RAM\n",
|
||
"\n",
|
||
"## 📦 Imports\n",
|
||
"\n",
|
||
"Importing the necessary libraries for this comparison."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import time\n",
|
||
"from pathlib import Path\n",
|
||
"from typing import Any, Callable, List, Tuple\n",
|
||
"\n",
|
||
"import numpy as np\n",
|
||
"import torch.nn.functional as F\n",
|
||
"from fastembed.embedding import DefaultEmbedding\n",
|
||
"from torch import Tensor\n",
|
||
"from transformers import AutoModel, AutoTokenizer"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 📖 Data\n",
|
||
"\n",
|
||
"data is a list of strings, each string is a document."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"12"
|
||
]
|
||
},
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"documents: List[str] = [\n",
|
||
" \"Chandrayaan-3 is India's third lunar mission\",\n",
|
||
" \"It aimed to land a rover on the Moon's surface - joining the US, China and Russia\",\n",
|
||
" \"The mission is a follow-up to Chandrayaan-2, which had partial success\",\n",
|
||
" \"Chandrayaan-3 will be launched by the Indian Space Research Organisation (ISRO)\",\n",
|
||
" \"The estimated cost of the mission is around $35 million\",\n",
|
||
" \"It will carry instruments to study the lunar surface and atmosphere\",\n",
|
||
" \"Chandrayaan-3 landed on the Moon's surface on 23rd August 2023\",\n",
|
||
" \"It consists of a lander named Vikram and a rover named Pragyan similar to Chandrayaan-2. Its propulsion module would act like an orbiter.\",\n",
|
||
" \"The propulsion module carries the lander and rover configuration until the spacecraft is in a 100-kilometre (62 mi) lunar orbit\",\n",
|
||
" \"The mission used GSLV Mk III rocket for its launch\",\n",
|
||
" \"Chandrayaan-3 was launched from the Satish Dhawan Space Centre in Sriharikota\",\n",
|
||
" \"Chandrayaan-3 was launched earlier in the year 2023\",\n",
|
||
"]\n",
|
||
"len(documents)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Setting up 🤗 Huggingface\n",
|
||
"\n",
|
||
"We'll be using the [Huggingface Transformers](https://huggingface.co/transformers/) with PyTorch library to generate embeddings. We'll be using the same model across both libraries for a fair(er?) comparison."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"torch.Size([12, 384])"
|
||
]
|
||
},
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"class HF:\n",
|
||
" \"\"\"\n",
|
||
" HuggingFace Transformer implementation of FlagEmbedding\n",
|
||
" Based on https://huggingface.co/BAAI/bge-base-en\n",
|
||
" \"\"\"\n",
|
||
"\n",
|
||
" def __init__(self, model_id: str):\n",
|
||
" self.model = AutoModel.from_pretrained(model_id)\n",
|
||
" self.tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
|
||
"\n",
|
||
" def embed(self, texts: List[str]):\n",
|
||
" encoded_input = self.tokenizer(texts, max_length=512, padding=True, truncation=True, return_tensors=\"pt\")\n",
|
||
" model_output = self.model(**encoded_input)\n",
|
||
" sentence_embeddings = model_output[0][:, 0]\n",
|
||
" sentence_embeddings = F.normalize(sentence_embeddings)\n",
|
||
" return sentence_embeddings\n",
|
||
"\n",
|
||
"hf = HF(model_id=\"BAAI/bge-small-en\")\n",
|
||
"hf.embed(documents).shape"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Setting up ⚡️FastEmbed\n",
|
||
"\n",
|
||
"Sorry, don't have a lot to set up here. We'll be using the default model, which is Flag Embedding, same as the Huggingface model."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"embedding_model = DefaultEmbedding()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 📊 Comparison\n",
|
||
"\n",
|
||
"We'll be comparing the following metrics: Minimum, Maximum, Mean, across k runs. Let's write a function to do that:\n",
|
||
"\n",
|
||
"### 🚀 Calculating Stats"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def calculate_time_stats(embed_func: Callable, documents: list, k: int) -> Tuple[float, float, float]:\n",
|
||
" times = []\n",
|
||
" for _ in range(k):\n",
|
||
" # Timing the embed_func call\n",
|
||
" start_time = time.time()\n",
|
||
" embeddings = embed_func(documents)\n",
|
||
" end_time = time.time()\n",
|
||
"\n",
|
||
" times.append(end_time - start_time)\n",
|
||
"\n",
|
||
" # Returning mean, max, and min time for the call\n",
|
||
" return (sum(times) / k, max(times), min(times))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Huggingface Transformers (Average, Max, Min): (0.06096994876861572, 0.06110382080078125, 0.060836076736450195)\n",
|
||
"FastEmbed (Average, Max, Min): (0.6889046430587769, 0.6905872821807861, 0.6872220039367676)\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"hf_stats = calculate_time_stats(hf.embed, documents, k=2)\n",
|
||
"print(f\"Huggingface Transformers (Average, Max, Min): {hf_stats}\")\n",
|
||
"fst_stats = calculate_time_stats(lambda x: list(embedding_model.embed(x)), documents, k=2)\n",
|
||
"print(f\"FastEmbed (Average, Max, Min): {fst_stats}\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 📈 Results\n",
|
||
"\n",
|
||
"Let's run the comparison and see the results."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
|
||
"To disable this warning, you can either:\n",
|
||
"\t- Avoid using `tokenizers` before the fork if possible\n",
|
||
"\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"!pip install matplotlib --quiet"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import matplotlib.pyplot as plt"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"image/png": "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jY2NFPPsdgpjCrdDREREpHXRtGnTJjRp0qRIe+PGjbFx40at+kpPT0dcXBzi4uIAPB38HRcXh1u3bkGhUGD06NH46quvsG3bNpw9exZ9+/aFs7OzdIedt7c32rVrh8GDB+PYsWM4dOgQQkJC0LNnTzg7OwMAevfuDWNjYwQHB+P8+fNYt24dFi5cKLu0NmrUKISHh2PevHm4dOkSpk+fjhMnTiAkJETbw0NERERvKa0vzz169AgqlapIu1KpxMOHD7Xq68SJE2jVqpX0vLCQ6devH1atWoWJEyciIyMDQ4YMQWpqKpo2bYrw8HCYmppK66xZswYhISFo06YNDAwM0L17d9mZMJVKhb1792L48OGoV68eypcvj9DQUNlcTo0bN8batWvx+eef43//+x+qVKmCrVu3okaNGlrtDxEREb29tJ6nqUaNGvj000+LnIVZvHgxli5digsXLug0wTcF52kiKjucp4mIXpU2v7+1PtM0duxYhISE4MGDB2jdujUAIDIyEvPmzcOCBQteKWEiIiIifad10TRw4EBkZ2dj5syZ+PLLLwEA7u7uWLp0Kfr27avzBImIiIj0wStNOTB06FAMHToUDx48gJmZGSwtLXWdFxEREZFe0fruOeDpXEj79u3D5s2bUTgk6t69e0hPT9dpckRERET6QuszTTdv3kS7du1w69YtZGdno23btrCyssKsWbOQnZ2t8RfcEhEREb1JtD7TNGrUKNSvXx8pKSkwMzOT2rt27VpkgkgiIiKit4XWZ5oOHjyIw4cPw9jYWNbu7u6Ou3fv6iwxIiIiIn2i9ZmmgoIC5OfnF2m/c+cOrKysdJIUERERkb7RumgKCAiQzcekUCiQnp6OadOmoUOHDrrMjYiIiEhvaH15bt68eQgMDISPjw+ysrLQu3dvXLlyBeXLl8fvv/9eGjkSERERlTmtiyYXFxecPn0a69atw+nTp5Geno7g4GAEBQXJBoYTERERvU1eaXJLIyMjBAUFISgoSNf5EBEREekljcc0Xb58GceOHZO1RUZGolWrVmjQoAG+/vprnSdHREREpC80LpomTZqEHTt2SM+vX7+Ozp07w9jYGH5+fggLC+MX9hIREdFbS+PLcydOnMDEiROl52vWrEHVqlWxZ88eAEDNmjWxePFijB49WudJEhEREZU1jc80PXz4EC4uLtLz/fv3o3Pn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FknLVSoV9u7di+HDh6NevXooX748QkNDOUcTERERSV55niaS45kmorLDM01E9KpKdZ4mIiIiov8iFk1EREREGmDRRERERKQBFk1EREREGnjtokmtVmPr1q3Sl/cSERERvY20Lpp69OiB7777DgDw5MkT1K9fHz169EDNmjWxadMmnSdIREREpA+0Lpqio6PRrFkzAMCWLVsghEBqaioWLVqEr776SucJEhEREekDrYumtLQ02NraAgDCw8PRvXt3mJubo2PHjrhy5YrOEyQiIiLSB1oXTa6uroiJiUFGRgbCw8MREBAAAEhJSZHNwk1ERET0NtH6a1RGjx6NoKAgWFpaws3NDS1btgTw9LKdr6+vrvMjIiIi0gtaF03Dhg1Dw4YNcevWLbRt2xYGBk9PVr3zzjsc00RERERvLa0uz+Xm5sLT0xPm5ubo2rUrLC0tpWUdO3ZEkyZNdJ4gERERkT7QqmgqV64csrKySisXIiIiIr2l9UDw4cOHY9asWcjLyyuNfIiIiIj0ktZjmo4fP47IyEjs3bsXvr6+sLCwkC3fvHmzzpIjIiIi0hdaF03W1tbo3r17aeRCREREpLe0LppWrlxZGnkQERER6bVX+sLevLw87Nu3D8uXL8fjx48BAPfu3UN6erpOkyMiIiLSF1qfabp58ybatWuHW7duITs7G23btoWVlRVmzZqF7OxsLFu2rDTyJCIiIipTWp9pGjVqFOrXr4+UlBSYmZlJ7V27dkVkZKROkyMiIiLSF1qfaTp48CAOHz4MY2NjWbu7uzvu3r2rs8SIiIiI9InWZ5oKCgqQn59fpP3OnTuwsrLSSVJERERE+kbroikgIAALFiyQnisUCqSnp2PatGno0KGDLnMjIiIi0htaX56bN28eAgMD4ePjg6ysLPTu3RtXrlxB+fLl8fvvv5dGjkRERERlTuuiycXFBadPn8a6detw+vRppKenIzg4GEFBQbKB4URERERvE62LpujoaDRu3BhBQUEICgqS2vPy8hAdHY3mzZvrNEEiIiIifaD1mKZWrVohOTm5SHtaWhpatWqlk6SIiIiI9I3WRZMQAgqFokj7o0ePinx5LxEREdHbQuPLc926dQPw9G65/v37w8TERFqWn5+PM2fOoHHjxrrPkIiIiEgPaFw0qVQqAE/PNFlZWckGfRsbG6NRo0YYPHiw7jMkIiIi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",
|
||
"text/plain": [
|
||
"<Figure size 640x480 with 1 Axes>"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"def plot_character_per_second_comparison(\n",
|
||
" hf_stats: Tuple[float, float, float], fst_stats: Tuple[float, float, float], documents: list\n",
|
||
"):\n",
|
||
" # Calculating total characters in documents\n",
|
||
" total_characters = sum(len(doc) for doc in documents)\n",
|
||
"\n",
|
||
" # Calculating characters per second for each model\n",
|
||
" hf_chars_per_sec = total_characters / hf_stats[0] # Mean time is at index 0\n",
|
||
" fst_chars_per_sec = total_characters / fst_stats[0]\n",
|
||
"\n",
|
||
" # Plotting the bar chart\n",
|
||
" models = [\"HF Embed (Torch)\", \"FastEmbed\"]\n",
|
||
" chars_per_sec = [hf_chars_per_sec, fst_chars_per_sec]\n",
|
||
"\n",
|
||
" bars = plt.bar(models, chars_per_sec, color=[\"#1f356c\", \"#dd1f4b\"])\n",
|
||
" plt.ylabel(\"Characters per Second\")\n",
|
||
" plt.title(\"Characters Processed per Second Comparison\")\n",
|
||
"\n",
|
||
" # Adding the number at the top of each bar\n",
|
||
" for bar, chars in zip(bars, chars_per_sec):\n",
|
||
" plt.text(\n",
|
||
" bar.get_x() + bar.get_width() / 2,\n",
|
||
" bar.get_height(),\n",
|
||
" f\"{chars:.1f}\",\n",
|
||
" ha=\"center\",\n",
|
||
" va=\"bottom\",\n",
|
||
" color=\"#1f356c\",\n",
|
||
" fontsize=12,\n",
|
||
" )\n",
|
||
"\n",
|
||
" plt.show()\n",
|
||
"\n",
|
||
"\n",
|
||
"plot_character_per_second_comparison(hf_stats, fst_stats, documents)"
|
||
]
|
||
}
|
||
],
|
||
"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
|
||
}
|