Ejemplo n.º 1
0
def _python_value_to_proto_value(feast_value_type, value) -> ProtoValue:
    """
    Converts a Python (native, pandas) value to a Feast Proto Value based
    on a provided value type

    Args:
        feast_value_type: The target value type
        value: Value that will be converted

    Returns:
        Feast Value Proto
    """

    # Detect list type and handle separately
    if "list" in feast_value_type.name.lower():

        if feast_value_type == ValueType.FLOAT_LIST:
            return ProtoValue(float_list_val=FloatList(val=[
                item if type(item) in
                [np.float32, np.float64] else _type_err(item, np.float32)
                for item in value
            ]))

        if feast_value_type == ValueType.DOUBLE_LIST:
            return ProtoValue(double_list_val=DoubleList(val=[
                item if type(item) in
                [np.float64, np.float32] else _type_err(item, np.float64)
                for item in value
            ]))

        if feast_value_type == ValueType.INT32_LIST:
            return ProtoValue(int32_list_val=Int32List(val=[
                item if type(item) is np.int32 else _type_err(item, np.int32)
                for item in value
            ]))

        if feast_value_type == ValueType.INT64_LIST:
            return ProtoValue(int64_list_val=Int64List(val=[
                item if type(item) in
                [np.int64, np.int32] else _type_err(item, np.int64)
                for item in value
            ]))

        if feast_value_type == ValueType.STRING_LIST:
            return ProtoValue(string_list_val=StringList(val=[
                item if type(item) in
                [np.str_, str] else _type_err(item, np.str_) for item in value
            ]))

        if feast_value_type == ValueType.BOOL_LIST:
            return ProtoValue(bool_list_val=BoolList(val=[
                item if type(item) in
                [np.bool_, bool] else _type_err(item, np.bool_)
                for item in value
            ]))

        if feast_value_type == ValueType.BYTES_LIST:
            return ProtoValue(bytes_list_val=BytesList(val=[
                item if type(item) in
                [np.bytes_, bytes] else _type_err(item, np.bytes_)
                for item in value
            ]))

    # Handle scalar types below
    else:
        if pd.isnull(value):
            return ProtoValue()
        elif feast_value_type == ValueType.INT32:
            return ProtoValue(int32_val=int(value))
        elif feast_value_type == ValueType.INT64:
            return ProtoValue(int64_val=int(value))
        elif feast_value_type == ValueType.FLOAT:
            return ProtoValue(float_val=float(value))
        elif feast_value_type == ValueType.DOUBLE:
            assert type(value) is float or np.float64
            return ProtoValue(double_val=value)
        elif feast_value_type == ValueType.STRING:
            return ProtoValue(string_val=str(value))
        elif feast_value_type == ValueType.BYTES:
            assert type(value) is bytes
            return ProtoValue(bytes_val=value)
        elif feast_value_type == ValueType.BOOL:
            assert type(value) is bool
            return ProtoValue(bool_val=value)

    raise Exception(f"Unsupported data type: ${str(type(value))}")
Ejemplo n.º 2
0
def test_basic_retrieve_online_entity_listform(client, list_entity_dataframe):
    # Case 1: Features retrieval with entity in list format check
    district_fs = FeatureSet(
        name="district",
        features=[
            Feature(name="district_rating", dtype=ValueType.INT64),
            Feature(name="district_cost", dtype=ValueType.FLOAT),
            Feature(name="district_past_transactions_int",
                    dtype=ValueType.INT64_LIST),
            Feature(name="district_past_transactions_double",
                    dtype=ValueType.DOUBLE_LIST),
            Feature(name="district_past_transactions_float",
                    dtype=ValueType.FLOAT_LIST),
            Feature(name="district_past_transactions_string",
                    dtype=ValueType.STRING_LIST),
            Feature(name="district_past_transactions_bool",
                    dtype=ValueType.BOOL_LIST),
        ],
        entities=[Entity("district_ids", dtype=ValueType.INT64_LIST)],
        max_age=Duration(seconds=3600),
    )

    client.set_project(PROJECT_NAME)
    client.apply(district_fs)

    district_fs = client.get_feature_set(name="district")
    client.ingest(district_fs, list_entity_dataframe, timeout=600)
    time.sleep(15)

    online_request_entity = [{
        "district_ids": [np.int64(1), np.int64(2),
                         np.int64(3)]
    }]
    online_request_features = [
        "district_rating",
        "district_cost",
        "district_past_transactions_int",
        "district_past_transactions_double",
        "district_past_transactions_float",
        "district_past_transactions_string",
        "district_past_transactions_bool",
    ]
    online_request_entity2 = [{
        "district_ids":
        Value(int64_list_val=Int64List(val=[1, 2, 3]))
    }]

    def try_get_features1():
        response = client.get_online_features(
            entity_rows=online_request_entity,
            feature_refs=online_request_features)
        return response, True

    def try_get_features2():
        response = client.get_online_features(
            entity_rows=online_request_entity2,
            feature_refs=online_request_features)
        return response, True

    online_features_actual = wait_retry_backoff(
        retry_fn=try_get_features1,
        timeout_secs=90,
        timeout_msg="Timed out trying to get online feature values",
    )

    online_features_actual2 = wait_retry_backoff(
        retry_fn=try_get_features2,
        timeout_secs=90,
        timeout_msg="Timed out trying to get online feature values",
    )

    online_features_expected = {
        "district_ids": [[np.int64(1), np.int64(2),
                          np.int64(3)]],
        "district_rating": [1],
        "district_cost": [1.5],
        "district_past_transactions_int": [[1, 3]],
        "district_past_transactions_double": [[1.5, 3.0]],
        "district_past_transactions_float": [[1.5, 3.0]],
        "district_past_transactions_string": [["first_1", "second_1"]],
        "district_past_transactions_bool": [[True, False]],
    }

    assert online_features_actual.to_dict() == online_features_expected
    assert online_features_actual2.to_dict() == online_features_expected

    # Case 2: Features retrieval with entity in list format check with mixed types
    with pytest.raises(ValueError) as excinfo:
        online_request_entity2 = [{
            "district_ids": [np.int64(1), np.int64(2), True]
        }]
        online_features_actual2 = client.get_online_features(
            entity_rows=online_request_entity2,
            feature_refs=online_request_features)

    assert (
        "List value type for field district_ids is inconsistent. ValueType.INT64 different from ValueType.BOOL."
        in str(excinfo.value))
Ejemplo n.º 3
0
def pd_value_to_proto_value(feast_value_type, value) -> ProtoValue:

    # Detect list type and handle separately
    if "list" in feast_value_type.name.lower():

        if feast_value_type == ValueType.FLOAT_LIST:
            return ProtoValue(float_list_val=FloatList(val=[
                item if type(item) is np.float32 else type_err(
                    item, np.float32) for item in value
            ]))

        if feast_value_type == ValueType.DOUBLE_LIST:
            return ProtoValue(double_list_val=DoubleList(val=[
                item if type(item) is np.float64 else type_err(
                    item, np.float64) for item in value
            ]))

        if feast_value_type == ValueType.INT32_LIST:
            return ProtoValue(int32_list_val=Int32List(val=[
                item if type(item) is np.int32 else type_err(item, np.int32)
                for item in value
            ]))

        if feast_value_type == ValueType.INT64_LIST:
            return ProtoValue(int64_list_val=Int64List(val=[
                item if type(item) is np.int64 else type_err(item, np.int64)
                for item in value
            ]))

        if feast_value_type == ValueType.STRING_LIST:
            return ProtoValue(string_list_val=StringList(val=[
                item if type(item) is np.str_ else type_err(item, np.str_)
                for item in value
            ]))

        if feast_value_type == ValueType.BOOL_LIST:
            return ProtoValue(bool_list_val=BoolList(val=[
                item if type(item) is np.bool_ else type_err(item, np.bool_)
                for item in value
            ]))

        if feast_value_type == ValueType.BYTES_LIST:
            return ProtoValue(bytes_list_val=BytesList(val=[
                item if type(item) is np.bytes_ else type_err(item, np.bytes_)
                for item in value
            ]))

    # Handle scalar types below
    else:
        if pd.isnull(value):
            return ProtoValue()
        elif feast_value_type == ValueType.INT32:
            return ProtoValue(int32_val=int(value))
        elif feast_value_type == ValueType.INT64:
            return ProtoValue(int64_val=int(value))
        elif feast_value_type == ValueType.FLOAT:
            return ProtoValue(float_val=float(value))
        elif feast_value_type == ValueType.DOUBLE:
            assert type(value) is float
            return ProtoValue(double_val=value)
        elif feast_value_type == ValueType.STRING:
            return ProtoValue(string_val=str(value))
        elif feast_value_type == ValueType.BYTES:
            assert type(value) is bytes
            return ProtoValue(bytes_val=value)
        elif feast_value_type == ValueType.BOOL:
            assert type(value) is bool
            return ProtoValue(bool_val=value)

    raise Exception(f"Unsupported data type: ${str(type(value))}")