pythongoogle-cloud-platformgoogle-cloud-vertex-aigoogle-ai-platform

Google Vertex AI Prediction API Prediction request error


I am trying to pass a Python Dict into aiplatform_v1.PredictRequest and make prediction with aiplatform_v1.PredictionServiceAsyncClient.

I have encountered this error: TypeError: Argument for field google.cloud.aiplatform.v1.PredictRequest.instances is not iterable

I have parsed my Python Dict into google.protobuf value and wrap it as a list, which should be iterable, as shown in this
Official Python Request Sample Link

Below please find my code for reference:

from google.protobuf.struct_pb2 import Value, Struct, ListValue
from google.protobuf import json_format
from google.oauth2 import service_account
from google.api_core import exceptions
from google.cloud import aiplatform_v1

async def model_predict(json_data):

    # Load credentials from a service account key file
    key_path = 'path-to-key-file.json'
    credentials = service_account.Credentials.from_service_account_file(
        key_path,
        scopes=['https://www.googleapis.com/auth/cloud-platform']
    )
   
    # Set up the endpoint configs and pass user input
    project_id = "XXXXXX"
    endpoint_id = "XXXXXXX"
    instance_dict = json_data
    location = "us-central1"
    api_endpoint = "us-central1-aiplatform.googleapis.com"
    
    # Format user input to pass into request
    instance = json_format.ParseDict(instance_dict, Value())
    parameters_dict = {}
    parameters= json_format.ParseDict(parameters_dict, Value())

    # Set up async prediction service client 
    client_options = {"api_endpoint": api_endpoint}

    prediction_client = aiplatform_v1.PredictionServiceAsyncClient(
        credentials=credentials, client_options=client_options
    )

    # Build Prediction request
    endpoint_path = prediction_client.endpoint_path(
        project=project_id, location=location, endpoint=endpoint_id,
    )

    request = aiplatform_v1.PredictRequest(
        endpoint=endpoint_path, instances= [instance], parameters = parameters
    )

    # Call the predict method asynchronously
    try:
        response = await prediction_client.predict(request=request)
        print(response)
        predictions = response.predictions

        return predictions, None

    except exceptions.GoogleAPIError as error:
        error_message = f"Prediction request failed: {error}"
        return None, error_message

I have printed the type and sample of instances passed through under this code. \

<class 'google.protobuf.struct_pb2.Value'> struct_value { fields { key: "Ticket_Subject" value { string_value: "Battery Issue" } } fields { key: "Ticket_Status" value { string_value: "Open" } } fields { key: "Ticket_Priority" value { string_value: "High" } } .... (more fields structured as above) }


Solution

  • Self-Answered

    #1
    Google has updated its protobuf package to rely on Proto Plus for Python
    Link to Library

    Inside the PDF documentation which is available for download, on P.17
    You can see that only ListValue are considered to be Mutable Sequence, which is the requirement for instance object in Google Prediction Request
    You can only append values into a ListValue Object, instead of direct assignment.

    #2
    Regarding the use of PredictionServiceAsyncClient to make PredictRequest:
    You can choose not to parse the instance_dict and directly append instead.

    from google.cloud import aiplatform_v1
    
    client_options = {"api_endpoint": api_endpoint}
    
    prediction_client = aiplatform_v1.PredictionServiceAsyncClient(
        credentials=credentials, 
        client_options=client_options
    )
    
    # Build Prediction request
    # Append the input python dictonary as instances
    endpoint_path = prediction_client.endpoint_path(
        project=project_id, location=location, endpoint=endpoint_id,
    )
    
    # Direct append instance_dict as instances
    request = aiplatform_v1.PredictRequest()
    request.endpoint = endpoint_path
    request.instances.append(instance_dict)
    
    # Call the predict method asynchronously
    try:
        response = await prediction_client.predict(request=request)
        predictions = response.predictions
        return predictions, None
    
    except exceptions.GoogleAPIError as error:
        error_message = f"Prediction request failed: {error}"
        return None, error_message