Repository: feast-dev/feast

Issue:
SpecifiedFeaturesNotPresentError when using @on_demand_feature_view
## Expected Behavior 
Trying to set up an on-demand feature view.

## Current Behavior
Get a SpecifiedFeaturesNotPresentError when applying store definition.

SpecifiedFeaturesNotPresentError: Explicitly specified features avg_fare, avg_speed, avg_trip_seconds, earned_per_hour not found in inferred list of features for 'on_demand_stats'

## Steps to reproduce
```
batch_source = FileSource(
    timestamp_field="day",
    path="trips_stats.parquet",  # using parquet file from previous step
)

taxi_entity = Entity(name='taxi_id',
                     value_type=String)

trips_stats_fv = FeatureView(
    name='trip_stats',
    entities=['taxi_id'],
    ttl=timedelta(seconds=86400), # 86400 sec = 1day
    schema=[
        Field(name="total_miles_travelled", dtype=Float32),
        Field(name="total_trip_seconds", dtype=Float32),
        Field(name="total_earned", dtype=Float32),
        Field(name="trip_count", dtype=Int32)],
    source=batch_source,
)

@on_demand_feature_view(
    sources = [trips_stats_fv.projection],
    schema=[
        Field(name="avg_fare", dtype=Float32),
        Field(name="avg_speed", dtype=Float32),
        Field(name="avg_trip_seconds", dtype=Float32),
        Field(name="earned_per_hour", dtype=Float32),
    ],
)
def on_demand_stats(inp):
    out = pd.DataFrame()
    out["avg_fare"] = inp["total_earned"] / inp["trip_count"]
    out["avg_speed"] = 3600 * inp["total_miles_travelled"] / inp["total_trip_seconds"]
    out["avg_trip_seconds"] = inp["total_trip_seconds"] / inp["trip_count"]
    out["earned_per_hour"] = 3600 * inp["total_earned"] / inp["total_trip_seconds"]
    return out

feature_svc = FeatureService(
    name="taxi_rides",
    features=[
        trips_stats_fv,
        on_demand_stats,
    ]
)
fs = FeatureStore(".")  # using feature_store.yaml stored in the same directory
fs.apply([taxi_entity, trips_stats_fv, on_demand_stats, feature_svc])
```
### Specifications

- Version: Feast SDK Version: "feast 0.21.3"
- Platform: macOS 12.4
- Subsystem: Python 3.8.5 (conda)

## Possible Solution



Discussion:
UPDATE:

If I define the on-demand feature view using deprecated params, then it works

```
#
@on_demand_feature_view(
    features=[
        Feature("avg_fare", ValueType.DOUBLE),
        Feature("avg_speed", ValueType.DOUBLE),
        Feature("avg_trip_seconds", ValueType.DOUBLE),
        Feature("earned_per_hour", ValueType.DOUBLE),
    ],
    sources=[trips_stats_fv]
)
def on_demand_stats(inp):
    out = pd.DataFrame()
    out["avg_fare"] = inp["total_earned"] / inp["trip_count"]
    out["avg_speed"] = 3600 * inp["total_miles_travelled"] / inp["total_trip_seconds"]
    out["avg_trip_seconds"] = inp["total_trip_seconds"] / inp["trip_count"]
    out["earned_per_hour"] = 3600 * inp["total_earned"] / inp["total_trip_seconds"]
    return out
```

Thanks for raising the issue @vecorro. We are investigating!
hey @vecorro thanks for raising this issue - the problem here is that your UDF results in a pandas dataframe with the following columns:
```
avg_fare            float64
avg_speed           float64
avg_trip_seconds    float64
earned_per_hour     float64
dtype: object
```
but in your initial feature definitions you specified the fields as having a `Float32` type - if you switch to `Float64` it should work correctly

note that `ValueType.DOUBLE` is the equivalent of `Float64` in the old typing system, which is why that worked for you

I'm going to update the error message to be more clear here, after which I'll close out this issue

Resolving patch:
diff --git a/sdk/python/feast/errors.py b/sdk/python/feast/errors.py
--- a/sdk/python/feast/errors.py
+++ b/sdk/python/feast/errors.py
@@ -2,6 +2,8 @@
 
 from colorama import Fore, Style
 
+from feast.field import Field
+
 
 class DataSourceNotFoundException(Exception):
     def __init__(self, path):
@@ -183,10 +185,15 @@ def __init__(self, feature_refs_collisions: List[str], full_feature_names: bool)
 
 
 class SpecifiedFeaturesNotPresentError(Exception):
-    def __init__(self, specified_features: List[str], feature_view_name: str):
-        features = ", ".join(specified_features)
+    def __init__(
+        self,
+        specified_features: List[Field],
+        inferred_features: List[Field],
+        feature_view_name: str,
+    ):
         super().__init__(
-            f"Explicitly specified features {features} not found in inferred list of features for '{feature_view_name}'"
+            f"Explicitly specified features {specified_features} not found in inferred list of features "
+            f"{inferred_features} for '{feature_view_name}'"
         )
 
 
diff --git a/sdk/python/feast/on_demand_feature_view.py b/sdk/python/feast/on_demand_feature_view.py
--- a/sdk/python/feast/on_demand_feature_view.py
+++ b/sdk/python/feast/on_demand_feature_view.py
@@ -479,7 +479,7 @@ def infer_features(self):
                     missing_features.append(specified_features)
             if missing_features:
                 raise SpecifiedFeaturesNotPresentError(
-                    [f.name for f in missing_features], self.name
+                    missing_features, inferred_features, self.name
                 )
         else:
             self.features = inferred_features


Test patch: