|
53 | 53 | "metadata": {}, |
54 | 54 | "outputs": [], |
55 | 55 | "source": [ |
56 | | - "!pip install \"sagemaker<3.0.0\" --upgrade --quiet" |
| 56 | + "!pip install \"sagemaker>=3.0.0\" --upgrade --quiet" |
57 | 57 | ] |
58 | 58 | }, |
59 | 59 | { |
60 | 60 | "cell_type": "markdown", |
61 | 61 | "metadata": {}, |
62 | 62 | "source": [ |
63 | | - "> [!WARNING]\n", |
64 | | - "> [SageMaker Python SDK v3 has been recently released](https://github.com/aws/sagemaker-python-sdk), so unless specified otherwise, all the documentation and tutorials are still using the [SageMaker Python SDK v2](https://github.com/aws/sagemaker-python-sdk/tree/master-v2). We are actively working on updating all the tutorials and examples, but in the meantime make sure to install the SageMaker SDK as `pip install \"sagemaker<3.0.0\"`." |
| 63 | + "> [!NOTE]\n", |
| 64 | + "> This example uses the [SageMaker Python SDK v3](https://github.com/aws/sagemaker-python-sdk). v3 introduces a new, framework-agnostic API built around `ModelBuilder` (inference) and `ModelTrainer` (training), which replaces the v2 `HuggingFaceModel` and `HuggingFace` classes." |
65 | 65 | ] |
66 | 66 | }, |
67 | 67 | { |
|
78 | 78 | "metadata": {}, |
79 | 79 | "outputs": [], |
80 | 80 | "source": [ |
81 | | - "import sagemaker\n", |
82 | 81 | "import boto3\n", |
83 | | - "sess = sagemaker.Session()\n", |
| 82 | + "from sagemaker.core.helper.session_helper import Session, get_execution_role\n", |
| 83 | + "\n", |
| 84 | + "sess = Session()\n", |
84 | 85 | "# sagemaker session bucket -> used for uploading data, models and logs\n", |
85 | | - "# sagemaker will automatically create this bucket if it not exists\n", |
86 | | - "sagemaker_session_bucket=None\n", |
87 | | - "if sagemaker_session_bucket is None and sess is not None:\n", |
88 | | - " # set to default bucket if a bucket name is not given\n", |
89 | | - " sagemaker_session_bucket = sess.default_bucket()\n", |
| 86 | + "# sagemaker will automatically create this bucket if it does not exist\n", |
| 87 | + "sagemaker_session_bucket = sess.default_bucket()\n", |
90 | 88 | "\n", |
91 | 89 | "try:\n", |
92 | | - " role = sagemaker.get_execution_role()\n", |
93 | | - "except ValueError:\n", |
| 90 | + " role = get_execution_role()\n", |
| 91 | + "except Exception:\n", |
94 | 92 | " iam = boto3.client('iam')\n", |
95 | 93 | " role = iam.get_role(RoleName='sagemaker_execution_role')['Role']['Arn']\n", |
96 | 94 | "\n", |
97 | | - "sess = sagemaker.Session(default_bucket=sagemaker_session_bucket)\n", |
98 | | - "\n", |
99 | 95 | "print(f\"sagemaker role arn: {role}\")\n", |
100 | | - "print(f\"sagemaker session region: {sess.boto_region_name}\")\n" |
| 96 | + "print(f\"sagemaker session region: {sess.boto_region_name}\")" |
101 | 97 | ] |
102 | 98 | }, |
103 | 99 | { |
|
107 | 103 | "source": [ |
108 | 104 | "## 2. Retrieve the new Hugging Face Embedding Container\n", |
109 | 105 | "\n", |
110 | | - "Compared to deploying regular Hugging Face models we first need to retrieve the container uri and provide it to our `HuggingFaceModel` model class with a `image_uri` pointing to the image. To retrieve the new Hugging Face Embedding Container in Amazon SageMaker, we can use the `get_huggingface_llm_image_uri` method provided by the `sagemaker` 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. " |
| 106 | + "To deploy an embedding model we provide the TEI container image to a `ModelBuilder`. To retrieve the URI of the Hugging Face Embedding Container in Amazon SageMaker, we use the `image_uris.retrieve` helper from `sagemaker.core`. TEI has two different versions for CPU and GPU, so we create a helper function to retrieve the correct image URI based on the instance type. The processor (CPU/GPU) is inferred from the `instance_type`." |
111 | 107 | ] |
112 | 108 | }, |
113 | 109 | { |
|
116 | 112 | "metadata": {}, |
117 | 113 | "outputs": [], |
118 | 114 | "source": [ |
119 | | - "from sagemaker.huggingface import get_huggingface_llm_image_uri\n", |
| 115 | + "from sagemaker.core import image_uris\n", |
120 | 116 | "\n", |
121 | 117 | "# retrieve the image uri based on instance type\n", |
122 | 118 | "def get_image_uri(instance_type):\n", |
123 | | - " key = \"huggingface-tei\" if instance_type.startswith(\"ml.g\") or instance_type.startswith(\"ml.p\") else \"huggingface-tei-cpu\"\n", |
124 | | - " return get_huggingface_llm_image_uri(key, version=\"1.4.0\")\n" |
| 119 | + " framework = \"huggingface-tei\" if instance_type.startswith((\"ml.g\", \"ml.p\")) else \"huggingface-tei-cpu\"\n", |
| 120 | + " return image_uris.retrieve(\n", |
| 121 | + " framework=framework,\n", |
| 122 | + " region=sess.boto_region_name,\n", |
| 123 | + " version=\"1.8.2\",\n", |
| 124 | + " image_scope=\"inference\",\n", |
| 125 | + " instance_type=instance_type,\n", |
| 126 | + " )" |
125 | 127 | ] |
126 | 128 | }, |
127 | 129 | { |
|
131 | 133 | "source": [ |
132 | 134 | "## 3. Deploy Snowflake Arctic to Amazon SageMaker\n", |
133 | 135 | "\n", |
134 | | - "To deploy [Snowflake/snowflake-arctic-embed-m](https://huggingface.co/Snowflake/snowflake-arctic-embed-m) to Amazon SageMaker we create a `HuggingFaceModel` model class and define our endpoint configuration including the `HF_MODEL_ID`, `instance_type` etc. We will use a `c6i.2xlarge` instance type, which has 4 Intel Ice-Lake vCPUs, 8GB of memory and costs around $0.204 per hour. " |
| 136 | + "To deploy [Snowflake/snowflake-arctic-embed-m](https://huggingface.co/Snowflake/snowflake-arctic-embed-m) to Amazon SageMaker we create a `ModelBuilder` and define our configuration: the Hugging Face model ID, the TEI container image, the instance type and the model server (`ModelServer.TEI`). `ModelBuilder` automatically sets `HF_MODEL_ID` from the model ID and lets TEI download the model directly from the Hugging Face Hub. We will use a `ml.g5.xlarge` GPU instance type." |
135 | 137 | ] |
136 | 138 | }, |
137 | 139 | { |
|
140 | 142 | "metadata": {}, |
141 | 143 | "outputs": [], |
142 | 144 | "source": [ |
143 | | - "import json\n", |
144 | | - "from sagemaker.huggingface import HuggingFaceModel\n", |
| 145 | + "role = \"arn:aws:iam::754289655784:role/sagemaker_execution_role\"" |
| 146 | + ] |
| 147 | + }, |
| 148 | + { |
| 149 | + "cell_type": "code", |
| 150 | + "execution_count": null, |
| 151 | + "metadata": {}, |
| 152 | + "outputs": [], |
| 153 | + "source": [ |
| 154 | + "from sagemaker.serve import ModelBuilder, ModelServer\n", |
| 155 | + "from sagemaker.serve.builder.schema_builder import SchemaBuilder\n", |
145 | 156 | "\n", |
146 | 157 | "# sagemaker config\n", |
147 | 158 | "instance_type = \"ml.g5.xlarge\"\n", |
| 159 | + "model_id = \"Snowflake/snowflake-arctic-embed-m\" # model_id from hf.co/models\n", |
148 | 160 | "\n", |
149 | | - "# Define Model and Endpoint configuration parameter\n", |
150 | | - "config = {\n", |
151 | | - " 'HF_MODEL_ID': \"Snowflake/snowflake-arctic-embed-m\", # model_id from hf.co/models\n", |
152 | | - "}\n", |
| 161 | + "# Create a ModelBuilder for the TEI (Text Embeddings Inference) server.\n", |
| 162 | + "# ModelBuilder sets HF_MODEL_ID from `model` and pulls the model from the Hub.\n", |
| 163 | + "model_builder = ModelBuilder(\n", |
| 164 | + " model=model_id,\n", |
| 165 | + " role_arn=role,\n", |
| 166 | + " sagemaker_session=sess,\n", |
| 167 | + " instance_type=instance_type,\n", |
| 168 | + " image_uri=get_image_uri(instance_type),\n", |
| 169 | + " model_server=ModelServer.TEI,\n", |
| 170 | + " schema_builder=SchemaBuilder(\n", |
| 171 | + " sample_input={\"inputs\": \"embed this sentence\"},\n", |
| 172 | + " sample_output=[[0.0] * 768],\n", |
| 173 | + " ),\n", |
| 174 | + ")\n", |
153 | 175 | "\n", |
154 | | - "# create HuggingFaceModel with the image uri\n", |
155 | | - "emb_model = HuggingFaceModel(\n", |
156 | | - " role=role,\n", |
157 | | - " image_uri=get_image_uri(instance_type),\n", |
158 | | - " env=config\n", |
159 | | - ")" |
| 176 | + "# Build the SageMaker model resource\n", |
| 177 | + "emb_model = model_builder.build()" |
160 | 178 | ] |
161 | 179 | }, |
162 | 180 | { |
163 | 181 | "attachments": {}, |
164 | 182 | "cell_type": "markdown", |
165 | 183 | "metadata": {}, |
166 | 184 | "source": [ |
167 | | - "After we have created the `HuggingFaceModel` we can deploy it to Amazon SageMaker using the `deploy` method. We will deploy the model with the `ml.c6i.2xlarge` instance type." |
| 185 | + "After we have built the model with `ModelBuilder` we can deploy it to Amazon SageMaker using the `deploy` method. We will deploy the model with the `ml.g5.xlarge` instance type. `deploy` returns an `Endpoint` object that we use to run inference." |
168 | 186 | ] |
169 | 187 | }, |
170 | 188 | { |
|
173 | 191 | "metadata": {}, |
174 | 192 | "outputs": [], |
175 | 193 | "source": [ |
176 | | - "# Deploy model to an endpoint\n", |
177 | | - "# https://sagemaker.readthedocs.io/en/stable/api/inference/model.html#sagemaker.model.Model.deploy\n", |
178 | | - "emb = emb_model.deploy(\n", |
179 | | - " initial_instance_count=1,\n", |
180 | | - " instance_type=instance_type,\n", |
181 | | - ")\n" |
| 194 | + "# Deploy the model to a real-time endpoint\n", |
| 195 | + "emb = model_builder.deploy(\n", |
| 196 | + " initial_instance_count=1,\n", |
| 197 | + " instance_type=instance_type,\n", |
| 198 | + ")" |
182 | 199 | ] |
183 | 200 | }, |
184 | 201 | { |
|
196 | 213 | "source": [ |
197 | 214 | "## 4. Run and evaluate Inference performance\n", |
198 | 215 | "\n", |
199 | | - "After our endpoint is deployed we can run inference on it. We will use the `predict` method from the `predictor` to run inference on our endpoint.\n" |
| 216 | + "After our endpoint is deployed we can run inference on it. We use the `invoke` method of the `Endpoint` to send requests. The request body is JSON and the response `body` contains the embeddings." |
200 | 217 | ] |
201 | 218 | }, |
202 | 219 | { |
|
205 | 222 | "metadata": {}, |
206 | 223 | "outputs": [], |
207 | 224 | "source": [ |
| 225 | + "import json\n", |
| 226 | + "\n", |
208 | 227 | "data = {\n", |
209 | | - " \"inputs\": \"the mesmerizing performances of the leads keep the film grounded and keep the audience riveted .\",\n", |
| 228 | + " \"inputs\": \"the mesmerizing performances of the leads keep the film grounded and keep the audience riveted .\",\n", |
210 | 229 | "}\n", |
211 | | - " \n", |
212 | | - "res = emb.predict(data=data)\n", |
213 | | - " \n", |
214 | | - " \n", |
| 230 | + "\n", |
| 231 | + "res = emb.invoke(body=json.dumps(data), content_type=\"application/json\")\n", |
| 232 | + "embeddings = json.loads(res.body.read())\n", |
| 233 | + "\n", |
215 | 234 | "# print some results\n", |
216 | | - "print(f\"length of embeddings: {len(res[0])}\")\n", |
217 | | - "print(f\"first 10 elements of embeddings: {res[0][:10]}\")" |
| 235 | + "print(f\"length of embeddings: {len(embeddings[0])}\")\n", |
| 236 | + "print(f\"first 10 elements of embeddings: {embeddings[0][:10]}\")" |
218 | 237 | ] |
219 | 238 | }, |
220 | 239 | { |
|
236 | 255 | "source": [ |
237 | 256 | "import threading\n", |
238 | 257 | "import time\n", |
| 258 | + "\n", |
239 | 259 | "number_of_threads = 10\n", |
240 | 260 | "number_of_requests = int(3900 // number_of_threads)\n", |
241 | 261 | "print(f\"number of threads: {number_of_threads}\")\n", |
242 | 262 | "print(f\"number of requests per thread: {number_of_requests}\")\n", |
243 | | - " \n", |
244 | | - "def send_rquests():\n", |
| 263 | + "\n", |
| 264 | + "# input counted at https://huggingface.co/spaces/Xenova/the-tokenizer-playground for ~100 tokens\n", |
| 265 | + "payload = json.dumps({\"inputs\": \"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\"})\n", |
| 266 | + "\n", |
| 267 | + "def send_requests():\n", |
245 | 268 | " for _ in range(number_of_requests):\n", |
246 | | - " # input counted at https://huggingface.co/spaces/Xenova/the-tokenizer-playground for 100 tokens\n", |
247 | | - " emb.predict(data={\"inputs\": \"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\"})\n", |
248 | | - " \n", |
| 269 | + " emb.invoke(body=payload, content_type=\"application/json\")\n", |
| 270 | + "\n", |
249 | 271 | "# Create multiple threads\n", |
250 | | - "threads = [threading.Thread(target=send_rquests) for _ in range(number_of_threads) ]\n", |
| 272 | + "threads = [threading.Thread(target=send_requests) for _ in range(number_of_threads)]\n", |
251 | 273 | "# start all threads\n", |
252 | 274 | "start = time.time()\n", |
253 | 275 | "[t.start() for t in threads]\n", |
|
300 | 322 | "metadata": {}, |
301 | 323 | "outputs": [], |
302 | 324 | "source": [ |
303 | | - "emb.delete_model()\n", |
304 | | - "emb.delete_endpoint()" |
| 325 | + "emb.delete()\n", |
| 326 | + "emb_model.delete()" |
305 | 327 | ] |
306 | 328 | } |
307 | 329 | ], |
308 | 330 | "metadata": { |
309 | 331 | "kernelspec": { |
310 | | - "display_name": "hf", |
| 332 | + "display_name": "Python 3 (ipykernel)", |
311 | 333 | "language": "python", |
312 | 334 | "name": "python3" |
313 | 335 | }, |
|
321 | 343 | "name": "python", |
322 | 344 | "nbconvert_exporter": "python", |
323 | 345 | "pygments_lexer": "ipython3", |
324 | | - "version": "3.9.13" |
| 346 | + "version": "3.12.13" |
325 | 347 | }, |
326 | | - "orig_nbformat": 4, |
327 | 348 | "vscode": { |
328 | 349 | "interpreter": { |
329 | 350 | "hash": "5fcf248a74081676ead7e77f54b2c239ba2921b952f7cbcdbbe5427323165924" |
330 | 351 | } |
331 | 352 | } |
332 | 353 | }, |
333 | 354 | "nbformat": 4, |
334 | | - "nbformat_minor": 2 |
| 355 | + "nbformat_minor": 4 |
335 | 356 | } |
0 commit comments