Package: sf-hamilton
Welcome to the official Hamilton Github RepositoryHamiltonThe general purpose micro-orchestration framework for creatingdataflowsfrom python functions! That is, your single tool to express things like data, ML, LLM pipelines/workflows, and even web request logic!Hamilton is a novel paradigm for specifying a flow of delayed execution in python. It works on python objects of any type and dataflows of any complexity. Core to the design of Hamilton is a clear mapping of function name to artifact, allowing you to quickly grok the relationship between the code you write and the data you produce.This paradigm makes modifications easy to build and track, ensures code is self-documenting, and makes it natural to unit test your data transformations. When connected together, these functions form aDirected Acyclic Graph(DAG), which the Hamilton framework can execute, optimize, and report on.Problems Hamilton Solves✅ Model a dataflow -- If you can model your problem as a DAG in python, Hamilton is the cleanest way to build it.✅ Unmaintainable spaghetti code -- Hamilton dataflows are unit testable, self-documenting, and provide lineage.✅ Long iteration/experimentation cycles -- Hamilton provides a clear, quick, and methodical path to debugging/modifying/extending your code.✅ Reusing code across contexts -- Hamilton encourages code that is independent of infrastructure and can run regardless of execution setting.Problems Hamilton Does not Solve❌ Provisioning infrastructure -- you want a macro-orchestration system (see airflow, kubeflow, sagemaker, etc...).❌ Doing your ML for you -- we organize your code, BYOL (bring your own libraries).❌ Tracking execution + associated artifacts -- Hamilton is lightweight, but if this is important to you see theDAGWorks product.See the table below for more specifics/how it compares to other common tooling.Full Feature ComparisonHere are common things that Hamilton is compared to, and how Hamilton compares to them.FeatureHamiltonMacro orchestration systems (e.g. Airflow)FeastdbtDaskPython 3.8+✅✅✅✅✅Helps you structure your code base✅❌❌✅❌Code is always unit testable✅❌❌❌❌Documentation friendly✅❌❌❌❌Can visualize lineage easily✅❌❌✅✅Is just a library✅❌❌❌✅Runs anywhere python runs✅❌❌❌✅Built for managing python transformations✅❌❌❌❌Can model GenerativeAI/LLM based workflows✅❌❌❌❌Replaces macro orchestration systems❌✅❌❌❌Is a feature store❌❌✅❌❌Can model transforms at row/column/object/dataset level✅❌❌❌❌Getting StartedIf you don't want to install anything to try Hamilton, we recommend tryingwww.tryhamilton.dev.
Otherwise, here's a quick getting started guide to get you up and running in less than 15 minutes.
If you need help join ourslackcommunity to chat/ask Qs/etc.
For the latest updates, follow us ontwitter!InstallationRequirements:Python 3.8+To get started, first you need to install hamilton. It is published to pypi undersf-hamilton:pip install sf-hamiltonNote: to use the DAG visualization functionality, you should instead do:pip install "sf-hamilton[visualization]"While it is installing we encourage you to start on the next section.Note: the content (i.e. names, function bodies) of our example code snippets are for illustrative purposes only, and don't reflect what we actually do internally.Hamilton in <15 minutesHamilton is a new paradigm when it comes to creating, um, dataframes (let's use dataframes as an example, otherwise you can createANYpython object).
Rather than thinking about manipulating a central dataframe, as is normal in some data engineering/data science work,
you instead think about the column(s) you want to create, and what inputs are required. There
is no need for you to think about maintaining this dataframe, meaning you do not need to think about any "glue" code;
this is all taken care of by the Hamilton framework.For example rather than writing the following to manipulate a central dataframe objectdf:df['col_c']=df['col_a']+df['col_b']you writedefcol_c(col_a:pd.Series,col_b:pd.Series)->pd.Series:"""Creating column c from summing column a and column b."""returncol_a+col_bIn diagram form:The Hamilton framework will then be able to build a DAG from this function definition.So let's create a "Hello World" and start using Hamilton!Your first hello world.By now, you should have installed Hamilton, so let's write some code.Create a filemy_functions.pyand add the following functions:importpandasaspddefavg_3wk_spend(spend:pd.Series)->pd.Series:"""Rolling 3 week average spend."""returnspend.rolling(3).mean()defspend_per_signup(spend:pd.Series,signups:pd.Series)->pd.Series:"""The cost per signup in relation to spend."""returnspend/signupsThe astute observer will notice we have not definedspendorsignupsas functions. That is okay,
this just means these need to be provided as input when we come to actually wanting to create a dataframe.Note: functions can take or create scalar values, in addition to any python object type.Create amy_script.pywhich is where code will live to tell Hamilton what to do:importsysimportloggingimportimportlibimportpandasaspdfromhamiltonimportdriverlogging.basicConfig(stream=sys.stdout)initial_columns={# load from actuals or wherever -- this is our initial data we use as input.# Note: these do not have to be all series, they could be scalar inputs.'signups':pd.Series([1,10,50,100,200,400]),'spend':pd.Series([10,10,20,40,40,50]),}# we need to tell hamilton where to load function definitions frommodule_name='my_functions'module=importlib.import_module(module_name)# or we could just do `import my_functions`dr=driver.Driver(initial_columns,module)# can pass in multiple modules# we need to specify what we want in the final dataframe.output_columns=['spend',# or module.spend'signups',# or module.signups'avg_3wk_spend',# or module.avg_3wk_spend'spend_per_signup',# or module.spend_per_signup]# let's create the dataframe!# if you only did `pip install sf-hamilton` earlier:df=dr.execute(output_columns)# else if you did `pip install "sf-hamilton[visualization]"` earlier:# dr.visualize_execution(output_columns, './my-dag.dot', {})print(df)Run my_script.pypython my_script.pyYou should see the following output:spend  signups  avg_3wk_spend  spend_per_signup
0     10        1            NaN            10.000
1     10       10            NaN             1.000
2     20       50      13.333333             0.400
3     40      100      23.333333             0.400
4     40      200      33.333333             0.200
5     50      400      43.333333             0.125You should see the following image if you randr.visualize_execution(output_columns, './my-dag.dot', {"format": "png"}, orient="TB"):Note: we treat displayingInputsin a special manner for readability in our visualizations. So you'll likely see input
nodes repeated.Congratulations - you just created your Hamilton dataflow that created a dataframe!Example Hamilton DataflowsWe have a growing list of examples showcasing how one might use Hamilton. You currently have two places to find them:TheHamilton Dataflow Hub-- which makes it easy to pull and then modify code.Theexamples/folder in this repository.For the Hub, this will contain user contributed dataflows, e.g. text_summarization, forecasting, data processing, that will be continually added to.For theexamples/directory, you'll have to copy/fork the repository to run them.
E.g.Hello worldScaling on toRay,Dask, orPandas on SparkTraininga model with scikit-learnDoingair quality analysis solely in numpyWe also have a docker container that contains some of these examples so you can pull that and run them locally. See theexamples folder READMEfor details.We forked and lost some starsThis repository is maintained by the original creators of Hamilton, who have since foundedDAGWorks inc., a company largely dedicated to building and maintaining the Hamilton library. We decided to fork the original because Stitch Fix did not want to transfer ownership to us; we had grown the star count in the original repository to 893:before forking.For the backstory on how Hamilton came about, see the original Stitch Fixblog post!.Slack CommunityWe have a small but active community onslack. Come join us!LicenseHamilton is released under theBSD 3-Clause Clear License.Used internally by:Stitch FixUK Government Digital ServicesIBMBritish CyclingPNNLORNLFederal Reserve BoardJoby AviationTwoTransfixRailofyHabitat EnergyKI-InsuranceAscena RetailOpendoorTo add your company, make a pull request to add it here.ContributingWe take contributions, large and small. We operate via aCode of Conductand expect anyone
contributing to do the same.To see how you can contribute, please read ourcontributing guidelinesand then ourdeveloper
setup guide.Blog PostsLineage + Hamilton in 10 minutes(Organic Content) The perks of creating dataflows with Hamilton by Thierry JeanDeveloping Scalable Feature Engineering DAGs with Metaflow & HamiltonTidy Production Pandas with HamiltonTowards Data Science post on backstory & introduction.How to use Hamilton with Pandas in 5 minutes.How to iterate with Hamilton in a Notebook.Original Stitch Fix Post.Extension Stitch Fix Post.Videos of talksHamilton: a python micro-framework for data/feature engineering at Stitch Fix - 40 mins:Hamilton: a python micro-framework for tidy scalable pandas - ~20 mins:Citing HamiltonWe'd appreciate citing Hamilton by referencing one of the following:@inproceedings{DBLP:conf/vldb/KrawczykI22,
  author    = {Stefan Krawczyk and Elijah ben Izzy},
  editor    = {Satyanarayana R. Valluri and Mohamed Za{\"{\i}}t},
  title     = {Hamilton: a modular open source declarative paradigm for high level
               modeling of dataflows},
  booktitle = {1st International Workshop on Composable Data Management Systems,
               CDMS@VLDB 2022, Sydney, Australia, September 9, 2022},
  year      = {2022},
  url       = {https://cdmsworkshop.github.io/2022/Proceedings/ShortPapers/Paper6\_StefanKrawczyk.pdf},
  timestamp = {Wed, 19 Oct 2022 16:20:48 +0200},
  biburl    = {https://dblp.org/rec/conf/vldb/KrawczykI22.bib},
  bibsource = {dblp computer science bibliography, https://dblp.org}
}

@inproceedings{CEURWS:conf/vldb/KrawczykIQ22,
  author    = {Stefan Krawczyk and Elijah ben Izzy and Danielle Quinn},
  editor    = {Cinzia Cappiello and Sandra Geisler and Maria-Esther Vidal},
  title     = {Hamilton: enabling software engineering best practices for data transformations via generalized dataflow graphs},
  booktitle = {1st International Workshop on Data Ecosystems co-located with 48th International Conference on Very Large Databases (VLDB 2022)},
  pages     = {41--50},
  url       = {https://ceur-ws.org/Vol-3306/paper5.pdf},
  year      = {2022}
}🛣🗺 Roadmap / Things you can do with HamiltonHamilton is an ambitious project to provide a unified way to describe any dataflow, independent of where it runs.
You can find currently support integrations and high-level roadmap below. Please reach out viaslackor email (stefan / elijah at dagworks.io) to contribute or share feedback!Object types:Any python object type! E.g. Pandas, Spark dataframes, Dask dataframes, Ray datasets, Polars, dicts, lists, primitives,
your custom objects, etc.Workflows:data processingfeature engineeringmodel trainingLLM application workflowsall of them togetherData QualitySee thedata qualitydocs.Ability to define data quality check on an object.Pandera schema integration.Custom object type validators.Integration with other data quality libraries (e.g. Great Expectations, Deequ, whylogs, etc.)Online MonitoringOpen telemetry/tracing plugin.Caching:Checkpoint caching (e.g. save a function's result to disk, independent of input) -WIP.Finergrained caching (e.g. save a function's result to disk, dependent on input).Execution:Runs anywhere python runs. E.g. airflow, prefect, dagster, kubeflow, sagemaker, jupyter, fastAPI, snowpark, etc.Backend integrations:Specific integrations with other systems where we help you write code that runs on those systems.RayDelegate function execution to Ray.Function grouping (e.g. fuse multiple functions into a single Ray task)DaskDelegate function execution to Dask.Function grouping (e.g. fuse multiple functions into a single Dask task)SparkPandas on spark integration (via GraphAdapter)PySpark native UDF map function integration (via GraphAdapter)PySpark native aggregation function integrationPySpark join, filter, groupby, etc. integrationSnowparkPackaging functions for SnowparkLLVMs & relatedNumba integrationCustom BackendsGenerate code to execute on a custom topology, e.g. microservices, etc.Integrations with other systems/tools:Generating Airflow | Prefect | Metaflow | Dagster | Kubeflow Pipelines | Sagemaker Pipelines | etc from Hamilton.Plugins for common MLOps/DataOps tools: MLFlow, DBT, etc.Dataflow/DAG Walking:Depth first search traversalAsync function support via AsyncDriverParallel walk over a generatorPython multiprocessing execution (still in beta)Python threading supportGrouping of nodes into tasks for efficient parallel computationBreadth first search traversalSequential walk over a generatorDAG/Dataflow resolution:At Driver instantiation time, using configuration/modules and@config.when.With@resolveduring Driver instantiation time.Prescribed Development WorkflowIn general we prescribe the following:Ensure you understandHamilton Basics.Familiarize yourself with some of theHamilton decorators. They will help keep your code DRY.Start creating Hamilton Functions that represent your work. We suggest grouping them in modules where it makes sense.Write a simple script so that you can easily run things end to end.Join ourSlackcommunity to chat/ask Qs/etc.For the backstory on Hamilton we invite you to watch a roughly-9 minute lightning talk on it that we gave at the apply conference:video,slides.PyCharm TipsIf you're using Hamilton, it's likely that you'll need to migrate some code. Here are some useful tricks we found
to speed up that process.Live templatesLive templates are a cool feature and allow you to type in a name which expands into some code.E.g. For example, we wrote one to make it quick to stub out Hamilton functions: typinggraphfuncwould turn into ->def_(_:pd.Series)->pd.Series:""""""return_Where the blanks are where you can tab with the cursor and fill things in. See your pycharm preferences for setting this up.Multiple CursorsIf you are doing a lot of repetitive work, one might consider multiple cursors. Multiple cursors allow you to do things on multiple lines at once.To use it hitoption + mouse clickto create multiple cursors.Escto revert back to a normal mode.Usage analytics & data privacyBy default, when using Hamilton, it collects anonymous usage data to help improve Hamilton and know where to apply development
efforts.We capture three types of events: one when theDriverobject is instantiated, one when theexecute()call on theDriverobject completes, and one for mostDriverobject function invocations.
No user data or potentially sensitive information is or ever will be collected. The captured data is limited to:Operating System and Python versionA persistent UUID to indentify the session, stored in ~/.hamilton.conf.Error stack trace limited to Hamilton code, if one occurs.Information on what features you're using from Hamilton: decorators, adapters, result builders.How Hamilton is being used: number of final nodes in DAG, number of modules, size of objects passed toexecute(), the name of the Driver function being invoked.If you're worried, see telemetry.py for details.If you do not wish to participate, one can opt-out with one of the following methods:Set it to false programmatically in your code before creating a Hamilton driver:fromhamiltonimporttelemetrytelemetry.disable_telemetry()Set the keytelemetry_enabledtofalsein ~/.hamilton.conf under theDEFAULTsection:[DEFAULT]
telemetry_enabled = FalseSet HAMILTON_TELEMETRY_ENABLED=false as an environment variable. Either setting it for your shell session:exportHAMILTON_TELEMETRY_ENABLED=falseor passing it as part of the run command:HAMILTON_TELEMETRY_ENABLED=falsepythonNAME_OF_MY_DRIVER.pyContributorsCode ContributorsStefan Krawczyk (@skrawcz)Elijah ben Izzy (@elijahbenizzy)Danielle Quinn (@danfisher-sf)Rachel Insoft (@rinsoft-sf)Shelly Jang (@shellyjang)Vincent Chu (@vslchusf)Christopher Prohm (@chmp)James Lamb (@jameslamb)Avnish Pal (@bovem)Sarah Haskins (@frenchfrywpepper)Thierry Jean (@zilto)Michał Siedlaczek (@elshize)Benjamin Hack (@benhhack)Bryan Galindo (@bryangalindo)Jordan Smith (@JoJo10Smith)Roel Bertens (@roelbertens)Bug Hunters/Special MentionsNils Olsson (@nilsso)Michał Siedlaczek (@elshize)Alaa Abedrabbo (@AAbedrabbo)Shreya Datar (@datarshreya)Baldo Faieta (@baldofaieta)Anwar Brini (@AnwarBrini)Gourav Kumar (@gms101)Amos Aikman (@amosaikman)Ankush Kundaliya (@akundaliya)David Weselowski (@j7zAhU)Peter Robinson (@Peter4137)Seth Stokes (@sT0vLouis Maddox (@lmmx)Stephen Bias (@s-ducks)Anup Joseph (@AnupJoseph)Jan Hurst (@janhurst)Flavia Santos (@flaviassantos)