В современных приложениях с ИИ производительность имеет большое значение. Вы могли заметить, что при работе с большими языковыми моделями (LLM) тратится много времени на ожидание — ответа API, завершения нескольких вызовов или операций ввода-вывода (I/O).
Именно здесь на помощь приходит asyncio. Удивительно, но многие разработчики используют LLM, не подозревая, что могут ускорить свои приложения с помощью асинхронного программирования.
Что такое Asyncio?
Библиотека asyncio в Python позволяет писать параллельный код с использованием синтаксиса async/await, обеспечивая эффективное выполнение нескольких задач, связанных с вводом-выводом, в рамках одного потока. По сути, asyncio работает с объектами, которые можно ожидать (awaitable objects), обычно с сопрограммами (coroutines), которые планируются и выполняются циклом событий (event loop) без блокировки.
Проще говоря, синхронный код выполняет задачи последовательно, как если бы вы стояли в очереди в магазине, в то время как асинхронный код выполняет задачи параллельно, как если бы вы использовали несколько касс самообслуживания. Это особенно полезно для вызовов API (например, OpenAI, Anthropic, Hugging Face), где большая часть времени тратится на ожидание ответов, что позволяет значительно ускорить выполнение.
Начало работы с асинхронным Python
Пример: выполнение задач с использованием asyncio и без него
В этом примере мы запускали простую функцию три раза синхронно. Вывод показывает, что каждый вызов say_hello() выводит «Hello…», ждёт 2 секунды, затем выводит «…World!». Поскольку вызовы происходят один за другим, общее время ожидания складывается — 2 секунды × 3 вызова = 6 секунд.
«`python
import time
def say_hello():
print(«Hello…»)
time.sleep(2) # имитация ожидания (например, вызов API)
print(«…World!»)
def main():
say_hello()
say_hello()
say_hello()
if name == «main«:
start = time.time()
main()
print(f»Finished in {time.time() — start:.2f} seconds»)
«`
Ниже показан код, в котором все три вызова функции say_hello() начались практически одновременно. Каждый выводит «Hello…» сразу, затем ждёт 2 секунды параллельно, прежде чем вывести «…World!». Поскольку эти задачи выполнялись параллельно, а не последовательно, общее время составило примерно самое длительное время ожидания (~2 секунды), а не сумму всех ожиданий (6 секунд в синхронной версии).
«`python
import nest_asyncio, asyncio
nest_asyncio.apply()
import time
async def say_hello():
print(«Hello…»)
await asyncio.sleep(2) # имитация ожидания (например, вызов API)
print(«…World!»)
async def main():
# Выполняем задачи параллельно
await asyncio.gather(
say_hello(),
say_hello(),
say_hello()
)
if name == «main«:
start = time.time()
asyncio.run(main())
print(f»Finished in {time.time() — start:.2f} seconds»)
«`
Использование asyncio в приложениях с ИИ и LLM
Теперь, когда мы понимаем, как работает asyncio, давайте применим его к реальному примеру из мира ИИ. Большие языковые модели (LLM), такие как модели GPT от OpenAI, часто включают в себя множество вызовов API, на выполнение которых требуется время. Если мы будем выполнять эти вызовы последовательно, мы будем тратить драгоценное время на ожидание ответов.
В этом разделе мы сравним выполнение нескольких запросов с использованием asyncio и без него с помощью клиента OpenAI. Мы будем использовать 15 коротких запросов, чтобы наглядно продемонстрировать разницу в производительности.
«`python
import asyncio
from openai import AsyncOpenAI
import os
from getpass import getpass
os.environ[‘OPENAIAPIKEY’] = getpass(‘Enter OpenAI API Key: ‘)
import time
from openai import OpenAI
Создаём синхронный клиент
client = OpenAI()
def ask_llm(prompt: str):
response = client.chat.completions.create(
model=»gpt-4o-mini»,
messages=[{«role»: «user», «content»: prompt}]
)
return response.choices[0].message.content
def main():
prompts = [
«Кратко объясните квантовые вычисления.»,
«Напишите трёхстишие об ИИ.»,
«Перечислите 3 идеи для стартапов в агротехе.»,
«Кратко перескажите фильм «Начало».»,
«Объясните блокчейн в двух предложениях.»,
«Напишите трёхстрочный рассказ о роботе.»,
«Перечислите 5 способов, которыми ИИ помогает здравоохранению.»,
«Объясните бозон Хиггса простыми словами.»,
«Опишите нейронные сети в двух предложениях.»,
«Перечислите 5 идей для блога о возобновляемой энергии.»,
«Дайте короткую метафору для времени.»,
«Перечислите 3 тенденции в машинном обучении.»,
«Напишите короткий лимерик о программировании.»,
«Объясните обучение с учителем и без учителя одним предложением.»,
«Перечислите 3 способа снижения городского трафика.»
]
start = time.time()
results = []
for prompt in prompts:
results.append(ask_llm(prompt))
end = time.time()
for i, res in enumerate(results, 1):
print(f»\n— Ответ {i} —«)
print(res)
print(f»\n[Синхронно] Закончено за {end — start:.2f} секунд»)
if name == «main«:
main()
«`
Синхронная версия обработала все 15 запросов последовательно, поэтому общее время — это сумма времени выполнения каждого запроса. Поскольку каждый запрос занимал время, общее время выполнения было значительно больше — 49,76 секунды в этом случае.
«`python
from openai import AsyncOpenAI
Создаём асинхронный клиент
client = AsyncOpenAI()
async def ask_llm(prompt: str):
response = await client.chat.completions.create(
model=»gpt-4o-mini»,
messages=[{«role»: «user», «content»: prompt}]
)
return response.choices[0].message.content
async def main():
prompts = [
«Кратко объясните квантовые вычисления.»,
«Напишите трёхстишие об ИИ.»,
«Перечислите 3 идеи для стартапов в агротехе.»,
«Кратко перескажите фильм «Начало».»,
«Объясните блокчейн в двух предложениях.»,
«Напишите трёхстрочный рассказ о роботе.»,
«Перечислите 5 способов, которыми ИИ помогает здравоохранению.»,
«Объясните бозон Хиггса простыми словами.»,
«Опишите нейронные сети в двух предложениях.»,
«Перечислите 5 идей для блога о возобновляемой энергии.»,
«Дайте короткую метафору для времени.»,
«Перечислите 3 тенденции в машинном обучении.»,
«Напишите короткий лимерик о программировании.»,
«Объясните обучение с учителем и без учителя одним предложением.»,
«Перечислите 3 способа снижения городского трафика.»
]
start = time.time()
results = await asyncio.gather(*(ask_llm(p) for p in prompts))
end = time.time()
for i, res in enumerate(results, 1):
print(f»\n— Ответ {i} —«)
print(res)
print(f»\n[Асинхронно] Закончено за {end — start:.2f} секунд»)
if name == «main«:
asyncio.run(main())
«`
Асинхронная версия обработала все 15 запросов параллельно, запустив их практически одновременно, а не последовательно. В результате общее время выполнения составило примерно время самого медленного запроса — 8,25 секунды вместо суммирования всех запросов.
Значительная разница возникает потому, что при синхронном выполнении каждый вызов API блокирует программу до своего завершения, поэтому время суммируется. В асинхронном выполнении с asyncio вызовы API выполняются параллельно, позволяя программе обрабатывать множество задач во время ожидания ответов, что значительно сокращает общее время выполнения.
Почему это важно для приложений с ИИ
В реальных приложениях с ИИ ожидание завершения каждого запроса перед началом следующего может быстро стать узким местом, особенно при работе с несколькими запросами или источниками данных. Это особенно распространено в таких рабочих процессах, как:
* Генерация контента для нескольких пользователей одновременно — например, в чат-ботах, рекомендательных системах или многопользовательских панелях.
* Выполнение нескольких вызовов LLM в одном рабочем процессе — например, для суммирования, уточнения, классификации или многошагового рассуждения.
* Получение данных из нескольких API — например, для объединения вывода LLM с информацией из векторной базы данных или внешних API.
Использование asyncio в этих случаях приносит значительные преимущества:
* Улучшение производительности — выполнение параллельных вызовов API вместо последовательного ожидания каждого из них позволяет вашей системе обрабатывать больше работы за меньшее время.
* Эффективность затрат — более быстрое выполнение может снизить эксплуатационные расходы, а пакетирование запросов, где это возможно, может дополнительно оптимизировать использование платных API.
* Улучшение пользовательского опыта — параллелизм делает приложения более отзывчивыми, что имеет решающее значение для систем реального времени, таких как ИИ-ассистенты и чат-боты.
* Масштабируемость — асинхронные шаблоны позволяют вашему приложению обрабатывать гораздо больше одновременных запросов без пропорционального увеличения потребления ресурсов.
1. Какие преимущества предоставляет использование библиотеки asyncio в приложениях с ИИ?
Ответ: использование asyncio в приложениях с ИИ позволяет ускорить выполнение задач за счёт параллельной обработки вызовов API. Это особенно полезно при работе с большими языковыми моделями (LLM), где значительная часть времени тратится на ожидание ответов. Asyncio обеспечивает эффективное выполнение нескольких задач, связанных с вводом-выводом, в рамках одного потока, что улучшает производительность, снижает затраты и улучшает пользовательский опыт.
2. Как asyncio влияет на производительность при работе с LLM?
Ответ: asyncio значительно ускоряет выполнение задач при работе с LLM, такими как модели GPT от OpenAI. В синхронном режиме запросы выполняются последовательно, что приводит к суммированию времени ожидания всех запросов. В асинхронном режиме запросы выполняются параллельно, что позволяет сократить общее время выполнения до времени самого медленного запроса.
3. Какие примеры использования asyncio приведены в статье и как они демонстрируют преимущества этого подхода?
Ответ: в статье приведены примеры выполнения задач с использованием asyncio и без него. В синхронном режиме функция say_hello() вызывается три раза последовательно, что приводит к общему времени ожидания 6 секунд. В асинхронном режиме те же вызовы выполняются параллельно, что сокращает общее время до примерно 2 секунд. Это наглядно демонстрирует преимущества использования asyncio для ускорения выполнения задач.
4. Какие типы приложений с ИИ могут особенно выиграть от использования asyncio?
Ответ: от использования asyncio могут выиграть приложения с ИИ, где требуется генерация контента для нескольких пользователей одновременно (например, в чат-ботах, рекомендательных системах), выполнение нескольких вызовов LLM в одном рабочем процессе (например, для суммирования, уточнения, классификации) и получение данных из нескольких API (например, для объединения вывода LLM с информацией из векторной базы данных или внешних API).
5. Какие основные выводы можно сделать из статьи о применении asyncio в приложениях с ИИ?
Ответ: из статьи можно сделать вывод, что использование asyncio в приложениях с ИИ значительно улучшает производительность, снижает затраты и улучшает пользовательский опыт. Asyncio позволяет обрабатывать больше работы за меньшее время, оптимизировать использование платных API и сделать приложения более отзывчивыми. Это особенно важно для систем реального времени, таких как ИИ-ассистенты и чат-боты.