Skip to content

Commit fdd8d02

Browse files
authored
Merge pull request #83 from PrefectHQ/tutorial
Begin updating tutorial and add better repr/print width
2 parents aecf16e + bcdf6f2 commit fdd8d02

File tree

7 files changed

+283
-157
lines changed

7 files changed

+283
-157
lines changed

docs/tutorial-tasks.mdx

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: "Tutorial: Tasks"
3+
---
4+
5+
Welcome to ControlFlow! In this tutorial, we'll explore the fundamental building block of ControlFlow workflows: `Tasks`.
6+
7+
We'll learn how to create tasks, define dependencies between them, and control their execution within a flow. By the end of this tutorial, you'll have a solid understanding of how to break down complex problems into manageable tasks and orchestrate them effectively.
8+
9+
## Creating a Simple Task
10+
11+
At the core of ControlFlow are `Task` objects, which represent discrete units of work to be performed by AI agents. Let's start by creating a simple task that generates a list of top attractions in Washington D.C.:
12+
13+
```python
14+
from controlflow import flow, Task
15+
16+
17+
@flow
18+
def generate_attractions(destination: str):
19+
attractions = Task(
20+
objective="Generate a list of 10 must-see attractions at the destination",
21+
result_type=list[str],
22+
)
23+
return attractions
24+
25+
26+
attractions = generate_attractions("Washington D.C.")
27+
print(attractions)
28+
# ['Lincoln Memorial', 'National Mall', 'United States Capitol', ...]
29+
```
30+
31+
In this example, we:
32+
33+
- Define a function `generate_attractions()` and decorate it with `@flow`, turning it into a ControlFlow workflow
34+
- Create a `Task` object named `attractions` with an objective and result type of `list[str]`. Tasks have access to their flow's context, which is why the task knew about the `destination`.
35+
- Return the `attractions` task from the flow function
36+
37+
When we call `generate_attractions()`, ControlFlow automatically detects and runs the task. When a task is returned from a flow, it is automatically resolved into its result, which is why we received a list of attractions as the output.
38+
39+
## Defining Task Dependencies
40+
41+
Complex workflows often involve multiple tasks with dependencies between them. ControlFlow makes it easy to define these dependencies and ensure tasks are executed in the correct order. Let's expand our example to generate a personalized travel itinerary for Washington D.C.:
42+
43+
```python
44+
@flow
45+
def generate_itinerary(destination: str):
46+
attractions = Task(
47+
objective="Generate a list of 10 must-see attractions at the destination",
48+
result_type=list[str],
49+
)
50+
51+
itinerary = [
52+
Task(
53+
objective=f"Make an itinerary for day {day} in the destination, focusing on attractions in the provided `area`",
54+
context=dict(attractions=attractions, destination=destination, area=area),
55+
result_type=str,
56+
)
57+
for day, area in enumerate(['National Mall', 'Tidal Basin', 'Downtown'], start=1)
58+
]
59+
60+
return itinerary
61+
62+
63+
itinerary = generate_itinerary('Washington D.C.')
64+
for day, activity in enumerate(itinerary, start=1):
65+
print(f"Day {day}:\n\n{activity}\n\n")
66+
67+
# Day 1:
68+
#
69+
# 8:00 AM - 9:00 AM: Lincoln Memorial
70+
# 9:00 AM - 10:00 AM: Washington Monument
71+
# 10:00 AM - 12:00 PM: National Museum of American History
72+
# ...
73+
```
74+
75+
In this example, we:
76+
77+
- Create an `attractions` task that generates a list of top attractions in Washington D.C.
78+
- Create an `itinerary` task for each day of the trip, focusing on attractions in specific areas of the city and using the `attractions` task as context
79+
80+
By passing the `attractions` task as context to the `itinerary` tasks, we define a dependency between them. ControlFlow ensures that the `attractions` task is executed before the `itinerary` tasks, and the `itinerary` tasks can access the result of the `attractions` task.
81+
82+
## Controlling Task Execution
83+
84+
Sometimes, you might want to control the execution of tasks within a flow based on the results of previous tasks. You can do this by calling `task.run()` to manually run a task and get its result:
85+
86+
```python
87+
@flow
88+
def generate_dc_itinerary_with_recommendations():
89+
trip = generate_dc_itinerary()
90+
91+
budget = Task(
92+
objective="Ask the user for their daily budget for meals and activities in Washington D.C.",
93+
result_type=float,
94+
user_access=True,
95+
)
96+
budget.run()
97+
98+
cuisine = Task(
99+
objective="Ask the user for their preferred cuisine type for dining in Washington D.C.",
100+
result_type=str,
101+
user_access=True,
102+
)
103+
cuisine.run()
104+
105+
recommendations = [
106+
Task(
107+
objective="Generate a list of restaurant recommendations for `cuisine` cuisine in Washington D.C. for a budget of `budget` per day",
108+
context=dict(cuisine=cuisine.result, budget=budget.result),
109+
result_type=list[str],
110+
)
111+
for _ in trip['itinerary']
112+
]
113+
114+
return dict(trip=trip, recommendations=recommendations)
115+
116+
trip_with_recs = generate_dc_itinerary_with_recommendations()
117+
print(f"Top attractions: {', '.join(trip_with_recs['trip']['attractions'])}")
118+
for day, (activity, recs) in enumerate(zip(trip_with_recs['trip']['itinerary'], trip_with_recs['recommendations']), start=1):
119+
print(f"Day {day}: {activity}")
120+
print(f"Restaurant recommendations: {', '.join(recs)}")
121+
122+
# Output:
123+
# Top attractions: Lincoln Memorial, National Mall, United States Capitol, White House, Smithsonian National Air and Space Museum, Washington Monument, Smithsonian National Museum of Natural History, Tidal Basin, Vietnam Veterans Memorial, Library of Congress
124+
# Day 1: Start your day at the Lincoln Memorial, then walk along the National Mall, taking in the sights of the Washington Monument and the Reflecting Pool. Visit the Smithsonian National Museum of American History and the Smithsonian National Museum of Natural History.
125+
# Restaurant recommendations: Ben's Chili Bowl, Founding Farmers, Busboys and Poets
126+
# Day 2: Explore the Tidal Basin area, starting with the Jefferson Memorial. Take a stroll around the Tidal Basin to enjoy the cherry blossoms (if in season). Visit the Martin Luther King Jr. Memorial and the Franklin Delano Roosevelt Memorial.
127+
# Restaurant recommendations: Old Ebbitt Grill, The Hamilton, Jaleo
128+
# Day 3: Spend the day in Downtown Washington D.C. Start at the White House Visitor Center, then take a guided tour of the United States Capitol. Visit the Library of Congress and the Supreme Court Building. End your day with a visit to the Smithsonian National Portrait Gallery.
129+
# Restaurant recommendations: Rasika, Zaytinya, Oyamel
130+
```
131+
132+
In this example, we:
133+
134+
- Call the `generate_dc_itinerary()` flow to get the top attractions and daily itinerary
135+
- Create a `budget` task to ask the user for their daily budget, using `user_access=True` to allow user interaction
136+
- Create a `cuisine` task to ask the user for their preferred cuisine type
137+
- Manually run the `budget` and `cuisine` tasks using `task.run()` to get their results
138+
- Create a `recommendations` list comprehension that generates a task for each day of the trip, providing restaurant recommendations based on the user's budget and preferred cuisine
139+
- Return a dictionary with the original `trip` and the `recommendations`
140+
141+
By calling `task.run()`, we can control the execution flow based on task results, allowing for more dynamic and responsive workflows.
142+
143+
## Next Steps
144+
145+
Congratulations on completing this introduction to tasks in ControlFlow! You've learned how to:
146+
147+
- Create simple tasks
148+
- Define dependencies between tasks using context
149+
- Control task execution within a flow using `task.run()`
150+
151+
In the next tutorial, we'll dive deeper into the world of AI agents and explore how they can be used to bring your workflows to life. Stay tuned!
152+
153+
If you can't wait to learn more, check out the [ControlFlow Concepts](/concepts) guide and [API Reference](/api-reference) for additional information and examples. Happy engineering!

0 commit comments

Comments
 (0)