Skip to content

Commit 6c27809

Browse files
committed
fix: tool-call-parser validation when using SGLang tokenizer
Signed-off-by: Krishnan Prashanth <[email protected]>
1 parent f6d6b34 commit 6c27809

File tree

2 files changed

+63
-18
lines changed

2 files changed

+63
-18
lines changed

components/src/dynamo/sglang/args.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,12 @@
4545
"flags": ["--dyn-tool-call-parser"],
4646
"type": str,
4747
"default": None,
48-
"choices": get_tool_parser_names(),
4948
"help": "Tool call parser name for the model.",
5049
},
5150
"reasoning-parser": {
5251
"flags": ["--dyn-reasoning-parser"],
5352
"type": str,
5453
"default": None,
55-
"choices": get_reasoning_parser_names(),
5654
"help": "Reasoning parser name for the model. If not specified, no reasoning parsing is performed.",
5755
},
5856
"custom-jinja-template": {
@@ -228,30 +226,14 @@ def _set_parser(
228226
229227
Returns:
230228
Resolved parser name, preferring Dynamo's value if both set.
231-
232-
Raises:
233-
ValueError: If parser name is not valid.
234229
"""
235-
# If both are present, give preference to dynamo_str
236230
if sglang_str is not None and dynamo_str is not None:
237231
logging.warning(
238232
f"--dyn-{arg_name} and --{arg_name} are both set. Giving preference to --dyn-{arg_name}"
239233
)
240234
return dynamo_str
241-
# If dynamo_str is not set, use try to use sglang_str if it matches with the allowed parsers
242235
elif sglang_str is not None:
243236
logging.warning(f"--dyn-{arg_name} is not set. Using --{arg_name}.")
244-
if arg_name == "tool-call-parser" and sglang_str not in get_tool_parser_names():
245-
raise ValueError(
246-
f"--{arg_name} is not a valid tool call parser. Valid parsers are: {get_tool_parser_names()}"
247-
)
248-
elif (
249-
arg_name == "reasoning-parser"
250-
and sglang_str not in get_reasoning_parser_names()
251-
):
252-
raise ValueError(
253-
f"--{arg_name} is not a valid reasoning parser. Valid parsers are: {get_reasoning_parser_names()}"
254-
)
255237
return sglang_str
256238
else:
257239
return dynamo_str
@@ -482,6 +464,23 @@ async def parse_args(args: list[str]) -> Config:
482464
"reasoning-parser",
483465
)
484466

467+
# Validate parser names when using Dynamo's tokenizer (not SGLang's)
468+
if not parsed_args.use_sglang_tokenizer:
469+
if tool_call_parser and tool_call_parser not in get_tool_parser_names():
470+
logging.error(
471+
f"Tool call parser '{tool_call_parser}' is not valid when using Dynamo's tokenizer. "
472+
f"Valid parsers are: {get_tool_parser_names()}. "
473+
f"Use --use-sglang-tokenizer to delegate tool parsing to SGLang."
474+
)
475+
sys.exit(1)
476+
if reasoning_parser and reasoning_parser not in get_reasoning_parser_names():
477+
logging.error(
478+
f"Reasoning parser '{reasoning_parser}' is not valid when using Dynamo's tokenizer. "
479+
f"Valid parsers are: {get_reasoning_parser_names()}. "
480+
f"Use --use-sglang-tokenizer to delegate reasoning parsing to SGLang."
481+
)
482+
sys.exit(1)
483+
485484
if parsed_args.custom_jinja_template and parsed_args.use_sglang_tokenizer:
486485
logging.error(
487486
"Cannot use --custom-jinja-template and --use-sglang-tokenizer together. "

components/src/dynamo/sglang/tests/test_sglang_unit.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,49 @@ async def test_custom_jinja_template_env_var_expansion(monkeypatch, mock_sglang_
7575
f"Expected custom_jinja_template value to be {JINJA_TEMPLATE_PATH}, "
7676
f"got {config.dynamo_args.custom_jinja_template}"
7777
)
78+
79+
80+
# --- Tool Call Parser Validation Tests ---
81+
82+
83+
@pytest.mark.asyncio
84+
async def test_tool_call_parser_valid_with_dynamo_tokenizer(mock_sglang_cli):
85+
"""Valid parser name works when using Dynamo's tokenizer."""
86+
mock_sglang_cli(
87+
"--model",
88+
"Qwen/Qwen3-0.6B",
89+
"--dyn-tool-call-parser",
90+
"hermes", # supported by Dynamo
91+
)
92+
93+
config = await parse_args(sys.argv[1:])
94+
95+
assert config.dynamo_args.tool_call_parser == "hermes"
96+
97+
98+
@pytest.mark.asyncio
99+
async def test_tool_call_parser_invalid_with_dynamo_tokenizer(mock_sglang_cli):
100+
"""Invalid parser name exits when using Dynamo's tokenizer."""
101+
mock_sglang_cli(
102+
"--model", "Qwen/Qwen3-0.6B", "--dyn-tool-call-parser", "nonexistent_parser"
103+
)
104+
105+
with pytest.raises(SystemExit):
106+
await parse_args(sys.argv[1:])
107+
108+
109+
@pytest.mark.asyncio
110+
async def test_tool_call_parser_invalid_with_sglang_tokenizer(mock_sglang_cli):
111+
"""Invalid Dynamo parser name is allowed when using SGLang's tokenizer."""
112+
mock_sglang_cli(
113+
"--model",
114+
"Qwen/Qwen3-0.6B",
115+
"--dyn-tool-call-parser",
116+
"sglang_only_parser",
117+
"--use-sglang-tokenizer",
118+
)
119+
120+
config = await parse_args(sys.argv[1:])
121+
122+
assert config.dynamo_args.tool_call_parser == "sglang_only_parser"
123+
assert config.dynamo_args.use_sglang_tokenizer is True

0 commit comments

Comments
 (0)