Handlers lambda development =========================== Here is *handlers* lambda development description. More information about lambda types and differences of *handlers* and others available at `lambda types description <./lambda_types.html#handlers>`_. Handlers lambda requirements ---------------------------- Handlers lambda has several requirements to addition with `basic requirements <./lambda_requirements.html#lunaservicesrequirements>`_: - `Luna Faces` available by credentials from `Luna-Configurator` - `Luna Events` available by credentials from `Luna-Configurator`; it can be disabled using *ADDITIONAL_SERVICES_USAGE* setting and it this case *lambda* should provide for work without `Luna-Events` usage - `Luna Python Matcher` available by credentials from `Luna-Configurator` - `Luna Faces/Bodies/Images Samples Store` available by credentials from `Luna-Configurator`; it can be disabled using *ADDITIONAL_SERVICES_USAGE* setting and it this case *lambda* should provide for work without `Luna-Image-Store` usage - `Luna Remote SDK` available by credentials from `Luna-Configurator` Usage and purpose of these services described `here <#handlers-lambda-examples>`_. Handlers lambda configuration ----------------------------- The handlers lambda required several settings from *luna-configurator*, whose can be separated to several groups: - *LUNA_LAMBDA_UNIT_LOGGER* - lambda logger settings - luna-services addresses and timeouts settings (for example, *LUNA_FACES_ADDRESS* and *LUNA_FACES_TIMEOUTS* will be used by lambda to make requests to *luna-faces* service) - *ADDITIONAL_SERVICES_USAGE* setting will be used to determine which *luna-services* can be used by the lambda (the lambda will not check connection to disabled services and will raise an error if user try to make request to such service) Handlers lambda request usage ----------------------------- The request to handlers lambda has some additions compared to `standalone lambda request <./standalone.html#id1>`_. The `HandlersLambdaRequest` has the `data` property (detailed description presented at `handlers incoming data <./handlers.html#handlers-lambda-incoming-data>`_) The simple example: .. code-block:: :caption: lambda_main.py from luna_lambda_tools import HandlersLambdaRequest, logger async def main(request: HandlersLambdaRequest) -> dict: logger.info(request.data.sources) # log count of images in request logger.info(request.handlerId) # request initiator handler id logger.info(request.headers) # all request headers logger.info(request.args) # print dictionary with query arguments ... Handlers lambda incoming data ----------------------------- The handlers lambda must be designed to process requests from *Luna-Handlers* service. .. raw:: html
The incoming request structure is presented here .. autosummary:: :toctree: _autosummary :recursive: luna_lambda_tools.public.handlers.schemas .. raw:: html
The `data` property usage assumes that request will be validated using presented schema and content type of this request is `application/msgpack`. If request's body content type will differs or incoming data not pass validation, it will raise an exception and reply with 400 status code will be returned. It will be available using `data` property of incoming request as follows: .. code-block:: :caption: lambda_main.py from luna_lambda_tools import HandlersLambdaRequest, logger async def main(request: HandlersLambdaRequest) -> dict: logger.info("request images count: ", len(request.data.sources)) for i, image in enumerate(request.data.sources): logger.info(f"face bounding box for image number {i+1}: {image.faceBoundingBoxes[0] if image.faceBoundingBoxes else 'not presented'}") ... Handlers lambda examples ------------------------ The handlers lambda can use luna-services for different operations. - The exception whose caused by requests to luna service processing can be regulated using `raiseError` flag (True by default). The examples demonstrate `raiseError` flag usage: - if request to luna service causes an error, the exception will be raised and the example will returns response with 500 status code and json like this: .. literalinclude:: examples/500/handlers_lambda_status_500/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/500/handlers_lambda_status_500/make_request.py :caption: request example :language: python .. code-block:: { "error_code": 42004, "desc": "Lambda exception", "detail": "Not expected code from service: 404 GET http://127.0.0.1:5030/3/faces/048e1428-c7de-426b-82f8-3971bf00284c, error: {\"error_code\":22002,\"desc\":\"Object not found\",\"detail\":\"Face with id '048e1428-c7de-426b-82f8-3971bf00284c' not found\",\"link\":\"https:\\/\\/docs.visionlabs.ai\\/info\\/luna\\/troubleshooting\\/errors-description\\/code-22002\"}", "link": "https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-42005" } - in this case, the request will raise an error and for any request, labmda will return response with 201 status code and json like this: .. literalinclude:: examples/201/handlers_lambda_status_201/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_status_201/make_request.py :caption: request example :language: python .. code-block:: { "error_code": 22002, "desc": "Object not found", "detail": "Face with id 'fece7f31-ea14-40fb-8c57-40230aa17256' not found", "link": "https://docs.visionlabs.ai/info/luna/troubleshooting/errors-description/code-22002" } - The example lambda which use canonical platform handler, enrich received result and send it to user as reply. The id of canonical (non-lambda) handler specified by query parameter. (such lambda cannot be used as canonical *luna-platform* handler) .. literalinclude:: examples/201/handlers_lambda_enrich/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_enrich/make_request.py :caption: request example :language: python - The example lambda which estimates emotions on each specified image and return received results as reply (such lambda cannot be used as canonical *luna-platform* handler) .. literalinclude:: examples/201/handlers_lambda_estimate/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_estimate/make_request.py :caption: request example :language: python - The lambda example which extracts face descriptors from two images, match them, saves general event if similarity higher than threshold and return result as reply (such lambda cannot be used as canonical *luna-platform* handler) .. literalinclude:: examples/201/handlers_lambda_extract_and_match/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_extract_and_match/make_request.py :caption: request example :language: python - The lambda example which extracts face descriptor, basic attributes and saves face descriptor, sample and event with estimated data (such lambda can be used as canonical *luna-platform* handler) .. literalinclude:: examples/201/handlers_lambda_extract_and_save/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_extract_and_save/make_request.py :caption: request example :language: python - The lambda example which gets face detection and estimate mask in some detection area directly using the LUNA SDK (such user lambda cannot be used as canonical *luna-platform* handler) (available at https://github.com/VisionLabs/lunasdk) LUNA python SDK must be added it to requirements.txt (`requirements description available here `_) .. note:: The LUNA python SDK is named and can be imported as `lunavl` library in lambda code. .. literalinclude:: examples/201/handlers_lambda_sdk/lambda/requirements.txt :caption: requirements.txt .. note:: To develop lambda with lunasdk locally it needs LUNA FSDK python bindings to be installed previously. .. warning:: Such user lambda requires LUNA SDK data available from user lambda (the `fsdk/data` folder near the `lambda_main.py` main file) The LUNA SDK is available on VL release portal which must be extracted to `fsdk` folder (see archive file structure below). The only thing which is needed is *data* folder with used fsdk plans and config files (*faceengine.conf* and *runtime.conf*). It is recommended to not include not using plans from folder in archive to decrease result lambda image size. .. code-block:: :caption: Archive file structure with files required for the example ├──lambda_main.py ├──requirements.txt └──fsdk └──data ├──faceengine.conf ├──runtime.conf ├──FaceDet_v3_a5_cpu-avx2.plan ├──FaceDet_v3_redetect_v3_cpu-avx2.plan ├──LNet_precise_v2_cpu-avx2.plan ├──mask_clf_v3_cpu-avx2.plan └──slnet_v5_cpu-avx2.plan .. literalinclude:: examples/201/handlers_lambda_sdk/lambda/lambda_main.py :caption: lambda_main.py :language: python .. literalinclude:: examples/201/handlers_lambda_sdk/make_request.py :caption: request example :language: python The LUNA SDK can work with CPU or GPU, by default all estimations, extraction and so on carried out using CPU. The GPU usage allows to speed up most of above actions. For more information about GPU usage, see `LUNA SDK documentation `_ It also needs to add required GPU plans to `fsdk/data` folder. Add the following code to the example to enable GPU usage for all estimators/extractor: .. code-block:: python :caption: example from lunavl.sdk.launch_options import DeviceClass, LaunchOptions from lunavl.sdk.faceengine.setting_provider import RuntimeSettingsProvider ... runtimeSettings = RuntimeSettingsProvider() runtimeSettings.runtimeSettings.deviceClass = DeviceClass.gpu faceEngine = VLFaceEngine(runtimeConf=runtimeSettings) ... Add the following code to the example to enable GPU usage for one specified estimator/extractor: .. code-block:: python :caption: example from lunavl.sdk.launch_options import DeviceClass, LaunchOptions ... faceEngine = VLFaceEngine() extractor = faceEngine.createFaceDescriptorEstimator(launchOptions=LaunchOptions(deviceClass=DeviceClass.gpu)) ...