AsyncGuard
Lesson 21's stream still blocked the thread it ran on. A desk answering several customers at once wants the awaitable version, and it is the same object with await in front of it.
import asyncio
from guardrails import AsyncGuard
from guardrails_ai.valid_length import ValidLength
desk = AsyncGuard().use(ValidLength(min=1, max=20, on_fail="noop"))
outcome = await desk.validate("Order 8821 is running late and arrives Friday.")
print(outcome.validation_passed)
print(outcome.validated_output)AsyncGuard is imported from guardrails beside Guard, takes the same validators, and returns the same ValidationOutcome. Everything you learned about on_fail, history and summaries carries over unchanged.
An async model
async def slow_model(**kwargs):
await asyncio.sleep(0.01)
return "Order 8821 ships today."
answer = await desk(slow_model, messages=[{"role": "user", "content": "Where is 8821?"}])
print(answer.raw_llm_output)
print(answer.validation_passed)The callable is the one from lesson 13 with async in front. Guardrails awaits it, which is the only difference in the contract.
Several at once
The stand-in model from lesson 13 is an ordinary synchronous callable, and AsyncGuard awaits whatever it is given. Two lines wrap it, which is the same thing you would do to any client that has no async version.
model = PretendModel()
async def call(**kwargs):
return model(**kwargs)
async def ask(question):
answer = await desk(call, messages=[{"role": "user", "content": question}])
return answer.validation_passed, answer.validated_output
questions = ["Where is order 8821?", "Can I get a refund on 8821?", "hello"]
for passed, text in await asyncio.gather(*(ask(q) for q in questions)):
print(passed, "|", text)Three calls in flight together, results in the order you asked. The Performance page recommends AsyncGuard as the first thing to reach for when latency matters, on the grounds that the Guard itself runs in under ten milliseconds and everything slow is either the model or a validator that calls one.
Validators inside a single Guard already run concurrently, whichever class you use. That is why lesson 6 sorted the summaries before printing them.
- Give one of the three questions a validator that raises and see what
asyncio.gatherdoes with the exception. - Time the loop with and without
gatherusing a model that sleeps for a second. - Try
awaiton a plainGuardand read the error, so you recognise it later.
You understood something today that you didn't yesterday.