【问题标题】:Vertex AI - Endpoint Call with JSON - Invalid JSON payload receivedVertex AI - 使用 JSON 的端点调用 - 收到无效的 JSON 有效负载
【发布时间】:2022-08-02 12:53:07
【问题描述】:

我在 Vertex AI 上成功训练并部署了一个 Tensorflow Recommender 模型。

一切都在线并预测输出。在笔记本中我这样做:

loaded = tf.saved_model.load(path)
scores, titles = loaded([\"doctor\"])

返回:

Recommendations: [b\'Nelly & Monsieur Arnaud (1995)\'
 b\'Three Lives and Only One Death (1996)\' b\'Critical Care (1997)\']

也就是说,有效载荷(神经网络的输入)必须是[\"doctor\"]

然后我为有效负载生成 JSON(错误在这里):

!echo {\"\\\"\"instances\"\\\"\" : [{\"\\\"\"input_1\"\\\"\" : {[\"\\\"\"doctor\"\\\"\"]}}]} > instances0.json

并提交到端点:

!curl -X POST  \\
-H \"Authorization: Bearer $(gcloud auth print-access-token)\" \\
-H \"Content-Type: application/json\" \\
https://us-west1-aiplatform.googleapis.com/v1/projects/my_project/locations/us-west1/endpoints/123456789:predict \\
-d @instances0.json > results.json

... 如此处所示:https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/master/notebooks/community/vertex_endpoints/tf_hub_obj_detection/deploy_tfhub_object_detection_on_vertex_endpoints.ipynb#scrollTo=35348dd21acd

但是,当我使用此有效负载时,我收到错误 400:

code: 400
message: \"Invalid JSON payload received. Expected an object key or }. s\" : [{\"input_1\" : {[\"doctor\"]}}]} ^\"
status: \"INVALID_ARGUMENT\"

下面的这个也不起作用:

!echo {\"inputs\": {\"input_1\": [\"doctor\"]}} > instances0.json

即使使用经过验证的 JSON Lint,它也不会返回正确的预测。

在另一个 Stackoverflow 问题中,建议删除有效负载中的 \" \\ \" ,但这也不起作用。

跑步:

!saved_model_cli show --dir /home/jupyter/model --all

我得到:

MetaGraphDef with tag-set: \'serve\' contains the following SignatureDefs:

signature_def[\'__saved_model_init_op\']:
  The given SavedModel SignatureDef contains the following input(s):
  The given SavedModel SignatureDef contains the following output(s):
    outputs[\'__saved_model_init_op\'] tensor_info:
        dtype: DT_INVALID
        shape: unknown_rank
        name: NoOp
  Method name is: 

signature_def[\'serving_default\']:
  The given SavedModel SignatureDef contains the following input(s):
    inputs[\'input_1\'] tensor_info:
        dtype: DT_STRING
        shape: (-1)
        name: serving_default_input_1:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs[\'output_1\'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 10)
        name: StatefulPartitionedCall_1:0
    outputs[\'output_2\'] tensor_info:
        dtype: DT_STRING
        shape: (-1, 10)
        name: StatefulPartitionedCall_1:1
  Method name is: tensorflow/serving/predict


Concrete Functions:
  Function Name: \'__call__\'
    Option #1
      Callable with:
        Argument #1
          input_1: TensorSpec(shape=(None,), dtype=tf.string, name=\'input_1\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: True
    Option #2
      Callable with:
        Argument #1
          queries: TensorSpec(shape=(None,), dtype=tf.string, name=\'queries\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: True
    Option #3
      Callable with:
        Argument #1
          input_1: TensorSpec(shape=(None,), dtype=tf.string, name=\'input_1\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: False
    Option #4
      Callable with:
        Argument #1
          queries: TensorSpec(shape=(None,), dtype=tf.string, name=\'queries\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: False

  Function Name: \'_default_save_signature\'
    Option #1
      Callable with:
        Argument #1
          input_1: TensorSpec(shape=(None,), dtype=tf.string, name=\'input_1\')

  Function Name: \'call_and_return_all_conditional_losses\'
    Option #1
      Callable with:
        Argument #1
          input_1: TensorSpec(shape=(None,), dtype=tf.string, name=\'input_1\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: False
    Option #2
      Callable with:
        Argument #1
          queries: TensorSpec(shape=(None,), dtype=tf.string, name=\'queries\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: True
    Option #3
      Callable with:
        Argument #1
          queries: TensorSpec(shape=(None,), dtype=tf.string, name=\'queries\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: False
    Option #4
      Callable with:
        Argument #1
          input_1: TensorSpec(shape=(None,), dtype=tf.string, name=\'input_1\')
        Argument #2
          DType: NoneType
          Value: None
        Argument #3
          DType: bool
          Value: True

关键是:我正在传递一个数组,但我不确定它是否必须是 b64 格式。

此 Python 代码有效,但返回的结果与预期不同:

import tensorflow as tf
import base64
from google.protobuf import json_format
from google.protobuf.struct_pb2 import Value
import numpy as np
from google.cloud import aiplatform
import os
vertex_model = tf.saved_model.load(\"gs://bucket/model\")

serving_input = list(
    vertex_model.signatures[\"serving_default\"].structured_input_signature[1].keys()
)[0]

print(\"Serving input :\", serving_input)

aip_endpoint_name = (
    f\"projects/my-project/locations/us-west1/endpoints/12345567\"
)
endpoint = aiplatform.Endpoint(aip_endpoint_name)

def encode_input(input):
    return base64.b64encode(np.array(input)).decode(\"utf-8\")

instances_list = [{serving_input: {\"b64\": encode_input(np.array([\"doctor\"]))}}]
instances = [json_format.ParseDict(s, Value()) for s in instances_list]

results = endpoint.predict(instances=instances)
print(results.predictions[0][\"output_2\"])


[\'8 1/2 (1963)\', \'Sword in the Stone, The (1963)\', \'Much Ado About Nothing (1993)\', \'Jumanji (1995)\', \'As Good As It Gets (1997)\', \'Age of Innocence, The (1993)\', \'Double vie de Véronique, La (Double Life of Veronique, The) (1991)\', \'Piano, The (1993)\', \'Eat Drink Man Woman (1994)\', \'Bullets Over Broadway (1994)\']

关于如何修复/编码有效载荷的任何想法?

    标签: json google-cloud-platform google-cloud-vertex-ai google-ai-platform


    【解决方案1】:

    我解决了这个问题。问题是base64编码。这是完美的工作:

    def encode_64(input):
        message = input
        message_bytes = message.encode('ascii')
        base64_bytes = base64.b64encode(message_bytes)
        base64_message = base64_bytes.decode('ascii')
        return base64_message
    
    
    instances_list = [{serving_input: {"b64": encode_64("doctor")}}]
    instances = [json_format.ParseDict(s, Value()) for s in instances_list]
    
    results = endpoint.predict(instances=instances)
    print(results.predictions[0]["output_2"][:3])
    
    ['Nelly & Monsieur Arnaud (1995)', 'Three Lives and Only One Death (1996)', 'Critical Care (1997)']
    

    【讨论】:

      猜你喜欢
      • 2020-12-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 2018-08-01
      • 1970-01-01
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多