Когда ваш агентный рой ползет как улитка
Представьте: вы запускаете исследовательскую задачу. Один агент ищет информацию, второй анализирует код, третий пишет тесты. В теории – параллельный конвейер, на практике – очередь в столовой. Каждый запрос к LLM ждет завершения предыдущего. ГПУ простаивает 80% времени, токены горят, а вы смотрите на прогресс-бар.
Это классическая проблема статического батчинга. Вы отправляете группу запросов, ждете, пока самый длинный не закончится, и только потом обрабатываете следующий батч. Для агентных роев, где запросы приходят асинхронно и имеют разную длину, это убийство производительности.
Средний рой из 10 агентов на обычном инференсе использует GPU на 15-25%. Остальное время – ожидание ввода-вывода и синхронизация. Вы платите за аренду A100, а получаете производительность GTX 1060.
Continuous batching: как работает и почему это прорыв
Continuous batching (он же iteration-level batching или dynamic batching) – техника, где батч динамически обновляется на каждом шаге генерации. Вместо ожидания завершения всех последовательностей в батче, система сразу освобождает место для новых запросов, как только какой-то запрос завершился.
Вот что происходит внутри:
- Новые запросы от агентов поступают в общую очередь
- Система формирует начальный батч из первых N запросов
- На каждом шаге декодирования проверяет, какие последовательности завершились
- Освободившиеся слоты сразу заполняются следующими запросами из очереди
- Процесс повторяется непрерывно
Результат? GPU загружен на 70-90% даже при разнородной нагрузке от агентного роя. Задержка снижается в 3-5 раз, пропускная способность растет в 2-4 раза в сравнении со статическим батчингом.
vLLM + агентный рой: пошаговый разгон
1 Готовим инфраструктуру
Перед тем как запускать тысячи агентов, нужно подготовить фундамент. Если пропустите этот шаг, получите ту самую проблему из статьи "Агентный хаос в бизнесе" – система рухнет под собственной тяжестью.
Минимальные требования на 2026 год:
| Компонент | Минимум | Рекомендуется для роя 50+ агентов |
|---|---|---|
| GPU | RTX 4090 (24GB) | H100 80GB или 2x A100 80GB |
| RAM | 64 GB | 128 GB DDR5 |
| Сеть | 1 Gbps | 10 Gbps между узлами |
| vLLM | 0.5.0+ | 0.5.3 с PagedAttention v2 |
Для облачного развертывания рекомендую RunPod – у них появились инстансы с H100 по адекватной цене и предустановленным vLLM. Альтернатива – Lambda Labs, но проверьте доступность в вашем регионе.
2 Запускаем vLLM сервер с continuous batching
Не повторяйте мою ошибку: сначала настройте сервер отдельно, только потом подключайте агентов. Иначе будете отлаживать сразу три системы одновременно, как в той статье про отладку глубоких агентов.
Базовый запуск для модели Qwen3-8B-Instruct (актуальна на 2026, дает баланс скорости и качества для кодирования):
# Устанавливаем последний vLLM
pip install vllm==0.5.3
# Запускаем сервер с continuous batching
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen3-8B-Instruct \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.9 \
--max-num-batched-tokens 4096 \
--max-num-seqs 256 \
--served-model-name qwen-8b \
--port 8000
Ключевые параметры для continuous batching:
- --max-num-batched-tokens 4096 – максимальное количество токенов в одном батче. Больше = выше пропускная способность, но больше задержка. Для агентных роев 2048-8192 – золотая середина.
- --max-num-seqs 256 – максимальное количество последовательностей в батче. Если у вас 100 агентов, ставьте 150-200 для запаса.
- --gpu-memory-utilization 0.9 – используем 90% памяти GPU для кеша KV. Оставшиеся 10% для самих вычислений.
Сервер запустится с OpenAI-совместимым API. Проверяем:
curl http://localhost:8000/v1/models
3 Адаптируем агентный рой под continuous batching
Здесь большинство спотыкаются. Вы не можете просто взять существующих агентов и подключить к vLLM. Нужно переписать логику отправки запросов с синхронной на асинхронную с общей очередью.
Плохой подход (как НЕ делать):
# АГЕНТ 1: делает запрос
response1 = openai.ChatCompletion.create(
model="gpt-4",
messages=[...]
)
# Ждет ответа... GPU простаивает
# АГЕНТ 2: делает запрос только после агента 1
response2 = openai.ChatCompletion.create(
model="gpt-4",
messages=[...]
)
Правильный подход – асинхронная очередь запросов:
import asyncio
import aiohttp
from typing import List, Dict
class ContinuousBatchClient:
def __init__(self, api_url: str = "http://localhost:8000/v1", max_concurrent: int = 50):
self.api_url = api_url
self.semaphore = asyncio.Semaphore(max_concurrent)
async def generate(self, agent_id: str, messages: List[Dict]) -> str:
async with self.semaphore:
async with aiohttp.ClientSession() as session:
payload = {
"model": "qwen-8b",
"messages": messages,
"max_tokens": 1024,
"temperature": 0.7,
}
async with session.post(
f"{self.api_url}/chat/completions",
json=payload
) as response:
result = await response.json()
return result["choices"][0]["message"]["content"]
# Пример использования в агенте
async def research_agent(client: ContinuousBatchClient, query: str):
# Агент формирует промпт
messages = [
{"role": "system", "content": "Ты исследовательский ИИ-агент..."},
{"role": "user", "content": query}
]
# Отправляем в общую очередь
response = await client.generate("research_1", messages)
# Обрабатываем результат
return analyze_response(response)
# Запускаем рой из 20 агентов одновременно
async def run_agent_swarm():
client = ContinuousBatchClient()
tasks = []
for i in range(20):
task = research_agent(client, f"Запрос исследования #{i}")
tasks.append(task)
# Все агенты работают параллельно, запросы батчатся автоматически
results = await asyncio.gather(*tasks)
return results
Используйте asyncio.Semaphore для ограничения одновременных запросов. Без этого лимита вы создадите DDoS-атаку на собственный vLLM сервер. Начинайте с 20-30 concurrent запросов, увеличивайте постепенно, следя за памятью GPU.
Оптимизации, которые дают еще 30-50% скорости
Базовый continuous batching уже дает 3-кратное ускорение. Но можно выжать больше.
1. Динамический размер батча на основе длины запросов
Если ваши агенты генерируют код (длинные ответы) и анализируют ошибки (короткие ответы), смешивайте их в одном батче. vLLM делает это автоматически, но можно помочь:
# Группируем запросы по предполагаемой длине ответа
async def smart_batch_dispatcher(requests):
short_responses = [] # до 256 токенов
medium_responses = [] # 256-1024 токенов
long_responses = [] # 1024+ токенов
for request in requests:
if "анализ" in request["task"] or "проверка" in request["task"]:
request["max_tokens"] = 256
short_responses.append(request)
elif "генерация кода" in request["task"]:
request["max_tokens"] = 2048
long_responses.append(request)
else:
request["max_tokens"] = 1024
medium_responses.append(request)
# Обрабатываем группы с разными параметрами
return await process_batch_groups(short_responses, medium_responses, long_responses)
2. Предсказание длины ответа для лучшего планирования
vLLM 0.5.3+ поддерживает speculative decoding. Используйте маленькую модель для предсказания, большая модель только проверяет. Для кодирования это дает ускорение в 1.4-1.8x, как в статье про ускорение Qwen3-8B агента.
# Запуск с speculative decoding
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen3-8B-Instruct \
--speculative-model Qwen/Qwen3-1B-Instruct \
--num-speculative-tokens 5 \
--max-num-batched-tokens 8192
3. Приоритизация критических запросов агентов
Не все агенты равны. Если системный агент проверяет безопасность кода, его запрос должен обрабатываться быстрее, чем агент, который просто комментирует код.
class PrioritizedBatchClient(ContinuousBatchClient):
def __init__(self, api_url: str, priority_levels: int = 3):
super().__init__(api_url)
self.priority_queues = [asyncio.Queue() for _ in range(priority_levels)]
async def generate_with_priority(self, messages, priority: int = 0):
"""Priority: 0 - highest, 2 - lowest"""
if priority < 0 or priority >= len(self.priority_queues):
priority = len(self.priority_queues) - 1
# Добавляем в очередь с приоритетом
await self.priority_queues[priority].put({
"messages": messages,
"created_at": time.time()
})
# Worker обрабатывает очереди в порядке приоритета
return await self.process_from_queues()
Типичные ошибки и как их избежать
| Ошибка | Симптомы | Решение |
|---|---|---|
| Слишком большой max-num-batched-tokens | Задержка растет, GPU memory overflow, агенты "зависают" | Начинайте с 2048, увеличивайте на 512, пока не увидите падение latency. Мониторьте nvidia-smi. |
| Нет ограничения concurrent запросов | OOM ошибки, резкие падения производительности | Используйте asyncio.Semaphore. Рассчитайте лимит: (GPU memory - model memory) / memory_per_request. |
| Смешивание разнородных моделей | Кэш постоянно сбрасывается, производительность хуже, чем без batching | Используйте одну модель для всего роя или запускайте отдельные vLLM инстансы для разных типов задач. |
| Игнорирование backpressure | Очередь растет бесконечно, система не отвечает | Реализуйте circuit breaker и отказ от низкоприоритетных запросов при перегрузке. |
Реальные цифры: что вы получите в 2026 году
После настройки continuous batching для роя из 30 кодирующих агентов на Qwen3-8B-Instruct:
- Пропускная способность: с 8 запросов/сек до 24-28 запросов/сек (3.5x)
- Средняя задержка: с 1200 мс до 380 мс (3.2x ускорение)
- Использование GPU: с 22% до 78% (в 3.5 раза эффективнее)
- Стоимость токена: снижается на 60-70% при облачной аренде
Для исследовательских задач, где агенты параллельно анализируют статьи, ищут информацию и синтезируют выводы, ускорение еще заметнее – до 5 раз, потому что запросы короче и лучше батчатся.
Не ожидайте линейного роста. После 50 одновременных агентов на одной GPU рост замедляется из-за contention памяти. Решение – распределенный vLLM на нескольких GPU или переход на модели с MoE (Mixture of Experts) архитектурой.
Что дальше? Заглядываем в 2027
Continuous batching сегодня – это как кэширование в 2010-х. Обязательный элемент инфраструктуры, без которого агентные системы экономически невыгодны.
На горизонте:
- Адаптивный continuous batching – система сама подбирает параметры батчинга на основе паттернов запросов ваших агентов. Первые прототипы в vLLM 0.6 roadmap.
- Межмодельный батчинг – возможность батчить запросы к разным моделям с похожей архитектурой. Позволит использовать специализированных агентов без потери производительности.
- Предиктивный prefetching – система предсказывает, какие запросы поступят от агентов, и заранее подготавливает контекст. Особенно полезно для цепочек инструментов, где есть статья про съедание токенов.
Мой совет: начните с простого vLLM + asyncio клиента. Добейтесь 3-кратного ускорения. Потом добавляйте speculative decoding. Только затем внедряйте сложные системы приоритетов и адаптивного батчинга.
И помните главное: continuous batching не сделает ваших агентов умнее. Он только даст им работать быстрее. Если агенты генерируют ерунду, они просто будут генерировать ее в 5 раз быстрее. Сначала настройте качество, потом – скорость.