Hello, I'm thinking of serving two tasks with the ...
# prefect-getting-started
p
Hello, I'm thinking of serving two tasks with the new
task.serve()
functionality, let's say task_a and task_b. From what I gathered from the docs, to execute a task I have to
Copy code
from module_a import task_a

result_a = task_a.delayed(1)
and the same with
task_b
. Now, if I want to run an equivalent of
result = task_b(task_a)
, I'd have to import both tasks and run
Copy code
from module_a import task_a
from module_b import task_b

result_a = task_a.delay(1).wait().result()  # not sure about the wait().result()
result_b = task_b.delay(result_a).wait().result()
But what if I can't import both modules (e.g. due to dependency conflicts, or different runtime environments)? What's the intended pattern to connect two relatively independent tasks? With the flows this is easy, because I can write a parent flow that internally runs
run_deployment("flow_a")
and then retrieve the result and pass it to
run_deployment("flow_b")
. The only import I have to do is the prefect itself, the parent flow doesn't care about implementation details of the subflows, once they are served/deployed.
n
hi @Paweł Biernat - ill leave a couple thoughts on this • you may just want to call two tasks in your served task (you can nest tasks in 3.x)
Copy code
@task
def a(): pass

@task
def b(): pass

@task
def to_serve(inputs):
  b(a())

to_serve.serve()
• background tasks might not suit your use case, since generally they're nice for cases where you want to scale instances of the tasks a lot horizontally (since unlike flows, its websockets and you dont need a unique port) and they perform side affects (like send an email on user signup) • it may end up being easier to use flows as you mention • remember that you can use state hooks here to emit custom events to signal downstream deployments if need be
p
My tasks are ML models & bioinformatic tools that can't possibly share the same docker environment (because of dependency conflict hell). I guess this rules out task.serve for my use case.
Thanks for the clarification though, I get the intent behind task.serve now.
@Nate this is slightly tangential, but what would be the prefect-way to serve a large ML model. I currently have a deployment that on startup pulls the model weights from s3, loads it into RAM, transfers it into GPU memory, and runs the predictions only after these steps. I tried serving the prediction-flow, but it still goes through the model setup each time the flow is run, which is painfully slow. Is there any way to preserve the state between flow runs? In the marvin example I saw somewhere the prediction requests were received by a FastAPI app, which then run the flow by calling it within the same python process, but I was hoping to avoid using another communication protocol aside from prefect.
My way around that was to run the flow with an entire batch of inputs for predictions, with the batch size large enough to justify the model set up, but that feels clunky, compared to having some sort of service running constantly.