Model preparation
Choosing deployment type
In order to successfully deploy your model for CloudVVUQ usage you must consider few aspects:
- Available services to you
- Source code language
- Services such as Google Cloud Functions do not support every language as runtime. If your code is written in e.g. Octave you have to use services that support running custom container images.
- Maximum execution time of your model
- If you deploy a model which takes 30 min to compute you should not use AWS Lambda but Google Cloud Run instead. More about the service-specific quotas in cloud configuration section.
- Dependencies
- If you need to package custom software or dependencies along the model's source code container image is your best option as deployment type.
Model preparation
In this step we assume you have a working computational model.
To prepare the model for deployment you must:
- specify requirements and dependencies
- support execution of the model which takes path to a json-file with model arguments/samples and saves results to json-file
For the 2nd step provide a command-line interface for your model such as:
Below is copy-ready code (in Python).
import sys
import json
json_input = sys.argv[1]
with open(json_input, 'r') as fd:
inputs = json.load(fd)
This is simple communication by file. The parent-process passes the filepath to child-process. Child process reads the sample's values from the file, executes the model with those values and returns the results to the parent in another file. The parent then sends back the response with model outputs to the client.
Alternatively if your model is written in Python you can import the interface method in the "server" code
This way you can skip the communication by files. Also, you slightly reduce the execution time because you don't start and new process but reuse existing one. Noticeable difference only for very fast models (<1s).Wrapper code ("server" code)
Each service requires slightly different wrapper code. Here are boilerplate code for each service. Reuse existing code are replace the 'model.py' with relative path to your model's code.
AWS Lambda - layers
import json
import subprocess
def lambda_handler(event, context):
input_json = event['body'] # extract sample
input_file = f"/tmp/input_{input_json['input_id']}.json"
input_json["outfile"] = f"/tmp/output_{input_json['input_id']}.json" # add outfile path to sample dict
with open(input_file, "w+") as f: # save sample to file
json.dump(input_json, f)
subprocess.run(["python3", "model.py", input_file]) # start a new process with model computation and pass sample
with open(input_json["outfile"]) as f: # read results from output file
result = json.load(f)
result.update(input_json)
return result # return model outputs to the client
AWS Lambda - image
import json
import subprocess
def lambda_handler(event, context):
input_json = json.loads(event['body'])
input_file = f"/tmp/input_{input_json['input_id']}.json"
input_json["outfile"] = f"/tmp/output_{input_json['input_id']}.json"
with open(input_file, "w+") as f:
json.dump(input_json, f)
subprocess.run(["python3", "model.py", input_file])
with open(input_json["outfile"]) as f:
result = json.load(f)
result.update(input_json)
return {
"statusCode": 200,
"body": json.dumps(result),
"headers": {
"content-type": "application/json"
},
"isBase64Encoded": False
}
Google Cloud Run
import os
import json
import subprocess
from flask import Flask, request
app = Flask(__name__)
@app.route("/", methods=["POST"])
def run_script():
input_json = request.get_json()
input_file = f"/tmp/input_{input_json['input_id']}.json"
input_json["outfile"] = f"/tmp/output_{input_json['input_id']}.json"
with open(input_file, "w+") as f:
json.dump(input_json, f)
subprocess.run(["python3", "model.py", input_file], capture_output=True)
with open(input_json["outfile"]) as f:
result = json.load(f)
result.update(input_json)
os.remove(input_file)
os.remove(input_json["outfile"])
return result
if __name__ == "__main__":
app.run(debug=False, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Google Cloud Functions
import json
import subprocess
def run_script(request):
input_json = request.get_json()
input_file = f"/tmp/input_{input_json['input_id']}.json"
input_json["outfile"] = f"/tmp/output_{input_json['input_id']}.json"
with open(input_file, "w+") as f:
json.dump(input_json, f)
subprocess.run(["python3", "model.py", input_file])
with open(input_json["outfile"]) as f:
result = json.load(f)
result.update(input_json)
return result