[Bugfix] Add Responses cache_write_tokens for API compat and CC parity (#57222)
Signed-off-by: Yifan Zong <yzong@redhat.com> Co-authored-by: Flora Feng <4florafeng@gmail.com>
yzong-rh committed
Sep 16, 2026 at 17:52 UTC
5a6ccc589281b4302791cc301e258adcbcc5fead
5 files changed
+17
tests/entrypoints/openai/responses/test_serving_responses.py
+7
@@ -18,6 +18,9 @@ from openai.types.responses import (
18
ResponseTextConfig,
19
ResponseTextDeltaEvent,
20
)
21
+from openai.types.responses import (
22
+ ResponseUsage as OpenAIResponseUsage,
23
+)
24
from openai.types.responses.response_format_text_json_schema_config import (
25
ResponseFormatTextJSONSchemaConfig,
26
)
@@ -975,6 +978,7 @@ async def test_reasoning_tokens_counted_for_text_reasoning_model(monkeypatch):
978
outputs=[completion],
979
finished=True,
980
num_cached_tokens=0,
981
+ num_cache_creation_tokens=3,
982
)
983
context.append_output(req_output)
984
@@ -995,6 +999,9 @@ async def test_reasoning_tokens_counted_for_text_reasoning_model(monkeypatch):
999
)
1000
1001
assert response.usage.output_tokens_details.reasoning_tokens == 1
1002
+ assert response.usage.input_tokens_details.cache_write_tokens == 3
1003
+
1004
+ OpenAIResponseUsage.model_validate(response.usage.model_dump(mode="json"))
1005
1006
1007
class TestExtractAllowedToolsFromMcpRequests:
tests/entrypoints/unit_tests/test_context.py
+5
@@ -682,6 +682,7 @@ def create_simple_context_output(
682
prompt="Test prompt",
683
prompt_token_ids=None,
684
num_cached_tokens=0,
685
+ num_cache_creation_tokens=None,
686
logprobs=None,
687
finished=True,
688
):
@@ -707,6 +708,7 @@ def create_simple_context_output(
708
],
709
finished=finished,
710
num_cached_tokens=num_cached_tokens,
711
+ num_cache_creation_tokens=num_cache_creation_tokens,
712
)
713
714
@@ -827,6 +829,7 @@ def test_simple_context_token_counting():
829
token_ids=[10, 11],
830
prompt_token_ids=[1, 2, 3, 4, 5],
831
num_cached_tokens=2,
832
+ num_cache_creation_tokens=3,
833
)
834
)
835
context.append_output(
@@ -835,12 +838,14 @@ def test_simple_context_token_counting():
838
token_ids=[12],
839
prompt_token_ids=[1, 2, 3, 4, 5],
840
num_cached_tokens=2,
841
+ num_cache_creation_tokens=3,
842
)
843
)
844
845
assert context.num_prompt_tokens == 5
846
assert context.num_output_tokens == 3 # 2 + 1
847
assert context.num_cached_tokens == 2
848
+ assert context.num_cache_creation_tokens == 3
849
850
851
def test_simple_context_final_output():
vllm/entrypoints/openai/responses/context.py
+3
@@ -189,6 +189,7 @@ class SimpleContext(ConversationContext):
189
self.num_prompt_tokens = 0
190
self.num_output_tokens = 0
191
self.num_cached_tokens = 0
192
+ self.num_cache_creation_tokens = 0
193
# todo num_reasoning_tokens is not implemented yet.
194
self.num_reasoning_tokens = 0
195
# not implemented yet for SimpleContext
@@ -204,6 +205,8 @@ class SimpleContext(ConversationContext):
205
raise ValueError("SimpleContext only supports RequestOutput.")
206
self.num_prompt_tokens = len(output.prompt_token_ids or [])
207
self.num_cached_tokens = output.num_cached_tokens or 0
208
+ if output.num_cache_creation_tokens is not None:
209
+ self.num_cache_creation_tokens = output.num_cache_creation_tokens
210
self.num_output_tokens += len(output.outputs[0].token_ids or [])
211
if output.kv_transfer_params is not None:
212
self.kv_transfer_params = output.kv_transfer_params
vllm/entrypoints/openai/responses/protocol.py
+1
@@ -80,6 +80,7 @@ _INT64_MAX = 2**63 - 1
80
81
class InputTokensDetails(OpenAIBaseModel):
82
cached_tokens: int
83
+ cache_write_tokens: int
84
input_tokens_per_turn: list[int] = Field(default_factory=list)
85
cached_tokens_per_turn: list[int] = Field(default_factory=list)
86
vllm/entrypoints/openai/responses/serving.py
+1
@@ -837,6 +837,7 @@ class OpenAIServingResponses(GenerateBaseServing):
837
output_tokens=num_generated_tokens,
838
total_tokens=num_prompt_tokens + num_generated_tokens,
839
input_tokens_details=InputTokensDetails(
840
+ cache_write_tokens=getattr(context, "num_cache_creation_tokens", 0),
841
cached_tokens=num_cached_tokens,
842
input_tokens_per_turn=[
843
turn.input_tokens for turn in context.all_turn_metrics