Чтобы получить чистую Markdown-версию этой страницы, добавьте .md к этому URL. Для полного указателя документации см. https://docs.nvidia.com/dynamo/llms.txt. Для полного содержимого, включая API reference и примеры SDK, см. https://docs.nvidia.com/dynamo/llms-full.txt.
SGLang для агентных нагрузок
SGLang для агентных нагрузок
Это руководство описывает конфигурацию SGLang для agentic serving в Dynamo. В нем показано, какие флаги движка SGLang нужно включить, как agent hints Dynamo сопоставляются с поведением SGLang и как использовать session control для управления KV cache в многоходовых agent-диалогах.
Обзор
Агентные нагрузки (циклы tool-calling, многотуровое рассуждение, пайплайны генерации кода) имеют иные характеристики производительности, чем batch inference:
- Prefix-heavy: Последовательные ходы разделяют растущий префикс диалога. Повторное использование KV cache критично для низкого TTFT.
- Priority-sensitive: Некоторые запросы (ходы агента, обращенные к пользователю) важнее фоновых задач.
- Long-lived: Диалоги длятся от минут до часов. Вытеснение cache при нехватке памяти может уничтожить накопленное состояние KV.
Agent hints Dynamo передают router метаданные на уровне каждого запроса. Флаги движка SGLang определяют, как эти метаданные влияют на планирование и вытеснение на worker.
Флаги движка SGLang
Планирование по приоритету
Включите планирование на основе приоритета, чтобы движок учитывал значение priority из nvext.agent_hints.priority:
python -m dynamo.sglang \
--model-path <model> \
--enable-priority-scheduling \
...
| Флаг | Описание |
|---|---|
--enable-priority-scheduling | Включает приоритетное планирование запросов вместо FCFS. |
Когда включено планирование по приоритету, движок использует поле priority из nvext.agent_hints для упорядочивания запросов во внутренней очереди. Запросы с более высоким эффективным приоритетом обслуживаются раньше запросов с более низким приоритетом. При равенстве учитывается время поступления.
Вытеснение KV cache по приоритету
По умолчанию SGLang вытесняет узлы radix tree по LRU. Можно переключиться на вытеснение по приоритету, чтобы низкоприоритетные записи cache вытеснялись раньше высокоприоритетных:
python -m dynamo.sglang \
--model-path <model> \
--radix-eviction-policy priority \
...
| Флаг | Значения | По умолчанию | Описание |
|---|---|---|---|
--radix-eviction-policy | lru, priority | lru | Стратегия вытеснения для GPU radix cache. priority использует heap, упорядоченный по значению приоритета запроса. |
Это не требует HiCache. Параметр управляет только вытеснением GPU radix tree. Когда GPU KV cache заполняется:
lru: Сначала вытесняет наименее недавно использованные leaf nodes.priority: Сначала вытесняет leaf nodes с самым низким приоритетом. Узлы с одинаковым приоритетом используют LRU-упорядочивание как запасной вариант.
Взаимодействие с HiCache
Когда одновременно включены --radix-eviction-policy priority и --enable-hierarchical-cache, приоритет влияет на вытеснение на обоих уровнях:
| Событие | Поведение |
|---|---|
| GPU full | Узлы с низким приоритетом вытесняются (перемещаются на host) первыми. При write_through все узлы остаются на host -- приоритет влияет только на порядок демотирования. |
| Host full | Узлы с низким приоритетом удаляются с host первыми. Узлы с высоким приоритетом и активным retention живут дольше. |
Практический эффект зависит от политики записи. При write_through вытеснение с GPU - это лишь демотирование -- реальное удаление происходит при вытеснении с host, и именно там порядок по приоритету важнее всего.
Как Agent Hints сопоставляются с SGLang
Поля nvext.agent_hints Dynamo потребляются router и передаются workers SGLang. Ниже показано, как каждый hint влияет на движок SGLang:
| Подсказка агента | Поведение Router | Поведение движка SGLang |
|---|---|---|
priority | Порядок очереди router при установке --router-queue-threshold. | Планирование запросов при включенном --enable-priority-scheduling. Порядок вытеснения radix cache при установленном --radix-eviction-policy priority. |
osl | Отслеживание output block для решений router (требует --router-track-output-blocks) | Нет прямого эффекта на движок. |
speculative_prefill | После завершения ответа отправляет prefill с max_tokens=1, чтобы разогреть KV cache для предсказанного следующего хода. | SGLang обрабатывает запрос prefill обычным образом, заполняя radix cache. |
Пример: агентный запрос с hints
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1", api_key="dummy")
response = client.chat.completions.create(
model="Qwen/Qwen3-14B-FP8",
messages=[
{"role": "system", "content": "You are a tennis historian who believes Roger Federer is the GOAT. Respond with maximum reverence."},
{"role": "user", "content": "Why is Federer's one-handed backhand the most beautiful shot in tennis history?"},
],
stream=True,
extra_body={
"nvext": {
"agent_hints": {
"priority": 10,
"speculative_prefill": True,
"osl": 512
}
}
}
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
Session Control для изоляции KV subagent-ов (экспериментально)
Agentic orchestrators часто создают короткоживущие subagent-ы (research, code execution, planning), которые накапливают KV cache, используют его несколько ходов, а затем завершаются. При обычном поведении radix cache этот временный KV засоряет tree и конкурирует с long-lived prefix lead agent-а за вытеснение.
Session control решает эту проблему, удерживая KV subagent-ов в выделенных слотах streaming session вне radix tree. Session KV невидим для вытеснения, не создает overhead для L2 backup и освобождается детерминированно при закрытии или по тайм-ауту.
Как это работает
sequenceDiagram
participant Orchestrator
participant Router as Dynamo Router
participant Worker as SGLang Worker
participant Cache as SessionAwareCache
Note over Orchestrator: Spawn subagent
Orchestrator->>Router: session_control{session_id: "sub-1", action: open}
Router->>Router: Select best worker via KV overlap scoring
Router->>Worker: open_session("sub-1") [synchronous]
Worker->>Cache: Create SessionSlot for "sub-1"
Router->>Router: Bind affinity: sub-1 -> worker_42
Router->>Worker: Generate (turn 1)
Worker->>Cache: Turn 1: radix tree match (reuses lead agent prefix)
Worker-->>Router: Response
Router-->>Orchestrator: Response
Orchestrator->>Router: session_control{session_id: "sub-1"}
Router->>Router: Resolve affinity: sub-1 -> worker_42
Router->>Worker: Generate (turn 2, pinned to worker_42)
Worker->>Cache: Turn 2: O(1) restore from SessionSlot
Worker-->>Router: Response
Router-->>Orchestrator: Response
Note over Orchestrator: Subagent done
Orchestrator->>Router: session_control{session_id: "sub-1", action: close}
Router->>Router: Remove affinity for sub-1
Router->>Worker: Generate (final turn)
Worker-->>Router: Response
Router-->>Orchestrator: Response
Note over Router,Worker: On stream completion
Router-)Worker: close_session("sub-1") [fire-and-forget]
Worker->>Cache: release_session -> free KV immediately
Ключевое поведение:
- Turn 1 идет через обычный radix tree, поэтому subagent разделяет cached system prompt prefix lead agent-а.
- Turns 2+ полностью обходят radix tree. KV восстанавливается из
SessionSlotза O(1). - Session KV невидим для вытеснения. Его нельзя вытеснить -- он освобождается только через явное закрытие или по тайм-ауту бездействия.
- Детерминированная очистка: при закрытии session KV освобождается немедленно.
- Affinity на стороне router:
StickySessionRouterподдерживает mappingsession_id -> (worker_id, dp_rank)со sliding-window TTL. Клиенты могут использоватьaction: "bind"для sticky routing только на стороне router илиaction: "open"для изоляции streaming session KV в SGLang; оба варианта отправляют последующие ходы на закрепленный worker/rank.
Включение Session Control
Session control задается запросом. StickySessionRouter активируется автоматически, когда запрос содержит nvext.session_control -- дополнительных флагов frontend, кроме --router-mode kv, не требуется. Используйте action: "bind" для sticky routing только на стороне router без вызова SGLang. На стороне worker streaming sessions нужно явно включать только для RPC жизненного цикла action: "open" / action: "close" и изоляции session KV.
Session control сейчас поддерживается только на backend SGLang. vLLM и TensorRT-LLM пока не предоставляют streaming session API.
Для streaming sessions требуется SGLang 0.5.11 или новее, включая изменения из sgl-project/sglang#21875 (session-aware cache, исправления race condition, метрики session).
SGLang worker:
python -m dynamo.sglang \
--model-path <model> \
--enable-streaming-session \
...
| Флаг | Описание |
|---|---|
--enable-streaming-session | Оборачивает radix cache в SessionAwareCache, включая slots streaming session для изоляции KV subagent-ов. |
Router:
python -m dynamo.frontend \
--router-mode kv \
...
Формат запроса
Открытие session
Добавьте session_control с action: "open" в первый запрос:
{
"model": "Qwen/Qwen3-14B-FP8",
"messages": [
{
"role": "user",
"content": "Research every Federer Grand Slam final in exhaustive detail."
}
],
"nvext": {
"session_control": {
"session_id": "sub-1",
"action": "open",
"timeout": 60
}
}
}
| Поле | Тип | Описание |
|---|---|---|
session_control.session_id | string | Уникальный идентификатор session. Должен присутствовать в каждом ходе. |
session_control.action | string | "bind", "open" или "close". На промежуточных ходах опускается. |
session_control.timeout | integer | Тайм-аут бездействия в секундах (по умолчанию 300). Используется с action: "bind" и action: "open". |
Последующие ходы
Добавьте session_control только с session_id (без action). Router автоматически разрешает affinity:
{
"model": "Qwen/Qwen3-14B-FP8",
"messages": [
{
"role": "user",
"content": "Now compare his Wimbledon 2007 final vs Nadal to any shot in human history."
}
],
"nvext": {
"session_control": {
"session_id": "sub-1"
}
}
}
Закрытие session
Добавьте action: "close". RPC close выполняется после завершения генерации:
{
"model": "Qwen/Qwen3-14B-FP8",
"messages": [
{
"role": "user",
"content": "Write a 500-word love letter to Federer's single-handed backhand."
}
],
"nvext": {
"session_control": {
"session_id": "sub-1",
"action": "close"
}
}
}
Ограничения
- Только streaming sessions: Sessions открываются с
streaming=True, поэтому поддерживаются только последовательные операции append. Ветвление (replace), покадровый rewind (offset) иdrop_previous_outputне поддерживаются. - Тайм-аут зависит от простоя: Тайм-аут обновляется на каждом запросе. Если subagent уходит на долгий tool call, превышающий тайм-аут, session reap-ится, а KV освобождается. Subagent должен снова открыть session и выполнить повторный prefill.
- Метрики session: Активное число session (
sglang:num_streaming_sessions) и удерживаемые токены KV (sglang:streaming_session_held_tokens) экспортируются как Prometheus gauges на metrics endpoint worker-а.
Быстрый старт
Скрипт запуска
Скрипт agg_agent.sh запускает один агрегированный worker с session control, sticky routing и KV events:
# Default model (GLM-4.7-Flash, 2 GPUs)
bash examples/backends/sglang/launch/agg_agent.sh
Frontend слушает на порту 8000 (можно переопределить через DYN_HTTP_PORT). Метрики worker-а доступны на порту 8081.
Тестирование с OpenCode
OpenCode — это open-source AI coding agent со встроенной поддержкой subagent-ов, tool calling и OpenAI-compatible endpoints. Fork провайдера Dynamo provider внедряет nvext.session_control в запросы subagent-ов, давая каждому spawned agent-у собственную Dynamo streaming session со sticky routing и изоляцией KV.
# Terminal 1 -- launch Dynamo with session control + tool/reasoning parsers
bash examples/backends/sglang/launch/agg_agent.sh \
--model-path zai-org/GLM-4.7-Flash --tp 2
# Terminal 2 -- run OpenCode against Dynamo
DYNAMO_API_KEY=dummy bun run --cwd packages/opencode src/index.ts \
-- --model "dynamo/zai-org/GLM-4.7-Flash"
Когда OpenCode создает subagent (через tool task), провайдер автоматически:
- Отправляет
session_control.action = "open"в первом ходе subagent-а - Маршрутизирует последующие ходы к тому же worker через
session_id - Отправляет
session_control.action = "close"после завершения subagent-а, освобождая KV
Primary agent работает без session control -- pinned только subagent sessions. Это сохраняет load balancing для запросов lead agent-а, а многотуровые диалоги subagent-ов остаются на одном worker с warm KV cache.
Конфигурация
Модель и endpoint настраиваются в .opencode/opencode.jsonc:
{
"provider": {
"dynamo": {
"npm": "@ai-sdk/openai-compatible",
"name": "Dynamo",
"env": ["DYNAMO_API_KEY"],
"models": {
"zai-org/GLM-4.7-Flash": {
"id": "zai-org/GLM-4.7-Flash",
"name": "GLM 4.7 Flash",
"tool_call": true,
"reasoning": true,
"temperature": true,
"attachment": false,
"release_date": "2025-06-01",
"limit": { "context": 131072, "output": 8192 },
"cost": { "input": 0, "output": 0 },
"interleaved": { "field": "reasoning_content" },
},
},
"options": {
"baseURL": "http://localhost:8000/v1",
},
},
},
}
См. также
- NVIDIA Request Extensions (nvext): Полная справка по полю
nvext, включая agent hints - Configuration and Tuning: Конфигурация router и CLI arguments
- SGLang HiCache: Включение hierarchical KV cache