@tduncan / Nvidia-Optimization-Stack-VLLM Mirror · read-only / commits / 665f9c4253
Fork 0

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 3, 17:45 UTC

[Bugfix] Fix Gemma4ToolParser streaming float corruption (#42128)

Signed-off-by: abinggo <107740309+abinggo@users.noreply.github.com>

longguo committed May 14, 2026 at 09:03 UTC 665f9c42535c34e7d04b1c0424d34fe7677bb245
2 files changed +41
tests/tool_parsers/test_gemma4_tool_parser.py
+29
@@ -135,6 +135,26 @@ class TestParseGemma4Args:
135 result = _parse_gemma4_args('name:<|"|>test<|"|>,flag:', partial=True)
136 assert result == {"name": "test"}
137
138 + def test_trailing_dot_float_partial_withheld(self):
139 + """Bare float ending with '.' is withheld in partial mode.
140 +
141 + Regression test for #42047: float("108.") → 108.0 causes
142 + streaming diff corruption (108.0 → 108.2 becomes 108.02).
143 + """
144 + # Single key with trailing dot — withheld entirely
145 + result = _parse_gemma4_args("left:108.,right:22.8", partial=True)
146 + assert result == {}
147 +
148 + # Stable key before trailing-dot key — stable key is kept
149 + result = _parse_gemma4_args(
150 + 'name:<|"|>test<|"|>,score:3.,count:1', partial=True
151 + )
152 + assert result == {"name": "test"}
153 +
154 + # Non-partial mode parses trailing dot normally
155 + result = _parse_gemma4_args("left:108.,right:22.8", partial=False)
156 + assert result == {"left": 108.0, "right": 22.8}
157 +
158 @pytest.mark.timeout(5)
159 def test_malformed_partial_array(self):
160 result = _parse_gemma4_args(":[t:[]")
@@ -164,6 +184,15 @@ class TestParseGemma4Array:
184 result = _parse_gemma4_array("42,]trailing")
185 assert result == [42]
186
187 + def test_trailing_dot_float_partial_withheld(self):
188 + """Array elements with trailing dot withheld in partial mode."""
189 + result = _parse_gemma4_array("108.,22.8", partial=True)
190 + assert result == []
191 +
192 + # Stable elements before trailing-dot element are kept
193 + result = _parse_gemma4_array("42,108.,3", partial=True)
194 + assert result == [42]
195 +
196
197 # ---------------------------------------------------------------------------
198 # Non-streaming extraction tests
vllm/tool_parsers/gemma4_tool_parser.py
+12
@@ -211,6 +211,14 @@ def _parse_gemma4_args(args_str: str, *, partial: bool = False) -> dict:
211 i,
212 )
213 break
214 + if partial:
215 + raw_val = args_str[val_start:i].strip()
216 + if raw_val.endswith("."):
217 + # Trailing dot means decimal digits may still arrive
218 + # (e.g. "108." may become "108.2"). Parsing now would
219 + # yield float("108.") == 108.0, whose json repr "108.0"
220 + # corrupts the streaming diff when the true digit lands.
221 + break
222 result[key] = _parse_gemma4_value(args_str[val_start:i])
223
224 return result
@@ -294,6 +302,10 @@ def _parse_gemma4_array(arr_str: str, *, partial: bool = False) -> list:
302 i,
303 )
304 break
305 + if partial:
306 + raw_val = arr_str[val_start:i].strip()
307 + if raw_val.endswith("."):
308 + break
309 items.append(_parse_gemma4_value(arr_str[val_start:i]))
310
311 return items