How to create a Python Text Classifier as a Cloud Function?

How to create a Python Text Classifier as a Cloud Function?

Previous reading: How to use the Serverless Manager module?

 

In this post, we are going to see an example of how to migrate a Flask application to a Cloud Function.

This is a classifier with a series of pre-trained models, that exposes a REST endpoint to predict a classification based on a text.

Code structure

The structure of the code is as follows:

The main is contained in the application.py file, where the flask application is launched and the “/predict” endpoint is declared.

#!/usr/bin/env python # coding: utf-8 # # Imports from flask import Flask, request, Response import numpy as np import pandas as pd import pickle import json import base64 # # Load models from model import load_model, predict primario_model, primario_vectorizer, primario_encoder = load_model() # Instantiate a flask application app = Flask(__name__) # Define the paths where we are going to work APP_PATH = app.root_path @app.route('/predict', methods=['POST']) def predict_post(): if request.method == 'POST': result = {} request_data = request.data.decode('latin1') request_data = json.loads(request_data, strict=False) content_str = request_data.get('text', '') base64_content = request_data.get('base64', False) if base64_content: content_str = base64.b64decode(content_str) if content_str: result = predict(content_str, primario_model, primario_vectorizer, primario_encoder) return Response( json.dumps(result), mimetype='application/json') # Main function that starts the service if __name__ == '__main__': app.run(host='localhost', port=8000, debug = False)

This will be the code that we will have to adapt in order to deploy the Flask application as a function. The rest of the pickles and components of the application will be packed in the function, so they will be accessible by the main without the need to modify anything.

Adaptation of the main

Following the official documentation of the repository, we will adapt the main class to be able to deploy it as a function.

We will need to create a new class “func.py” (the name doesn't matter, but we'll have to write it down in the Dockerfile later).

This class should be identical to "application.py", except because we will not be using Flask, and therefore those dependencies can be removed. Instead, we'll read the input data through a "handler" method that exposes the python FDK API.

def handler(ctx, data: io.BytesIO = None):

In the latest versions of the FDK API, data becomes a byte array instead of a string, thus increasing the flexibility to decode input content (e.g. non-UTF-8 encodings).

This method will have the content of the original predict_post() method, with the adaptations to read the data from the “data” variable, and will return a response with the FDK API instead of the Flask one.

# # Imports import io import json import logging import numpy as np import pandas as pd import pickle import base64 from fdk import response # # Load models from model import load_model, predict primario_model, primario_vectorizer, primario_encoder = load_model() def handler(ctx, data: io.BytesIO = None): result = {} byte_str = data.read() request_data = byte_str.decode('latin1') request_data = json.loads(request_data, strict=False) content_str = request_data.get('text', '') base64_content = request_data.get('base64', False) if base64_content: content_str = base64.b64decode(content_str) if content_str: result = predict(content_str, primario_model, primario_vectorizer, primario_encoder) return response.Response(ctx, response_data=json.dumps(result),headers={"Content-Type": "application/json"})

Yaml of the function

The next step is to create a Yaml descriptor for the Fn to process when building and deploying the function.

In this yaml, we must also define the endpoint that we want, to be able to invoke the function.

schema_version: 20180708 name: clasificador version: 0.0.1 runtime: python memory: 512 triggers: - name: endpoint type: http source: /predict

Depending on the (estimated) memory required, we may want to change the limit of “memory”.

Dockerfile of the function

Lastly, we will need to define a Dockerfile to deploy the function. This Dockerfile is provided generically in the Fn documentation.

We will be able to modify the generic Dockerfile to choose the version of Python that we want, in addition to being able to install dependencies or custom libraries.

FROM fnproject/python:3.7-dev as build-stage WORKDIR /function ADD requirements.txt /function/ #START ADDED LINE RUN pip3 install --force-reinstall numpy==1.19.4 #END ADDED LINE RUN pip3 install --target /python/ --no-cache --no-cache-dir -r requirements.txt &&\ rm -fr ~/.cache/pip /tmp* requirements.txt func.yaml Dockerfile .venv &&\ chmod -R o+r /python ADD . /function/ RUN rm -fr /function/.pip_cache FROM fnproject/python:3.7 WORKDIR /function COPY --from=build-stage /python /python COPY --from=build-stage /function /function RUN chmod -R o+r /function ENV PYTHONPATH=/function:/python ENTRYPOINT ["/python/bin/fdk", "/function/func.py", "handler"]

In this case, we have used version 3.7, which was compatible with the declared versions of the dependencies.

As we can see, the installation of Python dependencies takes those from the requirements.txt file, so it is important that this file has the fdk dependency.

fdk>=0.1.47

You can also see that the only extra line added to the generic Dockerfile is the one commented out:

RUN pip3 install --force-reinstall numpy==1.19.4

This is because this library needs to be installed first before the others.

Create the function in platform

Git repository

In order to create the function and deploy it to the platform, we will need to upload the code to a Git repository.

Create the application

With the Git code uploaded, we will create the serverless application in the platform (review the previous guide for these steps).

Create the function

Finally, we will create the function indicating the name and the path to “func.yaml”, taking into account that the structure of the repository is as follows:

Deploy the function

Once the function is defined within the application, we will deploy it.

Test the function

Finally, we will test the function deployed through the defined endpoint:

curl --silent --location --request POST 'https://development.onesaitplatform.com/fn/t/plenitude-classifier/predict' \ --header 'Content-Type: application/json' \ --data-raw '{ "text": "TASACIÓN DE VIVIENDA EN EDIFICIO Firma electrónica RESUMEN DE TASACIÓN Solicitante: NIF/CIF: Tipo de inmueble: Nº expediente: VIVIENDA EN EDIFICIO ALICANTE ESPAÑA País: Provincia: Municipio: Población: CP: Vía Pública: Nº: Bloque: Escalera: Planta: Puerta: 2 Ent. Mandataria: Finalidad Legal: Garantía hipotecaria de créditos o préstamos que formen o vayan a formar parte de la cartera de cobertura de títulos hipotecarios emitidos por las entidades, promotores y constructores a que se refiere el artículo segundo del Real Decreto 685/1982 de 17 de Marzo, por el que se desarrollan determinados aspectos de la Ley 2/1981, de 25 de marzo, de Regulación del Mercado Hipotecario. Provincia: País: ESPAÑA ALICANTE Domicilio del bien tasado: SUPERFICIES Sup. Const. con Z.C. Sup. const. Sup. Útil Sup. registrada Sup. comprobada Sup. valorada Vivienda m² m² m² m² m² m² m² m² m² Sup. catastral 90,00 m² 90,00 90,00 m² m² 106,55 106,55 106,55 119,00 116,10 116,10 Vivienda TABIMED es miembro de la Asociación Profesional de Sociedades de Valoración de España (A.T.A.S.A.) (*) El alcance de la Certificación AENOR se refiere a la Gestión de Expedientes de Tasación para todo tipo de bienes Página 1 de 3 Valor de tasación (Hipotecario): Valor mínimo a asegurar contra incendios y otros daños del continente CONDICIONANTES Y ADVERTENCIAS ADVERTENCIAS Consideración ligada al elemento Vivienda: A-42 Sobre el bien objeto de este expediente existen afecciones de cargas consistentes en servidumbres de luces y vistas, predio dominate la finca , predio sirviente la finca . Sevidumbre de paso recíproca predio dominante y sirviente las fincas 31.366 y 29.685, que no han sido tenidas en cuenta para la obtención del valor de tasación. Temporalidad: Riesgo: T-3 R-3 Consideración ligada al inmueble completo: A-34A Los linderos observados en la visita al bien no coinciden con los descritos en la Nota Simple aportada, sin embargo no existen dudas sobre la identificación del bien. Por lo que, a los efectos de finalidad hipotecaria deberá realizarse la adecuación de la descripción que figura en la Nota Simple con la realidad existente reflejada en este informe. Temporalidad: Riesgo: T-2 R-2 TABIMED, como asociado de A.T.A.S.A. es miembro de The European Group of Valuers Association (TEGOVA) TASACIÓN DE VIVIENDA EN EDIFICIO Consideración ligada al elemento Vivienda: A04A Se advierte que el bien objeto de estudio presenta una superficie edificada distinta de la que consta como reflejada en la documentación catastral. La diferencia radica en que: 1.- En la Nota Simple se indica una superficie construida de 106,55 m2 que se corresponde con la superficie construida sin comunes. 2.- En la ficha catastral se indica una superficie construida de 119,00 m2 3.- La superficie construida con comunes computable es de 116,10 m2, siendo coincidente la construida sin comunes (106,55 m2) con lo especificado en la Nota Simple. La diferencia se debe, posiblemente, a un error en la asignación catastral de la superficie. Este aspecto (en ausencia de condicionantes relacionados) no influye previsiblemente sobre los valores calculados; no obstante, esta discrepancia debería corregirse o regularse, si ello es posible, con arreglo a la realidad física comprobada en visita. Temporalidad: Riesgo: T-3 R-2 Consideración ligada al inmueble completo: A01A Se advierte que existen discrepancias entre la realidad física del inmueble y sus descripciones registral y catastral en cuanto a la localización, que no inducen a dudar sobre su identificación o características; no obstante, este aspecto debería ser corregido. Las discrepancias se deben a que: 1.- En la Nota Simple que el bien es de tipo B... y se ubica en la calle .... Temporalidad: Riesgo: T-3 R-3 OBSERVACIONES Ver en informe apartado Condicionantes, advertencias y observaciones. Situación de ocupación: Usuario actual (según visita): La propiedad Edad edificación: 10 DESGLOSE DE ELEMENTOS -DESGLOSE DEL VALOR DE TASACIÓN POR ELEMENTOS Elementos Valor de Tasación Seguro de incendios y otros daños del continente V.P.O. Vivienda (Vivienda en edificio vertical) VPO y se aporta documento acreditativo del VML TABIMED está inscrita en el registro especial de Sociedades de Tasación Hipotec. del Ministerio de E. y H. (B. de E. Nº 4320) desde 27-05-86 Página 3 de FINALIDAD LEGAL PARA LA QUE SE SOLICITA EL INFORME Garantía hipotecaria de créditos o préstamos que formen o vayan a formar parte de la cartera de cobertura de títulos hipotecarios emitidos por las entidades, promotores y constructores a que se refiere el artículo segundo del Real Decreto 685/1982 de 17 de Marzo, por el que se desarrollan determinados aspectos de la Ley 2/1981, de 25 de marzo, de Regulación del Mercado Hipotecario. " }'

The first time the function is called, it will take a long time, like in the screenshot above (4.52 seconds), but subsequent calls will be very fast: