File size: 13,292 Bytes
c6a4560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "copyright": [
     "INTEL CONFIDENTIAL",
     "Copyright (C) 2023 Intel Corporation",
     "This software and the related documents are Intel copyrighted materials, and your use of them is governed by",
     "the express license under which they were provided to you (\"License\"). Unless the License provides otherwise,",
     "you may not use, modify, copy, publish, distribute, disclose or transmit this software or the related documents",
     "without Intel's prior written permission.",
     "This software and the related documents are provided as is, with no express or implied warranties,",
     "other than those that are expressly stated in the License."
    ]
   },
   "source": [
    "# Serving Intel® Geti™ models with OpenVINO Model Server\n",
    "This notebook shows how to set up an OpenVINO model server to serve the models trained\n",
    "in your Intel® Geti™ project. It also shows how to use the Geti SDK as a client to\n",
    "make inference requests to the model server.\n",
    "\n",
    "# Contents\n",
    "\n",
    "1. **OpenVINO Model Server**\n",
    "    1. Requirements\n",
    "    2. Generating the model server configuration\n",
    "    3. Launching the model server\n",
    "\n",
    "2. **OVMS inference with Geti SDK**\n",
    "    1. Loading inference model and sample image\n",
    "    2. Requesting inference\n",
    "    3. Inspecting the results\n",
    "\n",
    "3. **Conclusion**\n",
    "    1. Cleaning up\n",
    "\n",
    "> **NOTE**: This notebook will set up a model server on the same machine that will be\n",
    "> used as a client to request inference. In a real scenario you'd most likely\n",
    "> want the server and the client to be different physical machines. The steps to set up\n",
    "> OVMS on a remote server are the same as for the local server outlined in this\n",
    "> notebook, but additional network configuration and security measures are most likely\n",
    "> required.\n",
    "\n",
    "# OpenVINO Model Server\n",
    "## Requirements\n",
    "We will be running the OpenVINO Model Server (OVMS) with Docker. Please make sure you\n",
    "have docker available on your system. You can install it by following the instructions\n",
    "[here](https://docs.docker.com/get-docker/).\n",
    "\n",
    "## Generating the model server configuration\n",
    "The `deployment` that was downloaded from the Intel® Geti™ platform can be used to create\n",
    "the configuration files that are needed to set up an OpenVINO model server for your project.\n",
    "\n",
    "The cell below shows how to create the configuration. Running this cell should create\n",
    "a folder called `ovms_models` in a temporary directory. The `ovms_models` folder\n",
    "contains the models and the configuration files required to run OVMS for the Intel®\n",
    "Geti™ project."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import tempfile\n",
    "\n",
    "from geti_sdk.deployment import Deployment\n",
    "\n",
    "deployment_path = os.path.join(\"..\", \"deployment\")\n",
    "\n",
    "# Load the Geti deployment\n",
    "deployment = Deployment.from_folder(deployment_path)\n",
    "\n",
    "# Creating the OVMS configuration for the deployment\n",
    "# First, we'll create a temporary directory to store the config files\n",
    "ovms_config_path = os.path.join(tempfile.mkdtemp(), \"ovms_models\")\n",
    "\n",
    "# Next, we generate the OVMS configuration and save it\n",
    "deployment.generate_ovms_config(output_folder=ovms_config_path)\n",
    "\n",
    "print(f\"Configuration for OpenVINO Model Server was created at '{ovms_config_path}'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Launching the model server\n",
    "As mentioned before, we will run OVMS in a Docker container. First, we need to make sure\n",
    "that we have the latest OVMS image on our system. Run the cell below to pull the image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "! docker pull openvino/model_server:latest"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Next, we have to start the container with the configuration that we just generated. This\n",
    "is done in the cell below.\n",
    "\n",
    "> NOTE: The cell below starts the OVMS container and sets it up to listen for inference\n",
    "> requests on port 9000 on your system. If this port is already occupied the `docker run`\n",
    "> command will fail and you may need to try a different port number."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# Launch the OVMS container\n",
    "result = ! docker run -d --rm -v {ovms_config_path}:/models -p 9000:9000 --name ovms_demo openvino/model_server:latest --port 9000 --config_path /models/ovms_model_config.json\n",
    "\n",
    "# Check that the container was created successfully\n",
    "if len(result) == 1:\n",
    "    container_id = result[0]\n",
    "    print(f\"OVMS container with ID '{container_id}' created.\")\n",
    "else:\n",
    "    # Anything other than 1 result indicates that something went wrong\n",
    "    raise RuntimeError(result)\n",
    "\n",
    "# Check that the container is running properly\n",
    "container_info = ! docker container inspect {container_id}\n",
    "container_status = str(container_info.grep(\"Status\"))\n",
    "\n",
    "if not container_status or not \"running\" in container_status:\n",
    "    raise RuntimeError(\n",
    "        f\"Invalid ovms docker container status found: {container_status}. Most \"\n",
    "        f\"likely the container has not started properly.\"\n",
    "    )\n",
    "print(\"OVMS container is up and running.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "That's it! If all went well the cell above should print the ID of the container that\n",
    "was created. This can be used to identify your container if you have a lot of docker\n",
    "containers running on your system.\n",
    "\n",
    "# OVMS inference with Geti SDK\n",
    "Now that the OVMS container is running, we can use the Geti SDK to talk to it and make an\n",
    "inference request. The remaining part of this notebook shows how to do so.\n",
    "\n",
    "## Loading inference model and sample image\n",
    "In the first part of this notebook we created configuration files for OVMS, using the\n",
    "`deployment` that was generated for your Intel® Geti™ project. To do inference, we need\n",
    "to connect the deployment to the OVMS container that is now running. This is done in the\n",
    "cell below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# Load the inference models by connecting to OVMS on port 9000\n",
    "deployment.load_inference_models(device=\"http://localhost:9000\")\n",
    "\n",
    "print(\"Connected to OpenVINO Model Server.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "You should see some output indicating that the connection to OVMS was made successfully.\n",
    "If you see any errors at this stage, make sure your OVMS container is running and that the\n",
    "port number is correct.\n",
    "\n",
    "Next up, we'll load a sample image from the project to run inference on"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import cv2\n",
    "\n",
    "# Load the sample image\n",
    "image = cv2.imread(\"../sample_image.jpg\")\n",
    "image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "# Show the image in the notebook\n",
    "from IPython.display import display\n",
    "from PIL import Image\n",
    "\n",
    "display(Image.fromarray(image_rgb))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Requesting inference\n",
    "Now that everything is set up, making an inference request is very simple:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "t_start = time.time()\n",
    "prediction = deployment.infer(image_rgb)\n",
    "t_end = time.time()\n",
    "\n",
    "print(\n",
    "    f\"OVMS inference on sample image completed in {(t_end - t_start) * 1000:.1f} milliseconds.\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Inspecting the results\n",
    "Note that the code to request inference is exactly the same as for the case when the model\n",
    "is loaded on the CPU (see `demo_notebook.ipynb`). Like The `prediction` can be shown using\n",
    "the Geti SDK visualization utility function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from geti_sdk.utils import show_image_with_annotation_scene\n",
    "\n",
    "show_image_with_annotation_scene(image_rgb, prediction, show_in_notebook=True);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Conclusion\n",
    "That's all there is to it! Of course in practice the client would request inference\n",
    "from an OpenVINO model server on a different physical machine, in contrast to the\n",
    "example here where client and server are running on the same machine.\n",
    "\n",
    "The steps outlined in this notebook can be used as a basis to set up a remote\n",
    "client/server combination, but please note that additional network configuration will\n",
    "be required (along with necessary security measures).\n",
    "\n",
    "## Cleaning up\n",
    "To clean up, we'll stop the OVMS docker container that we started. This will\n",
    "automatically remove the container. After that, we'll delete the temporary directory\n",
    "we created to store the config files."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Stop the container\n",
    "result = ! docker stop {container_id}\n",
    "\n",
    "# Check if removing the container worked correctly\n",
    "if result[0] == container_id:\n",
    "    print(f\"OVMS container '{container_id}' stopped and removed successfully.\")\n",
    "else:\n",
    "    print(\n",
    "       \"An error occurred while removing OVMS docker container. Most likely the container \"\n",
    "       \"was already removed. \"\n",
    "    )\n",
    "    print(f\"The docker daemon responded with the following error: \\n{result}\")\n",
    "    \n",
    "# Remove the temporary directory with the OVMS configuration\n",
    "import shutil\n",
    "\n",
    "temp_dir = os.path.dirname(ovms_config_path)\n",
    "try:\n",
    "    shutil.rmtree(temp_dir)\n",
    "    print(\"Temporary configuration directory removed successfully.\")\n",
    "except FileNotFoundError:\n",
    "    print(\n",
    "        f\"Temporary directory with OVMS configuration '{temp_dir}' was \"\n",
    "        f\"not found on the system. Most likely it is already removed.\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.8.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}