Deploying a REST API using Anaconda Enterprise

With Anaconda Enterprise, you can create functions or models that can be easily deployed so other data scientists can use them without having to add a web stack.

Rather than giving other data scientists your model, you can give them an interface to the model, which you can then update, improve and redeploy.

You should know how to deploy a project and how to use deployment tokens to share the deployment.

This example is based on the Scotch whisky recommendation engine and can also be found at the ae_scotches_api folder within the Anaconda Enterprise distribution.

Make a scotch-recommending API

The original scotch classification data is from the Classification of whiskies page.

The data have been made public as a Python pickled dataframe.

  1. In a terminal window, enter these commands to add the data to download to the project:

    anaconda-project add-download FEATURES https://ibm.box.com/shared/static/2vntdqbozf9lzmukkeoq1lfi2pcb00j1.dataframe
    anaconda-project add-download SIM https://ibm.box.com/shared/static/54kzs5zquv0vjycemjckjbh0n00e7m5t.dataframe
    

    Or add the following to the file anaconda-project.yml:

    downloads:
      FEATURES:
        url: 'https://ibm.box.com/shared/static/2vntdqbozf9lzmukkeoq1lfi2pcb00j1.dataframe'
      SIM:
        url: 'https://ibm.box.com/shared/static/54kzs5zquv0vjycemjckjbh0n00e7m5t.dataframe'
    

    And in a terminal window run:

    anaconda-project prepare
    
  2. Add the packages that your REST API will depend on:

    anaconda-project add-packages pandas
    anaconda-project add-packages -c anaconda-enterprise anaconda-enterprise-web-publisher
    
  3. Open a Jupyter Notebook, rename it to Scotches and load the data.

    import os
    import pandas as pd
    import pickle
    
    features_pickle = os.getenv('FEATURES', '2vntdqbozf9lzmukkeoq1lfi2pcb00j1.dataframe')  # These ENV VARS were defined on add-download
    sim_pickle = os.getenv('SIM', '54kzs5zquv0vjycemjckjbh0n00e7m5t.dataframe')
    
    with open(features_pickle, 'rb') as pkl:
        features_df = pickle.loads(pkl.read())
    
    with open(sim_pickle, 'rb') as pkl:
        sim_df = pickle.loads(pkl.read())
    
  4. Add this code to be able to handle HTTP requests.

    Define a global REQUEST JSON string that will be replaced on each invocation of the API.

    import json
    REQUEST = json.dumps({
        'path' : {},
        'args' : {},
        'body': {}
    })
    
  5. Import the Anaconda Enterprise publish function.

    from anaconda_enterprise import publish
    
  6. Create a function that will be available from the /scotches URL when deployed.

    @publish()
    def scotches():
        names = sim_df.columns.tolist()
        return json.dumps(dict(names=names), indent=4)
    
  7. To be able to run, add this to the file anaconda-project.yml:

    commands:
      api:
        rest_api: Scotches.ipynb
        supports_http_options: true
        default: true
      default:
        notebook: Scotches.ipynb
        description: Run the notebook for local development
    
    variables:
      KG_FORCE_KERNEL_NAME: python3
    
  8. Then you can execute:

    anaconda-project run api
    
  9. Now if you visit http://localhost:8888/scotches from within the editing session you will see the list of scotches.

    From an editing session terminal, execute:

    curl localhost:8888/scotches
    
  10. To deploy the project as an API, go to the Project menu and select the Deploy project tab. From the command drop-down, select the api command.

    This deploys the notebook as an API which you can then query.

  11. To query externally, create a token and find the url to the running project. You can do both from the deployment view of your project.

    Go to the deployments menu and click on your deployed project. On the Advanced tab, find the url for the running project. Click the Generate button. This generates a long JWT token. A JWT token is a JSON Web Token, and JSON is JavaScript Object Notation.

    Example using curl:

    export TOKEN="<generated-token-goes-here>"  # save long string of text in variable
    curl -L -H "Authorization: Bearer $TOKEN" <url-of-project>
    

    The -L option tells curl to follow redirects. The -H adds a header. In this case -H adds the token required to authorize the client to visit that URL.

  12. You can also use Postman. Remember to include the authorization header.

  13. You can specify the HTTP verb you want use to access the data:

    @publish(methods=['POST'])
    def scotch_details(name):
        features = features_df.loc[name]
        return '{"features":%s}' % features.to_json()
    

    If you do curl -X POST -d name=Talisker 127.0.0.1:8889/scotch_details or POST to the platform, you can use the REST API to access data about the scotch named Talisker.

    If you deploy the project as described above you can add the -X POST option to curl to access that function.