Flask App

Flask is a micro web framework written in Python. We first show how a simple service works, and then show how to load a model (e.g., based on pytorch) and serve it as well.

Weather Reporting Service

The key thing to see here are that the HTTP route / is mapped directly to a function weather. For instance, when someone hits localhost:5000 (5000 is the default unless specified in app.run() below) the function weather starts execution based on any received inputs.


# load Flask 
import flask
from flask import jsonify
from geopy.geocoders import Nominatim
import requests

app = flask.Flask(__name__)

# define a predict function as an endpoint 
@app.route("/", methods=["GET","POST"])
def weather():

    data = {"success": False}
    #https://pypi.org/project/geopy/
    geolocator = Nominatim(user_agent="cloud_function_weather_app")


    params = flask.request.json
    if params is None:
        params = flask.request.args


    # params = request.get_json()
    if "msg" in params:
        location = geolocator.geocode(str(params['msg']))
        # https://www.weather.gov/documentation/services-web-api
        result1 = requests.get(f"https://api.weather.gov/points/{location.latitude},{location.longitude}")
        result2 = requests.get(f"{result1.json()['properties']['forecast']}")
        data["response"] = result2.json()
        data["success"] = True
    return jsonify(data)
    
# start the flask app, allow remote connections
if __name__ == '__main__':
    app.run(host='0.0.0.0')


This service can be run by using the command python weather.py (assuming that is the filename for the above script) locally. If the port 5000 is open, then this server will be accessible to the world if the server has an external IP address.

Model Serving

We can modify the above to serve the recommendation models we built earlier as follows:

from surprise import Dataset
from surprise.dump import load
from collections import defaultdict
import pandas as pd
import flask

def get_top_n(predictions, n=10):

    # First map the predictions to each user.
    top_n = defaultdict(list)
    for uid, iid, true_r, est, _ in predictions:
        top_n[uid].append((iid, est))

    # Then sort the predictions for each user and retrieve the k highest ones.
    for uid, user_ratings in top_n.items():
        user_ratings.sort(key=lambda x: x[1], reverse=True)
        top_n[uid] = user_ratings[:n]

    return top_n


df = pd.read_csv('./movies.dat',sep="::",header=None,engine='python')
df.columns = ['iid','name','genre']
df.set_index('iid',inplace=True)
predictions, algo = load('./surprise_model')
top_n = get_top_n(predictions, n=5)
app = flask.Flask(__name__)

# define a predict function as an endpoint
@app.route("/", methods=["GET"])
def predict():
    data = {"success": False}


    # check for passed in parameters   
    params = flask.request.json
    if params is None:
        params = flask.request.args
    
    if "uid" in params.keys(): 
        data["response"] = str([df.loc[int(iid),'name'] for (iid, _) in top_n[params.get("uid")]])
        data["success"] = True
        
    # return a response in json format 
    return flask.jsonify(data)


# start the flask app, allow remote connections
app.run(host='0.0.0.0')

You can use the following request in the browser http://0.0.0.0:5000/?uid=196 or use the requests module.