Dear team, in the <feature engineering example> th...
# hamilton-help
y
Dear team, in the feature engineering example there's a note at the end about choosing different data sources based on what's requested in the dag
Copy code
How to ask Hamilton what features are needed as input to know what to request from the feature store. With tags, and querying the DAG at the start of the app, you could dynamically ask Hamilton what's required and then only go to the feature store for that data. If this type of example would be of interest, let us know.
Can you share some tips on how to accomplish that?
s
It shows how to use tags. For the second part, I'll sketch some code tonight.
here’s an example sketch — in this example we only pull data from the DB that’s relevant to the features we want:
Copy code
# functions.py
import pandas as pd
from hamilton.function_modifiers import tag, tag_outputs, extract_columns

COL_NAMES = ["a", "b", "c"] # hardcoded list of the schema

@tag_outputs(**{c: dict(attributes=["source"]) for c in COL_NAMES})
@extract_columns(*COL_NAMES)
def raw_dataset(table_name: str, columns: list[str], db_client: object) -> pd.DataFrame:
    query = " ... " # use table_name and columns to create the query
    return pd.read_sql(query, con=db_client)

@tag(feature="prod")
def transform_a(a: pd.Series) -> pd.Series:
   ...

@tag(feature="staging")
def transform_b(b: pd.Series) -> pd.Series:
   ...
then in the driver we could do something like:
Copy code
from hamilton import driver, base
import functions
# create a driver
dr = ( 
  driver.Builder()
    .with_modules(functions)
    .with_adapters(base.PandasDataFrameResult())
    .build()
)
# get prod features
prod_features = dr.list_available_variables(tag_filter={"feature":"prod"})
print(prod_features)
# find the sources that feed these features
all_nodes = dr.what_is_upstream_of(*[f.name for f in prod_features])
print(all_nodes)
# get the source column names
just_sources = [s.name for s in all_nodes if "source" in s.tags.get("attributes", [])]
print(just_sources)

# execute it
result = dr.execute(
  [f.name for f in prod_features], 
  inputs={'columns': just_sources, ...}
)
So the technical term of what we’ve down above is a lightweight “predicate pushdown”. From a feature store perspective it would in general be similar: 1. tag features 2. tag sources 3. given requested features, walk the dag to find sources starting from what you want to compute 4. using those sources, create the relevant input for the DAG, in the example above we passed in
columns
as a value… 5. execute things… Does this help? make sense?
y
That's perfect @Stefan Krawczyk! Thanks for the quick and detailed response. You guys have top-notch support
👍 1