[Bugfix] Set stop_sequence explicitly in streaming message_delta event (#55325)
Signed-off-by: Colin McNamara <colin@2cups.com>
Colin McNamara committed
Sep 10, 2026 at 17:21 UTC
360f33f61ce02bda04bcb7ea876f1d2e5af8d06d
2 files changed
+29
-1
tests/entrypoints/anthropic/test_anthropic_messages_conversion.py
+26
@@ -1610,6 +1610,32 @@ class TestStopSequenceReason:
1610
assert msg_deltas[0]["delta"]["stop_reason"] == "stop_sequence"
1611
assert msg_deltas[0]["delta"]["stop_sequence"] == "</tool>"
1612
1613
+ @pytest.mark.asyncio
1614
+ async def test_streaming_no_stop_string_emits_explicit_null_stop_sequence(self):
1615
+ """exclude_unset=True drops stop_sequence unless it is set explicitly."""
1616
+
1617
+ async def sse_input():
1618
+ yield _make_stream_chunk(delta=DeltaMessage(role="assistant"))
1619
+ yield _make_stream_chunk(delta=DeltaMessage(content="hi"))
1620
+ yield _make_stream_chunk(finish_reason="stop")
1621
+ yield _make_stream_chunk(
1622
+ choices=[],
1623
+ usage=UsageInfo(prompt_tokens=5, total_tokens=8, completion_tokens=3),
1624
+ )
1625
+ yield "data: [DONE]"
1626
+
1627
+ converter = _make_stream_converter()
1628
+ output = []
1629
+ async for event in converter.message_stream_converter(sse_input()):
1630
+ output.append(event)
1631
+
1632
+ events = _parse_sse_events(output)
1633
+ msg_deltas = [data for ev_type, data in events if ev_type == "message_delta"]
1634
+ assert len(msg_deltas) == 1
1635
+ assert msg_deltas[0]["delta"]["stop_reason"] == "end_turn"
1636
+ assert "stop_sequence" in msg_deltas[0]["delta"]
1637
+ assert msg_deltas[0]["delta"]["stop_sequence"] is None
1638
+
1639
1640
# ======================================================================
1641
# Client-caused errors are 4xx, not 500 (Issue #52088)
vllm/entrypoints/anthropic/serving.py
+3
-1
@@ -842,7 +842,9 @@ class AnthropicServingMessages(OpenAIServingChat):
842
stop_delta = AnthropicDelta(
843
stop_reason=self.stop_reason_map.get(
844
finish_reason or "stop"
845
- )
845
+ ),
846
+ # Set explicitly so exclude_unset=True keeps it.
847
+ stop_sequence=None,
848
)
849
chunk = AnthropicStreamEvent(
850
type="message_delta",