Compare commits

...
Author SHA1 Message Date
Nirant Kasliwal 65545829f6 Merge branch 'main' into onnx-pipeline 2024-02-20 13:23:39 +05:30
generall da16752e57 rollback dependency changes 2024-02-05 15:12:32 +01:00
Nirant Kasliwal 683fb1a6df Update poetry install command to exclude dev dependencies 2024-02-05 18:01:09 +05:30
Nirant Kasliwal f22383fcf3 Merge branch 'main' into onnx-pipeline 2024-02-05 17:49:59 +05:30
Nirant Kasliwal 69c00f5a9c chore: Update poetry.lock 2024-02-05 11:03:24 +05:30
Nirant Kasliwal 2be2d8c8fe Merge branch 'main' into onnx-pipeline 2024-02-05 11:01:48 +05:30
Nirant Kasliwal c064af5eb9 Merge branch 'main' into onnx-pipeline 2024-01-30 21:50:01 +05:30
Nirant Kasliwal 79b2c837d3 Update poetry lock to latest versions 2024-01-23 12:52:24 +05:30
Nirant Kasliwal e71073cc20 Merge branch 'main' into onnx-pipeline 2024-01-23 12:51:22 +05:30
Nirant Kasliwal f02bd57570 Merge branch 'main' into onnx-pipeline 2024-01-17 13:01:52 +05:30
Nirant Kasliwal 68fa679422 Update poetry lock 2024-01-17 11:07:39 +05:30
Nirant Kasliwal 5ac9a19cd3 Add pre-commit package to pyproject.toml 2024-01-17 11:06:34 +05:30
Nirant Kasliwal 8407d122e1 Merge branch 'main' into onnx-pipeline 2024-01-17 11:02:39 +05:30
Nirant Kasliwal f087e4bd89 Update typing imports and fix formatting in documentation files 2024-01-17 11:01:30 +05:30
Nirant Kasliwal 559854f76d Update poetry lock 2024-01-17 11:00:34 +05:30
Nirant Kasliwal 3c62ee7283 Update dependencies in pyproject.toml 2024-01-17 10:59:49 +05:30
Nirant Kasliwal e17421634e Update installation instructions in To_ONNX.ipynb 2024-01-15 13:04:30 +05:30
Nirant Kasliwal 126fdb0d31 Update optimum library version to 1.15 2024-01-15 12:51:07 +05:30
Nirant Kasliwal 30fddf688d Add local_cache to .gitignore 2024-01-15 12:34:23 +05:30
Nirant Kasliwal ee96fc7f64 Add jupyter-nbextensions-configurator package 2024-01-15 12:34:18 +05:30
Nirant Kasliwal 38ecb33eff Add new dependencies: optimum, sentence-transformers, python-dotenv 2024-01-15 12:02:46 +05:30
Nirant Kasliwal f3bf86ee4e ONNX Port 2024-01-15 12:02:40 +05:30
Nirant Kasliwal 6fa4331771 Add saved models to .gitignore 2024-01-15 12:02:22 +05:30
3 changed files with 371 additions and 357 deletions
+2
View File
@@ -176,3 +176,5 @@ fooling_around/fast-multilingual-e5-large/sentencepiece.bpe.model
fooling_around/fast-multilingual-e5-large/special_tokens_map.json
fooling_around/fast-multilingual-e5-large/tokenizer_config.json
fooling_around/fast-multilingual-e5-large/tokenizer.json
docs/examples/saved_models/*
docs/examples/local_cache/*
+369
View File
@@ -0,0 +1,369 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "7412714c",
"metadata": {},
"source": [
"# Porting to ONNX\n",
"\n",
"This notebook demonstrates how to port models from Transformers/PyTorch package to ONNX. It is based on the [Optimum](https://github.com/huggingface/optimum) library.\n",
"\n",
"## Installation\n",
"\n",
"We use [poetry](https://python-poetry.org/docs/cli) to manage dependencies. To install the dependencies, run:\n",
"\n",
"```bash\n",
"poetry install\n",
"```\n",
"\n",
"Optimum is not backward compatible, so do not upgrade to the latest version. Instead, use the versions pinned in `pyproject.toml`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "0e9dbcde",
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "c37e1fda-c7f1-46e7-a5d4-19fa05c36ac1",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/homebrew/Caskroom/miniconda/base/envs/fst/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
],
"source": [
"import os\n",
"from pathlib import Path\n",
"from typing import List, Tuple, Any\n",
"\n",
"import numpy as np\n",
"import time\n",
"from torch import Tensor\n",
"from transformers import AutoTokenizer, AutoModel\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv() # take environment variables from .env.\n",
"from optimum.onnxruntime import AutoOptimizationConfig, ORTModelForFeatureExtraction, ORTOptimizer, ORTModel\n",
"from optimum.pipelines import pipeline\n",
"import torch.nn.functional as F"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "b1ecf0b6-db81-4da3-b47f-e31460ccfbf1",
"metadata": {},
"outputs": [],
"source": [
"# Load the tokenizer and PyTorch model from HuggingFace Transformers\n",
"model_id = \"BAAI/bge-small-en-v1.5\"\n",
"\n",
"hf_model = AutoModel.from_pretrained(model_id)\n",
"hf_tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"quantize = True\n",
"if quantize:\n",
" repository_id = f\"Qdrant/{model_id.split('/')[1]}-onnx-Q\"\n",
"else:\n",
" repository_id = f\"Qdrant/{model_id.split('/')[1]}-onnx\"\n",
"\n",
"save_dir = f\"local_cache/{repository_id}\""
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a38f5aed",
"metadata": {},
"outputs": [],
"source": [
"# The input texts can be in any language, not just English.\n",
"# Each input text should start with \"query: \" or \"passage: \", even for non-English texts.\n",
"# For tasks other than retrieval, you can simply use the \"query: \" prefix.\n",
"multilingual_queries = [\n",
" \"query: how much protein should a female eat\",\n",
" \"query: 南瓜的家常做法\",\n",
" \"query: भारत का राष्ट्रीय खेल कौन-सा है?\", # Hindi text\n",
" \"query: భారత్ దేశంలో రాష్ట్రపతి ఎవరు?\", # Telugu text\n",
" \"query: இந்தியாவின் தேசிய கோப்பை எது?\", # Tamil text\n",
" \"query: ಭಾರತದಲ್ಲಿ ರಾಷ್ಟ್ರಪತಿ ಯಾರು?\", # Kannada text\n",
" \"query: ഇന്ത്യയുടെ രാഷ്ട്രീയ ഗാനം എന്താണ്?\", # Malayalam text\n",
"]\n",
"\n",
"english_texts = [\n",
" \"India: Where the Taj Mahal meets spicy curry.\",\n",
" \"Machine Learning: Turning data into knowledge, one algorithm at a time.\",\n",
" \"Python: The language that makes programming a piece of cake.\",\n",
" \"fastembed: Accelerating embeddings for lightning-fast similarity search.\",\n",
" \"Qdrant: The ultimate tool for high-dimensional indexing and search.\",\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9f8c761c",
"metadata": {},
"outputs": [],
"source": [
"def average_pool(last_hidden_states: Tensor, attention_mask: Tensor) -> Tensor:\n",
" last_hidden = last_hidden_states.masked_fill(~attention_mask[..., None].bool(), 0.0)\n",
" return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None]\n",
"\n",
"\n",
"def hf_embed(model_id: str, inputs: List[str]):\n",
" # Tokenize the input texts\n",
" batch_dict = hf_tokenizer(inputs, max_length=512, padding=True, truncation=True, return_tensors=\"pt\")\n",
"\n",
" outputs = hf_model(**batch_dict)\n",
" embeddings = average_pool(outputs.last_hidden_state, batch_dict[\"attention_mask\"])\n",
"\n",
" # normalize embeddings\n",
" embeddings = F.normalize(embeddings, p=2, dim=1)\n",
" return embeddings.detach().numpy()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "69bb4501",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 0.05485763, 0.08136623, -0.00395789, ..., 0.02512371,\n",
" -0.03349504, -0.0593129 ],\n",
" [ 0.01078518, 0.01582215, 0.04614557, ..., -0.01674951,\n",
" -0.00244641, -0.06179965],\n",
" [-0.06607923, -0.01235531, -0.00689854, ..., 0.10634594,\n",
" 0.12025263, -0.05135345],\n",
" [-0.07568254, 0.00908228, -0.02221818, ..., 0.00177038,\n",
" -0.0325426 , 0.05233581],\n",
" [-0.07008213, 0.02070545, 0.02720274, ..., -0.01158645,\n",
" -0.01457597, 0.01262206]], dtype=float32)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"hf_embed(inputs=english_texts, model_id=model_id)"
]
},
{
"cell_type": "markdown",
"id": "bc9d1594",
"metadata": {},
"source": [
"## Load the model using ORTModelForFeatureExtraction"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "451dbd16",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Framework not specified. Using pt to export to ONNX.\n",
"Using the export variant default. Available variants are:\n",
" - default: The default ONNX variant.\n",
"Using framework PyTorch: 2.1.2\n",
"Overriding 1 configuration item(s)\n",
"\t- use_cache -> False\n",
"/opt/homebrew/Caskroom/miniconda/base/envs/fst/lib/python3.11/site-packages/optimum/onnxruntime/configuration.py:770: FutureWarning: disable_embed_layer_norm will be deprecated soon, use disable_embed_layer_norm_fusion instead, disable_embed_layer_norm_fusion is set to True.\n",
" warnings.warn(\n",
"The argument use_external_data_format in the ORTOptimizer.optimize() method is deprecated and will be removed in optimum 2.0.\n",
"Optimizing model...\n",
"There is no gpu for onnxruntime to do optimization.\n",
"Configuration saved in local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/ort_config.json\n",
"Optimized model saved at: local_cache/Qdrant/bge-small-en-v1.5-onnx-Q (external data format: False; saved all tensor to one file: True)\n"
]
},
{
"data": {
"text/plain": [
"('local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/tokenizer_config.json',\n",
" 'local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/special_tokens_map.json',\n",
" 'local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/vocab.txt',\n",
" 'local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/added_tokens.json',\n",
" 'local_cache/Qdrant/bge-small-en-v1.5-onnx-Q/tokenizer.json')"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"model = ORTModelForFeatureExtraction.from_pretrained(model_id, export=True)\n",
"\n",
"# Remove all existing files in the save_dir using Path.unlink()\n",
"save_dir = Path(save_dir)\n",
"save_dir.mkdir(parents=True, exist_ok=True)\n",
"for p in save_dir.iterdir():\n",
" p.unlink()\n",
"\n",
"# Load the optimization configuration detailing the optimization we wish to apply\n",
"optimization_config = AutoOptimizationConfig.O4()\n",
"optimizer = ORTOptimizer.from_pretrained(model)\n",
"\n",
"optimizer.optimize(save_dir=save_dir, optimization_config=optimization_config, use_external_data_format=True)\n",
"model = ORTModelForFeatureExtraction.from_pretrained(save_dir)\n",
"tokenizer.save_pretrained(save_dir)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "3587d3c4",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"model_optimized.onnx: 100%|██████████| 66.5M/66.5M [00:09<00:00, 7.37MB/s]\n"
]
}
],
"source": [
"model.push_to_hub(save_directory=save_dir, repository_id=repository_id, use_auth_token=True)"
]
},
{
"cell_type": "markdown",
"id": "fde9f7a3",
"metadata": {},
"source": [
"## Trying out the model from Huggingface Hub"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "be18d371",
"metadata": {},
"outputs": [],
"source": [
"onnx_model = ORTModelForFeatureExtraction.from_pretrained(repository_id)\n",
"onnx_tokenizer = AutoTokenizer.from_pretrained(repository_id)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "532bd348",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(tensor([[-0.2167, 0.0514, 0.0928, 0.1594, 0.2467, 0.3481, -0.0795, 0.1916,\n",
" 0.2227, -0.1297, 0.2020, -0.1873, 0.2221, 0.3651, 0.2194, -0.0692,\n",
" 0.1239, 0.2137, 0.0195, -0.2582, 0.2084, -0.1736, -0.0366, -0.2664,\n",
" -0.2339, 0.2233, -0.0657, -0.2686, -0.2866, -0.2278, 0.0309, 0.0677,\n",
" 0.2661, 0.1537, -0.0069, -0.3319, -0.3038, 0.2219, 0.3027, -0.2240,\n",
" -0.0523, 0.1749, -0.2705, 0.1487, -0.3244, -0.2069, -0.2114, -0.1821,\n",
" -0.1516, 0.2255, -0.2053, -0.2625, -0.0964, 0.3533, 0.2315, 0.1583,\n",
" 0.2405, -0.1198, -0.2908, 0.0707, 0.1949, 0.2105, -0.1731, 0.2771,\n",
" 0.2203, -0.1494, 0.0959, -0.1590, -0.1761, -0.0311, 0.3467, 0.2385,\n",
" 0.0964, 0.1245, 0.0470, -0.1691, -0.1228, -0.2064, -0.1982, -0.2398,\n",
" 0.0165, 0.0306, -0.1663, -0.0887, -0.1120, -0.2306, 0.1256, -0.2352,\n",
" 0.1686, -0.4168, -0.1018, -0.1619, -0.1757, -0.3001, -0.2155, -0.2885,\n",
" 0.1868, 0.1945, 0.0881, 0.6445, -0.3311, 0.1964, -0.0292, -0.2312,\n",
" -0.0040, -0.2386, -0.2235, -0.2751, -0.1402, -0.1766, 0.2363, -0.4445,\n",
" 0.2357, -0.0622, -0.0413, -0.0783, 0.1433, 0.2122, 0.2078, 0.1495,\n",
" -0.3446, 0.1067, 0.1613, 0.2959, 0.2626, -0.4740, -0.1082, 0.3239,\n",
" -0.1803, 0.0997, -0.2434, 0.2762, -0.2583, 0.3141, 0.0112, 0.1745,\n",
" 0.2053, -0.1768, -0.1194, 0.0859, -0.3041, -0.1982, 0.2145, -0.0532,\n",
" -0.2455, 0.2052, -0.1348, -0.2428, -0.2488, -0.2168, 0.2666, 0.2777,\n",
" -0.1524, -0.2402, 0.0133, 0.2093, 0.2458, -0.1074, -0.2419, -0.2991,\n",
" -0.1752, 0.0802, -0.2866, 0.2294, -0.2542, -0.2342, 0.3443, -0.3247,\n",
" -0.1445, -0.0290, 0.1546, 0.0302, -0.1828, 0.2438, 0.0751, 0.0462,\n",
" -0.1671, -0.3660, -0.0694, -0.0095, 0.1836, -0.1069, 0.0990, 0.2472,\n",
" 0.0868, -0.0425, 0.2824, -0.2537, 0.1205, 0.1889, -0.2124, 0.0136,\n",
" -0.1349, 0.0912, -0.0262, -0.2412, 0.2757, 0.2797, 0.0145, -0.2441,\n",
" 0.2213, -0.0217, -0.1446, 0.2326, 0.0941, 0.1203, -0.1906, -0.1431,\n",
" -0.0583, 0.2193, 0.1849, -0.0185, 0.0284, -0.1525, 0.2094, -0.1811,\n",
" 0.2608, 0.2625, -0.0797, 0.2194, -0.1662, -0.0763, -0.1854, -0.3313,\n",
" -0.1781, -0.1981, 0.1939, -0.2452, -0.2262, -0.0456, -0.1490, 0.2020,\n",
" 0.1871, -0.1022, 0.2299, -0.2127, 0.1315, 0.0536, -0.0557, 0.1494,\n",
" 0.2217, -0.3015, -0.3018, 0.1369, 0.1541, 0.2631, -0.2188, 0.1107,\n",
" -0.1987, 0.2343, 0.0984, -0.2731, -0.1080, -0.0538, -0.2362, -0.2376,\n",
" -0.1168, 0.2176, 0.0687, 0.0626, 0.1006, -0.1661, -0.1415, -0.1248,\n",
" -0.2594, 0.2187, -0.1395, -0.2153, -0.4498, -0.1936, -0.1451, -0.1676,\n",
" 0.2641, -0.1155, -0.0400, 0.2400, -0.3057, -0.0794, -0.2021, 0.0650,\n",
" 0.1192, -0.0939, 0.1083, 0.1714, -0.2247, -0.3154, -0.1720, 0.1512,\n",
" -0.2241, -0.3141, 0.2288, -0.1172, -0.1860, -0.2495, 0.0397, -0.0322,\n",
" 0.2313, 0.2013, 0.0296, 0.2663, 0.0793, 0.2103, -0.1596, 0.2250,\n",
" 0.1019, 0.2159, -0.2309, 0.1712, 0.2584, 0.1692, -0.0331, 0.1986,\n",
" 0.2638, 0.1509, 0.0965, -0.1657, -0.1721, 0.2107, 0.2588, -0.2725,\n",
" 0.1890, -0.0129, 0.0519, -0.1113, 0.2591, 0.2191, -0.2598, 0.2012,\n",
" 0.1182, -0.0599, 0.1190, 0.1726, -0.2416, -0.1674, -0.0343, 0.1782,\n",
" 0.0531, 0.3363, -0.0606, 0.1282, 0.3418, 0.2447, -0.3291, 0.1275,\n",
" -0.0873, 0.0312, -0.2825, -0.1609, -0.1207, -0.3035, -0.2454, 0.2148,\n",
" -0.2081, 0.0118, 0.2411, 0.2439, 0.1598, -0.3169, -0.2042, 0.2784,\n",
" 0.1087, -0.1713, 0.2854, 0.1956, 0.1949, 0.3777, -0.3244, 0.1883,\n",
" 0.0507, -0.1668, -0.0155, 0.0348, 0.1672, -0.1819, -0.1733, -0.1864,\n",
" -0.2057, 0.0486, -0.1979, 0.0774, -0.0145, -0.0991, -0.2121, 0.0822]]),\n",
" 'Qdrant: The ultimate tool for high-dimensional indexing and search.',\n",
" 5,\n",
" 5)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"onnx_quant_embed = pipeline(\"feature-extraction\", model=onnx_model, accelerator=\"ort\", tokenizer=onnx_tokenizer,return_tensors=True)\n",
"embeddings = onnx_quant_embed(inputs=english_texts)\n",
"F.normalize(embeddings[4])[:,0], english_texts[4], len(embeddings), len(english_texts)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
-357
View File
@@ -1,357 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "0e9dbcde",
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c37e1fda-c7f1-46e7-a5d4-19fa05c36ac1",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from typing import List, Tuple, Any\n",
"\n",
"import numpy as np\n",
"import time\n",
"from torch import Tensor\n",
"from transformers import AutoTokenizer, AutoModel\n",
"\n",
"from optimum.onnxruntime import AutoOptimizationConfig, ORTModelForFeatureExtraction, ORTOptimizer\n",
"from optimum.pipelines import pipeline\n",
"import torch.nn.functional as F"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "78a65856",
"metadata": {},
"outputs": [],
"source": [
"# Load the tokenizer and export the model to the ONNX format\n",
"# model_id = \"sentence-transformers/all-MiniLM-L6-v2\"\n",
"# model_id = \"thenlper/gte-base\"\n",
"# model_id = \"intfloat/multilingual-e5-large\"\n",
"model_id = \"BAAI/bge-small-en-v1.5\"\n",
"save_dir = f\"fast-{model_id.split('/')[1]}\"\n",
"print(save_dir)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b1ecf0b6-db81-4da3-b47f-e31460ccfbf1",
"metadata": {},
"outputs": [],
"source": [
"hf_model = AutoModel.from_pretrained(model_id)\n",
"hf_tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"\n",
"# The input texts can be in any language, not just English.\n",
"# Each input text should start with \"query: \" or \"passage: \", even for non-English texts.\n",
"# For tasks other than retrieval, you can simply use the \"query: \" prefix.\n",
"input_texts = [\n",
" \"query: how much protein should a female eat\",\n",
" \"query: 南瓜的家常做法\",\n",
" \"query: भारत का राष्ट्रीय खेल कौन-सा है?\", # Hindi text\n",
" \"query: భారత్ దేశంలో రాష్ట్రపతి ఎవరు?\", # Telugu text\n",
" \"query: இந்தியாவின் தேசிய கோப்பை எது?\", # Tamil text\n",
" \"query: ಭಾರತದಲ್ಲಿ ರಾಷ್ಟ್ರಪತಿ ಯಾರು?\", # Kannada text\n",
" \"query: ഇന്ത്യയുടെ രാഷ്ട്രീയ ഗാനം എന്താണ്?\", # Malayalam text\n",
"]\n",
"\n",
"english_texts = [\n",
" \"India: Where the Taj Mahal meets spicy curry.\",\n",
" \"Machine Learning: Turning data into knowledge, one algorithm at a time.\",\n",
" \"Python: The language that makes programming a piece of cake.\",\n",
" \"fastembed: Accelerating embeddings for lightning-fast similarity search.\",\n",
" \"Qdrant: The ultimate tool for high-dimensional indexing and search.\",\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9f8c761c",
"metadata": {},
"outputs": [],
"source": [
"def average_pool(last_hidden_states: Tensor, attention_mask: Tensor) -> Tensor:\n",
" last_hidden = last_hidden_states.masked_fill(~attention_mask[..., None].bool(), 0.0)\n",
" return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None]\n",
"\n",
"\n",
"def hf_embed(model_id: str, inputs: List[str]):\n",
" # Tokenize the input texts\n",
" batch_dict = hf_tokenizer(inputs, max_length=512, padding=True, truncation=True, return_tensors=\"pt\")\n",
"\n",
" outputs = hf_model(**batch_dict)\n",
" embeddings = average_pool(outputs.last_hidden_state, batch_dict[\"attention_mask\"])\n",
"\n",
" # normalize embeddings\n",
" embeddings = F.normalize(embeddings, p=2, dim=1)\n",
" return embeddings.detach().numpy()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "69bb4501",
"metadata": {},
"outputs": [],
"source": [
"hf_embed(inputs=english_texts, model_id=model_id)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "451dbd16",
"metadata": {},
"outputs": [],
"source": [
"tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
"model = ORTModelForFeatureExtraction.from_pretrained(model_id, export=True)\n",
"\n",
"# Remove all existing files in the save_dir using Path.unlink()\n",
"save_dir = Path(save_dir)\n",
"save_dir.mkdir(parents=True, exist_ok=True)\n",
"for p in save_dir.iterdir():\n",
" p.unlink()\n",
"\n",
"# Load the optimization configuration detailing the optimization we wish to apply\n",
"optimization_config = AutoOptimizationConfig.O4()\n",
"optimizer = ORTOptimizer.from_pretrained(model)\n",
"\n",
"optimizer.optimize(save_dir=save_dir, optimization_config=optimization_config, use_external_data_format=True)\n",
"model = ORTModelForFeatureExtraction.from_pretrained(save_dir)\n",
"\n",
"tokenizer.save_pretrained(save_dir)\n",
"# model.save_pretrained(save_dir)\n",
"# model.push_to_hub(\"new_path_for_directory\", repository_id=\"my-onnx-repo\", use_auth_token=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8422cddd",
"metadata": {},
"outputs": [],
"source": [
"onnx_quant_embed = pipeline(\n",
" \"feature-extraction\", model=model, accelerator=\"ort\", tokenizer=tokenizer, return_tensors=True\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51fa5775",
"metadata": {},
"outputs": [],
"source": [
"embeddings = onnx_quant_embed(inputs=english_texts)\n",
"F.normalize(embeddings[4])[:, 0], english_texts[4], len(embeddings), len(english_texts)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "df405d70",
"metadata": {},
"outputs": [],
"source": [
"def measure_pipeline_time(pipeline, input_texts: List[str], num_runs=10, **kwargs: Any) -> Tuple[float, float]:\n",
" \"\"\"Measures the time it takes to run the pipeline on the input texts.\"\"\"\n",
" times = []\n",
" total_chars = sum(len(text) for text in input_texts)\n",
" for _ in range(num_runs):\n",
" start_time = time.time()\n",
" _ = pipeline(inputs=input_texts, **kwargs)\n",
" end_time = time.time()\n",
" times.append(end_time - start_time)\n",
"\n",
" mean_time = np.mean(times)\n",
" std_dev = np.std(times)\n",
" chars_per_second = total_chars / mean_time\n",
" return mean_time, std_dev, chars_per_second"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "2d72aba5",
"metadata": {},
"source": [
"# Ours"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6b881152",
"metadata": {},
"outputs": [],
"source": [
"_, _, chars_per_sec = measure_pipeline_time(onnx_quant_embed, input_texts)\n",
"print(f\"Multilingual Speed: {chars_per_sec:.2f} chars/sec\")\n",
"_, _, chars_per_sec = measure_pipeline_time(onnx_quant_embed, english_texts)\n",
"print(f\"English Speed: {chars_per_sec:.2f} chars/sec\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "49e1daf8",
"metadata": {},
"source": [
"# Original"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "61b3bf53",
"metadata": {},
"outputs": [],
"source": [
"_, _, chars_per_sec = measure_pipeline_time(hf_embed, input_texts=input_texts, model_id=model_id)\n",
"print(f\"Multilingual Speed: {chars_per_sec:.2f} chars/sec\")\n",
"_, _, chars_per_sec = measure_pipeline_time(hf_embed, input_texts=english_texts, model_id=model_id)\n",
"print(f\"English Speed: {chars_per_sec:.2f} chars/sec\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "f0b7da8f-ffe7-4f58-95dd-7e9836f19328",
"metadata": {},
"source": [
"# Compress & Upload\n",
"\n",
"## Compress"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "578b1d74",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from pathlib import Path\n",
"import tarfile\n",
"\n",
"save_dir = Path(\"../local_cache/fast-bge-small-en-v1.5\")\n",
"\n",
"\n",
"def compress(directory_path):\n",
" directory_path = Path(directory_path)\n",
" assert directory_path.exists(), f\"{directory_path} does not exist\"\n",
" output_filename = directory_path.name + \".tar.gz\"\n",
" if Path(output_filename).exists():\n",
" print(\"We've an output file already? Manually delete that first\")\n",
" return output_filename\n",
"\n",
" with tarfile.open(output_filename, \"w:gz\") as tar:\n",
" tar.add(directory_path, arcname=os.path.basename(directory_path))\n",
" return output_filename\n",
"\n",
"\n",
"compressed_file_name = compress(save_dir)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "96cdf140-eca8-4778-9ebe-947988b4cfcb",
"metadata": {},
"source": [
"## Upload to Qdrant Google Cloud Storage"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "1dab9595",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/homebrew/Caskroom/miniconda/base/envs/fst/lib/python3.9/site-packages/google/auth/_default.py:76: UserWarning: Your application has authenticated using end user credentials from Google Cloud SDK without a quota project. You might receive a \"quota exceeded\" or \"API not enabled\" error. See the following page for troubleshooting: https://cloud.google.com/docs/authentication/adc-troubleshooting/user-creds. \n",
" warnings.warn(_CLOUD_SDK_CREDENTIALS_WARNING)\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"File fast-bge-small-en-v1.5.tar.gz uploaded to qdrant-fastembed.\n"
]
}
],
"source": [
"from google.cloud import storage\n",
"\n",
"\n",
"def upload(bucket_name, source_file_path):\n",
" storage_client = storage.Client(project=\"main\")\n",
" bucket = storage_client.bucket(bucket_name)\n",
" blob = bucket.blob(os.path.basename(source_file_path))\n",
"\n",
" blob.upload_from_filename(source_file_path)\n",
"\n",
" print(f\"File {source_file_path} uploaded to {bucket_name}.\")\n",
"\n",
"\n",
"upload(\"qdrant-fastembed\", source_file_path=compressed_file_name)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "731554f0",
"metadata": {},
"outputs": [],
"source": [
"# Remove the directory and compressed file\n",
"!rm -rvf {save_dir}\n",
"!rm -vf {save_dir}.tar.gz"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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"
}
},
"nbformat": 4,
"nbformat_minor": 5
}