A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 7, 15:15 UTC
[Bugfix] Emit reasoning_part events in simple streaming path for Resp… (#35184)
Signed-off-by: Daniel Salib <danielsalib@meta.com>
daniel-salib committed
Feb 26, 2026 at 17:49 UTC
d43048ce0585e6c9178f212aa0b7aeed95eb48df
2 files changed
+78
-22
tests/entrypoints/openai/responses/test_simple.py
+21
@@ -6,6 +6,7 @@ import pytest_asyncio
6
from openai import OpenAI
7
8
from ....utils import RemoteOpenAIServer
9
+from .conftest import validate_streaming_event_stack
10
11
MODEL_NAME = "Qwen/Qwen3-8B"
12
@@ -219,3 +220,23 @@ async def test_extra_sampling_params(client: OpenAI, model_name: str):
220
assert response.status in ["completed", "incomplete"]
221
assert len(response.output) > 0
222
assert response.output[0].content[0].text # Has text output
223
+
224
+
225
+@pytest.mark.asyncio
226
+@pytest.mark.parametrize("model_name", [MODEL_NAME])
227
+async def test_streaming_types(
228
+ pairs_of_event_types: dict[str, str], client: OpenAI, model_name: str
229
+):
230
+ stream = await client.responses.create(
231
+ model=model_name,
232
+ input="tell me a story about a cat in 20 words",
233
+ reasoning={"effort": "low"},
234
+ tools=[],
235
+ stream=True,
236
+ background=False,
237
+ )
238
+ events = []
239
+ async for event in stream:
240
+ events.append(event)
241
+
242
+ validate_streaming_event_stack(events, pairs_of_event_types)
vllm/entrypoints/openai/responses/serving.py
+57
-22
@@ -85,6 +85,8 @@ from vllm.entrypoints.openai.responses.protocol import (
85
ResponseCreatedEvent,
86
ResponseInProgressEvent,
87
ResponseInputOutputMessage,
88
+ ResponseReasoningPartAddedEvent,
89
+ ResponseReasoningPartDoneEvent,
90
ResponsesRequest,
91
ResponsesResponse,
92
ResponseUsage,
@@ -1339,6 +1341,19 @@ class OpenAIServingResponses(OpenAIServing):
1341
),
1342
)
1343
)
1344
+ yield _increment_sequence_number_and_return(
1345
+ ResponseReasoningPartAddedEvent(
1346
+ type="response.reasoning_part.added",
1347
+ sequence_number=-1,
1348
+ output_index=current_output_index,
1349
+ item_id=current_item_id,
1350
+ content_index=current_content_index,
1351
+ part=ResponseReasoningTextContent(
1352
+ text="",
1353
+ type="reasoning_text",
1354
+ ),
1355
+ )
1356
+ )
1357
else:
1358
yield _increment_sequence_number_and_return(
1359
ResponseOutputItemAddedEvent(
@@ -1354,22 +1369,21 @@ class OpenAIServingResponses(OpenAIServing):
1369
),
1370
)
1371
)
1357
- yield _increment_sequence_number_and_return(
1358
- ResponseContentPartAddedEvent(
1359
- type="response.content_part.added",
1360
- sequence_number=-1,
1361
- output_index=current_output_index,
1362
- item_id=current_item_id,
1363
- content_index=current_content_index,
1364
- part=ResponseOutputText(
1365
- type="output_text",
1366
- text="",
1367
- annotations=[],
1368
- logprobs=[],
1369
- ),
1372
+ yield _increment_sequence_number_and_return(
1373
+ ResponseContentPartAddedEvent(
1374
+ type="response.content_part.added",
1375
+ sequence_number=-1,
1376
+ output_index=current_output_index,
1377
+ item_id=current_item_id,
1378
+ content_index=current_content_index,
1379
+ part=ResponseOutputText(
1380
+ type="output_text",
1381
+ text="",
1382
+ annotations=[],
1383
+ logprobs=[],
1384
+ ),
1385
+ )
1386
)
1371
- )
1372
- current_content_index += 1
1387
first_delta_sent = True
1388
# todo(kebe7jun) tool call support
1389
@@ -1397,6 +1411,19 @@ class OpenAIServingResponses(OpenAIServing):
1411
text=reason_content,
1412
)
1413
)
1414
+ yield _increment_sequence_number_and_return(
1415
+ ResponseReasoningPartDoneEvent(
1416
+ type="response.reasoning_part.done",
1417
+ sequence_number=-1,
1418
+ item_id=current_item_id,
1419
+ output_index=current_output_index,
1420
+ content_index=current_content_index,
1421
+ part=ResponseReasoningTextContent(
1422
+ text=reason_content,
1423
+ type="reasoning_text",
1424
+ ),
1425
+ )
1426
+ )
1427
current_content_index = 0
1428
reasoning_item = ResponseReasoningItem(
1429
type="reasoning",
@@ -1418,6 +1445,8 @@ class OpenAIServingResponses(OpenAIServing):
1445
item=reasoning_item,
1446
)
1447
)
1448
+ current_output_index += 1
1449
+ current_item_id = str(uuid.uuid4())
1450
yield _increment_sequence_number_and_return(
1451
ResponseOutputItemAddedEvent(
1452
type="response.output_item.added",
@@ -1432,8 +1461,6 @@ class OpenAIServingResponses(OpenAIServing):
1461
),
1462
)
1463
)
1435
- current_output_index += 1
1436
- current_item_id = str(uuid.uuid4())
1464
yield _increment_sequence_number_and_return(
1465
ResponseContentPartAddedEvent(
1466
type="response.content_part.added",
@@ -1449,7 +1476,6 @@ class OpenAIServingResponses(OpenAIServing):
1476
),
1477
)
1478
)
1452
- current_content_index += 1
1479
# reset previous delta messages
1480
previous_delta_messages = []
1481
@@ -1485,7 +1511,6 @@ class OpenAIServingResponses(OpenAIServing):
1511
),
1512
)
1513
)
1488
- current_content_index += 1
1514
1515
previous_delta_messages.append(delta_message)
1516
if previous_delta_messages:
@@ -1505,7 +1530,19 @@ class OpenAIServingResponses(OpenAIServing):
1530
text=reason_content,
1531
)
1532
)
1508
- current_content_index += 1
1533
+ yield _increment_sequence_number_and_return(
1534
+ ResponseReasoningPartDoneEvent(
1535
+ type="response.reasoning_part.done",
1536
+ sequence_number=-1,
1537
+ item_id=current_item_id,
1538
+ output_index=current_output_index,
1539
+ content_index=current_content_index,
1540
+ part=ResponseReasoningTextContent(
1541
+ text=reason_content,
1542
+ type="reasoning_text",
1543
+ ),
1544
+ )
1545
+ )
1546
reasoning_item = ResponseReasoningItem(
1547
type="reasoning",
1548
content=[
@@ -1543,7 +1580,6 @@ class OpenAIServingResponses(OpenAIServing):
1580
item_id=current_item_id,
1581
)
1582
)
1546
- current_content_index += 1
1583
part = ResponseOutputText(
1584
text=final_content,
1585
type="output_text",
@@ -1559,7 +1595,6 @@ class OpenAIServingResponses(OpenAIServing):
1595
part=part,
1596
)
1597
)
1562
- current_content_index += 1
1598
item = ResponseOutputMessage(
1599
type="message",
1600
role="assistant",