Search code examples
google-cloud-platformgoogle-authenticationgoogle-ai-platform

Authenticating API Call to Google ML Engine with an API Key


I have a saved model in Google AI Platform that works when I test the predictions in the AI Platform UI.

However, when I try and access the API via REST, I keep getting a response with a 401 status. I would like to know how to do this successfully.

My api URL looks like the following:

'https://ml.googleapis.com/v1/projects/ml-project-name/models/my-model-names/versions/v2:predict

I would like to be able to access this endpoint in an external app that's residing on any platform to generate predictions with it.

Google Cloud recommends service account authorization, however, all of the directions for it require setting environment variables so the app can automatically authenticate you. I'd prefer to supply them directly in the request to make things more portable and congruent with how it's done elsewhere at work.

So instead I tried getting an API key.

According to this page: https://cloud.google.com/docs/authentication/api-keys you can authenticate a request in the following way:

POST https://language.googleapis.com/v1/documents:analyzeEntities?key=API_KEY

However, when I run the following code, my request status is 401:

import requests

api_key = my_sample_api_key
url     = f'https://ml.googleapis.com/v1/projects/project-name/models/model-name/versions/v2:predict?key={api_key}'

json    = {"instances": [ {"input_1": ["Please predict this text"]}]}

res = request.post(url, json=json)

Any help would be appreciated, thank you.


Solution

  • Auto ML does not support the use of API keys when sending requests. I suggest to use the auth token on your request or use the available client libraries to send predictions.

    Here is a code snippet using its python client library for sending prediction request:

    # Create the AI Platform service object.
    # To authenticate set the environment variable
    # GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_file>
    service = googleapiclient.discovery.build('ml', 'v1')
    
    def predict_json(project, model, instances, version=None):
        """Send json data to a deployed model for prediction.
    
        Args:
            project (str): project where the AI Platform Model is deployed.
            model (str): model name.
            instances ([Mapping[str: Any]]): Keys should be the names of Tensors
                your deployed model expects as inputs. Values should be datatypes
                convertible to Tensors, or (potentially nested) lists of datatypes
                convertible to tensors.
            version: str, version of the model to target.
        Returns:
            Mapping[str: any]: dictionary of prediction results defined by the
                model.
        """
        name = 'projects/{}/models/{}'.format(project, model)
    
        if version is not None:
            name += '/versions/{}'.format(version)
    
        response = service.projects().predict(
            name=name,
            body={'instances': instances}
        ).execute()
    
        if 'error' in response:
            raise RuntimeError(response['error'])
    
        return response['predictions']
    

    Here is a sample of sending a POST request using curl with the auth token:

    curl -X POST \
    -H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
    -H "Content-Type: application/json; charset=utf-8" \
    -d @request.json \
    https://ml.googleapis.com/v1/projects/your-project/models/you-model-name/versions/your-version-name:predict