0
votes

I tried to call predict request on one of my deployed models using the HTTP API method from postman and I got this as a response:

{ "error": { "code": 401, "message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" } }

I realised that we need authentication, So I tried using the Firebase Cloud Functions to make the same HTTP call and I still get the same response as above. I did a bit of digging and came across all the services that can used with cloud functions and I see ML Engine in it.

I added the Cloud Functions service account as ML Engine Owner in the permissions tab of my model, expecting it to add auth required for the API calls, which still did not work.

I don't want to use the cli or python-client-library for the same, the intention is to make this work server-less.

Anybody who can help me out on why this is happening or how else I could do a HTTP call to the predict request?

Thanks.

2

2 Answers

2
votes

Have you set the authorization header for the http request? Authorization: Bearer

There's some documentation here for cloud ml engine: https://cloud.google.com/ml-engine/docs/access-control

Documentation for another Google Cloud feature (concept is the same): https://cloud.google.com/vision/docs/auth#using_a_service_account

BTW, just in case, Functions is not a must and I believe you can call from your native apps passing an ApiKey in the header.

0
votes

For me it works as follows. Within the same google cloud project I have deployed ML model (ML Platform -> Models) and Cloud Function, I have created service account with role 'Cloud ML Developer'. Created service account name has to be provided in Cloud Function configuration:

enter image description here Code for cloud function: main.py

googleapiclient import discovery
import json

def run(request):
  request_json = request.get_json()
  if request.args and 'message' in request.args:
    return request.args.get('message')
  elif request_json and 'message' in request_json:
    return request_json['message']
  elif request_json and hasattr(request_json, "__len__"):
    res = ml_call(prepare_frame(request_json))
    return json.dumps(res) 

  else:
    return f'Request error'

def ml_call(req):    
  PROJECT = 'test_proj'
  MODEL_NAME = 'test_name'
  MODEL_VERSION = 'test_ver'
  parent = 'projects/{}/models/{}/versions/{}'.format(PROJECT, MODEL_NAME, MODEL_VERSION)

  # Build a representation of the Cloud ML API.
  ml = discovery.build('ml', 'v1')

  # Create a dictionary with the fields from the request body.
  data = {'instances': [{'input_image': req}]}

  # Create a request 
  request = ml.projects().predict(name = parent, body = data) 

  response = request.execute()
  return response

def prepare_frame(xxx):
...
  return x

requirements.txt:

google-api-python-client