Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ML engine library does not work. #241

Closed
Mistobaan opened this issue Nov 9, 2017 · 12 comments
Closed

The ML engine library does not work. #241

Mistobaan opened this issue Nov 9, 2017 · 12 comments
Assignees
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.

Comments

@Mistobaan
Copy link

I have to manually patch the library to make it work:

diff --git a/ml/v1/ml.go b/ml/v1/ml.go
index 30573fa..498edb1 100644
--- a/ml/v1/ml.go
+++ b/ml/v1/ml.go
@@ -14,15 +14,16 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	context "golang.org/x/net/context"
-	ctxhttp "golang.org/x/net/context/ctxhttp"
-	gensupport "google.golang.org/api/gensupport"
-	googleapi "google.golang.org/api/googleapi"
 	"io"
 	"net/http"
 	"net/url"
 	"strconv"
 	"strings"
+
+	context "golang.org/x/net/context"
+	ctxhttp "golang.org/x/net/context/ctxhttp"
+	gensupport "google.golang.org/api/gensupport"
+	googleapi "google.golang.org/api/googleapi"
 )
 
 // Always reference these packages, just in case the auto-generated code
@@ -2731,15 +2732,21 @@ func (c *ProjectsPredictCall) doRequest(alt string) (*http.Response, error) {
 	}
 	reqHeaders.Set("User-Agent", c.s.userAgent())
 	var body io.Reader = nil
-	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudmlv1__predictrequest)
-	if err != nil {
-		return nil, err
-	}
+	// body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudmlv1__predictrequest)
+	// if err != nil {
+	// 	return nil, err
+	// }
+	body = strings.NewReader(c.googlecloudmlv1__predictrequest.HttpBody.Data)
+
 	reqHeaders.Set("Content-Type", "application/json")
 	c.urlParams_.Set("alt", alt)
 	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:predict")
 	urls += "?" + c.urlParams_.Encode()
-	req, _ := http.NewRequest("POST", urls, body)
+	req, err := http.NewRequest("POST", urls, body)
+	if err != nil {
+		return nil, err
+	}
+
 	req.Header = reqHeaders
 	googleapi.Expand(req.URL, map[string]string{
 		"name": c.name,
@@ -2779,10 +2786,17 @@ func (c *ProjectsPredictCall) Do(opts ...googleapi.CallOption) (*GoogleApi__Http
 			HTTPStatusCode: res.StatusCode,
 		},
 	}
-	target := &ret
-	if err := json.NewDecoder(res.Body).Decode(target); err != nil {
+
+	var b bytes.Buffer
+
+	io.Copy(&b, res.Body)
+
+	if err := json.NewDecoder(bytes.NewReader(b.Bytes())).Decode(&ret); err != nil {
 		return nil, err
 	}
+
+	ret.Data = b.String()
+
 	return ret, nil
 	// {
 	//   "description": "Performs prediction on the data in the request.\n\n**** REMOVE FROM GENERATED DOCUMENTATION",

creating the request with:

func newMLRequest(image []byte) (*ml.GoogleCloudMlV1__PredictRequest, error) {

	imageStrValue := base64.StdEncoding.EncodeToString(image)

	jsonreq := request{
		Instances: []instance{
			{
				Key: "0",
				Image: imageb64{
					B64: imageStrValue,
				},
			},
		},
	}

	payload, err := json.Marshal(&jsonreq)
	if err != nil {
		return nil, errors.Wrap(err, "mkreq could not marshal JSON")
	}

	body := &ml.GoogleApi__HttpBody{
		Data: string(payload),
	}

	req := ml.GoogleCloudMlV1__PredictRequest{
		HttpBody: body,
	}

	req.HttpBody.ContentType = "application/json"

	return &req, nil
}

and calling the service with:

	req, err := newMLRequest(image)
	if err != nil {
		return nil, nil, errors.Wrap(err, "newMLRequest")
	}

	mlPredictCall := s.ml.Projects.Predict(s.endpoint, req)

	r, err := mlPredictCall.Context(ctx).Do()
	if err != nil {
		return nil, nil, errors.Wrap(err, "ml.predict")
	}

	var msg PredictionResponse

	log.Printf("%#v", r.Data)

	if err := json.NewDecoder(strings.NewReader(r.Data)).Decode(&msg); err != nil {
		if _, ok := err.(*json.SyntaxError); ok {
			return nil, nil, errors.Wrap(err, "ml.predict returned an unexpected json")
		}
	}

	if len(msg.Predictions) == 0 {
		return
	}
@carlosrgomes
Copy link

Hi @Mistobaan , how are you? Were you able to use ML's predict api in golang? I'm trying and it always makes mistakes.

@Mistobaan
Copy link
Author

Yes, apply that patch and is able to do the prediction correctly. Keep in mind that how you setup the input of the model is important too.

@carlosrgomes
Copy link

Thanks I was able to call api predict! I did according to your path.

@fdc-christiansteck
Copy link

fdc-christiansteck commented Mar 8, 2018

Thanks, this has been very helpful!
I put the library with your patches in a vendor folder in my project and can now make predictions.

Before patching the json payload got wrapped in a http body, which resulted in the following error message in the Cloud ML Engine logs:

jsonPayload: {
@type:  "type.googleapis.com/google.cloud.ml.v1.PredictionLogEntry"   
message:  "{"error": "Invalid request. The service expects the request to be a valid JSON object with a list-valued attribute called `instances`, i.e. `{\"instances\": [...]}`. The received request was:\n{\"httpBody\":{\"contentType\":\"application/json\",\"data\":\"{\"instances\": [...]}\"}}\n"}"
numInstances:  "1"   
}

@samsends
Copy link

samsends commented May 10, 2018

Mistake:

Appears to be fixed @Mistobaan

@fdc-christiansteck
Copy link

Unfortunately the new version (2018-04-26) still doesn't work for me, error is the same as before.

@samsends
Copy link

samsends commented May 11, 2018

@christiansteck Sorry, I was using a vendored version by mistake. I published this patch to GitHub as a temporary fix. Hopefully it works for you.

import  "github.com/tensortask/go-ml-engine/v1"

@JustinBeckwith JustinBeckwith added priority: p2 Moderately-important priority. Fix may not be included in next release. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. labels Jun 7, 2018
@jba jba self-assigned this Jun 7, 2018
@JustinBeckwith JustinBeckwith added the 🚨 This issue needs some love. label Jun 8, 2018
@destagia
Copy link

destagia commented Jul 6, 2018

I have the same problem. How is the progress and when will this be fixed?

@jba
Copy link
Contributor

jba commented Aug 13, 2018

We're actively working on this. Sorry, no ETA yet.

@jeanbza jeanbza assigned jba and jeanbza and unassigned jba Sep 17, 2018
@jeanbza jeanbza removed 🚨 This issue needs some love. priority: p2 Moderately-important priority. Fix may not be included in next release. labels Sep 17, 2018
@JustinBeckwith JustinBeckwith added the 🚨 This issue needs some love. label Sep 17, 2018
@jeanbza jeanbza added the priority: p2 Moderately-important priority. Fix may not be included in next release. label Sep 17, 2018
@christianwiese
Copy link

We are also desperately waiting for a solution here. Especially, since with go1.11 modules we can not vendor our own patch anymore and do not really want to create a separate fork for this.

@jeanbza
Copy link
Member

jeanbza commented Oct 16, 2018

This is on my radar, but we're dealing with several high priority issues at the moment. I'm hoping to return to this soon.

@enocom enocom self-assigned this Oct 22, 2018
gopherbot pushed a commit that referenced this issue Oct 30, 2018
Releated to #241.

Change-Id: I577740c3a2f0f88ffc23ac4850dba3f38872ae17
Reviewed-on: https://code-review.googlesource.com/c/34810
Reviewed-by: Jean de Klerk <deklerk@google.com>
@enocom enocom removed the 🚨 This issue needs some love. label Oct 31, 2018
@JustinBeckwith JustinBeckwith added the 🚨 This issue needs some love. label Oct 31, 2018
@christianwiese
Copy link

Works like a charm 🎉. Thanks for your effort.

@enocom enocom removed the 🚨 This issue needs some love. label Nov 2, 2018
gopherbot pushed a commit that referenced this issue Apr 30, 2019
This takes a different approach than the changes made for the ML API
(see #241). Healthcare and ML API, strangely, have different formats for
HttpBody. They are the only two APIs currently using HttpBody.

This change makes any HttpBody call accept an io.Reader, which is used
as the HTTP request's Body. Headers can be added using the existing
Header() function on the Call. Additional headers and parameters are not
added, nor is any processing done on the response.

This is quite a bit better than requiring users construct their own
*http.Request, because they get type safety on the correct method and
URL path parameters via the discovery service.

Updates #344.

Code looks like this to use:

	call := fhirService.CreateResource(parent, resourceType, bytes.NewReader(jsonPayload))
	call.Header().Set("Content-Type", "application/fhir+json;charset=utf-8")
	resp, err := call.Do()
	if err != nil {
		return fmt.Errorf("CreateResource: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 {
		return fmt.Errorf("CreateResource: status %d %s", resp.StatusCode, resp.Status)
	}

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("Could not read response: %v", err)
	}

Change-Id: I87cbf7535fbdeacf8cf74ba4ead82ecbd9f187f8
Reviewed-on: https://code-review.googlesource.com/c/google-api-go-client/+/39310
Reviewed-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Tyler Bui-Palsulich <tbp@google.com>
Reviewed-by: Jean de Klerk <deklerk@google.com>
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Apr 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns.
Projects
None yet
Development

No branches or pull requests