[go: nahoru, domu]

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

TablesClient: predict does not work with Python list or dictionary #9887

Closed
helinwang opened this issue Nov 23, 2019 · 1 comment · Fixed by #9991
Closed

TablesClient: predict does not work with Python list or dictionary #9887

helinwang opened this issue Nov 23, 2019 · 1 comment · Fixed by #9991
Assignees
Labels
api: automl Issues related to the AutoML API. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@helinwang
Copy link
Contributor
helinwang commented Nov 23, 2019

The problematic line is at:

elif type_code == data_types_pb2.ARRAY:
return {"list_value": value}
elif type_code == data_types_pb2.STRUCT:
return {"struct_value": value}

The expected type of the array/struct is google.protobuf.ListValue/google.protobuf.StructValue, not Python list/dictionary.

The failure message is:

*** TypeError: Parameter to MergeFrom() must be instance of same class: expect ed google.protobuf.ListValue got list.

Preferably we should only support Python list/dictionary. Now for backwards compatibility, we should support list/dictionary/google.protobuf.ListValue/google.protobuf.StructValue

@helinwang helinwang self-assigned this Nov 23, 2019
@helinwang helinwang changed the title TablesClient: predict does not work with array or struct TablesClient: predict does not work with Python list or dictionary Nov 23, 2019
@yoshi-automation yoshi-automation added the triage me I really want to be triaged. label Nov 23, 2019
@emar-kar emar-kar added api: automl Issues related to the AutoML API. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. and removed triage me I really want to be triaged. labels Nov 24, 2019
@helinwang
Copy link
Contributor Author
helinwang commented Dec 3, 2019

Before this bug being resolved, the user has to convert Python list/struct to google.protobuf.Value. E.g.:

predict({"array_feature": to_list_value([1,2,3]), "struct_feature": to_struct_value({"field": 1})})

Here is the helper function:

from google.protobuf import struct_pb2
import six

def to_list_value(value):
  value, _ = to_proto_value(value)
  return value.list_value

def to_struct_value(value):
  value, _ = to_proto_value(value)
  return value.struct_value

def to_proto_value(value):
  """translates a Python value to a google.protobuf.Value.

  Args:
    value: The Python value to be translated.

  Returns:
    The translated google.protobuf.Value.
  """
  # possible Python types (this is a Python3 module):
  # https://simplejson.readthedocs.io/en/latest/#encoders-and-decoders
  #   JSON              Python 2        Python 3
  # object              dict            dict
  # array               list            list
  # string              unicode         str
  # number (int)        int, long       int
  # number (real)       float           float
  # true                True            True
  # false               False           False
  # null                None            None
  if value is None:
    # translate null to an empty value.
    return struct_pb2.Value(), None
  elif isinstance(value, bool):
    # This check needs to happen before isinstance(value, int),
    # isinstance(value, int) returns True when value is bool.
    return struct_pb2.Value(bool_value=value), None
  if isinstance(value, six.integer_types) or isinstance(value, float):
    return struct_pb2.Value(number_value=value), None
  elif isinstance(value, six.string_types) or isinstance(value, six.text_type):
    return struct_pb2.Value(string_value=value), None
  elif isinstance(value, dict):
    struct_value = struct_pb2.Struct()
    for key, v in value.items():
      field_value, err = to_proto_value(v)
      if err is not None:
        return None, err

      struct_value.fields[key].CopyFrom(field_value)
    return struct_pb2.Value(struct_value=struct_value), None
  elif isinstance(value, list):
    list_value = []
    for v in value:
      proto_value, err = to_proto_value(v)
      if err is not None:
        return None, err
      list_value.append(proto_value)
    return struct_pb2.Value(list_value=struct_pb2.ListValue(
        values=list_value)), None
  else:
    return None, "unsupport data type: {}".format(type(value))

helinwang pushed a commit to helinwang/google-cloud-python that referenced this issue Dec 17, 2019
The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES googleapis#9887
helinwang pushed a commit to helinwang/google-cloud-python that referenced this issue Dec 17, 2019
The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES googleapis#9887
helinwang pushed a commit to helinwang/google-cloud-python that referenced this issue Dec 18, 2019
The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES googleapis#9887
helinwang pushed a commit to helinwang/google-cloud-python that referenced this issue Dec 18, 2019
The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES googleapis#9887
helinwang added a commit that referenced this issue Jan 28, 2020
* fix(automl): fix TablesClient.predict for list and struct

The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES #9887

* Address comment: remove protobuf dependency requirement.

protobuf is already a transitive dependency (see google-api-core's
setup.py)
parthea pushed a commit that referenced this issue Oct 21, 2023
* fix(automl): fix TablesClient.predict for list and struct

The Predict request payload is proto. Previously Python dict is
automatically converted to proto. However, the conversion failed for
google.protobuf.ListValue and google.protobuf.Struct. Changing the
structure of the Python dict might fix the problem. However, this PR
fixes the problem by generating the proto message directly. So there
is no auto conversion step.

FIXES #9887

* Address comment: remove protobuf dependency requirement.

protobuf is already a transitive dependency (see google-api-core's
setup.py)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: automl Issues related to the AutoML API. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants