Приключения в стране симуляции агентного ИИ
(Или как мы научились не волноваться и полюбили облако)
Вы когда-нибудь задумывались, как облачный сервис с множеством ИИ-агентов справляется с потоком входящих запросов пользователей, не взрываясь? Что ж, больше не нужно гадать! В этом блоге мы отправимся в увлекательное путешествие по симуляции, которая проверяет, насколько грациозно система агентного ИИ (набор ИИ-агентов, работающих вместе) масштабируется, разделяется и обрабатывает различные запросы. Мы расскажем о нашей структуре, предположениях, коде и результатах — с красивой диаграммой.
Задача
Представьте, что вы управляете волшебной системой агентного ИИ в облаке. Пользователи отправляют запросы, каждый из которых состоит из некоторого количество токенов, а ваши агенты их обрабатывают. Иногда агент может самоcтоятельно обработать запрос. В других случаях он может решить, что запрос надо разбить на кучу подзапросов, и запустить еще толпу агентов на их обработку, а затем собрать все ответы в готовый результат. При построении системы мы хотим заранее оценить:
- Сколько запросов мы получаем всего?
- Сколько мы разделяем по сравнению с отправкой напрямую?
- Как часто мы отбрасываем запросы, если они превышают емкость нашего вычистельного кластера?
- Как все это влияет на использование ресурсов и общую стоимость (в долларах)?
Другими словами, мы хотим смоделировать повседневную жизнь нашей системы агентного ИИ и посмотреть, что происходит когда все хорошо. Ну или аоборот, увидеть, насколько все бывает плохо.
Наша структура симуляции
Для нашей модели исользуем SimPy
- библиотеку для discrete event simulation
, а также знакомые библиотеки Python, такие как NumPy, Pandas и Matplotlib для обработки данных и визуализации. Симуляция охватывает 30 дней работы (9 часов симулированного активного обслуживания в день), но учитывает, что узлы могут работать 24 часа (поэтому расчет стоимости ВМ использует 30 × 24 часа).
Ключевые моменты:
- Генерация запросов: Мы генерируем запросы с использованием экспоненциального времени между прибытием (в среднем 2 запроса в минуту).
- Управление ресурсами: Симуляция отслеживает использование ЦП и ОЗУ на узел. Если запрос требует больше ресурсов, чем доступно, система пытается масштабироваться — до определенного предела.
- Режимы обработки: Запрос либо обрабатывается напрямую (вероятность 20%), либо разбивается на пять задач агентов (вероятность 80%). Каждая ветвь имеет свои собственные количество токенов и требования к ресурсам.
- Расчет стоимости: Мы рассчитываем стоимость LLM на основе общего количества обработанных токенов и стоимость ВМ на основе среднего количества узлов, умноженного на количество часов (используя стоимость полного дня, т.е. 24 часа в сутки).
Предположения и числа
Вот некоторые из наших ключевых предположений:
- Время и запросы: Симуляция длится 30 дней по 9 рабочих часов в день (16200 симулированных минут), со средним временем между запросами 0,5 минуты.
- Узлы и емкость: Мы начинаем с 7 узлов и можем масштабироваться до 11. Каждый узел имеет 8 vCPU и 32 ГБ ОЗУ (32 × 1024 МБ).
- Затраты:
- LLM: $3 за миллион токенов.
- ВМ: $0,397 за узел-час. Мы используем полный 24-часовой период (720 часов за 30 дней) для расчета стоимости ВМ.
- Обработка запросов: Прямые запросы и разделенные запросы имеют разные диапазоны токенов и время обработки. Разделенные запросы имитируют участие 5 отдельных ИИ-агентов.
Эти цифры не являются “реальными”, но служат для иллюстрации компромиссов в масштабировании и управлении ресурсами.
Быстрый взгляд на код
Мы не будем перегружать вас всеми деталями, но вот общая структура нашего кода на Python:
import numpy as np
import pandas as pd
from tqdm import trange
NUM_RUNS = 100
results = []
for run in trange(NUM_RUNS):
# 1. Генерация запросов
user_queries = np.random.poisson(lam=5000, size=some_size) # Просто пример
# 2. Маршрутизация запросов
direct_requests = 0
split_requests = 0
dropped_requests = 0
total_tokens = 0
# ... Некоторая логика для разделения или отбрасывания запросов ...
# 3. Отслеживание стоимости (в долларах)
llm_cost = ...
aks_cost = ...
total_cost = llm_cost + aks_cost
# 4. Добавление результатов для каждого запуска
results.append({
'direct_requests': direct_requests,
'split_requests': split_requests,
'dropped_requests': dropped_requests,
'total_requests': direct_requests + split_requests,
'llm_cost': llm_cost,
'aks_cost': aks_cost,
'total_cost': total_cost,
# ... другие статистические данные ...
})
# Преобразование результатов в DataFrame и вычисление сводной статистики
df = pd.DataFrame(results)
summary = df.describe()
print(summary)
По сути:
- Мы генерируем пакет запросов с случайными размерами.
- Мы решаем, направлять их напрямую, разделять или отбрасывать.
- Мы рассчитываем, сколько токенов прошло и стоимость в долларах.
- Мы собираем все эти статистические данные в DataFrame и выводим сводную статистику.
Ноутбук здесь
Результаты: Великое раскрытие
После 100 запусков симуляции мы получили некоторые интересные сводные статистические данные:
Statistic | Mean | Std Dev | Min | Max |
---|---|---|---|---|
direct_requests | 6479 | 74 | 6332 | 6656 |
split_requests | 25921 | 174 | 25481 | 26307 |
dropped_requests | 595 | 40 | 498 | 710 |
total_requests | 32400 | 188 | 32010 | 32794 |
percent_split | 80 | 0 | 79 | 80 |
user_query_tokens | 3563557 | 47046 | 3464816 | 3683875 |
system_query_tokens | 95052192 | 579792 | 93631816 | 96394838 |
llm_response_tokens | 42768946 | 262227 | 42142061 | 43473226 |
total_llm_tokens | 141384694 | 838885 | 139355251 | 143270004 |
llm_cost | 424 | 3 | 418 | 430 |
aks_cost | 2290 | 6 | 2272 | 2307 |
total_cost | 2714 | 9 | 2690 | 2737 |
max_nodes | 11 | 0 | 11 | 11 |
avg_nodes | 8 | 0 | 8 | 8 |
Что все это значит?
Конечно! Давайте разберем данные, представленные в таблице:
Показатель | Среднее | Стандартное отклонение | Минимум | Максимум |
---|---|---|---|---|
direct_requests | 6479 | 74 | 6332 | 6656 |
split_requests | 25921 | 174 | 25481 | 26307 |
dropped_requests | 595 | 40 | 498 | 710 |
total_requests | 32400 | 188 | 32010 | 32794 |
percent_split | 80 | 0 | 79 | 80 |
user_query_tokens | 3563557 | 47046 | 3464816 | 3683875 |
system_query_tokens | 95052192 | 579792 | 93631816 | 96394838 |
llm_response_tokens | 42768946 | 262227 | 42142061 | 43473226 |
total_llm_tokens | 141384694 | 838885 | 139355251 | 143270004 |
llm_cost | 424 | 3 | 418 | 430 |
aks_cost | 2290 | 6 | 2272 | 2307 |
total_cost | 2714 | 9 | 2690 | 2737 |
max_nodes | 11 | 0 | 11 | 11 |
avg_nodes | 8 | 0 | 8 | 8 |
Интерпретация данных:
- direct_requests (Прямые запросы): Среднее значение около 6479 означает, что за период симуляции система напрямую обработала примерно 6500 запросов, без дополнительного разделения. Диапазон от 6332 до 6656 указывает на небольшие колебания между запусками симуляции.
- split_requests (Разделенные запросы): Среднее значение около 25921 показывает, что большая часть запросов (примерно 80% от общего числа) обрабатываются через разделение на несколько подзадач. Это подтверждается процентным соотношением (percent_split) – всегда около 80%.
- dropped_requests (Отброшенные запросы): Среднее значение в районе 595 означает, что иногда система не справляется с нагрузкой и вынуждена отбросить примерно 600 запросов за период, что свидетельствует о том, что иногда ресурсы оказываются ограничены.
- total_requests (Общее количество запросов): В среднем система получила около 32400 запросов за симуляционный период, что является суммой прямых и разделенных запросов.
Токены и стоимость:
- user_query_tokens, system_query_tokens, llm_response_tokens: Эти показатели показывают, сколько токенов (единиц данных) прошло через систему на каждом этапе: от пользовательских запросов до ответов LLM. Это важно для понимания нагрузки на систему.
- total_llm_tokens (Общее количество токенов LLM): Суммарное количество токенов, задействованных в обработке запроса, что позволяет оценить вычислительную нагрузку и, соответственно, стоимость обработки.
- llm_cost (Стоимость LLM): Стоимость обработки токенов, которая в среднем составляет около $424. Это вычисляется исходя из тарифа $3 за миллион токенов.
- aks_cost (Стоимость вычислительных узлов): Стоимость работы вычислительных ресурсов (узлов), которая составляет примерно $2290, что рассчитывается на основе среднего количества узлов и числа часов работы (с учетом работы 24 часа в сутки).
- total_cost (Общая стоимость): Суммарные затраты, получающиеся как сумма затрат на LLM и вычислительные ресурсы – около $2714.
Масштабирование:
- max_nodes (Максимальное количество узлов): Всегда достигается максимум в 11 узлов, что говорит о предельной возможности масштабирования системы в пиковых моментах нагрузки.
- avg_nodes (Среднее количество узлов): В среднем система работает с 8 узлами, что указывает на то, что большую часть времени не требуется максимальное количество ресурсов, но система готова к пиковым нагрузкам.
Подведение итогов (и вопрос к вам!)
Вот и все, друзья! Наша небольшая симуляция показывает, как облачная система агентного ИИ может вести себя при различных нагрузках, размерах токенов и ограничениях по стоимости. Мы сделали некоторые предположения о том, как запросы разделяются, что отбрасывается и как масштабируются затраты — но в реальности вы бы настроили эти параметры в соответствии с вашей производственной средой.
Вопрос к вам: Если вы управляете аналогичной системой ИИ-агентов, коррелируют ли ваши числа с нашими? Возможно, вы видите другое соотношение разделенных и прямых запросов, или, возможно, ваши затраты ведут себя иначе. Дайте нам знать, как наша модель сравнивается с вашими реальными опытами!
Мы надеемся, что это дало вам увлекательный взгляд на мир симуляции ИИ и планирования ресурсов. Если вам когда-нибудь будет интересно, не разорит ли ваша следующая большая идея банк (или ваш кластер), быстрая симуляция, подобная этой, может дать вам некоторое спокойствие — или, по крайней мере, направление для более детализированного моделирования!
Спасибо, что присоединились к нам в этом облачном серфинге, токеновом хрусте и управлении агентами. До следующего раза, удачных симуляций!