Hi, does Hamilton support the following: if an inp...
# hamilton-help
y
Hi, does Hamilton support the following: if an input is missing, automatically skip executing the subdag that depends on it. The use case is to implement backward compatibility when adding a new input
new_df
. It would be useful to be still able to run the DAG on an older dataset that doesn’t have
new_df
.
s
🤔 we don’t have that explicit functionality. Some thoughts: • Functions can take default values. So if an input is missing, it has a default value. • @config.when could be useful, and you could resolve it at DAG build time via @resolve. • we have the graceful error adapter that maybe could be used here? • else you could create two DAGs (one for new, one for old) and then know which one to call? • or use hamilton within hamilton
t
@Yijun Tang If I understand, you're managing a project where you have a
version 1
that's being used, you made some change to create
version 2
, and now both versions are in use. Sounds accurate? I think @config.when can be useful. This allows you to have 2 nodes with the same name but different implementation. Let's say your
version 1
looked like this:
Copy code
# report.py
import pandas as pd

def monthly_report(sales: pd.DataFrame) -> pd.DataFrame:
   return ...
Copy code
# where you execute code
import report
from hamilton import driver

dr = driver.Builder().with_modules(report).build()
dr.execute(...)
Then, as your project evolve and you want to modify
monthly_report()
you could use
@config.when
Copy code
# report.py
import pandas as pd
from hamilton.function_modifiers import config

@config.when_not(version="v2")
def monthly_report__v1(sales: pd.DataFrame) -> pd.DataFrame:
   return ...

@config.when(version="v2)
def monthy_report__v2(sales: pd.DataFrame, new_df: pd.DataFrame) -> pd.DataFrame:
  return ...
Now, when you create your
Driver
you can pass a config. By passing
version="v2"
in a dictionary it will use the implementation that has
new_df
. If the config is empty, it will use the
v1
implementation
Copy code
import report
from hamilton import driver

dr = (
  driver.Builder()
  .with_modules(report)
  .with_config({"version": "v2"})
  .build()
)
dr.execute(...)
y
Thank you both! I’m trying to implement the following. The gray nodes are V1. The red nodes are added in V2. We’d like to run just the gray nodes on V1 dataset.
config
sounds like a viable option, although is it possible to select all nodes with
version <= 2
? My understanding is
.with_config({"version": "v2"})
will only select the red nodes.
s
Check out the docs. You only need to annotate the functions that are different. IIUC.
👀 1
Otherwise Hamilton only walks the graph for things upstream of requested outputs. So if you didn’t request the bottom right most red node (or any red node for that matter), “red” wouldn’t be executed. So perhaps know what you can or cannot request?
In case it’s helpful you can always ask what is upstream of some requested outputs - see here.
y
Ah ok, seems like I can mark the gray nodes with
@config.when_in(param=["v1", "v2"])
and the red ones with
@config.when_in(param=["v2"])
. This way when V3 is introduced, we can add
"v3"
to both lists.
s
to clarify, are successive versions purely additive? or do they actually replace certain functions (i.e. nodes)? or both?
y
Great question, for now I think they will be additive in our use case, and perhaps deprecating some old nodes, instead of replacing nodes.
s
Without knowing more about how you’re determining what to “request” as output there’s a few more possibilities.
E.g. GracefulErrorAdapter. You could check within a function whether something exists, and if it doesn’t then throw a sentinel error that will cascade downstream for only what’s downstream — then you’d just need to look for it in the output…
💡 1
👀 1
y
Ah thanks!
GracefulErrorAdaptor
is looking very promising. I’ll give it a try.