From 4dfca3ad9124f13574406edb94b3d54ae9895044 Mon Sep 17 00:00:00 2001 From: Varad Pimpalkhute Date: Thu, 2 Jul 2026 08:35:41 +0000 Subject: [PATCH 1/3] Keep raw string for tool-call args that literal_eval to non-JSON types --- .../srt/function_call/multi_format_detector.py | 4 +++- .../function_call/test_multi_format_detector.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/python/sglang/srt/function_call/multi_format_detector.py b/python/sglang/srt/function_call/multi_format_detector.py index 14a540a4706e..75da4a16c284 100644 --- a/python/sglang/srt/function_call/multi_format_detector.py +++ b/python/sglang/srt/function_call/multi_format_detector.py @@ -1046,7 +1046,9 @@ def _deserialize_glm_value(value: str) -> Any: except Exception: pass try: - return ast.literal_eval(value) + result = ast.literal_eval(value) + json.dumps(result) + return result except Exception: pass return value diff --git a/test/registered/function_call/test_multi_format_detector.py b/test/registered/function_call/test_multi_format_detector.py index a80f49def64f..d94b1cfda03f 100644 --- a/test/registered/function_call/test_multi_format_detector.py +++ b/test/registered/function_call/test_multi_format_detector.py @@ -276,6 +276,18 @@ def test_python_tuple_literal_value(self): # ast.literal handles tuple syntax; serialized as a JSON array. self.assertEqual(args["days"], [1, 2]) + def test_python_set_literal_value_stays_string(self): + text = ( + "get_weather" + "days{1, 2}" + "" + ) + result = self.det.detect_and_parse(text, self.tools) + args = json.loads(result.calls[0].parameters) + # ast.literal_eval yields a set, which JSON cannot represent; the raw + # string is kept so the arguments dict stays serializable. + self.assertEqual(args["days"], "{1, 2}") + class TestGptOssDialect(unittest.TestCase): def setUp(self): From aeec8f8bcf0f4e0c98cfe1c007ac48ee57cc3f3f Mon Sep 17 00:00:00 2001 From: Rupesh K Srivastava Date: Thu, 2 Jul 2026 17:48:35 -0700 Subject: [PATCH 2/3] Apply suggestion from @flukeskywalker --- python/sglang/srt/function_call/multi_format_detector.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/sglang/srt/function_call/multi_format_detector.py b/python/sglang/srt/function_call/multi_format_detector.py index 75da4a16c284..25eb1acc7d7e 100644 --- a/python/sglang/srt/function_call/multi_format_detector.py +++ b/python/sglang/srt/function_call/multi_format_detector.py @@ -1047,6 +1047,7 @@ def _deserialize_glm_value(value: str) -> Any: pass try: result = ast.literal_eval(value) + # Try json serialization here in case that raises json.dumps(result) return result except Exception: From 6032806e809a010d130bfe9922445ebe3ab299e1 Mon Sep 17 00:00:00 2001 From: Varad Pimpalkhute Date: Wed, 15 Jul 2026 20:44:45 +0000 Subject: [PATCH 3/3] Clarify GLM literal serialization fallback --- python/sglang/srt/function_call/multi_format_detector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/sglang/srt/function_call/multi_format_detector.py b/python/sglang/srt/function_call/multi_format_detector.py index 25eb1acc7d7e..fae320a38c2c 100644 --- a/python/sglang/srt/function_call/multi_format_detector.py +++ b/python/sglang/srt/function_call/multi_format_detector.py @@ -1047,7 +1047,7 @@ def _deserialize_glm_value(value: str) -> Any: pass try: result = ast.literal_eval(value) - # Try json serialization here in case that raises + # Keep literal_eval results only when they remain JSON-serializable. json.dumps(result) return result except Exception: