Skip to content

Commit f874ea9

Browse files
Async tutorial (#8184)
* init * add tutorial on async
1 parent 6f6ec9e commit f874ea9

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

docs/docs/tutorials/async/index.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Async DSPy Programming
2+
3+
DSPy provides native support for asynchronous programming, allowing you to build more efficient and
4+
scalable applications. This guide will walk you through how to leverage async capabilities in DSPy,
5+
covering both built-in modules and custom implementations.
6+
7+
## Why Use Async in DSPy?
8+
9+
Asynchronous programming in DSPy offers several benefits:
10+
- Improved performance through concurrent operations
11+
- Better resource utilization
12+
- Reduced waiting time for I/O-bound operations
13+
- Enhanced scalability for handling multiple requests
14+
15+
## When Should I use Sync or Async?
16+
17+
Choosing between synchronous and asynchronous programming in DSPy depends on your specific use case.
18+
Here's a guide to help you make the right choice:
19+
20+
Use Synchronous Programming When
21+
22+
- You're exploring or prototyping new ideas
23+
- You're conducting research or experiments
24+
- You're building small to medium-sized applications
25+
- You need simpler, more straightforward code
26+
- You want easier debugging and error tracking
27+
28+
Use Asynchronous Programming When:
29+
30+
- You're building a high-throughput service (high QPS)
31+
- You're working with tools that only support async operations
32+
- You need to handle multiple concurrent requests efficiently
33+
- You're building a production service that requires high scalability
34+
35+
### Important Considerations
36+
37+
While async programming offers performance benefits, it comes with some trade-offs:
38+
39+
- More complex error handling and debugging
40+
- Potential for subtle, hard-to-track bugs
41+
- More complex code structure
42+
- Different code between ipython (Colab, Jupyter lab, Databricks notebooks, ...) and normal python runtime.
43+
44+
We recommend starting with synchronous programming for most development scenarios and switching to async
45+
only when you have a clear need for its benefits. This approach allows you to focus on the core logic of
46+
your application before dealing with the additional complexity of async programming.
47+
48+
## Using Built-in Modules Asynchronously
49+
50+
Most DSPy built-in modules support asynchronous operations through the `acall()` method. This method
51+
maintains the same interface as the synchronous `__call__` method but operates asynchronously.
52+
53+
Here's a basic example using `dspy.Predict`:
54+
55+
```python
56+
import dspy
57+
import asyncio
58+
import os
59+
60+
os.environ["OPENAI_API_KEY"] = "your_api_key"
61+
62+
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))
63+
predict = dspy.Predict("question->answer")
64+
65+
async def main():
66+
# Use acall() for async execution
67+
output = await predict.acall(question="why did a chicken cross the kitchen?")
68+
print(output)
69+
70+
71+
asyncio.run(main())
72+
```
73+
74+
### Working with Async Tools
75+
76+
DSPy's `Tool` class seamlessly integrates with async functions. When you provide an async
77+
function to `dspy.Tool`, you can execute it using `acall()`. This is particularly useful
78+
for I/O-bound operations or when working with external services.
79+
80+
```python
81+
import asyncio
82+
import dspy
83+
import os
84+
85+
os.environ["OPENAI_API_KEY"] = "your_api_key"
86+
87+
async def foo(x):
88+
# Simulate an async operation
89+
await asyncio.sleep(0.1)
90+
print(f"I get: {x}")
91+
92+
# Create a tool from the async function
93+
tool = dspy.Tool(foo)
94+
95+
async def main():
96+
# Execute the tool asynchronously
97+
await tool.acall(x=2)
98+
99+
asyncio.run(main())
100+
```
101+
102+
Note: When using `dspy.ReAct` with tools, calling `acall()` on the ReAct instance will automatically
103+
execute all tools asynchronously using their `acall()` methods.
104+
105+
## Creating Custom Async DSPy Modules
106+
107+
To create your own async DSPy module, implement the `aforward()` method instead of `forward()`. This method
108+
should contain your module's async logic. Here's an example of a custom module that chains two async operations:
109+
110+
```python
111+
import dspy
112+
import asyncio
113+
import os
114+
115+
os.environ["OPENAI_API_KEY"] = "your_api_key"
116+
dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))
117+
118+
class MyModule(dspy.Module):
119+
def __init__(self):
120+
self.predict1 = dspy.ChainOfThought("question->answer")
121+
self.predict2 = dspy.ChainOfThought("answer->simplified_answer")
122+
123+
async def aforward(self, question, **kwargs):
124+
# Execute predictions sequentially but asynchronously
125+
answer = await self.predict1.acall(question=question)
126+
return await self.predict2.acall(answer=answer)
127+
128+
129+
async def main():
130+
mod = MyModule()
131+
result = await mod.acall(question="Why did a chicken cross the kitchen?")
132+
print(result)
133+
134+
135+
asyncio.run(main())
136+
```

docs/docs/tutorials/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@ Welcome to DSPy tutorials! We've organized our tutorials into three main categor
3535
- [Deployment](/tutorials/deployment/)
3636
- [Debugging & Observability](/tutorials/observability/)
3737
- [Streaming](/tutorials/streaming/)
38+
- [Async](/tutorials/async/)
3839

3940

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ nav:
5252
- Deployment: tutorials/deployment/index.md
5353
- Debugging & Observability: tutorials/observability/index.md
5454
- Streaming: tutorials/streaming/index.md
55+
- Async: tutorials/async/index.md
5556
- DSPy in Production: production/index.md
5657
- Community:
5758
- Community Resources: community/community-resources.md

0 commit comments

Comments
 (0)