-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Question]: step function outside workflow class #17980
Comments
Hey @AnnPe! How can I assist you today? I'm here to help you with any bugs, questions, or contributions while you wait for a human maintainer. Yes, it is possible to define step functions outside the workflow class so that they can be used as modular components to easily create different flows for experiments. You can define these step functions as free functions and use the To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
Yes! However, this is undocumented for now since I feel the UX isn't great, but we weren't really sure of a solid use case or how people would use this.
Basically the UX is something like
Im realizing already how janky that is haha, but it's there |
hi, thanks for your quick reply! thanks! |
i need to create them w/o associating them to a specific class - so that i can use them as building blocks for different workflows. is that possible? |
Yes, you can define step functions without immediately associating them with a specific workflow instance. You can use the Here's an example of how you can define a step function without associating it with a specific workflow initially: @step
def my_step_function(event: Event) -> Event:
# Define your step logic here
return some_event Later, you can associate this step function with different workflows as needed. If you don't specify a workflow class when using the To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
@AnnPe it's tied to the instance
|
yeah, to the instance of course - but this means that i have to define another function to tie it to another workflow, don't i? |
@dosu |
To link step functions defined outside of a class together within a workflow using specific from llama_index.core.workflow import (
Event,
StartEvent,
StopEvent,
Workflow,
step,
)
class MyStart(StartEvent):
query: str
class MyStop(StopEvent):
outcome: str
# Define step functions without associating them with a specific workflow initially
@step
async def start_step(ev: MyStart) -> Event:
# Your logic here
return Event() # Replace with actual event
@step
async def middle_step(ev: Event) -> Event:
# Your logic here
return Event() # Replace with actual event
@step
async def end_step(ev: Event) -> MyStop:
# Your logic here
return MyStop(outcome="Workflow completed")
# Create workflow instances and associate steps
w1 = Workflow()
w1.add_step(start_step)
w1.add_step(middle_step)
w1.add_step(end_step)
w2 = Workflow()
w2.add_step(start_step)
w2.add_step(middle_step)
w2.add_step(end_step)
# Example of running a workflow
handler = w1.run(stepwise=True)
while ev := await handler.run_step():
handler.ctx.send_event(ev)
result = await handler In this setup, To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
@dosu, great |
To add a from llama_index.core.workflow import Context
async def set_name(ctx: Context, name: str) -> str:
state = await ctx.get("state")
state["name"] = name
await ctx.set("state", state)
return f"Name set to {name}" Create an workflow = AgentWorkflow.from_tools_or_functions(
[set_name],
llm=llm,
system_prompt="You are a helpful assistant that can set a name.",
initial_state={"name": "unset"},
) Create a ctx = Context(workflow)
response = await workflow.run(user_msg="My name is Logan", ctx=ctx)
print(str(response))
state = await ctx.get("state")
print(state["name"]) The To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
you created two identical workflows, didn't you? |
To create different workflows with loops and conditions using input/output events for each step defined outside a class, you can define custom event types and use them in your workflow steps. Here's how you can do it:
class LoopEvent(Event):
loop_output: str
class BranchA1Event(Event):
payload: str
class BranchA2Event(Event):
payload: str
class BranchB1Event(Event):
payload: str
class BranchB2Event(Event):
payload: str
@step
async def step_one(ev: StartEvent | LoopEvent) -> FirstEvent | LoopEvent:
if random.randint(0, 1) == 0:
print("Bad thing happened")
return LoopEvent(loop_output="Back to step one.")
else:
print("Good thing happened")
return FirstEvent(first_output="First step complete.")
@step
async def start(ev: StartEvent) -> BranchA1Event | BranchB1Event:
if random.randint(0, 1) == 0:
print("Go to branch A")
return BranchA1Event(payload="Branch A")
else:
print("Go to branch B")
return BranchB1Event(payload="Branch B")
@step
async def step_a1(ev: BranchA1Event) -> BranchA2Event:
print(ev.payload)
return BranchA2Event(payload=ev.payload)
@step
async def step_b1(ev: BranchB1Event) -> BranchB2Event:
print(ev.payload)
return BranchB2Event(payload=ev.payload)
@step
async def step_a2(ev: BranchA2Event) -> StopEvent:
print(ev.payload)
return StopEvent(result="Branch A complete.")
@step
async def step_b2(ev: BranchB2Event) -> StopEvent:
print(ev.payload)
return StopEvent(result="Branch B complete.")
workflow = Workflow()
workflow.add_step(step_one)
workflow.add_step(start)
workflow.add_step(step_a1)
workflow.add_step(step_b1)
workflow.add_step(step_a2)
workflow.add_step(step_b2)
async def main():
result = await workflow.run()
print(result)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
from llama_index.utils.workflow import draw_all_possible_flows
draw_all_possible_flows(workflow, filename="workflow_visualization.html") This setup allows you to create workflows with loops and branches by defining the appropriate event types and using them to control the flow of your application [1]. To continue talking to Dosu, mention @dosu. Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Bug Report | Other |
Question Validation
Question
is it possible to define step functions outside workflow class? so that they can be used as lego pieces - to easily create different flows for experiments?
The text was updated successfully, but these errors were encountered: