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 9, 07:30 UTC
Remove deprecated `reasoning_content` message field (#33402)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Harry Mellor committed
Jan 30, 2026 at 11:48 UTC
c5113f60f2ca39334cdbe1657d5a8fd512767e04
8 files changed
+26
-55
tests/entrypoints/openai/tool_parsers/test_openai_tool_parser.py
+4
-4
@@ -131,7 +131,7 @@ def extract_reasoning_and_calls(chunks: list) -> tuple[str, list[str], list[str]
131
Extract accumulated reasoning text and tool call arguments
132
from streaming chunks.
133
"""
134
- reasoning_content: str = ""
134
+ reasoning: str = ""
135
tool_calls: dict[int, dict[str, str]] = {}
136
137
for chunk in chunks:
@@ -139,8 +139,8 @@ def extract_reasoning_and_calls(chunks: list) -> tuple[str, list[str], list[str]
139
if not choice:
140
continue
141
142
- if hasattr(choice, "reasoning_content") and choice.reasoning_content:
143
- reasoning_content += choice.reasoning_content
142
+ if hasattr(choice, "reasoning") and choice.reasoning:
143
+ reasoning += choice.reasoning
144
145
for tc in getattr(choice, "tool_calls", []) or []:
146
idx = getattr(tc, "index", 0)
@@ -156,7 +156,7 @@ def extract_reasoning_and_calls(chunks: list) -> tuple[str, list[str], list[str]
156
function_names: list[str] = [v["name"] for _, v in sorted(tool_calls.items())]
157
arguments: list[str] = [v["arguments"] for _, v in sorted(tool_calls.items())]
158
159
- return reasoning_content, arguments, function_names
159
+ return reasoning, arguments, function_names
160
161
162
# ==========================================================
tests/reasoning/utils.py
-3
@@ -18,9 +18,6 @@ class StreamingReasoningReconstructor:
18
assert delta.content is None or delta.reasoning is None, (
19
"Both content and reasoning content are present in the delta message"
20
)
21
- assert delta.reasoning == delta.reasoning_content, (
22
- "reasoning_content should be present for backwards compatibility"
23
- )
21
if delta.content is not None:
22
if self.other_content is None:
23
self.other_content = delta.content
vllm/entrypoints/chat_utils.py
+1
-4
@@ -1437,7 +1437,7 @@ def _parse_chat_message_content(
1437
) -> list[ConversationMessage]:
1438
role = message["role"]
1439
content = message.get("content")
1440
- reasoning = message.get("reasoning") or message.get("reasoning_content")
1440
+ reasoning = message.get("reasoning")
1441
1442
if content is None:
1443
content = []
@@ -1463,9 +1463,6 @@ def _parse_chat_message_content(
1463
# Include reasoning if present for interleaved thinking.
1464
if reasoning is not None:
1465
result_msg["reasoning"] = cast(str, reasoning)
1466
- result_msg["reasoning_content"] = cast(
1467
- str, reasoning
1468
- ) # keep compatibility
1466
elif role == "tool":
1467
parsed_msg = _ToolParser(message)
1468
if "tool_call_id" in parsed_msg:
vllm/entrypoints/openai/chat_completion/protocol.py
-8
@@ -61,14 +61,6 @@ class ChatMessage(OpenAIBaseModel):
61
62
# vLLM-specific fields that are not in OpenAI spec
63
reasoning: str | None = None
64
- reasoning_content: str | None = None
65
- """Deprecated: use `reasoning` instead."""
66
-
67
- @model_validator(mode="after")
68
- def handle_deprecated_reasoning_content(self):
69
- """Copy reasoning to reasoning_content for backward compatibility."""
70
- self.reasoning_content = self.reasoning
71
- return self
64
65
66
class ChatCompletionLogProb(OpenAIBaseModel):
vllm/entrypoints/openai/chat_completion/serving.py
+2
-2
@@ -1186,8 +1186,8 @@ class OpenAIServingChat(OpenAIServing):
1186
delta_content_parts = []
1187
if delta_message.content:
1188
delta_content_parts.append(delta_message.content)
1189
- if delta_message.reasoning_content:
1190
- reasoning = delta_message.reasoning_content
1189
+ if delta_message.reasoning:
1190
+ reasoning = delta_message.reasoning
1191
delta_content_parts.append(f"[reasoning: {reasoning}]")
1192
if delta_message.tool_calls:
1193
tool_args = "".join(
vllm/entrypoints/openai/engine/protocol.py
-8
@@ -261,16 +261,8 @@ class DeltaMessage(OpenAIBaseModel):
261
role: str | None = None
262
content: str | None = None
263
reasoning: str | None = None
264
- reasoning_content: str | None = None
265
- """Deprecated: use `reasoning` instead."""
264
tool_calls: list[DeltaToolCall] = Field(default_factory=list)
265
268
- @model_validator(mode="after")
269
- def handle_deprecated_reasoning_content(self):
270
- """Copy reasoning to reasoning_content for backward compatibility."""
271
- self.reasoning_content = self.reasoning
272
- return self
273
-
266
267
####### Tokens IN <> Tokens OUT #######
268
class GenerateRequest(BaseModel):
vllm/entrypoints/openai/parser/harmony_utils.py
+10
-14
@@ -321,13 +321,9 @@ def parse_chat_input_to_harmony_message(
321
commentary_msg = commentary_msg.with_channel("commentary")
322
msgs.append(commentary_msg)
323
324
- reasoning_content = chat_msg.get("reasoning") or chat_msg.get(
325
- "reasoning_content"
326
- )
327
- if reasoning_content:
328
- analysis_msg = Message.from_role_and_content(
329
- Role.ASSISTANT, reasoning_content
330
- )
324
+ reasoning = chat_msg.get("reasoning")
325
+ if reasoning:
326
+ analysis_msg = Message.from_role_and_content(Role.ASSISTANT, reasoning)
327
analysis_msg = analysis_msg.with_channel("analysis")
328
msgs.append(analysis_msg)
329
@@ -362,9 +358,9 @@ def parse_chat_input_to_harmony_message(
358
return [msg]
359
360
# Non-tool reasoning content
365
- reasoning_content = chat_msg.get("reasoning") or chat_msg.get("reasoning_content")
366
- if role == "assistant" and reasoning_content:
367
- analysis_msg = Message.from_role_and_content(Role.ASSISTANT, reasoning_content)
361
+ reasoning = chat_msg.get("reasoning")
362
+ if role == "assistant" and reasoning:
363
+ analysis_msg = Message.from_role_and_content(Role.ASSISTANT, reasoning)
364
analysis_msg = analysis_msg.with_channel("analysis")
365
msgs.append(analysis_msg)
366
@@ -545,7 +541,7 @@ def _parse_function_call(message: Message, recipient: str) -> list[ResponseOutpu
541
return output_items
542
543
548
-def _parse_reasoning_content(message: Message) -> list[ResponseOutputItem]:
544
+def _parse_reasoning(message: Message) -> list[ResponseOutputItem]:
545
"""Parse reasoning/analysis content into reasoning items."""
546
output_items = []
547
for content in message.content:
@@ -646,7 +642,7 @@ def parse_output_message(message: Message) -> list[ResponseOutputItem]:
642
elif recipient.startswith(("python", "browser", "container")):
643
# Built-in tool recipients (python/browser/container)
644
# generate reasoning output
649
- output_items.extend(_parse_reasoning_content(message))
645
+ output_items.extend(_parse_reasoning(message))
646
647
# All other recipients are MCP calls
648
else:
@@ -654,12 +650,12 @@ def parse_output_message(message: Message) -> list[ResponseOutputItem]:
650
651
# No recipient - handle based on channel for non-tool messages
652
elif message.channel == "analysis":
657
- output_items.extend(_parse_reasoning_content(message))
653
+ output_items.extend(_parse_reasoning(message))
654
655
elif message.channel == "commentary":
656
# Per Harmony format, commentary channel can contain preambles to calling
657
# multiple functions - explanatory text with no recipient
662
- output_items.extend(_parse_reasoning_content(message))
658
+ output_items.extend(_parse_reasoning(message))
659
660
elif message.channel == "final":
661
output_items.append(_parse_final_message(message))
vllm/tokenizers/deepseek_v32_encoding.py
+9
-12
@@ -45,7 +45,7 @@ dsml_token: str = "|DSML|"
45
system_msg_template: str = "{content}"
46
user_msg_template: str = "<|User|>{content}<|Assistant|>"
47
assistant_msg_template: str = "{reasoning}{content}{tool_calls}<|end▁of▁sentence|>"
48
-thinking_template = "{reasoning_content}"
48
+thinking_template = "{reasoning}"
49
50
response_format_template: str = "## Response Format:\n\nYou MUST strictly adhere to the following schema to reply:\n{schema}"
51
tool_call_template: str = (
@@ -170,7 +170,7 @@ def render_message(
170
tools = msg.get("tools")
171
response_format = msg.get("response_format")
172
tool_calls = msg.get("tool_calls")
173
- reasoning_content = msg.get("reasoning") or msg.get("reasoning_content")
173
+ reasoning = msg.get("reasoning")
174
is_prefix = msg.get("prefix", False)
175
176
if tools:
@@ -269,13 +269,12 @@ def render_message(
269
summary_content = content or ""
270
271
if thinking_mode == "thinking" and index > last_user_idx:
272
- if not (reasoning_content or tool_calls):
272
+ if not (reasoning or tool_calls):
273
raise ValueError(
274
- f"ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message"
274
+ f"ThinkingMode: {thinking_mode}, invalid message without reasoning/tool_calls `{msg}` after last user message"
275
)
276
thinking_part = (
277
- thinking_template.format(reasoning_content=reasoning_content or "")
278
- + thinking_end_token
277
+ thinking_template.format(reasoning=reasoning or "") + thinking_end_token
278
)
279
280
if not tool_calls and is_prefix:
@@ -307,7 +306,6 @@ def drop_thinking_messages(
306
307
elif role == "assistant":
308
msg_wo_thinking = copy.copy(msg)
310
- msg_wo_thinking.pop("reasoning_content", None)
309
msg_wo_thinking.pop("reasoning", None)
310
messages_wo_thinking.append(msg_wo_thinking)
311
@@ -421,7 +419,7 @@ def parse_tool_calls(index: int, text: str):
419
# formatted string and will not attempt to correct malformed output
420
# that may be generated by the model.
421
def parse_message_from_completion_text(text: str, thinking_mode: str):
424
- summary_content, reasoning_content, tool_calls = "", "", []
422
+ summary_content, reasoning, tool_calls = "", "", []
423
index, stop_token = 0, None
424
tool_calls_start_token = f"\n\n<{dsml_token}function_calls"
425
@@ -431,7 +429,7 @@ def parse_message_from_completion_text(text: str, thinking_mode: str):
429
index, content_delta, stop_token = _read_until_stop(
430
index, text, [thinking_end_token, tool_calls_start_token]
431
)
434
- reasoning_content = content_delta
432
+ reasoning = content_delta
433
if stop_token != thinking_end_token:
434
raise RuntimeError("Invalid thinking format")
435
@@ -462,13 +460,12 @@ def parse_message_from_completion_text(text: str, thinking_mode: str):
460
thinking_end_token,
461
dsml_token,
462
]:
465
- if sp_token in summary_content or sp_token in reasoning_content:
463
+ if sp_token in summary_content or sp_token in reasoning:
464
raise RuntimeError("Unexpected special token in content")
465
466
return {
467
"role": "assistant",
468
"content": summary_content,
471
- "reasoning_content": reasoning_content,
472
- "reasoning": reasoning_content,
469
+ "reasoning": reasoning,
470
"tool_calls": tool_calls_to_openai_format(tool_calls),
471
}