gogoogle-cloud-rungoogle-cloud-vertex-ai

aiplatformb.PredictRequest.Instances expects type []*structpb.Value (GCP golang client library; aiplatform)


I am trying to hit my Vertex AI endpoint from a Golang web application (the web server/application is running on cloud run+build). The web application has a form that I'm landing into the Details Submission, my question is, how do I take the struct received from the web application and cast it to a type accepted in the Instances field of the aiplatformb.PredictRequest struct?

   type Submission struct {
        MonthlyIncome                 int
        Age                           int
        Passport                      int
    }

    var Details = Submission{}


    Ctx := context.Background()
        C, err := aiplatform.NewPredictionClient(Ctx)
    
        if err != nil {
            log.Fatalf("Error 1: %v", err)
        }

        defer C.Close()

        reqs := &aiplatformpb.PredictRequest{
            Endpoint:  "{{my endpoint that is formatted correctly}",
            Instances: []*structpb.Value{},

I've tried hitting this endpoint externally using postman and the request below confirms the endpoint is up and running. Those values are the values of the Details Submission

    {
        "instances": [
            [
                29823,
                43.5,
                1
            ]
        ]
    }

Solution

  • After several attempts using the client libraries and consulting documentation, the .Predict() method [which acts on a pointer to PredictionClient type] doesn't allow you to specify the schema of the vertex AI model endpoint. So the solution is to send the request via the .RawPredict() method, so making a serialized JSON (structpb) request works only if the schema implemented by the golang GCP client library matches that of your deployed model.

    Here's the GCP documentation for PredictionClient:

    https://cloud.google.com/go/docs/reference/cloud.google.com/go/aiplatform/1.0.0/apiv1#cloud_google_com_go_aiplatform_apiv1_PredictionClient

    Here are the necessary libraries for forming and using the RawPredict() method:

    import (
        "context"
        "fmt"
        "log"
        "reflect"
        "strconv"
    
        aiplatform "cloud.google.com/go/aiplatform/apiv1"
        "cloud.google.com/go/aiplatform/apiv1/aiplatformpb"
        "google.golang.org/api/option"
        "google.golang.org/genproto/googleapis/api/httpbody"
    )
    

    And here's the code:

    // Get the form values from the web application
        income, _ := strconv.Atoi(r.FormValue("MonthlyIncome")) 
        age, _ := strconv.Atoi(r.FormValue("Age"))
        passport, _ := strconv.Atoi(r.FormValue("Passport"))
    
    // create our struct from the form values
    
        Details = Submission{
            MonthlyIncome:                 income,
            Age:                           age,
            Passport:                      passport,
        }
    
        v := reflect.ValueOf(Details)
        body = ""
    
        for i := 0; i < v.NumField(); i++ {
    
            body = body + fmt.Sprintf("%v", v.Field(i).Interface()) + ","
        }
    
        if last := len(body) - 1; last >= 0 && body[last] == ',' {
            body = body[:last]
        }
    
        Requestb = pre + body + post
        log.Println("The request string was:", Requestb)
    
        // structure the body of the raw request
        Raw := &httpbody.HttpBody{}
        Raw.Data = []byte(Requestb)
    
        // identify the post request using the raw body and the endpoint
        reqs := &aiplatformpb.RawPredictRequest{
    
        // Note  GCP Project ID, Region, and endpoint ID
            Endpoint: "projects/<PROJECT-HERE>/locations/<REGDION-HERE>/endpoints/<ENDPOINT-ID-HERE>",
            HttpBody: Raw,
        }
    
    
        // CTX gets the credentials of the application service account - NOTE THE REGION
        Ctx := context.Background()
        C, err := aiplatform.NewPredictionClient(Ctx, option.WithEndpoint("<REGION-HERE>-aiplatform.googleapis.com:443"))
    
        if err != nil {
            log.Println("Error 1, connectrion:", err)
        }
        defer C.Close()
    
        // gets the response using the credentials of the application service account
        resp, err := C.RawPredict(Ctx, reqs)
        if err != nil {
            log.Fatalf("Error 2, response: %v", err)
        }
        log.Println(resp)
    
    
        RespString := fmt.Sprintf("%+v", resp)
        log.Println("The Response String was:", resp)