Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"How to deploy Embedding Models to Amazon SageMaker using new Hugging Face Embedding DLC","local":"how-to-deploy-embedding-models-to-amazon-sagemaker-using-new-hugging-face-embedding-dlc","sections":[{"title":"What is Hugging Face Embedding DLC?","local":"what-is-hugging-face-embedding-dlc","sections":[],"depth":2},{"title":"1. Setup development environment","local":"1-setup-development-environment","sections":[],"depth":2},{"title":"2. Retrieve the new Hugging Face Embedding Container","local":"2-retrieve-the-new-hugging-face-embedding-container","sections":[],"depth":2},{"title":"3. Deploy Snowflake Arctic to Amazon SageMaker","local":"3-deploy-snowflake-arctic-to-amazon-sagemaker","sections":[],"depth":2},{"title":"4. Run and evaluate Inference performance","local":"4-run-and-evaluate-inference-performance","sections":[],"depth":2},{"title":"5. Delete model and endpoint","local":"5-delete-model-and-endpoint","sections":[],"depth":2}],"depth":1}"> | |
| <link href="/docs/sagemaker/pr_2188/en/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/entry/start.48a18f09.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/scheduler.aec39e6a.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/singletons.8e7a9ddc.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/paths.a4e52f32.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/entry/app.8481cdda.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/preload-helper.382cad4e.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/index.4ee0a2d0.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/nodes/0.52c1f0fb.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/each.e59479a4.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/nodes/5.abe82d18.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/Tip.e2132029.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/MermaidChart.svelte_svelte_type_style_lang.3c60bfa3.js"> | |
| <link rel="modulepreload" href="/docs/sagemaker/pr_2188/en/_app/immutable/chunks/CodeBlock.543f5448.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{"title":"How to deploy Embedding Models to Amazon SageMaker using new Hugging Face Embedding DLC","local":"how-to-deploy-embedding-models-to-amazon-sagemaker-using-new-hugging-face-embedding-dlc","sections":[{"title":"What is Hugging Face Embedding DLC?","local":"what-is-hugging-face-embedding-dlc","sections":[],"depth":2},{"title":"1. Setup development environment","local":"1-setup-development-environment","sections":[],"depth":2},{"title":"2. Retrieve the new Hugging Face Embedding Container","local":"2-retrieve-the-new-hugging-face-embedding-container","sections":[],"depth":2},{"title":"3. Deploy Snowflake Arctic to Amazon SageMaker","local":"3-deploy-snowflake-arctic-to-amazon-sagemaker","sections":[],"depth":2},{"title":"4. Run and evaluate Inference performance","local":"4-run-and-evaluate-inference-performance","sections":[],"depth":2},{"title":"5. Delete model and endpoint","local":"5-delete-model-and-endpoint","sections":[],"depth":2}],"depth":1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg></button></div> </div> <h1 class="relative group"><a id="how-to-deploy-embedding-models-to-amazon-sagemaker-using-new-hugging-face-embedding-dlc" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#how-to-deploy-embedding-models-to-amazon-sagemaker-using-new-hugging-face-embedding-dlc"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>How to deploy Embedding Models to Amazon SageMaker using new Hugging Face Embedding DLC</span></h1> <p data-svelte-h="svelte-107ao9g">This is an example on how to deploy the open Embedding Models, like <a href="https://huggingface.co/Snowflake/snowflake-arctic-embed-l" rel="nofollow">Snowflake/snowflake-arctic-embed-l</a>, <a href="https://huggingface.co/BAAI/bge-large-en-v1.5" rel="nofollow">BAAI/bge-large-en-v1.5</a> or <a href="https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2" rel="nofollow">sentence-transformers/all-MiniLM-L6-v2</a> to Amazon SageMaker for inference using the new Hugging Face Embedding Inference Container. We will deploy the <a href="https://huggingface.co/Snowflake/snowflake-arctic-embed-m" rel="nofollow">Snowflake/snowflake-arctic-embed-m</a> one of the best open Embedding Models for retrieval and ranking on the <a href="https://huggingface.co/spaces/mteb/leaderboard" rel="nofollow">MTEB Leaderboard</a>.</p> <p data-svelte-h="svelte-1fk91jb">The example covers:</p> <ol data-svelte-h="svelte-t9j2qn"><li><a href="#1-setup-development-environment">Setup development environment</a></li> <li><a href="#2-retrieve-the-new-hugging-face-embedding-container">Retrieve the new Hugging Face Embedding Container</a></li> <li><a href="#3-deploy-snowflake-arctic-to-amazon-sagemaker">Deploy Snowflake Arctic to Amazon SageMaker</a></li> <li><a href="#4-run-and-evaluate-inference-performance">Run and evaluate Inference performance</a></li> <li><a href="#5-delete-model-and-endpoint">Delete model and endpoint</a></li></ol> <h2 class="relative group"><a id="what-is-hugging-face-embedding-dlc" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#what-is-hugging-face-embedding-dlc"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>What is Hugging Face Embedding DLC?</span></h2> <p data-svelte-h="svelte-1g12ipz">The Hugging Face Embedding DLC is a new purpose-built Inference Container to easily deploy Embedding Models in a secure and managed environment. The DLC is powered by <a href="https://github.com/huggingface/text-embeddings-inference" rel="nofollow">Text Embedding Inference (TEI)</a> a blazing fast and memory efficient solution for deploying and serving Embedding Models. TEI enables high-performance extraction for the most popular models, including FlagEmbedding, Ember, GTE and E5. TEI implements many features such as:</p> <ul data-svelte-h="svelte-13nwd7v"><li>No model graph compilation step</li> <li>Small docker images and fast boot times</li> <li>Token based dynamic batching</li> <li>Optimized transformers code for inference using Flash Attention, Candle and cuBLASLt</li> <li>Safetensors weight loading</li> <li>Production ready (distributed tracing with Open Telemetry, Prometheus metrics)</li></ul> <p data-svelte-h="svelte-dbg7bd">TEI supports the following model architectures</p> <ul data-svelte-h="svelte-1qk5wei"><li>BERT/CamemBERT, e.g. <a href="https://huggingface.co/BAAI/bge-large-en-v1.5" rel="nofollow">BAAI/bge-large-en-v1.5</a> or <a href="https://huggingface.co/Snowflake/snowflake-arctic-embed-m" rel="nofollow">Snowflake/snowflake-arctic-embed-m</a></li> <li>RoBERTa, <a href="https://huggingface.co/sentence-transformers/all-roberta-large-v1" rel="nofollow">sentence-transformers/all-roberta-large-v1</a></li> <li>XLM-RoBERTa, e.g. <a href="https://huggingface.co/sentence-transformers/paraphrase-xlm-r-multilingual-v1" rel="nofollow">sentence-transformers/paraphrase-xlm-r-multilingual-v1</a></li> <li>NomicBert, e.g. <a href="https://huggingface.co/jinaai/jina-embeddings-v2-base-en" rel="nofollow">jinaai/jina-embeddings-v2-base-en</a></li> <li>JinaBert, e.g. <a href="https://huggingface.co/nomic-ai/nomic-embed-text-v1.5" rel="nofollow">nomic-ai/nomic-embed-text-v1.5</a></li></ul> <p data-svelte-h="svelte-6zk712">Lets get started!</p> <h2 class="relative group"><a id="1-setup-development-environment" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#1-setup-development-environment"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>1. Setup development environment</span></h2> <p data-svelte-h="svelte-ivso52">We are going to use the <code>sagemaker</code> python SDK to deploy Snowflake Arctic to Amazon SageMaker. We need to make sure to have an AWS account configured and the <code>sagemaker</code> python SDK installed.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->!pip install <span class="hljs-string">"sagemaker<3.0.0"</span> --upgrade --quiet<!-- HTML_TAG_END --></pre></div> <blockquote class="warning"><p data-svelte-h="svelte-1rh974s"><a href="https://github.com/aws/sagemaker-python-sdk" rel="nofollow">SageMaker Python SDK v3 has been recently released</a>, so unless specified otherwise, all the documentation and tutorials are still using the <a href="https://github.com/aws/sagemaker-python-sdk/tree/master-v2" rel="nofollow">SageMaker Python SDK v2</a>. We are actively working on updating all the tutorials and examples, but in the meantime make sure to install the SageMaker SDK as <code>pip install "sagemaker<3.0.0"</code>.</p></blockquote> <p data-svelte-h="svelte-s0u97w">If you are going to use Sagemaker in a local environment. You need access to an IAM Role with the required permissions for Sagemaker. You can find <a href="https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html" rel="nofollow">here</a> more about it.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> sagemaker | |
| <span class="hljs-keyword">import</span> boto3 | |
| sess = sagemaker.Session() | |
| <span class="hljs-comment"># sagemaker session bucket -> used for uploading data, models and logs</span> | |
| <span class="hljs-comment"># sagemaker will automatically create this bucket if it not exists</span> | |
| sagemaker_session_bucket=<span class="hljs-literal">None</span> | |
| <span class="hljs-keyword">if</span> sagemaker_session_bucket <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">and</span> sess <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>: | |
| <span class="hljs-comment"># set to default bucket if a bucket name is not given</span> | |
| sagemaker_session_bucket = sess.default_bucket() | |
| <span class="hljs-keyword">try</span>: | |
| role = sagemaker.get_execution_role() | |
| <span class="hljs-keyword">except</span> ValueError: | |
| iam = boto3.client(<span class="hljs-string">'iam'</span>) | |
| role = iam.get_role(RoleName=<span class="hljs-string">'sagemaker_execution_role'</span>)[<span class="hljs-string">'Role'</span>][<span class="hljs-string">'Arn'</span>] | |
| sess = sagemaker.Session(default_bucket=sagemaker_session_bucket) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"sagemaker role arn: <span class="hljs-subst">{role}</span>"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"sagemaker session region: <span class="hljs-subst">{sess.boto_region_name}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="2-retrieve-the-new-hugging-face-embedding-container" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#2-retrieve-the-new-hugging-face-embedding-container"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>2. Retrieve the new Hugging Face Embedding Container</span></h2> <p data-svelte-h="svelte-aifr08">Compared to deploying regular Hugging Face models we first need to retrieve the container uri and provide it to our <code>HuggingFaceModel</code> model class with a <code>image_uri</code> pointing to the image. To retrieve the new Hugging Face Embedding Container in Amazon SageMaker, we can use the <code>get_huggingface_llm_image_uri</code> method provided by the <code>sagemaker</code> SDK. This method allows us to retrieve the URI for the desired Hugging Face Embedding Container. Important to note is that TEI has 2 different versions for cpu and gpu, so we create a helper function to retrieve the correct image uri based on the instance type.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">from</span> sagemaker.huggingface <span class="hljs-keyword">import</span> get_huggingface_llm_image_uri | |
| <span class="hljs-comment"># retrieve the image uri based on instance type</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">get_image_uri</span>(<span class="hljs-params">instance_type</span>): | |
| key = <span class="hljs-string">"huggingface-tei"</span> <span class="hljs-keyword">if</span> instance_type.startswith(<span class="hljs-string">"ml.g"</span>) <span class="hljs-keyword">or</span> instance_type.startswith(<span class="hljs-string">"ml.p"</span>) <span class="hljs-keyword">else</span> <span class="hljs-string">"huggingface-tei-cpu"</span> | |
| <span class="hljs-keyword">return</span> get_huggingface_llm_image_uri(key, version=<span class="hljs-string">"1.4.0"</span>)<!-- HTML_TAG_END --></pre></div> <h2 class="relative group"><a id="3-deploy-snowflake-arctic-to-amazon-sagemaker" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#3-deploy-snowflake-arctic-to-amazon-sagemaker"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>3. Deploy Snowflake Arctic to Amazon SageMaker</span></h2> <p data-svelte-h="svelte-1nrpwhp">To deploy <a href="https://huggingface.co/Snowflake/snowflake-arctic-embed-m" rel="nofollow">Snowflake/snowflake-arctic-embed-m</a> to Amazon SageMaker we create a <code>HuggingFaceModel</code> model class and define our endpoint configuration including the <code>HF_MODEL_ID</code>, <code>instance_type</code> etc. We will use a <code>c6i.2xlarge</code> instance type, which has 4 Intel Ice-Lake vCPUs, 8GB of memory and costs around $0.204 per hour.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> json | |
| <span class="hljs-keyword">from</span> sagemaker.huggingface <span class="hljs-keyword">import</span> HuggingFaceModel | |
| <span class="hljs-comment"># sagemaker config</span> | |
| instance_type = <span class="hljs-string">"ml.g5.xlarge"</span> | |
| <span class="hljs-comment"># Define Model and Endpoint configuration parameter</span> | |
| config = { | |
| <span class="hljs-string">'HF_MODEL_ID'</span>: <span class="hljs-string">"Snowflake/snowflake-arctic-embed-m"</span>, <span class="hljs-comment"># model_id from hf.co/models</span> | |
| } | |
| <span class="hljs-comment"># create HuggingFaceModel with the image uri</span> | |
| emb_model = HuggingFaceModel( | |
| role=role, | |
| image_uri=get_image_uri(instance_type), | |
| env=config | |
| )<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-rq9vzg">After we have created the <code>HuggingFaceModel</code> we can deploy it to Amazon SageMaker using the <code>deploy</code> method. We will deploy the model with the <code>ml.c6i.2xlarge</code> instance type.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-comment"># Deploy model to an endpoint</span> | |
| <span class="hljs-comment"># https://sagemaker.readthedocs.io/en/stable/api/inference/model.html#sagemaker.model.Model.deploy</span> | |
| emb = emb_model.deploy( | |
| initial_instance_count=<span class="hljs-number">1</span>, | |
| instance_type=instance_type, | |
| )<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-fhd04v">SageMaker will now create our endpoint and deploy the model to it. This can takes ~5 minutes.</p> <h2 class="relative group"><a id="4-run-and-evaluate-inference-performance" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#4-run-and-evaluate-inference-performance"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>4. Run and evaluate Inference performance</span></h2> <p data-svelte-h="svelte-u88v21">After our endpoint is deployed we can run inference on it. We will use the <code>predict</code> method from the <code>predictor</code> to run inference on our endpoint.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->data = { | |
| <span class="hljs-string">"inputs"</span>: <span class="hljs-string">"the mesmerizing performances of the leads keep the film grounded and keep the audience riveted ."</span>, | |
| } | |
| res = emb.predict(data=data) | |
| <span class="hljs-comment"># print some results</span> | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"length of embeddings: <span class="hljs-subst">{<span class="hljs-built_in">len</span>(res[<span class="hljs-number">0</span>])}</span>"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"first 10 elements of embeddings: <span class="hljs-subst">{res[<span class="hljs-number">0</span>][:<span class="hljs-number">10</span>]}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-mxy82q">Awesome we can now generate embeddings with our model, Lets test the performance of our model.</p> <p data-svelte-h="svelte-mcpcg9">We will send 3,900 requests to our endpoint use threading with 10 concurrent threads. We will measure the average latency and throughput of our endpoint. We are going to sent an input of 256 tokens to have a total of ~1 Million tokens. We decided to use 256 tokens as input length to find the balance between shorter and longer inputs.</p> <p data-svelte-h="svelte-4wtzg0">Note: When running the load test, the requests are sent from europe and the endpoint is deployed in us-east-1. This adds a network overhead to it.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-keyword">import</span> threading | |
| <span class="hljs-keyword">import</span> time | |
| number_of_threads = <span class="hljs-number">10</span> | |
| number_of_requests = <span class="hljs-built_in">int</span>(<span class="hljs-number">3900</span> // number_of_threads) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"number of threads: <span class="hljs-subst">{number_of_threads}</span>"</span>) | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"number of requests per thread: <span class="hljs-subst">{number_of_requests}</span>"</span>) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">send_rquests</span>(): | |
| <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(number_of_requests): | |
| <span class="hljs-comment"># input counted at https://huggingface.co/spaces/Xenova/the-tokenizer-playground for 100 tokens</span> | |
| emb.predict(data={<span class="hljs-string">"inputs"</span>: <span class="hljs-string">"Hugging Face is a company and a popular platform in the field of natural language processing (NLP) and machine learning. They are known for their contributions to the development of state-of-the-art models for various NLP tasks and for providing a platform that facilitates the sharing and usage of pre-trained models. One of the key offerings from Hugging Face is the Transformers library, which is an open-source library for working with a variety of pre-trained transformer models, including those for text generation, translation, summarization, question answering, and more. The library is widely used in the research and development of NLP applications and is supported by a large and active community. Hugging Face also provides a model hub where users can discover, share, and download pre-trained models. Additionally, they offer tools and frameworks to make it easier for developers to integrate and use these models in their own projects. The company has played a significant role in advancing the field of NLP and making cutting-edge models more accessible to the broader community. Hugging Face also provides a model hub where users can discover, share, and download pre-trained models. Additionally, they offer tools and frameworks to make it easier for developers and ma"</span>}) | |
| <span class="hljs-comment"># Create multiple threads</span> | |
| threads = [threading.Thread(target=send_rquests) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(number_of_threads) ] | |
| <span class="hljs-comment"># start all threads</span> | |
| start = time.time() | |
| [t.start() <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> threads] | |
| <span class="hljs-comment"># wait for all threads to finish</span> | |
| [t.join() <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> threads] | |
| <span class="hljs-built_in">print</span>(<span class="hljs-string">f"total time: <span class="hljs-subst">{<span class="hljs-built_in">round</span>(time.time() - start)}</span> seconds"</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1fbhrxg">Sending 3,900 requests or embedding 1 million tokens took around 841 seconds. This means we can run around ~5 requests per second. But keep in mind that includes the network latency from europe to us-east-1. When we inspect the latency of the endpoint through cloudwatch we can see that latency for our Embeddings model is 2s at 10 concurrent requests. This is very impressive for a small & old CPU instance, which cost ~150$ per month. You can deploy the model to a GPU instance to get faster inference times.</p> <p data-svelte-h="svelte-1gr1muv"><em>Note: We ran the same test on a <code>ml.g5.xlarge</code> with 1x NVIDIA A10G GPU. Embedding 1 million tokens took around 30 seconds. This means we can run around ~130 requests per second. The latency for the endpoint is 4ms at 10 concurrent requests. The <code>ml.g5.xlarge</code> costs around $1.408 per hour on Amazon SageMaker.</em></p> <p data-svelte-h="svelte-1bwshbf">GPU instance are much faster than CPU instances, but they are also more expensive. If you want to bulk process embeddings, you can use a GPU instance. If you want to run a small endpoint with low costs, you can use a CPU instance. We plan to work on a dedicated benchmark for the Hugging Face Embedding DLC in the future.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-built_in">print</span>(<span class="hljs-string">f"https://console.aws.amazon.com/cloudwatch/home?region=<span class="hljs-subst">{sess.boto_region_name}</span>#metricsV2:graph=~(metrics~(~(~'AWS*2fSageMaker~'ModelLatency~'EndpointName~'<span class="hljs-subst">{emb.endpoint_name}</span>~'VariantName~'AllTraffic))~view~'timeSeries~stacked~false~region~'<span class="hljs-subst">{sess.boto_region_name}</span>~start~'-PT5M~end~'P0D~stat~'Average~period~30);query=~'*7bAWS*2fSageMaker*2cEndpointName*2cVariantName*7d*20<span class="hljs-subst">{emb.endpoint_name}</span>"</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-kooosy"><img src="https://raw.githubusercontent.com/huggingface/hub-docs/refs/heads/main/docs/sagemaker/notebooks/sagemaker-sdk/deploy-embedding-models/assets/cw.png" alt="cw"></p> <h2 class="relative group"><a id="5-delete-model-and-endpoint" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#5-delete-model-and-endpoint"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>5. Delete model and endpoint</span></h2> <p data-svelte-h="svelte-1y233zi">To clean up, we can delete the model and endpoint</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->emb.delete_model() | |
| emb.delete_endpoint()<!-- HTML_TAG_END --></pre></div> <hr> <blockquote class="tip"><p data-svelte-h="svelte-17nt2nn">📍 Find the complete example on GitHub <a href="https://github.com/huggingface/hub-docs/tree/main/notebooks/sagemaker-sdk/deploy-embedding-models/sagemaker-notebook.ipynb" rel="nofollow">here</a>!</p></blockquote> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/hub-docs/blob/main/docs/sagemaker/source/examples/sagemaker-sdk-deploy-embedding-models.mdx" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg> <span data-svelte-h="svelte-zjs2n5"><span class="underline">Update</span> on GitHub</span></a> <p></p> | |
| <script> | |
| { | |
| __sveltekit_16a821l = { | |
| assets: "/docs/sagemaker/pr_2188/en", | |
| base: "/docs/sagemaker/pr_2188/en", | |
| env: {} | |
| }; | |
| const element = document.currentScript.parentElement; | |
| const data = [null,null]; | |
| Promise.all([ | |
| import("/docs/sagemaker/pr_2188/en/_app/immutable/entry/start.48a18f09.js"), | |
| import("/docs/sagemaker/pr_2188/en/_app/immutable/entry/app.8481cdda.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 5], | |
| data, | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 44.2 kB
- Xet hash:
- a22e3f02a39e411b89bd102fc5bc9317a66aab50307c42fc13d2cf3a611cafcc
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.