Запрос к LLM длится секунды. Сервис, который ждёт его синхронно, обслуживает единицы пользователей; асинхронный — сотни на одном процессе. Агенты и RAG тоже выигрывают: поиск по нескольким источникам и вызовы инструментов идут параллельно.
async def answer(question: str) -> str:
async with asyncio.TaskGroup() as tg:
docs = tg.create_task(search(question))
profile = tg.create_task(load_profile(user_id))
return await llm.complete(build_prompt(question, docs.result(), profile.result()))
Что важно знать
- Блокирующий вызов (синхронный HTTP-клиент,
time.sleep, тяжёлые вычисления) внутриasync-функции останавливает весь event loop. TaskGroupиgather— параллельный запуск; таймауты —asyncio.timeout.- Ограничение параллельности (
Semaphore) — чтобы не упереться в лимиты провайдера. - Асинхронные клиенты:
httpx.AsyncClient, асинхронные версии SDK. - Потоковые ответы — асинхронные генераторы (
async for chunk in stream).