Hey all! Is there any way to access a node's metad...
# hamilton-help
e
Hey all! Is there any way to access a node's metadata like run_id from within the node itself? I'd like to use to add it to some manual telemetry.
e
The run ID for tracking purposes you mean, right? E.G. that is in the UI?
e
correct, i want to pass it to some API call functions that have mlflow tracking on them
Maybe I could implement BaseDoNodeExecuteAsync and inject it into kwargs? https://github.com/DAGWorks-Inc/hamilton/blob/main/hamilton/lifecycle/base.py#L554
e
Oh, cool, yeah thatr’s a good use-case. There isn’t an easy way to do this now that I can think of, but it’s definitely doable. High-level: 1. there are two concepts of run IDs — the UI ones (which are numbers) and the internal unique ones (which are UUIDs) 2. The tracker stores a mapping — you’d have to have the tracker object available 3. You’d access it in a hook (as you mentioned) 4. You could either inject it into kwargs or use a context variable. Injecting it in kwargs is a bit dangerous as you have to check whether the node needs it, and there is a compilation step that checks for missing inputs. Can provide pseudocode if this makes sense? Just checking — you’re using async right?
e
a context manager sounds like what I have in mind!
e
yep — that could be part of a hook that takes in the tracker object
e
I've been workin on an async compatible mlflow adapter: https://gist.github.com/dmexs/3f7b697bab806494051b17a76bc4bab7
🔥 1
e
things are a bit odd with async but it should work
e
yeah I've noticed, but I think it's worth it
e
That’s awesome!
lmk what help you need to get started
e
sure, to be transparent, I cut much of the original code out that I don't need but if I get this to where I want perhaps I can contribute back
Oh I think I get where you're going, I'd store my node metadata to a context var in one of my pre-exec hooks and then be able to access that within the node?
e
Yep, exactly. You’d use the tracker to get the mapping + run_id passed in in the hook to get the ID
s
@Emeka Anyanwu you could do this:
Copy code
def my_function(a: int, b: int, __run_id: str) -> ...
then in your adapter code (actually this is something we could add to the SDK version easily)
Copy code
def pre_graph_execute(...) :
   ...
   if inputs is not None: # always have to pass in a dict for inputs to execution
       inputs["__run_id"] = run_id
e
that makes sense, though I think I like the context manager approach, I'm not quite sure what @Elijah Ben Izzy means by use the tracker to get the mapping + run_id though
s
> means by use the tracker to get the mapping + run_id though I think he means the tracker code shows various IDs — so you can mimic / copy that. Otherwise using threadlocal context could also work like this example - you have the adapter set values, and then your code pulls them (I assume it should work)
otherwise we’d love an async mlflow tracker addition
e
Yes Stefan’s is simpler. The problem is that you still need the run ID for the tracker — it’s different than that from the hook.
Can send over some links in a minute
e
got it, I haven't used contextvars before, i'm trying to figure out where to set the context var with the task_Id (which I'm using as my mlflow parent span id), such that the node's function can acesss it, in lieu of parameter injection
also, thanks for the help and the package btw, really have liked it so far
❤️ 2
Here's a short blog about my use case: https://emeka.ca/thoughts/to-agent-or-not-to-agent
🙌 1
e
Yeah I think inputs are easiest here actually — less global context. But to be clear — which ID do you want specifically? The one for the Hamilton UI? Or the task ID?
e
I'm looking for the task_id passed to my async pre_node_execute hook: https://gist.github.com/dmexs/3f7b697bab806494051b17a76bc4bab7#file-mlflowtrackerasync-py-L55
e
Ok, sorry I thought you were talking about the hamilton run ID. Then yeah, setting a context var in pre node execute is easiest
s
@Emeka Anyanwu in case it’s useful: • FutureAdapter could be a fit for your use case if you didn’t need asyncio • Then you might just be able to use the MLFlow adapter? (or are you after tracing specifically?)
e
I am planning on asyncio, i wanted to try without it but my nodejs habits wouldn't let me lol
👍 1
s
Otherwise to ask the question - what do you want to get out of MLFlow? There’s some Hamilton UI overlap - and we do have an async Hamilton Tracker for the Hamilton UI
e
yes, I saw, I am running on databricks so wanted to leverage mlflow integration as much as possible
👍 1
I briefly looked into running the hamilton tracking server on my databricks compute but couldn't figure out networking issues
👍 1
e
Ok so I can send you some sample pseudo code for context vars soon — it’s similar to how we do otel tracing
🙏 1
And makes sense — async is good if you’re leveraging async APIs. Feel free to open an issue on Databricks stuff — we can look in or see if the community has input
👍 1
s
Yep great feedback thanks. In any case the more adapters the better — and async mlflow one for tracing sounds great to have.
e
Tried a couple things, I think in order to get contextvars to work I'd need to wrap this line in context.run() ?
otherwise I'm not sure how the context set in the pre_graph hook would be available in the function
e
That’s how context vars work — they’re available globally. You: 1. Create a global context var object with all the information you want 2. Call
.set()
in
pre_node_execute
3. Call
.get()
from within the function 4. Call
.set(None)
in
post_node_execute
to reset it
e
alright, let me play around over here, since these functions are async and run out of order, I'm trying to figure out how the function will get the right contextvar
e
OK, so yeah, you want to use the async
pre_node_execute
and
post_node_execute
— context vars will work if you do (they’re meant to work in async contexts as well
We don’t have a more user-friendly class (This isn’t a public API) , but we should add one — here’s the class to override: https://github.com/DAGWorks-Inc/hamilton/blob/1057a40db370d235fce647d65872221365da6bfa/hamilton/lifecycle/base.py#L491
👍 1
e
Alright, I have a reproduction of the issue I'm encountering with contextvars, perhaps a misunderstanding of how they're supported to work on my part: https://github.com/dmexs/hamilton-contextvar-repro
I expect to see the same node context output multiple times but instead it reverts to the contextvar defautl value when accessed from within the node or in the post node hook
would love some guidance when you have a chance to review
e
To follow up — we discussed during office hours: 1. We have a nice approach for injecting into the application using kwargs — it uses some internal APIs for now, but: 2. Going to scope out adding a
DataflowContext
object that functions can declare or get globally (like burr does) — this is long overdue IMO 3. @Emeka Anyanwu to figure out what works for him, then post with code and we’ll take it over 4. @Elijah Ben Izzy to figure out why the context var approach didn’t work (there’s some weirdness with context/the indirection layer that Hamilton uses for execute — my guess is we need to do this directly for running the fn, not in pre/post node execute)
🙌 1