Repository navigation
[None][fix] Chat completions honor TRTLLM_KVCACHE_TIME_OUTPUT_PATH like completions and Responses - #21667
Draft
JunyiXu-nv wants to merge 1 commit into
Draft
[None][fix] Chat completions honor TRTLLM_KVCACHE_TIME_OUTPUT_PATH like completions and Responses#21667JunyiXu-nv wants to merge 1 commit into
JunyiXu-nv wants to merge 1 commit into
Conversation
1 task done
…ke completions and Responses With TRTLLM_KVCACHE_TIME_OUTPUT_PATH set to a non-empty value, the completions handler, the gpt-oss chat handler and the Responses preprocessing force SamplingParams.return_perf_metrics=True for every request; the chat completions handler did not. Chat completion requests (and the Anthropic Messages routes and /health_generate, which run through the chat handler) now request per-request engine perf metrics in the same way, with the same statements as the other three sites. Response bodies, status codes and headers are unchanged. The new CPU tests build the server through the fixture factory and read the sampling_params the handlers hand to the scripted generate_async, for /v1/chat/completions (variable set and unset), /v1/messages, /v1/messages/batches, /health_generate and the pre-existing /v1/completions behavior. Signed-off-by: JunyiXu-nv <219237550+JunyiXu-nv@users.noreply.github.com>
JunyiXu-nv
force-pushed
the
dev-junyix-fix-serve-chat-kvcache-time-output
branch
from
November 12, 2026 08:14
36fbf3f to
c14f872
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@coderabbitai summary
Refreshed onto main
c0468112f4after #21406 merged as9ceb00a84e. This PR now contains only its own commit; the patch is identical to the previously reviewed version. It remains draft while the inherited main-side constructor-baseline failure is repaired by #22174.Description
With
TRTLLM_KVCACHE_TIME_OUTPUT_PATHset to a non-empty value, three request paths force per-request engine perf metrics (SamplingParams.return_perf_metrics=True) right after building the sampling parameters: the completions handler (openai_completion), the gpt-oss chat handler (chat_harmony) and the Responses preprocessing (responses_utils.request_preprocess). The chat completions handler (openai_chat), which every non-gpt-oss chat request takes, did not. This PR adds the same two statements toopenai_chat, in the same position, so the four sites run the same check and assignment.Why every chat request rather than a gpt-oss-only special case: the four request paths now agree, and moving gpt-oss chat onto the common chat handler later needs no model-specific branch for this variable. Enabling the variable for all chat completions was chosen deliberately over keeping a special case for one model.
A prerequisite of the trtllm-serve refactor (epic TRTLLM-17056), not one of its tasks. Uses the fixture factory and fake generators (
tests/test_common/serve/) delivered on main by #21406.Behavior
This PR changes behavior. With
TRTLLM_KVCACHE_TIME_OUTPUT_PATHset, chat completion requests (including the Anthropic Messages routes and/health_generate, which use the chat handler) now request per-request engine perf metrics, as completions, gpt-oss chat and Responses already do. Response bodies, status codes and headers are unchanged./v1/completions(openai_completion)return_perf_metrics=True/v1/chat/completionsfor gpt-oss (chat_harmony)return_perf_metrics=True/v1/responses(request_preprocess)return_perf_metrics=True/v1/chat/completionsfor every other model (openai_chat, on the aggregated server and on the disaggregated context and generation workers, which serve chat through the same handler)return_perf_metrics=True/v1/messagesand/v1/messages/batches(run throughopenai_chat)return_perf_metrics=True/health_generate(runs throughopenai_chat)return_perf_metrics=TrueWhat the per-request flag does: the engine attaches
RequestPerfMetricsto the request's results andLLM.generate_asyncstamps the wall-clock arrival timestamp intometrics_dict. Response bodies never carry these metrics; per-request headers and JSONL records are produced only when server-level collection (return_perf_metricsorperf_metrics_output_dir) is on, which already covered chat. One consumer is unlocked by the per-request flag alone: OpenTelemetry tracing.GenerationResultBase.do_tracing(tensorrt_llm/executor/result.py) returns withinsufficient_request_metrics_warning()unless the result carriesreq_perf_metrics_dict, which is built only from the engine'srequest_perf_metrics; withotlp_traces_endpointconfigured and server-level perf metrics off, chat requests now produce theirllm_requestspan, as completions requests already do; before, tracing stopped at that warning and the request had no span. The KV-cache transfer time CSVs are written by the C++ side when the variable is set, independently of this flag. Server-level perf metrics, the other three sites and the variable's meaning do not change; gathering the environment reads oftensorrt_llm/serve/into one module is left to a later change, so the new site repeats the two statements of the completions site, with a comment that explains them in place of that site'sTODO.Moves
None.
CI bookkeeping
tensorrt_llm/serve/openai_server.pyis already listed, so the multi-GPU stages are added to this PR's pre-merge and stay blocked until theci: full pre-merge approvedlabel is applied.openai_server.pykeeps its formatting group; the new test file uses the default ruff configuration).tests/unittest/serve/test_kvcache_time_output_perf_metrics.pyis collected through theunittest/servedirectory entry oftests/integration/test_lists/test-db/l0_cpu.yml(stages CPU-Generic-x86-1/2 and CPU-Generic-arm-1/2) and carriespytest.mark.cpu_only.Related open PRs on the same lines
openai_chatas part of a kvbm disaggregated test change. If it merges first, this PR's production change is already onmainand a rebase keeps only the tests.TRTLLM_KVCACHE_TIME_OUTPUT_PATHorTRTLLM_PERF_TIME_EVENTS_PATHand does not touchopenai_chat. This PR does not add the second variable (out of its scope). If [None][feat] Add per-rank perf time events capture (TRTLLM_PERF_TIME_EVENTS_PATH) #16900 merges first, the chat site is the one site without the widened condition until the later change that gathers these reads; if it merges second, it should extend the chat site too.openai_server.py; the completions parity test here goes through the HTTP route and does not depend on where the handler lives.Test Coverage
New CPU tests in
tests/unittest/serve/test_kvcache_time_output_perf_metrics.py(7 tests). Each builds the aggregated server throughisolated_serve_envon the scripted fakes (server-level perf metrics off), sets the variable through the environment's configuration, sends one request, asserts that the handler reached the fakegenerate_asyncexactly once (so a harness that stops early fails for the right reason), and reads the submittedsampling_params:test_chat_requests_metrics_when_kvcache_time_output_is_set(/v1/chat/completions, non-streaming; the fake engine is scripted to fail at the call, so the handler stops right after submitting the request and the recorded flag is the value the engine was handed),test_streaming_chat_requests_metrics_when_kvcache_time_output_is_set(/v1/chat/completionswithstream: true),test_anthropic_messages_request_metrics_when_kvcache_time_output_is_set(/v1/messages),test_anthropic_batch_requests_metrics_when_kvcache_time_output_is_set(/v1/messages/batches, waits for the batch to end),test_health_generate_requests_metrics_when_kvcache_time_output_is_set(/health_generate):return_perf_metrics is True.test_chat_does_not_request_metrics_when_unset:return_perf_metrics is Falsewith the variable unset and server-level perf metrics off.test_completions_requests_metrics_when_kvcache_time_output_is_set(/v1/completions): the pre-existing behavior the chat path now matches.Refresh verification (2026-11-12)
Pinned base
c0468112f4, refreshed headc14f872715;git range-diffreports the own commit's patch unchanged. CPU runs used the worktree's code and the same local compiled-op stub on both sides where applicable.pytest -m cpu_only tests/unittest/serve tests/unittest/api_stability/test_serve_routes.py -q: 142 passed, 1 failed. The only failure istest_no_new_object_new_sites, with the same six historical baseline discrepancies observed on pinned main (135 passed, 1 failed). [None][fix] Align the serve constructor ratchet with its landing baseline #22174 corrects that main-side baseline; this PR does not change it.pytest tests/unittest/api_stability -q: 99 passed.LLM_MODELS_ROOT=... PYTHONPATH=$PWD/tests python3 -m test_common.serve.cpu_tests.Earlier validation on the original stacked version
The following results describe
36fbf3f3d9on its original base, not the refreshed main-based tree:pytest -m cpu_only tests/unittest/serve/test_kvcache_time_output_perf_metrics.py -q -rs: 7 passed, no skips.return_perf_metricsassertion and none on the "never reached generate_async" guard), 2 passed (unset, completions); condition always true (> 0to>= 0): 1 failed (test_chat_does_not_request_metrics_when_unset), 6 passed; condition always false (> 0to< 0): 5 failed, 2 passed; statements moved to after thegenerate_asynccall: 1 failed (test_chat_requests_metrics_when_kvcache_time_output_is_set), 6 passed; condition restricted to non-streaming requests: 1 failed (test_streaming_chat_requests_metrics_when_kvcache_time_output_is_set), 6 passed.git grep -n "TRTLLM_KVCACHE_TIME_OUTPUT_PATH" -- tensorrt_llm/serve/: four lines (chat, completions, gpt-oss chat, Responses).pytest -m cpu_only tests/unittest/api_stability tests/unittest/serve -q: 181 passed (route snapshot, middleware order,object.__new__ratchet, layering, shim identity, the new file).pytest -m cpu_only tests/unittest/llmapi/apps/test_anthropic_routes.py tests/unittest/llmapi/apps/test_openai_chat_disagg_multimodal.py tests/unittest/llmapi/apps/test_openai_chat_multimodal_prompt.py -q -rf: 61 passed, the same as on the base of this PR (no failures on either).LLM_MODELS_ROOT=... PYTHONPATH=tests python3 -m test_common.serve.cpu_tests(every serve CPU test, one pytest process per test-db entry): 70 processes, 4636 passed, 0 failed, 55 deselected; theunittest/serveentry runs 108 tests including the seven new ones. Four files that fail in this environment on the base of this PR as well (tests/unittest/disaggregated/test_context_first_profile.py,test_lifecycle_activation.py,test_peer.py;tests/unittest/llmapi/test_config_database.py) are not selected by that runner; run with plainpytest -m cpu_onlyon this branch and on its base they fail with the same 110 test ids (44 + 66), none specific to this change.pre-commit run --files tensorrt_llm/serve/openai_server.py tests/unittest/serve/test_kvcache_time_output_perf_metrics.py, twice: all hooks pass, nothing modified.grep -n "unittest/serve" tests/integration/test_lists/test-db/l0_cpu.ymlshows the directory entry (line 344);python scripts/test_to_stage_mapping.py --tests "unittest/serve"names CPU-Generic-arm-1, CPU-Generic-arm-2, CPU-Generic-x86-1 and CPU-Generic-x86-2;grep -c "pytest.mark.cpu_only" tests/unittest/serve/test_kvcache_time_output_perf_metrics.pyis 1.tests/integration/defs/disaggregated/test_disaggregated.py::test_disaggregated_kv_cache_time_outputandtest_disaggregated_perf_metrics(A10 list),tests/integration/defs/test_e2e.py::test_openai_chat_harmony_perf_metrics(H100 list).PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.🤖 Generated with Claude Code