Skip to content

Commit af42658

Browse files
jiaganclfr-0531
andauthored
[None][feat] Add conversation params API (#15452)
Signed-off-by: Jiagan Cheng <jiaganc@nvidia.com> Co-authored-by: Fanrong Li <23290157+lfr-0531@users.noreply.github.com>
1 parent acbcb93 commit af42658

30 files changed

Lines changed: 467 additions & 209 deletions

tensorrt_llm/_torch/pyexecutor/_util.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ def _create_dummy_mm_context_request(
392392
torch.zeros(1, 1, dtype=torch.int32)
393393
}
394394
}
395+
request.py_conversation_params = None
395396
remaining_tokens -= len(prompt_token_ids)
396397
requests.append(request)
397398

@@ -438,6 +439,7 @@ def _create_dummy_context_requests(
438439
torch.zeros(1, 1, dtype=torch.int32)
439440
}
440441
}
442+
request.py_conversation_params = None
441443
requests.append(request)
442444
remaining_tokens -= input_seq_len
443445
if self._mapping.enable_attention_dp:

tensorrt_llm/_torch/pyexecutor/llm_request.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ def __init__(
713713
self.py_logprobs_mode = LogprobMode(
714714
logprobs_mode) # handle passed a raw string
715715
self.py_disaggregated_params = None
716+
self.py_conversation_params = None
716717

717718
self.py_num_connector_matched_tokens = 0
718719

@@ -1041,6 +1042,8 @@ def executor_request_to_llm_request(
10411042
llm_request.py_disaggregated_params = getattr(executor_request,
10421043
"py_disaggregated_params",
10431044
None)
1045+
llm_request.py_conversation_params = getattr(executor_request,
1046+
"py_conversation_params", None)
10441047
if child_req_ids:
10451048
for child_id in child_req_ids:
10461049
llm_request.create_child_request(child_id)

tensorrt_llm/_torch/pyexecutor/request_utils.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ def get_num_child_requests(request: ExecutorRequest) -> int:
3838

3939

4040
def collect_py_objects_from_requests(
41-
requests: List, attribute_name: str
41+
requests: List, attribute_name: str, include_none: bool = False
4242
) -> Optional[Tuple[str, Dict]]:
4343
"""Collect Python-only objects from requests.
4444
4545
Args:
4646
requests: List of RequestQueueItem objects.
4747
attribute_name: Name of the attribute to collect.
48+
include_none: Include requests whose attribute value is None. When
49+
enabled, the source request must have the attribute.
4850
4951
Returns:
5052
Tuple of (attribute_name, dict mapping request_id to object) or None if empty.
@@ -54,9 +56,12 @@ def collect_py_objects_from_requests(
5456
if not item.is_normal_request:
5557
continue
5658
if item.request:
57-
obj = getattr(item.request, attribute_name, None)
58-
if obj is not None:
59-
req_id_to_obj[item.id] = obj
59+
if include_none:
60+
req_id_to_obj[item.id] = getattr(item.request, attribute_name)
61+
else:
62+
obj = getattr(item.request, attribute_name, None)
63+
if obj is not None:
64+
req_id_to_obj[item.id] = obj
6065
return None if not req_id_to_obj else (attribute_name, req_id_to_obj)
6166

6267

@@ -70,9 +75,8 @@ def attach_py_objects_to_requests(requests: List, py_request_objects: Tuple) ->
7075
for attr_name, req_obj_dict in py_request_objects:
7176
for item in requests:
7277
if item.request:
73-
py_obj = req_obj_dict.get(item.id)
74-
if py_obj is not None:
75-
setattr(item.request, attr_name, py_obj)
78+
if item.id in req_obj_dict:
79+
setattr(item.request, attr_name, req_obj_dict[item.id])
7680

7781

7882
def build_no_fitting_reqs_diagnostic(active_requests, kv_cache_manager) -> str:
@@ -578,6 +582,9 @@ def _collect_py_objects(self, new_requests: List) -> Tuple:
578582
py_disaggregated_params = collect_py_objects_from_requests(
579583
new_requests, "py_disaggregated_params"
580584
)
585+
py_conversation_params = collect_py_objects_from_requests(
586+
new_requests, "py_conversation_params", include_none=True
587+
)
581588
py_lora_path = collect_py_objects_from_requests(new_requests, "py_lora_path")
582589

583590
return tuple(
@@ -589,6 +596,7 @@ def _collect_py_objects(self, new_requests: List) -> Tuple:
589596
py_scheduling_params,
590597
py_num_logprobs,
591598
py_disaggregated_params,
599+
py_conversation_params,
592600
py_lora_path,
593601
],
594602
)

tensorrt_llm/_torch/pyexecutor/scheduler/adp_router.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,13 @@ def create_rank_state(
749749

750750
@staticmethod
751751
def _conversation_id(req_item) -> "str | None":
752-
req = getattr(req_item, "request", None)
752+
req = req_item.request
753753
if req is None:
754754
return None
755-
disagg = getattr(req, "py_disaggregated_params", None)
756-
if disagg is None:
755+
conversation_params = req.py_conversation_params
756+
if conversation_params is None:
757757
return None
758-
conv_id = getattr(disagg, "conversation_id", None)
759-
return conv_id if conv_id else None
758+
return conversation_params.conversation_id
760759

761760
def _record_target_rank(self, conv_id: str, rank: int) -> None:
762761
"""Bind/refresh the rank a conversation is pinned to (LRU-touch + evict)."""
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from dataclasses import dataclass
2+
3+
4+
@dataclass(slots=True, kw_only=True)
5+
class ConversationParams:
6+
"""Conversation parameters.
7+
8+
Args:
9+
conversation_id (str): Stable multi-turn conversation id used for routing.
10+
"""
11+
12+
conversation_id: str
13+
14+
def __post_init__(self) -> None:
15+
if self.conversation_id is None:
16+
raise ValueError("conversation_id must be non-empty")
17+
conversation_id = str(self.conversation_id).strip()
18+
if not conversation_id:
19+
raise ValueError("conversation_id must be non-empty")
20+
self.conversation_id = conversation_id

tensorrt_llm/disaggregated_params.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ class DisaggregatedParams:
5151
ctx_dp_rank: Optional[int] = None
5252
ctx_info_endpoint: Optional[str] = None
5353
schedule_style: Optional[DisaggScheduleStyle] = None
54-
# Multi-turn conversation id (from session headers such as X-Session-ID),
55-
# carried through so worker-side consumers (e.g. the ADP router) can see
56-
# the same id the disagg orchestrator routed on.
57-
conversation_id: Optional[str] = None
5854

5955
# E-P Disaggregated Params
6056
multimodal_embedding_handles: Optional[List[Dict[str, Any]]] = (

tensorrt_llm/executor/base_worker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,10 @@ def _deduce_max_tokens(request: GenerationRequest,
619619
if self._is_pytorch_backend and request.scheduling_params is not None:
620620
executor_request.py_scheduling_params = request.scheduling_params
621621

622+
executor_request.py_conversation_params = None
623+
if self._is_pytorch_backend and request.conversation_params is not None:
624+
executor_request.py_conversation_params = request.conversation_params
625+
622626
if request.arrival_time is not None:
623627
executor_request.py_arrival_time = request.arrival_time
624628

tensorrt_llm/executor/executor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .._utils import mpi_world_size
2222
from ..bindings import executor as tllm
2323
from ..builder import Engine
24+
from ..conversation_params import ConversationParams
2425
from ..disaggregated_params import DisaggregatedParams
2526
from ..llmapi.llm_args import BaseLlmArgs, TorchLlmArgs
2627
from ..llmapi.llm_utils import KvCacheRetentionConfig
@@ -134,6 +135,7 @@ def generate_async(
134135
postproc_params: Optional[PostprocParams] = None,
135136
multimodal_params: Optional[MultimodalParams] = None,
136137
scheduling_params: Optional[SchedulingParams] = None,
138+
conversation_params: Optional[ConversationParams] = None,
137139
cache_salt_id: Optional[int] = None,
138140
arrival_time: Optional[float] = None,
139141
priority: float = DEFAULT_REQUEST_PRIORITY,
@@ -162,6 +164,7 @@ def generate_async(
162164
trace_headers=trace_headers,
163165
multimodal_params=multimodal_params,
164166
scheduling_params=scheduling_params,
167+
conversation_params=conversation_params,
165168
cache_salt_id=cache_salt_id,
166169
arrival_time=arrival_time,
167170
priority=priority)
@@ -180,6 +183,7 @@ def generate(
180183
prompt_adapter_request: Optional[Union[
181184
PromptAdapterRequest, List[PromptAdapterRequest]]] = None,
182185
disaggregated_params: Optional[DisaggregatedParams] = None,
186+
conversation_params: Optional[ConversationParams] = None,
183187
) -> Union[GenerationResult, List[GenerationResult]]:
184188
"""Generate output for the given prompt token ids in the synchronous mode.
185189
Synchronous generation accepts either single prompt or batched prompts.
@@ -212,7 +216,8 @@ def generate(
212216
lora_request=lora_req,
213217
prompt_adapter_request=pa_req,
214218
streaming=False,
215-
disaggregated_params=disaggregated_params)
219+
disaggregated_params=disaggregated_params,
220+
conversation_params=conversation_params)
216221
futures.append(future)
217222

218223
for future in futures:

tensorrt_llm/executor/request.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from tensorrt_llm.inputs.multimodal import MultimodalParams
1010

11+
from ..conversation_params import ConversationParams
1112
from ..disaggregated_params import DisaggregatedParams
1213
from ..llmapi.llm_utils import KvCacheRetentionConfig
1314
from ..sampling_params import SamplingParams
@@ -105,6 +106,7 @@ def __init__(
105106
postproc_params: Optional[PostprocParams] = None,
106107
multimodal_params: Optional[MultimodalParams] = None,
107108
scheduling_params: Optional[SchedulingParams] = None,
109+
conversation_params: Optional[ConversationParams] = None,
108110
cache_salt_id: Optional[int] = None,
109111
arrival_time: Optional[float] = None,
110112
priority: float = DEFAULT_REQUEST_PRIORITY,
@@ -134,6 +136,7 @@ def __init__(
134136
self.disaggregated_params = disaggregated_params
135137
self.trace_headers = trace_headers
136138
self.scheduling_params = scheduling_params
139+
self.conversation_params = conversation_params
137140
self.cache_salt_id = cache_salt_id
138141
self.arrival_time = arrival_time
139142
if not (0.0 <= priority <= 1.0):

tensorrt_llm/llmapi/__init__.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
from .._torch.async_llm import AsyncLLM
2+
from ..conversation_params import ConversationParams
23
from ..disaggregated_params import DisaggregatedParams, DisaggScheduleStyle
34
from ..executor import CompletionOutput, LoRARequest, RequestError
45
from ..sampling_params import GuidedDecodingParams, SamplingParams
56
from ..scheduling_params import SchedulingParams
67
from .build_cache import BuildCacheConfig
78
from .llm import LLM, RequestOutput
8-
99
# yapf: disable
1010
from .llm_args import (AttentionDpConfig, AutoDecodingConfig, BatchingType,
1111
CacheTransceiverConfig, CalibConfig,
1212
CapacitySchedulerPolicy, ContextChunkingPolicy,
1313
CudaGraphConfig, DeepSeekSparseAttentionConfig,
14-
DeepSeekV4SparseAttentionConfig,
15-
DFlashDecodingConfig, DraftTargetDecodingConfig,
16-
DynamicBatchConfig, Eagle3DecodingConfig,
17-
EagleDecodingConfig, ExtendedRuntimePerfKnobConfig,
18-
KvCacheConfig, LlmArgs, LookaheadDecodingConfig,
19-
MedusaDecodingConfig, MoeConfig, MTPDecodingConfig,
20-
NGramDecodingConfig, PARDDecodingConfig,
21-
PrometheusMetricsConfig, ReorderRequestPolicyConfig,
22-
RocketSparseAttentionConfig, SADecodingConfig,
23-
SAEnhancerConfig, SaveHiddenStatesDecodingConfig,
24-
SchedulerConfig, SkipSoftmaxAttentionConfig,
25-
TorchCompileConfig, TorchLlmArgs, TrtLlmArgs,
26-
UserProvidedDecodingConfig)
14+
DeepSeekV4SparseAttentionConfig, DFlashDecodingConfig,
15+
DraftTargetDecodingConfig, DynamicBatchConfig,
16+
Eagle3DecodingConfig, EagleDecodingConfig,
17+
ExtendedRuntimePerfKnobConfig, KvCacheConfig, LlmArgs,
18+
LookaheadDecodingConfig, MedusaDecodingConfig, MoeConfig,
19+
MTPDecodingConfig, NGramDecodingConfig,
20+
PARDDecodingConfig, PrometheusMetricsConfig,
21+
ReorderRequestPolicyConfig, RocketSparseAttentionConfig,
22+
SADecodingConfig, SAEnhancerConfig,
23+
SaveHiddenStatesDecodingConfig, SchedulerConfig,
24+
SkipSoftmaxAttentionConfig, TorchCompileConfig,
25+
TorchLlmArgs, TrtLlmArgs, UserProvidedDecodingConfig)
2726
from .llm_utils import (BuildConfig, KvCacheRetentionConfig, QuantAlgo,
2827
QuantConfig)
2928
from .mm_encoder import MultimodalEncoder
@@ -38,6 +37,7 @@
3837
'GuidedDecodingParams',
3938
'SamplingParams',
4039
'DisaggregatedParams',
40+
'ConversationParams',
4141
'DisaggScheduleStyle',
4242
'KvCacheConfig',
4343
'KvCacheRetentionConfig',

0 commit comments

Comments
 (0)