64 lines
1.7 KiB
Markdown
64 lines
1.7 KiB
Markdown
---
|
|
layout: default
|
|
title: "Async"
|
|
parent: "Core Abstraction"
|
|
nav_order: 5
|
|
---
|
|
|
|
# Async
|
|
|
|
**Async** pattern allows the `post()` step to be asynchronous: `post_async()`. This is especially helpful if you need to `await` something—for example, user feedback or external async requests.
|
|
|
|
**⚠️ Warning**: Only `post_async()` is async. `prep()` and `exec()` must be sync.
|
|
|
|
---
|
|
|
|
## 1. AsyncNode
|
|
|
|
Below is a minimal **AsyncNode** that calls an LLM in `exec()` to summarize texts, and then awaits user feedback in `post_async()`:
|
|
|
|
```python
|
|
class SummarizeThenVerify(AsyncNode):
|
|
def prep(self, shared):
|
|
return shared.get("doc", "")
|
|
|
|
def exec(self, prep_res):
|
|
return call_llm(f"Summarize: {prep_res}")
|
|
|
|
async def post_async(self, shared, prep_res, exec_res):
|
|
user_decision = await gather_user_feedback(exec_res)
|
|
if user_decision == "approve":
|
|
shared["summary"] = exec_res
|
|
return "approve"
|
|
else:
|
|
return "deny"
|
|
```
|
|
|
|
- `exec()`: Summarizes text (sync LLM call).
|
|
- `post_async()`: Waits for user approval (async).
|
|
|
|
---
|
|
|
|
## 2. AsyncFlow
|
|
|
|
We can build an **AsyncFlow** around this node. If the user denies, we loop back for another attempt; if approved, we pass to a final node:
|
|
|
|
```python
|
|
summarize_node = SummarizeThenVerify()
|
|
final_node = Finalize()
|
|
|
|
# Chain conditions
|
|
summarize_node - "approve" >> final_node
|
|
summarize_node - "deny" >> summarize_node # retry loop
|
|
|
|
flow = AsyncFlow(start=summarize_node)
|
|
|
|
async def main():
|
|
shared = {"doc": "Mini LLM Flow is a lightweight LLM framework."}
|
|
await flow.run_async(shared)
|
|
print("Final stored summary:", shared.get("final_summary"))
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|