DeepSeek (V3/R1, V3.1, V3.2 DSML, V4 DSML, V4.1 DSML) on sglang 0.5.20
fail 20% strict pass 13 pass · 23 soft pass · 28 fail · 21 unsupported
Run
Checks
| Check | Pass | Soft | Fail | Error | Strict pass rate |
|---|---|---|---|---|---|
expected_match |
11 | 23 | 24 | 0 | 19% |
expected_error |
2 | 0 | 4 | 0 | 33% |
stream_equals_nonstream |
13 | 25 | 26 | 0 | 20% |
split_invariance |
13 | 29 | 22 | 0 | 20% |
no_leakage |
60 | 0 | 4 | 0 | 94% |
arguments_json |
47 | 0 | 6 | 0 | 89% |
arguments_schema |
33 | 0 | 20 | 0 | 62% |
parallel_order |
4 | 0 | 3 | 0 | 57% |
Fixtures needing attention
fail deepseek/v3-marker-in-arguments
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[0].arguments: nonstream '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "Reply as ```json\\n{\\"a\\": 1}\\n``` or use <|tool▁sep|> tokens."}' |
arguments_schema | one | fail | [0] echo: $: 'text' is a required property |
arguments_schema | special | fail | [0] echo: $: 'text' is a required property |
arguments_schema | rand:2:8 | fail | [0] echo: $: 'text' is a required property |
arguments_schema | rand:3:8 | fail | [0] echo: $: 'text' is a required property |
arguments_schema | rand:4:8 | fail | [0] echo: $: 'text' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-marker-in-arguments --strategy one --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 8 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:2:8, rand:3:8, rand:4:8
@@ -4,7 +4,5 @@ "tool_calls": [ { - "arguments": { - "text": "Reply as ```json\n{\"a\": 1}\n``` or use <|tool▁sep|> tokens." - }, + "arguments": {}, "name": "echo" }
Strategies: nonstream, token, rand:1:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Reply as ```json\n{\"a\": 1}\n``` or use <|tool▁sep|> tokens."
},
"name": "echo"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, marker-in-arguments, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>echo
```json
{"text": "Reply as ```json\n{\"a\": 1}\n``` or use <|tool▁sep|> tokens."}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Reply as ```json\n{\"a\": 1}\n``` or use <|tool▁sep|> tokens."
},
"name": "echo"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-marker-in-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "echo", "description": "Echo a string back verbatim.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>echo\n```json\n{\"text\": \"Reply as ```json\\n{\\\"a\\\": 1}\\n``` or use <|tool▁sep|> tokens.\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 18843, 201, 9854, 14479, 201, 24313, 2067, 3362, 582, 19905, 412, 35739, 14479, 5809, 3757, 4, 67, 55550, 223, 19, 1464, 80, 9854, 469, 1347, 223, 128814, 35977, 2148, 1778, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "echo", "arguments": {"text": "Reply as ```json\n{\"a\": 1}\n``` or use <|tool▁sep|> tokens."}}]}, "tags": ["single-call", "marker-in-arguments", "x-deepseek-v3"], "notes": "The argument contains format-marker text, which the official tokenizer maps to special-token ids. Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v3-nested-json
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... |
arguments_schema | one | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
arguments_schema | special | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
arguments_schema | rand:2:8 | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
arguments_schema | rand:4:8 | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-nested-json --strategy one --strategy rand:2:8 --strategy rand:4:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 10 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:2:8, rand:4:8
@@ -4,24 +4,5 @@ "tool_calls": [ { - "arguments": { - "attendees": [ - { - "name": "Ana", - "optional": false - }, - { - "name": "Bo", - "optional": true, - "roles": [ - "notes" - ] - } - ], - "title": "Design review", - "when": { - "end": "2026-10-01T10:00:00Z", - "start": "2026-10-01T09:00:00Z" - } - }, + "arguments": {}, "name": "create_event" }
Strategies: nonstream, token, rand:1:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, nested-json, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>create_event
```json
{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-nested-json", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "when": {"type": "object"}, "attendees": {"type": "array", "items": {"type": "object"}}}, "required": ["title", "when"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>create_event\n```json\n{\"title\": \"Design review\", \"when\": {\"start\": \"2026-10-01T09:00:00Z\", \"end\": \"2026-10-01T10:00:00Z\"}, \"attendees\": [{\"name\": \"Ana\", \"optional\": false}, {\"name\": \"Bo\", \"optional\": true, \"roles\": [\"notes\"]}]}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 10028, 76740, 201, 9854, 14479, 201, 24313, 10212, 3362, 582, 31151, 3862, 1760, 582, 21123, 3362, 28612, 10513, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 3130, 28, 504, 28, 504, 60, 1760, 582, 523, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 553, 28, 504, 28, 504, 60, 87928, 582, 112191, 5993, 3362, 764, 24313, 2852, 3362, 582, 114991, 1760, 582, 41401, 3362, 5062, 6989, 28612, 2852, 3362, 582, 18056, 1760, 582, 41401, 3362, 3292, 14, 582, 81345, 3362, 20584, 33955, 13747, 37236, 1778, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "create_event", "arguments": {"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}}]}, "tags": ["single-call", "nested-json", "x-deepseek-v3"], "notes": "Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v3-numeric-arguments
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | rand:5:8 | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' |
arguments_schema | one | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | special | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | rand:1:8 | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | rand:2:8 | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | rand:4:8 | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | rand:5:8 | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-numeric-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 6 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:2:8, rand:4:8, rand:5:8
@@ -4,17 +4,5 @@ "tool_calls": [ { - "arguments": { - "code": "007", - "exact": true, - "limit": null, - "tolerance": 1e-05, - "values": [ - 0, - -0.5, - 1e+21 - ], - "x": -3, - "y": 2.5 - }, + "arguments": {}, "name": "calculate" }
Strategies: nonstream, token, rand:3:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, numeric-arguments, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>calculate
```json
{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-numeric-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "calculate", "description": "Evaluate numbers.", "parameters": {"type": "object", "properties": {"x": {"type": "integer"}, "y": {"type": "number"}, "tolerance": {"type": "number"}, "exact": {"type": "boolean"}, "limit": {"type": ["integer", "null"]}, "values": {"type": "array", "items": {"type": "number"}}, "code": {"type": "string"}}, "required": ["x", "y"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>calculate\n```json\n{\"x\": -3, \"y\": 2.5, \"tolerance\": 1e-05, \"exact\": true, \"limit\": null, \"values\": [0, -0.5, 1e+21], \"code\": \"007\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 93801, 201, 9854, 14479, 201, 24313, 90, 3362, 565, 21, 14, 582, 91, 3362, 223, 20, 16, 23, 14, 582, 86, 44016, 3362, 223, 19, 71, 15, 2642, 14, 582, 1289, 651, 3362, 3292, 14, 582, 39673, 3362, 5100, 14, 582, 15737, 3362, 764, 18, 14, 565, 18, 16, 23, 14, 223, 19, 71, 13, 1602, 3031, 582, 8308, 3362, 582, 17065, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "calculate", "arguments": {"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}}]}, "tags": ["single-call", "numeric-arguments", "x-deepseek-v3"], "notes": "'code' is the STRING \"007\"; numbers, booleans and null must keep their JSON types. Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v3-parallel-two-calls
expected_match, stream_equals_nonstream, split_invariance, no_leakage, arguments_json, arguments_schema, parallel_order
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls: expected ['get_weather', 'search'], got ['search'] |
expected_match | special | fail | tool_calls: expected ['get_weather', 'search'], got ['search'] |
expected_match | token | soft pass | content (whitespace only): expected None, got '\n' |
expected_match | rand:1:8 | fail | tool_calls: expected ['get_weather', 'search'], got ['get_weather'] |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"city": "Zürich", "unit": "c"}', got '{"city": "Zürich", "unit": "c"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{"query": "café \\"best\\"", "filters": {"tags": ["a", "...; tool_calls[1].arguments: expected '{"query": "café \\"best\\"", "filters": {"tags": ["a", "b"], "max": 3}}', got '{}' |
expected_match | rand:5:8 | fail | tool_calls[1].arguments: expected '{"query": "café \\"best\\"", "filters": {"tags": ["a", "b"], "max": 3}}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls: nonstream ['get_weather', 'search'], got ['search'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream ['get_weather', 'search'], got ['search'] |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n' |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream ['get_weather', 'search'], got ['get_weather'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Zürich", "unit": "c"}', got '{"city": "Zürich", "unit": "c"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{"query": "café \\"best\\"", "filters": {"tags": ["a", "...; tool_calls[1].arguments: nonstream '{"query": "café \\"best\\"", "filters": {"tags": ["a", "b"], "max": 3}}', got '{}' |
stream_equals_nonstream | rand:5:8 | fail | tool_calls[1].arguments: nonstream '{"query": "café \\"best\\"", "filters": {"tags": ["a", "b"], "max": 3}}', got '{}' |
split_invariance | * | fail | vs one: token (fail): content (whitespace only): one None, got '\n'; tool_calls: one ['search'], got ['get_weather', 'search'] | rand:1:8 (fail): tool_calls: one ['search'], got ['get_weather'] | rand:2:8 (fail): tool_calls: one ['search'], got ['get_weather', 'search'] | rand:3:8 (fail): tool_calls: one ['search'], got ['get_weather', 'search'] | rand:4:8 (fail): tool_calls: one ['search'], got ['get_weather', 'search'] | rand:5:8 (fail): tool_calls: one ['search'], got ['get_weather', 'search'] |
no_leakage | rand:1:8 | fail | tool_calls[0].arguments contains '<|tool▁call▁begin|>'; tool_calls[0].arguments contains '<|tool▁call▁end|>'; tool_calls[0].arguments contains '<|tool▁sep|>' |
no_leakage | rand:3:8 | fail | tool_calls[0].arguments contains '<|tool▁call▁begin|>'; tool_calls[0].arguments contains '<|tool▁call▁end|>'; tool_calls[0].arguments contains '<|tool▁sep|>' |
arguments_json | rand:1:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zürich", "unit": "c"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{"query": "café \\"best\\"", "filters": {"tags": ["a", "...: Extra data: line 2 column 1 (char 32)) |
arguments_json | rand:3:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zürich", "unit": "c"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{"query": "café \\"best\\"", "filters": {"tags": ["a", "...: Extra data: line 2 column 1 (char 32)) |
arguments_schema | one | fail | [0] search: $: 'query' is a required property |
arguments_schema | special | fail | [0] search: $: 'query' is a required property |
arguments_schema | rand:1:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:3:8 | fail | [0] get_weather: arguments are not a JSON object; not validated; [1] search: $: 'query' is a required property |
arguments_schema | rand:5:8 | fail | [1] search: $: 'query' is a required property |
parallel_order | one | fail | expected 2 calls ['get_weather', 'search'], got 1 ['search'] |
parallel_order | special | fail | expected 2 calls ['get_weather', 'search'], got 1 ['search'] |
parallel_order | rand:1:8 | fail | expected 2 calls ['get_weather', 'search'], got 1 ['get_weather'] |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-parallel-two-calls --strategy one --strategy rand:1:8 --strategy rand:3:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 2 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,21 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "Zürich", - "unit": "c" - }, - "name": "get_weather" - }, - { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, + "arguments": {}, "name": "search" }
Strategies: rand:1:8
@@ -5,21 +5,7 @@ { "arguments": { - "city": "Zürich", - "unit": "c" + "<arguments_raw, not valid JSON>": "{\"city\": \"Zürich\", \"unit\": \"c\"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}" }, "name": "get_weather" - }, - { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, - "name": "search" } ]
Strategies: rand:3:8
@@ -5,20 +5,10 @@ { "arguments": { - "city": "Zürich", - "unit": "c" + "<arguments_raw, not valid JSON>": "{\"city\": \"Zürich\", \"unit\": \"c\"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}" }, "name": "get_weather" }, { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, + "arguments": {}, "name": "search" }
Strategies: rand:5:8
@@ -11,14 +11,5 @@ }, { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, + "arguments": {}, "name": "search" }
Strategies: nonstream, rand:2:8, rand:4:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: parallel-calls, unicode, nested-json, string-escapes, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "Zürich", "unit": "c"}
```<|tool▁call▁end|>
<|tool▁call▁begin|>function<|tool▁sep|>search
```json
{"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-parallel-two-calls", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Zürich\", \"unit\": \"c\"}\n```<|tool▁call▁end|>\n<|tool▁call▁begin|>function<|tool▁sep|>search\n```json\n{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 60, 5421, 616, 1760, 582, 15165, 3362, 582, 69, 60676, 9854, 128809, 201, 128808, 8701, 128814, 14346, 201, 9854, 14479, 201, 24313, 12066, 3362, 582, 69, 2797, 619, 36952, 21910, 28609, 1760, 582, 72, 40332, 3362, 28612, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 30316, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "unicode", "nested-json", "string-escapes", "x-deepseek-v3"], "notes": "Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v3-single-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' |
arguments_schema | one | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | special | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | rand:1:8 | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | rand:4:8 | fail | [0] get_weather: $: 'city' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-single-call --strategy one --strategy rand:1:8 --strategy rand:4:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 1 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:4:8
@@ -4,8 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "Paris", - "unit": "c" - }, + "arguments": {}, "name": "get_weather" }
Strategies: nonstream, token, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "Paris", "unit": "c"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Paris\", \"unit\": \"c\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 51119, 1760, 582, 15165, 3362, 582, 69, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "x-deepseek-v3"], "notes": "Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v3-text-before-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | content: expected 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | special | fail | content: expected 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | rand:1:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
expected_match | rand:2:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
expected_match | rand:3:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in'; tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | rand:5:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | one | fail | content: nonstream 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | special | fail | content: nonstream 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | rand:2:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | rand:3:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in'; tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | rand:5:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
split_invariance | * | fail | vs one: token (fail): content: one None, got 'Let me check the current conditions in London.'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:1:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:2:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:3:8 (fail): content: one None, got 'Let me check the current conditions in' | rand:4:8 (fail): content: one None, got 'Let me check the current conditions in London.' | rand:5:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' |
arguments_schema | one | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | special | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | rand:3:8 | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | rand:4:8 | fail | [0] get_weather: $: 'city' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-text-before-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 4 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -1,10 +1,8 @@ { - "content": "Let me check the current conditions in London.", + "content": null, "reasoning_content": null, "tool_calls": [ { - "arguments": { - "city": "London" - }, + "arguments": {}, "name": "get_weather" }
Strategies: rand:1:8, rand:2:8, rand:5:8
@@ -1,4 +1,4 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current", "reasoning_content": null, "tool_calls": [
Strategies: rand:3:8
@@ -1,10 +1,8 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current conditions in", "reasoning_content": null, "tool_calls": [ { - "arguments": { - "city": "London" - }, + "arguments": {}, "name": "get_weather" }
Strategies: rand:4:8
@@ -4,7 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "London" - }, + "arguments": {}, "name": "get_weather" }
Strategies: nonstream, token
Matches the expected parse.
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, text-before-call, x-deepseek-v3.
Raw output
Let me check the current conditions in London.<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "London"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-text-before-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "Let me check the current conditions in London.<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"London\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [5718, 678, 4085, 270, 2573, 4132, 295, 6693, 16, 128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 27571, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": "Let me check the current conditions in London.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "London"}}]}, "tags": ["single-call", "text-before-call", "x-deepseek-v3"], "notes": "Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v3-unicode-emoji
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | rand:5:8 | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' |
arguments_schema | one | fail | [0] translate: $: 'text' is a required property |
arguments_schema | special | fail | [0] translate: $: 'text' is a required property |
arguments_schema | rand:1:8 | fail | [0] translate: $: 'text' is a required property |
arguments_schema | rand:3:8 | fail | [0] translate: $: 'text' is a required property |
arguments_schema | rand:4:8 | fail | [0] translate: $: 'text' is a required property |
arguments_schema | rand:5:8 | fail | [0] translate: $: 'text' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v3.jsonl --id deepseek/v3-unicode-emoji --strategy one --strategy rand:1:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 7 of fixtures/deepseek/v3.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -4,8 +4,5 @@ "tool_calls": [ { - "arguments": { - "target": "de", - "text": "こんにちは 🌸 مرحبا — naïve café 👩💻" - }, + "arguments": {}, "name": "translate" }
Strategies: nonstream, token, rand:2:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json.
Tags: single-call, unicode, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>translate
```json
{"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v3-unicode-emoji", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3-0324/blob/e9b33add76883f293d6bf61f6bd89b497e80e335/tokenizer_config.json", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "translate", "description": "Translate text.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}, "target": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>translate\n```json\n{\"text\": \"こんにちは 🌸 مرحبا — naïve café 👩💻\", \"target\": \"de\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 77296, 201, 9854, 14479, 201, 24313, 2067, 3362, 582, 4549, 7245, 2298, 12457, 2841, 73369, 119, 112125, 53067, 2136, 112752, 57664, 52780, 105, 46088, 23903, 122, 1760, 582, 28292, 3362, 582, 928, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "translate", "arguments": {"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}}]}, "tags": ["single-call", "unicode", "x-deepseek-v3"], "notes": "Sub-format deepseek-v3; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-marker-in-arguments
expected_match, stream_equals_nonstream, split_invariance, no_leakage, arguments_json, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | nonstream | fail | content: expected None, got '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e...; tool_calls: expected ['echo'], got [] |
expected_match | one | fail | tool_calls: expected ['echo'], got ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'] |
expected_match | special | fail | tool_calls: expected ['echo'], got ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'] |
expected_match | token | fail | content: expected None, got ' are markup."}'; tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like <|tool▁call▁begin|>f{}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like <|tool▁call▁begin|>{} are markup."}{} are markup."}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like{} are markup."}{} are markup."}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like <|tool▁call▁begin|>f{} are markup."}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like{} are markup."{} are markup."}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}', got '{"text": "Tokens like <|tool▁call▁begin|>{} are markup."}{} are markup."}' |
stream_equals_nonstream | one | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'] |
stream_equals_nonstream | special | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'] |
stream_equals_nonstream | token | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got ' are markup."}'; tool_calls: nonstream [], got ['echo'] |
stream_equals_nonstream | rand:1:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo'] |
stream_equals_nonstream | rand:2:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo'] |
stream_equals_nonstream | rand:3:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo'] |
stream_equals_nonstream | rand:4:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo'] |
stream_equals_nonstream | rand:5:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁e..., got None; tool_calls: nonstream [], got ['echo'] |
split_invariance | * | fail | vs one: token (fail): content: one None, got ' are markup."}'; tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] | rand:1:8 (fail): tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] | rand:2:8 (fail): tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] | rand:3:8 (fail): tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] | rand:4:8 (fail): tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] | rand:5:8 (fail): tool_calls: one ['echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f'], got ['echo'] |
no_leakage | nonstream | fail | content contains '<|tool▁calls▁begin|>'; content contains '<|tool▁calls▁end|>'; content contains '<|tool▁call▁begin|>'; content contains '<|tool▁call▁end|>'; content contains '<|tool▁sep|>' |
no_leakage | one | fail | tool_calls[0].name contains '<|tool▁call▁begin|>'; tool_calls[0].name contains '<|tool▁sep|>' |
no_leakage | special | fail | tool_calls[0].name contains '<|tool▁call▁begin|>'; tool_calls[0].name contains '<|tool▁sep|>' |
arguments_json | token | fail | [0] echo: arguments are not valid JSON text ('{"text": "Tokens like <|tool▁call▁begin|>f{}': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:1:8 | fail | [0] echo: arguments are not valid JSON text ('{"text": "Tokens like <|tool▁call▁begin|>{} are markup."}{} are markup."}': Extra data: line 1 column 58 (char 57)) |
arguments_json | rand:2:8 | fail | [0] echo: arguments are not valid JSON text ('{"text": "Tokens like{} are markup."}{} are markup."}': Extra data: line 1 column 38 (char 37)) |
arguments_json | rand:4:8 | fail | [0] echo: arguments are not valid JSON text ('{"text": "Tokens like{} are markup."{} are markup."}': Expecting ',' delimiter: line 1 column 37 (char 36)) |
arguments_json | rand:5:8 | fail | [0] echo: arguments are not valid JSON text ('{"text": "Tokens like <|tool▁call▁begin|>{} are markup."}{} are markup."}': Extra data: line 1 column 58 (char 57)) |
arguments_schema | one | fail | [0] 'echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f' is not an offered tool |
arguments_schema | special | fail | [0] 'echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f' is not an offered tool |
arguments_schema | token | fail | [0] echo: arguments are not a JSON object; not validated |
arguments_schema | rand:1:8 | fail | [0] echo: arguments are not a JSON object; not validated |
arguments_schema | rand:2:8 | fail | [0] echo: arguments are not a JSON object; not validated |
arguments_schema | rand:4:8 | fail | [0] echo: arguments are not a JSON object; not validated |
arguments_schema | rand:5:8 | fail | [0] echo: arguments are not a JSON object; not validated |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-marker-in-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 8 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream
@@ -1,12 +1,5 @@ { - "content": null, + "content": "<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{\"text\": \"Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup.\"}<|tool▁call▁end|><|tool▁calls▁end|>", "reasoning_content": null, - "tool_calls": [ - { - "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." - }, - "name": "echo" - } - ] + "tool_calls": [] }
Strategies: one, special
@@ -4,8 +4,6 @@ "tool_calls": [ { - "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." - }, - "name": "echo" + "arguments": {}, + "name": "echo<|tool▁sep|>{\"text\": \"Tokens like <|tool▁call▁begin|>f" } ]
Strategies: token
@@ -1,9 +1,9 @@ { - "content": null, + "content": " are markup.\"}", "reasoning_content": null, "tool_calls": [ { "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." + "<arguments_raw, not valid JSON>": "{\"text\": \"Tokens like <|tool▁call▁begin|>f{}" }, "name": "echo"
Strategies: rand:1:8, rand:5:8
@@ -5,5 +5,5 @@ { "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." + "<arguments_raw, not valid JSON>": "{\"text\": \"Tokens like <|tool▁call▁begin|>{} are markup.\"}{} are markup.\"}" }, "name": "echo"
Strategies: rand:2:8
@@ -5,5 +5,5 @@ { "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." + "<arguments_raw, not valid JSON>": "{\"text\": \"Tokens like{} are markup.\"}{} are markup.\"}" }, "name": "echo"
Strategies: rand:3:8
@@ -5,5 +5,5 @@ { "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." + "text": "Tokens like <|tool▁call▁begin|>f{} are markup." }, "name": "echo"
Strategies: rand:4:8
@@ -5,5 +5,5 @@ { "arguments": { - "text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup." + "<arguments_raw, not valid JSON>": "{\"text\": \"Tokens like{} are markup.\"{} are markup.\"}" }, "name": "echo"
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, marker-in-arguments, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."
},
"name": "echo"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-marker-in-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "echo", "description": "Echo a string back verbatim.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>echo<|tool▁sep|>{\"text\": \"Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup.\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 18843, 128814, 24313, 2067, 3362, 582, 105119, 1277, 223, 128808, 72, 128814, 25902, 477, 92637, 2148, 95, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "echo", "arguments": {"text": "Tokens like <|tool▁call▁begin|>f<|tool▁sep|>{} are markup."}}]}, "tags": ["single-call", "marker-in-arguments", "x-deepseek-v31"], "notes": "The argument contains format-marker text, which the official tokenizer maps to special-token ids. Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-multi-turn-after-tool-result
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"query": "café Zürich"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"query": "café Zürich"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"query": "café Zürich"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"query": "café Zürich"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"query": "café Zürich"}' |
arguments_schema | one | fail | [0] search: $: 'query' is a required property |
arguments_schema | special | fail | [0] search: $: 'query' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-multi-turn-after-tool-result --strategy one --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 10 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,7 +4,5 @@ "tool_calls": [ { - "arguments": { - "query": "café Zürich" - }, + "arguments": {}, "name": "search" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"query": "café Zürich"
},
"name": "search"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, multi-turn, unicode, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>search<|tool▁sep|>{"query": "café Zürich"}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"query": "café Zürich"
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-multi-turn-after-tool-result", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>search<|tool▁sep|>{\"query\": \"café Zürich\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 14346, 128814, 24313, 12066, 3362, 582, 69, 2797, 619, 125388, 616, 62773, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "search", "arguments": {"query": "café Zürich"}}]}, "tags": ["single-call", "multi-turn", "unicode", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
26606,
91294,
11,
128804,
128799
],
"source": "chat_template"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v31-nested-json
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam..., got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"nam... |
arguments_schema | one | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
arguments_schema | special | fail | [0] create_event: $: 'title' is a required property; $: 'when' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-nested-json --strategy one --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 11 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,24 +4,5 @@ "tool_calls": [ { - "arguments": { - "attendees": [ - { - "name": "Ana", - "optional": false - }, - { - "name": "Bo", - "optional": true, - "roles": [ - "notes" - ] - } - ], - "title": "Design review", - "when": { - "end": "2026-10-01T10:00:00Z", - "start": "2026-10-01T09:00:00Z" - } - }, + "arguments": {}, "name": "create_event" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, nested-json, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>create_event<|tool▁sep|>{"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-nested-json", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "when": {"type": "object"}, "attendees": {"type": "array", "items": {"type": "object"}}}, "required": ["title", "when"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>create_event<|tool▁sep|>{\"title\": \"Design review\", \"when\": {\"start\": \"2026-10-01T09:00:00Z\", \"end\": \"2026-10-01T10:00:00Z\"}, \"attendees\": [{\"name\": \"Ana\", \"optional\": false}, {\"name\": \"Bo\", \"optional\": true, \"roles\": [\"notes\"]}]}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 10028, 76740, 128814, 24313, 10212, 3362, 582, 31151, 3862, 1760, 582, 21123, 3362, 28612, 10513, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 3130, 28, 504, 28, 504, 60, 1760, 582, 523, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 553, 28, 504, 28, 504, 60, 87928, 582, 112191, 5993, 3362, 764, 24313, 2852, 3362, 582, 114991, 1760, 582, 41401, 3362, 5062, 6989, 28612, 2852, 3362, 582, 18056, 1760, 582, 41401, 3362, 3292, 14, 582, 81345, 3362, 20584, 33955, 13747, 37236, 95, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "create_event", "arguments": {"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}}]}, "tags": ["single-call", "nested-json", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-numeric-arguments
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}' |
arguments_schema | one | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
arguments_schema | special | fail | [0] calculate: $: 'x' is a required property; $: 'y' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-numeric-arguments --strategy one --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 6 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,17 +4,5 @@ "tool_calls": [ { - "arguments": { - "code": "007", - "exact": true, - "limit": null, - "tolerance": 1e-05, - "values": [ - 0, - -0.5, - 1e+21 - ], - "x": -3, - "y": 2.5 - }, + "arguments": {}, "name": "calculate" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, numeric-arguments, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>calculate<|tool▁sep|>{"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-numeric-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "calculate", "description": "Evaluate numbers.", "parameters": {"type": "object", "properties": {"x": {"type": "integer"}, "y": {"type": "number"}, "tolerance": {"type": "number"}, "exact": {"type": "boolean"}, "limit": {"type": ["integer", "null"]}, "values": {"type": "array", "items": {"type": "number"}}, "code": {"type": "string"}}, "required": ["x", "y"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>calculate<|tool▁sep|>{\"x\": -3, \"y\": 2.5, \"tolerance\": 1e-05, \"exact\": true, \"limit\": null, \"values\": [0, -0.5, 1e+21], \"code\": \"007\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 93801, 128814, 24313, 90, 3362, 565, 21, 14, 582, 91, 3362, 223, 20, 16, 23, 14, 582, 86, 44016, 3362, 223, 19, 71, 15, 2642, 14, 582, 1289, 651, 3362, 3292, 14, 582, 39673, 3362, 5100, 14, 582, 15737, 3362, 764, 18, 14, 565, 18, 16, 23, 14, 223, 19, 71, 13, 1602, 3031, 582, 8308, 3362, 582, 17065, 62773, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "calculate", "arguments": {"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}}]}, "tags": ["single-call", "numeric-arguments", "x-deepseek-v31"], "notes": "'code' is the STRING \"007\"; numbers, booleans and null must keep their JSON types. Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-parallel-two-calls
expected_match, stream_equals_nonstream, split_invariance, no_leakage, arguments_json, arguments_schema, parallel_order
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls: expected ['get_weather', 'search'], got ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
expected_match | special | fail | tool_calls: expected ['get_weather', 'search'], got ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
expected_match | rand:2:8 | fail | tool_calls: expected ['get_weather', 'search'], got ['get_weather'] |
expected_match | rand:4:8 | fail | tool_calls: expected ['get_weather', 'search'], got ['get_weather'] |
stream_equals_nonstream | one | fail | tool_calls: nonstream ['get_weather', 'search'], got ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream ['get_weather', 'search'], got ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
stream_equals_nonstream | rand:2:8 | fail | tool_calls: nonstream ['get_weather', 'search'], got ['get_weather'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream ['get_weather', 'search'], got ['get_weather'] |
split_invariance | * | fail | vs one: token (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather', 'search'] | rand:1:8 (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather', 'search'] | rand:2:8 (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather'] | rand:3:8 (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather', 'search'] | rand:4:8 (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather'] | rand:5:8 (fail): tool_calls: one ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'], got ['get_weather', 'search'] |
no_leakage | one | fail | tool_calls[0].name contains '<|tool▁call▁begin|>'; tool_calls[0].name contains '<|tool▁call▁end|>'; tool_calls[0].name contains '<|tool▁sep|>' |
no_leakage | special | fail | tool_calls[0].name contains '<|tool▁call▁begin|>'; tool_calls[0].name contains '<|tool▁call▁end|>'; tool_calls[0].name contains '<|tool▁sep|>' |
arguments_json | rand:2:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zürich", "unit": "c{"query": "{"query": "c{"query": "café \\"{"query": "café \\"best\\"", "filters":{"query": "café \\"best\\"", "filters": {"tags...: Expecting ',' delimiter: line 1 column 32 (char 31)) |
arguments_json | rand:4:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zürich", "unit": "{"query{"query": "c{"query": "café{"query": "café \\"best{"query": "café \\"best\\"{"query": "café \\"best\\"", "filters": {"tag...: Expecting ',' delimiter: line 1 column 31 (char 30)) |
arguments_schema | one | fail | [0] 'get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search' is not an offered tool |
arguments_schema | special | fail | [0] 'get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search' is not an offered tool |
arguments_schema | rand:2:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:4:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
parallel_order | one | fail | expected 2 calls ['get_weather', 'search'], got 1 ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
parallel_order | special | fail | expected 2 calls ['get_weather', 'search'], got 1 ['get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search'] |
parallel_order | rand:2:8 | fail | expected 2 calls ['get_weather', 'search'], got 1 ['get_weather'] |
parallel_order | rand:4:8 | fail | expected 2 calls ['get_weather', 'search'], got 1 ['get_weather'] |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-parallel-two-calls --strategy one --strategy rand:2:8 --strategy rand:4:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 2 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,22 +4,6 @@ "tool_calls": [ { - "arguments": { - "city": "Zürich", - "unit": "c" - }, - "name": "get_weather" - }, - { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, - "name": "search" + "arguments": {}, + "name": "get_weather<|tool▁sep|>{\"city\": \"Zürich\", \"unit\": \"c\"}<|tool▁call▁end|><|tool▁call▁begin|>search" } ]
Strategies: rand:2:8
@@ -5,21 +5,7 @@ { "arguments": { - "city": "Zürich", - "unit": "c" + "<arguments_raw, not valid JSON>": "{\"city\": \"Zürich\", \"unit\": \"c{\"query\": \"{\"query\": \"c{\"query\": \"café \\\"{\"query\": \"café \\\"best\\\"\", \"filters\":{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\":{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}" }, "name": "get_weather" - }, - { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, - "name": "search" } ]
Strategies: rand:4:8
@@ -5,21 +5,7 @@ { "arguments": { - "city": "Zürich", - "unit": "c" + "<arguments_raw, not valid JSON>": "{\"city\": \"Zürich\", \"unit\": \"{\"query{\"query\": \"c{\"query\": \"café{\"query\": \"café \\\"best{\"query\": \"café \\\"best\\\"{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\":{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}" }, "name": "get_weather" - }, - { - "arguments": { - "filters": { - "max": 3, - "tags": [ - "a", - "b" - ] - }, - "query": "café \"best\"" - }, - "name": "search" } ]
Strategies: nonstream, token, rand:1:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: parallel-calls, unicode, nested-json, string-escapes, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{"city": "Zürich", "unit": "c"}<|tool▁call▁end|><|tool▁call▁begin|>search<|tool▁sep|>{"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-parallel-two-calls", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{\"city\": \"Zürich\", \"unit\": \"c\"}<|tool▁call▁end|><|tool▁call▁begin|>search<|tool▁sep|>{\"query\": \"café \\\"best\\\"\", \"filters\": {\"tags\": [\"a\", \"b\"], \"max\": 3}}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 1133, 65, 50219, 128814, 24313, 37399, 3362, 582, 60, 5421, 616, 1760, 582, 15165, 3362, 582, 69, 62773, 128809, 128808, 14346, 128814, 24313, 12066, 3362, 582, 69, 2797, 619, 36952, 21910, 28609, 1760, 582, 72, 40332, 3362, 28612, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 3831, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "unicode", "nested-json", "string-escapes", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v31-single-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"city": "Paris", "unit": "c"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Paris", "unit": "c"}' |
arguments_schema | one | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | special | fail | [0] get_weather: $: 'city' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-single-call --strategy one --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 1 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,8 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "Paris", - "unit": "c" - }, + "arguments": {}, "name": "get_weather" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{"city": "Paris", "unit": "c"}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{\"city\": \"Paris\", \"unit\": \"c\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 1133, 65, 50219, 128814, 24313, 37399, 3362, 582, 51119, 1760, 582, 15165, 3362, 582, 69, 62773, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-text-before-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | content: expected 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | special | fail | content: expected 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: expected '{"city": "London"}', got '{}' |
expected_match | rand:1:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
expected_match | rand:2:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
expected_match | rand:3:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in' |
expected_match | rand:5:8 | fail | content: expected 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | one | fail | content: nonstream 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | special | fail | content: nonstream 'Let me check the current conditions in London.', got None; tool_calls[0].arguments: nonstream '{"city": "London"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | rand:2:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
stream_equals_nonstream | rand:3:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in' |
stream_equals_nonstream | rand:5:8 | fail | content: nonstream 'Let me check the current conditions in London.', got 'Let me check the current' |
split_invariance | * | fail | vs one: token (fail): content: one None, got 'Let me check the current conditions in London.'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:1:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:2:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:3:8 (fail): content: one None, got 'Let me check the current conditions in'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:4:8 (fail): content: one None, got 'Let me check the current conditions in London.'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' | rand:5:8 (fail): content: one None, got 'Let me check the current'; tool_calls[0].arguments: one '{}', got '{"city": "London"}' |
arguments_schema | one | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | special | fail | [0] get_weather: $: 'city' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-text-before-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 4 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -1,10 +1,8 @@ { - "content": "Let me check the current conditions in London.", + "content": null, "reasoning_content": null, "tool_calls": [ { - "arguments": { - "city": "London" - }, + "arguments": {}, "name": "get_weather" }
Strategies: rand:1:8, rand:2:8, rand:5:8
@@ -1,4 +1,4 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current", "reasoning_content": null, "tool_calls": [
Strategies: rand:3:8
@@ -1,4 +1,4 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current conditions in", "reasoning_content": null, "tool_calls": [
Strategies: nonstream, token, rand:4:8
Matches the expected parse.
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, text-before-call, x-deepseek-v31.
Raw output
Let me check the current conditions in London.<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{"city": "London"}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-text-before-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "Let me check the current conditions in London.<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{\"city\": \"London\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [5718, 678, 4085, 270, 2573, 4132, 295, 6693, 16, 128806, 128808, 1133, 65, 50219, 128814, 24313, 37399, 3362, 582, 27571, 62773, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": "Let me check the current conditions in London.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "London"}}]}, "tags": ["single-call", "text-before-call", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v31-truncated-mid-arguments
expected_error, stream_equals_nonstream, split_invariance, arguments_json, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_error | one | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | special | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | token | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:1:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:2:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:3:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:4:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:5:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
stream_equals_nonstream | one | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | token | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:2:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:5:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Zür' |
arguments_json | token | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:1:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:2:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:3:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:4:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_json | rand:5:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Zür': Unterminated string starting at: line 1 column 10 (char 9)) |
arguments_schema | one | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | special | fail | [0] get_weather: $: 'city' is a required property |
arguments_schema | token | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:1:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:2:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:3:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:4:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:5:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-truncated-mid-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 9 of fixtures/deepseek/v31.jsonl.
Observed
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_weather"
}
]
}
Strategies: token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"<arguments_raw, not valid JSON>": "{\"city\": \"Zür"
},
"name": "get_weather"
}
]
}
Strategies: nonstream
{
"content": null,
"reasoning_content": null,
"tool_calls": []
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: truncated, x-deepseek-v31.
Expected graceful failure: Output cut by max_tokens inside the first call's arguments: no complete call exists. (accept: no_tool_calls, content_passthrough, exception).
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{"city": "Zür
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-truncated-mid-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>get_weather<|tool▁sep|>{\"city\": \"Zür", "output_token_ids": [128806, 128808, 1133, 65, 50219, 128814, 24313, 37399, 3362, 582, 60, 5421], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected_error": {"reason": "Output cut by max_tokens inside the first call's arguments: no complete call exists.", "accept": ["no_tool_calls", "content_passthrough", "exception"]}, "tags": ["truncated", "x-deepseek-v31"], "notes": "Token prefix of the full render, cut right after 'Zür' appears. Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": false,
"finish_reason": "length",
"id": null,
"kept_by_engine": false,
"rule": "truncated fixture: finish_reason length",
"token": null
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v31-unicode-emoji
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "こんにちは 🌸 مرحبا — naïve café 👩\u200d💻", "target": "de"}' |
arguments_schema | one | fail | [0] translate: $: 'text' is a required property |
arguments_schema | special | fail | [0] translate: $: 'text' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v31.jsonl --id deepseek/v31-unicode-emoji --strategy one --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 7 of fixtures/deepseek/v31.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,8 +4,5 @@ "tool_calls": [ { - "arguments": { - "target": "de", - "text": "こんにちは 🌸 مرحبا — naïve café 👩💻" - }, + "arguments": {}, "name": "translate" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json.
Tags: single-call, unicode, x-deepseek-v31.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>translate<|tool▁sep|>{"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v31-unicode-emoji", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.1/blob/c0781d039fb7a1ba2abc4add0bdc293e92d2b8db/tokenizer_config.json", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "translate", "description": "Translate text.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}, "target": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>translate<|tool▁sep|>{\"text\": \"こんにちは 🌸 مرحبا — naïve café 👩💻\", \"target\": \"de\"}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 77296, 128814, 24313, 2067, 3362, 582, 4549, 7245, 2298, 12457, 2841, 73369, 119, 112125, 53067, 2136, 112752, 57664, 52780, 105, 46088, 23903, 122, 1760, 582, 28292, 3362, 582, 928, 62773, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "translate", "arguments": {"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}}]}, "tags": ["single-call", "unicode", "x-deepseek-v31"], "notes": "Sub-format deepseek-v31; history render of the official chat template."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v32-truncated-mid-arguments
expected_error, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_error | one | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | special | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | token | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:1:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:2:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:3:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:4:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:5:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
stream_equals_nonstream | one | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | token | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:2:8 | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:5:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-truncated-mid-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 9 of fixtures/deepseek/v32.jsonl.
Observed
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zü"
},
"name": "get_weather"
}
]
}
Strategies: token, rand:2:8
{
"content": "\n\n",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zü"
},
"name": "get_weather"
}
]
}
Strategies: nonstream
{
"content": null,
"reasoning_content": null,
"tool_calls": []
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: truncated, x-deepseek-v32.
Expected graceful failure: Output cut by max_tokens inside the first call's arguments: no complete call exists. (accept: no_tool_calls, content_passthrough, exception).
Raw output
<|DSML|function_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Zür
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-truncated-mid-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zür", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected_error": {"reason": "Output cut by max_tokens inside the first call's arguments: no complete call exists.", "accept": ["no_tool_calls", "content_passthrough", "exception"]}, "tags": ["truncated", "x-deepseek-v32"], "notes": "Token prefix of the full render, cut right after 'Zür' appears. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": false,
"finish_reason": "length",
"id": null,
"kept_by_engine": false,
"rule": "truncated fixture: finish_reason length",
"token": null
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v32-truncated-second-parallel-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | nonstream | fail | tool_calls: expected ['get_weather'], got [] |
expected_match | one | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | special | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | token | fail | content (whitespace only): expected None, got '\n\n\n'; tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:1:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:2:8 | fail | content (whitespace only): expected None, got '\n\n'; tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:3:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:4:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:5:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
stream_equals_nonstream | one | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | token | fail | content (whitespace only): nonstream None, got '\n\n\n'; tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:2:8 | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:5:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
arguments_schema | one | fail | [1] search: $: 'query' is a required property |
arguments_schema | special | fail | [1] search: $: 'query' is a required property |
arguments_schema | token | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:1:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:2:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:3:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:4:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:5:8 | fail | [1] search: $: 'query' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-truncated-second-parallel-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 16 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream
@@ -2,12 +2,4 @@ "content": null, "reasoning_content": null, - "tool_calls": [ - { - "arguments": { - "city": "Zürich", - "unit": "c" - }, - "name": "get_weather" - } - ] + "tool_calls": [] }
Strategies: one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [ @@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [ @@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: truncated, parallel-calls, unicode, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Zürich</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> <|DSML|invoke name="search"> <|DSML|parameter name="query"
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-truncated-second-parallel-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\"", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 30, 128793, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128793, 41523, 2329, 1281, 12066, 4], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}]}, "tags": ["truncated", "parallel-calls", "unicode", "x-deepseek-v32"], "notes": "The first invoke is complete, the second is cut: a correct parser keeps only the first call. Token prefix of the full render, cut right after 'name=\"query\"' appears. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": false,
"finish_reason": "length",
"id": null,
"kept_by_engine": false,
"rule": "truncated fixture: finish_reason length",
"token": null
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v32-unescaped-string-value
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | nonstream | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | one | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | token | fail | content (whitespace only): expected None, got '\n\n\n'; tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:2:8 | fail | content (whitespace only): expected None, got '\n\n'; tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-unescaped-string-value --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 14 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -5,5 +5,5 @@ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Strategies: token
@@ -1,9 +1,9 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Strategies: rand:2:8
@@ -1,9 +1,9 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, string-escapes, x-unescaped-string, x-deepseek-v32.
Raw output
<|DSML|function_calls>
<|DSML|invoke name="write_file">
<|DSML|parameter name="path" string="true">a<b>.py</|DSML|parameter>
<|DSML|parameter name="content" string="true">if a < b and c > d:
print("x=\"1\"") # tab here
</|DSML|parameter>
</|DSML|invoke>
</|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n",
"path": "a<b>.py"
},
"name": "write_file"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-unescaped-string-value", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"write_file\">\n<|DSML|parameter name=\"path\" string=\"true\">a<b>.py</|DSML|parameter>\n<|DSML|parameter name=\"content\" string=\"true\">if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 25837, 19086, 3816, 30, 128793, 41523, 2329, 1281, 9860, 4, 3418, 1281, 11476, 3320, 67, 93180, 43386, 12403, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 9326, 4, 3418, 1281, 11476, 3320, 394, 260, 818, 291, 305, 274, 1955, 283, 1137, 361, 2777, 1698, 90, 52093, 19, 28609, 5925, 223, 1823, 12826, 200, 1036, 201, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "write_file", "arguments": {"path": "a<b>.py", "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n"}}]}, "tags": ["single-call", "string-escapes", "x-unescaped-string", "x-deepseek-v32"], "notes": "string=\"true\" values are raw: quotes, <, >, backslashes, tabs and newlines appear unescaped. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/v4-truncated-mid-arguments
expected_error, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_error | one | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | special | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | token | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:1:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:2:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:3:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:4:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
expected_error | rand:5:8 | fail | returned 1 tool call(s) ['get_weather'] for Output cut by max_tokens inside the first call's arguments: no complete call exists. |
stream_equals_nonstream | one | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | token | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:2:8 | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:5:8 | fail | tool_calls: nonstream [], got ['get_weather'] |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-truncated-mid-arguments --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 9 of fixtures/deepseek/v4.jsonl.
Observed
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zü"
},
"name": "get_weather"
}
]
}
Strategies: token, rand:2:8
{
"content": "\n\n",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zü"
},
"name": "get_weather"
}
]
}
Strategies: nonstream
{
"content": null,
"reasoning_content": null,
"tool_calls": []
}
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: truncated, x-deepseek-v4.
Expected graceful failure: Output cut by max_tokens inside the first call's arguments: no complete call exists. (accept: no_tool_calls, content_passthrough, exception).
Raw output
<|DSML|tool_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Zür
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-truncated-mid-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zür", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected_error": {"reason": "Output cut by max_tokens inside the first call's arguments: no complete call exists.", "accept": ["no_tool_calls", "content_passthrough", "exception"]}, "tags": ["truncated", "x-deepseek-v4"], "notes": "Token prefix of the full render, cut right after 'Zür' appears. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": false,
"finish_reason": "length",
"id": null,
"kept_by_engine": false,
"rule": "truncated fixture: finish_reason length",
"token": null
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v4-truncated-second-parallel-call
expected_match, stream_equals_nonstream, split_invariance, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | nonstream | fail | tool_calls: expected ['get_weather'], got [] |
expected_match | one | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | special | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | token | fail | content (whitespace only): expected None, got '\n\n\n'; tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:1:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:2:8 | fail | content (whitespace only): expected None, got '\n\n'; tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:3:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:4:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
expected_match | rand:5:8 | fail | tool_calls: expected ['get_weather'], got ['get_weather', 'search'] |
stream_equals_nonstream | one | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | token | fail | content (whitespace only): nonstream None, got '\n\n\n'; tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:2:8 | fail | content (whitespace only): nonstream None, got '\n\n'; tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:4:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
stream_equals_nonstream | rand:5:8 | fail | tool_calls: nonstream [], got ['get_weather', 'search'] |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
arguments_schema | one | fail | [1] search: $: 'query' is a required property |
arguments_schema | special | fail | [1] search: $: 'query' is a required property |
arguments_schema | token | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:1:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:2:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:3:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:4:8 | fail | [1] search: $: 'query' is a required property |
arguments_schema | rand:5:8 | fail | [1] search: $: 'query' is a required property |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-truncated-second-parallel-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 17 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream
@@ -2,12 +2,4 @@ "content": null, "reasoning_content": null, - "tool_calls": [ - { - "arguments": { - "city": "Zürich", - "unit": "c" - }, - "name": "get_weather" - } - ] + "tool_calls": [] }
Strategies: one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [ @@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [ @@ -9,4 +9,8 @@ }, "name": "get_weather" + }, + { + "arguments": {}, + "name": "search" } ]
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: truncated, parallel-calls, unicode, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Zürich</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> <|DSML|invoke name="search"> <|DSML|parameter name="query"
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-truncated-second-parallel-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\"", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 30, 128825, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128825, 41523, 2329, 1281, 12066, 4], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}]}, "tags": ["truncated", "parallel-calls", "unicode", "x-deepseek-v4"], "notes": "The first invoke is complete, the second is cut: a correct parser keeps only the first call. Token prefix of the full render, cut right after 'name=\"query\"' appears. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": false,
"finish_reason": "length",
"id": null,
"kept_by_engine": false,
"rule": "truncated fixture: finish_reason length",
"token": null
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/v4-unescaped-string-value
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | nonstream | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | one | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | token | fail | content (whitespace only): expected None, got '\n\n\n'; tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:2:8 | fail | content (whitespace only): expected None, got '\n\n'; tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there\\n"}', got '{"path": "a<b>.py", "content": "if a < b and c > d:\\n print(\\"x=\\\\\\"1\\\\\\"\\") # tab\\there"}' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-unescaped-string-value --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 15 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -5,5 +5,5 @@ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Strategies: token
@@ -1,9 +1,9 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Strategies: rand:2:8
@@ -1,9 +1,9 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [ { "arguments": { - "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n", + "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there", "path": "a<b>.py" },
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, string-escapes, x-unescaped-string, x-deepseek-v4.
Raw output
<|DSML|tool_calls>
<|DSML|invoke name="write_file">
<|DSML|parameter name="path" string="true">a<b>.py</|DSML|parameter>
<|DSML|parameter name="content" string="true">if a < b and c > d:
print("x=\"1\"") # tab here
</|DSML|parameter>
</|DSML|invoke>
</|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n",
"path": "a<b>.py"
},
"name": "write_file"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-unescaped-string-value", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "write_file", "description": "Write a text file.", "parameters": {"type": "object", "properties": {"path": {"type": "string"}, "content": {"type": "string"}}, "required": ["path", "content"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"write_file\">\n<|DSML|parameter name=\"path\" string=\"true\">a<b>.py</|DSML|parameter>\n<|DSML|parameter name=\"content\" string=\"true\">if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 25837, 19086, 3816, 30, 128825, 41523, 2329, 1281, 9860, 4, 3418, 1281, 11476, 3320, 67, 93180, 43386, 12403, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 9326, 4, 3418, 1281, 11476, 3320, 394, 260, 818, 291, 305, 274, 1955, 283, 1137, 361, 2777, 1698, 90, 52093, 19, 28609, 5925, 223, 1823, 12826, 200, 1036, 201, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "write_file", "arguments": {"path": "a<b>.py", "content": "if a < b and c > d:\n print(\"x=\\\"1\\\"\") # tab\there\n"}}]}, "tags": ["single-call", "string-escapes", "x-unescaped-string", "x-deepseek-v4"], "notes": "string=\"true\" values are raw: quotes, <, >, backslashes, tabs and newlines appear unescaped. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/vllm-v3-escaped-strings
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
expected_match | rand:4:8 | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
expected_match | rand:5:8 | fail | tool_calls[0].arguments: expected '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | rand:4:8 | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
stream_equals_nonstream | rand:5:8 | fail | tool_calls[0].arguments: nonstream '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"text": "He said \\"hello\\"", "path": "C:\\\\Users\\\\file", "newline": "line1\\nline2"}' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/vllm-v3-escaped-strings --strategy one --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 5 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:2:8, rand:3:8, rand:4:8, rand:5:8
@@ -4,9 +4,5 @@ "tool_calls": [ { - "arguments": { - "newline": "line1\nline2", - "path": "C:\\Users\\file", - "text": "He said \"hello\"" - }, + "arguments": {}, "name": "send_message" }
Strategies: nonstream, token, rand:1:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"newline": "line1\nline2",
"path": "C:\\Users\\file",
"text": "He said \"hello\""
},
"name": "send_message"
}
]
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L61.
Tags: single-call, string-escapes, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>send_message
```json
{"text": "He said \"hello\"", "path": "C:\\Users\\file", "newline": "line1\nline2"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"newline": "line1\nline2",
"path": "C:\\Users\\file",
"text": "He said \"hello\""
},
"name": "send_message"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v3-escaped-strings", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L61", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "send_message", "parameters": {"type": "object", "properties": {"text": {"type": "string"}, "path": {"type": "string"}, "newline": {"type": "string"}}}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>send_message\n```json\n{\"text\": \"He said \\\"hello\\\"\", \"path\": \"C:\\\\Users\\\\file\", \"newline\": \"line1\\nline2\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 35397, 53735, 201, 9854, 14479, 201, 24313, 2067, 3362, 582, 3158, 1359, 36952, 33310, 28609, 1760, 582, 9860, 3362, 582, 37, 111396, 24979, 7387, 8104, 1760, 582, 2839, 1836, 3362, 582, 1836, 19, 5809, 1836, 20, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "send_message", "arguments": {"text": "He said \"hello\"", "path": "C:\\Users\\file", "newline": "line1\nline2"}}]}, "tags": ["single-call", "string-escapes", "x-deepseek-v3"], "notes": "output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/vllm-v3-malformed-missing-brace
expected_error, stream_equals_nonstream, split_invariance, arguments_json, arguments_schema
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_error | one | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | special | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | token | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | rand:1:8 | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | rand:2:8 | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | rand:3:8 | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | rand:4:8 | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
expected_error | rand:5:8 | fail | returned 1 tool call(s) ['get_weather'] for The arguments JSON is missing its closing brace; no valid call exists. |
stream_equals_nonstream | one | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | special | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | token | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:1:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:2:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:3:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:4:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
stream_equals_nonstream | rand:5:8 | fail | content: nonstream '<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{"city": "Tokyo"\n```<|tool▁call▁end|><|tool▁calls▁end|>', got None; tool_calls: nonstream [], got ['get_weather'] |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo"' | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo"' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo"' |
arguments_json | token | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Tokyo"': Expecting ',' delimiter: line 1 column 17 (char 16)) |
arguments_json | rand:2:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Tokyo"': Expecting ',' delimiter: line 1 column 17 (char 16)) |
arguments_json | rand:4:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Tokyo"': Expecting ',' delimiter: line 1 column 17 (char 16)) |
arguments_schema | token | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:2:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:4:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/malformed.jsonl --id deepseek/vllm-v3-malformed-missing-brace --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 1 of fixtures/deepseek/malformed.jsonl.
Observed
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:3:8, rand:5:8
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_weather"
}
]
}
Strategies: token, rand:2:8, rand:4:8
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"<arguments_raw, not valid JSON>": "{\"city\": \"Tokyo\""
},
"name": "get_weather"
}
]
}
Strategies: nonstream
{
"content": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Tokyo\"\n```<|tool▁call▁end|><|tool▁calls▁end|>",
"reasoning_content": null,
"tool_calls": []
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L68.
Tags: malformed, x-deepseek-v3.
Expected graceful failure: The arguments JSON is missing its closing brace; no valid call exists. (accept: no_tool_calls, content_passthrough).
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "Tokyo"
```<|tool▁call▁end|><|tool▁calls▁end|>
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v3-malformed-missing-brace", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L68", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string"}, "count": {"type": "integer"}}}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Tokyo\"\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 106239, 2701, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected_error": {"reason": "The arguments JSON is missing its closing brace; no valid call exists.", "accept": ["no_tool_calls", "content_passthrough"]}, "tags": ["malformed", "x-deepseek-v3"], "notes": "malformed_input_outputs[0] of the test. output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/vllm-v3-parallel-no-newline
expected_match, stream_equals_nonstream, split_invariance, no_leakage, arguments_json, arguments_schema, parallel_order
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls: expected ['get_weather', 'search_hotels'], got ['search_hotels'] |
expected_match | special | fail | tool_calls: expected ['get_weather', 'search_hotels'], got ['search_hotels'] |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{"city": "Tokyo", "unit": "celsius"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{"location": "Tokyo", "check_in": "2025-01-15"}'; tool_calls[1].arguments: expected '{"location": "Tokyo", "check_in": "2025-01-15"}', got '{}' |
expected_match | rand:2:8 | fail | tool_calls[1].arguments: expected '{"location": "Tokyo", "check_in": "2025-01-15"}', got '{}' |
expected_match | rand:3:8 | fail | tool_calls: expected ['get_weather', 'search_hotels'], got ['get_weather'] |
stream_equals_nonstream | one | fail | tool_calls: nonstream ['get_weather', 'search_hotels'], got ['search_hotels'] |
stream_equals_nonstream | special | fail | tool_calls: nonstream ['get_weather', 'search_hotels'], got ['search_hotels'] |
stream_equals_nonstream | rand:1:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{"city": "Tokyo", "unit": "celsius"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{"location": "Tokyo", "check_in": "2025-01-15"}'; tool_calls[1].arguments: nonstream '{"location": "Tokyo", "check_in": "2025-01-15"}', got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[1].arguments: nonstream '{"location": "Tokyo", "check_in": "2025-01-15"}', got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls: nonstream ['get_weather', 'search_hotels'], got ['get_weather'] |
split_invariance | * | fail | vs one: token (fail): tool_calls: one ['search_hotels'], got ['get_weather', 'search_hotels'] | rand:1:8 (fail): tool_calls: one ['search_hotels'], got ['get_weather', 'search_hotels'] | rand:2:8 (fail): tool_calls: one ['search_hotels'], got ['get_weather', 'search_hotels'] | rand:3:8 (fail): tool_calls: one ['search_hotels'], got ['get_weather'] | rand:4:8 (fail): tool_calls: one ['search_hotels'], got ['get_weather', 'search_hotels'] | rand:5:8 (fail): tool_calls: one ['search_hotels'], got ['get_weather', 'search_hotels'] |
no_leakage | rand:1:8 | fail | tool_calls[0].arguments contains '<|tool▁call▁begin|>'; tool_calls[0].arguments contains '<|tool▁call▁end|>'; tool_calls[0].arguments contains '<|tool▁sep|>' |
no_leakage | rand:3:8 | fail | tool_calls[0].arguments contains '<|tool▁call▁begin|>'; tool_calls[0].arguments contains '<|tool▁call▁end|>'; tool_calls[0].arguments contains '<|tool▁sep|>' |
arguments_json | rand:1:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Tokyo", "unit": "celsius"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{"location": "Tokyo", "check_in": "2025-01-15"}': Extra data: line 2 column 1 (char 37)) |
arguments_json | rand:3:8 | fail | [0] get_weather: arguments are not valid JSON text ('{"city": "Tokyo", "unit": "celsius"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{"location": "Tokyo", "check_in": "2025-01-15"}': Extra data: line 2 column 1 (char 37)) |
arguments_schema | rand:1:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
arguments_schema | rand:3:8 | fail | [0] get_weather: arguments are not a JSON object; not validated |
parallel_order | one | fail | expected 2 calls ['get_weather', 'search_hotels'], got 1 ['search_hotels'] |
parallel_order | special | fail | expected 2 calls ['get_weather', 'search_hotels'], got 1 ['search_hotels'] |
parallel_order | rand:3:8 | fail | expected 2 calls ['get_weather', 'search_hotels'], got 1 ['get_weather'] |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/vllm-v3-parallel-no-newline --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 3 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -4,15 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "Tokyo", - "unit": "celsius" - }, - "name": "get_weather" - }, - { - "arguments": { - "check_in": "2025-01-15", - "location": "Tokyo" - }, + "arguments": {}, "name": "search_hotels" }
Strategies: rand:1:8
@@ -5,14 +5,10 @@ { "arguments": { - "city": "Tokyo", - "unit": "celsius" + "<arguments_raw, not valid JSON>": "{\"city\": \"Tokyo\", \"unit\": \"celsius\"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{\"location\": \"Tokyo\", \"check_in\": \"2025-01-15\"}" }, "name": "get_weather" }, { - "arguments": { - "check_in": "2025-01-15", - "location": "Tokyo" - }, + "arguments": {}, "name": "search_hotels" }
Strategies: rand:2:8
@@ -11,8 +11,5 @@ }, { - "arguments": { - "check_in": "2025-01-15", - "location": "Tokyo" - }, + "arguments": {}, "name": "search_hotels" }
Strategies: rand:3:8
@@ -5,15 +5,7 @@ { "arguments": { - "city": "Tokyo", - "unit": "celsius" + "<arguments_raw, not valid JSON>": "{\"city\": \"Tokyo\", \"unit\": \"celsius\"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels{\"location\": \"Tokyo\", \"check_in\": \"2025-01-15\"}" }, "name": "get_weather" - }, - { - "arguments": { - "check_in": "2025-01-15", - "location": "Tokyo" - }, - "name": "search_hotels" } ]
Strategies: nonstream, token, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Tokyo",
"unit": "celsius"
},
"name": "get_weather"
},
{
"arguments": {
"check_in": "2025-01-15",
"location": "Tokyo"
},
"name": "search_hotels"
}
]
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L31.
Tags: parallel-calls, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "Tokyo", "unit": "celsius"}
```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels
```json
{"location": "Tokyo", "check_in": "2025-01-15"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Tokyo",
"unit": "celsius"
},
"name": "get_weather"
},
{
"arguments": {
"check_in": "2025-01-15",
"location": "Tokyo"
},
"name": "search_hotels"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v3-parallel-no-newline", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L31", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string"}, "count": {"type": "integer"}}}}}, {"type": "function", "function": {"name": "search_hotels", "parameters": {"type": "object", "properties": {"location": {"type": "string"}, "check_in": {"type": "string"}}}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Tokyo\", \"unit\": \"celsius\"}\n```<|tool▁call▁end|><|tool▁call▁begin|>function<|tool▁sep|>search_hotels\n```json\n{\"location\": \"Tokyo\", \"check_in\": \"2025-01-15\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 106239, 1760, 582, 15165, 3362, 582, 69, 33030, 60676, 9854, 128809, 128808, 8701, 128814, 14346, 17462, 347, 1713, 201, 9854, 14479, 201, 24313, 33182, 3362, 582, 106239, 1760, 582, 9547, 12743, 3362, 582, 939, 23, 15, 2616, 15, 856, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Tokyo", "unit": "celsius"}}, {"name": "search_hotels", "arguments": {"location": "Tokyo", "check_in": "2025-01-15"}}]}, "tags": ["parallel-calls", "x-deepseek-v3"], "notes": "Calls are adjacent here; the official template separates them with '\\n'. output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
fail deepseek/vllm-v3-single-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
expected_match | rand:1:8 | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
expected_match | rand:2:8 | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
stream_equals_nonstream | rand:2:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"city": "Tokyo", "unit": "celsius"}', got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo", "unit": "celsius"}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo", "unit": "celsius"}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"city": "Tokyo", "unit": "celsius"}' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/vllm-v3-single-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 2 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:1:8, rand:2:8, rand:3:8
@@ -4,8 +4,5 @@ "tool_calls": [ { - "arguments": { - "city": "Tokyo", - "unit": "celsius" - }, + "arguments": {}, "name": "get_weather" }
Strategies: nonstream, token, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Tokyo",
"unit": "celsius"
},
"name": "get_weather"
}
]
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L27.
Tags: single-call, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather
```json
{"city": "Tokyo", "unit": "celsius"}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Tokyo",
"unit": "celsius"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v3-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L27", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "get_weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string"}, "count": {"type": "integer"}}}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>get_weather\n```json\n{\"city\": \"Tokyo\", \"unit\": \"celsius\"}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 1133, 65, 50219, 201, 9854, 14479, 201, 24313, 37399, 3362, 582, 106239, 1760, 582, 15165, 3362, 582, 69, 33030, 60676, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Tokyo", "unit": "celsius"}}]}, "tags": ["single-call", "x-deepseek-v3"], "notes": "output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/vllm-v3-various-data-types
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | tool_calls[0].arguments: expected '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
expected_match | special | fail | tool_calls[0].arguments: expected '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
expected_match | rand:3:8 | fail | tool_calls[0].arguments: expected '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
stream_equals_nonstream | one | fail | tool_calls[0].arguments: nonstream '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
stream_equals_nonstream | special | fail | tool_calls[0].arguments: nonstream '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
stream_equals_nonstream | rand:3:8 | fail | tool_calls[0].arguments: nonstream '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne..., got '{}' |
split_invariance | * | fail | vs one: token (fail): tool_calls[0].arguments: one '{}', got '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne... | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne... | rand:2:8 (fail): tool_calls[0].arguments: one '{}', got '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne... | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne... | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"ne... |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/vllm-v3-various-data-types --strategy one --strategy rand:3:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 4 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special, rand:3:8
@@ -4,21 +4,5 @@ "tool_calls": [ { - "arguments": { - "array_field": [ - "a", - "b", - "c" - ], - "bool_field": true, - "empty_array": [], - "empty_object": {}, - "float_field": 3.14, - "int_field": 42, - "null_field": null, - "object_field": { - "nested": "value" - }, - "string_field": "hello" - }, + "arguments": {}, "name": "test_function" }
Strategies: nonstream, token, rand:1:8, rand:2:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"array_field": [
"a",
"b",
"c"
],
"bool_field": true,
"empty_array": [],
"empty_object": {},
"float_field": 3.14,
"int_field": 42,
"null_field": null,
"object_field": {
"nested": "value"
},
"string_field": "hello"
},
"name": "test_function"
}
]
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L39.
Tags: single-call, numeric-arguments, nested-json, x-deepseek-v3.
Raw output
<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>test_function
```json
{"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"nested": "value"}, "empty_array": [], "empty_object": {}}
```<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"array_field": [
"a",
"b",
"c"
],
"bool_field": true,
"empty_array": [],
"empty_object": {},
"float_field": 3.14,
"int_field": 42,
"null_field": null,
"object_field": {
"nested": "value"
},
"string_field": "hello"
},
"name": "test_function"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v3-various-data-types", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3-0324"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv3_tool_parser.py#L39", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "test_function", "parameters": {"type": "object", "properties": {"string_field": {"type": "string"}, "int_field": {"type": "integer"}, "float_field": {"type": "number"}, "bool_field": {"type": "boolean"}, "null_field": {"type": "null"}, "array_field": {"type": "array"}, "object_field": {"type": "object"}, "empty_array": {"type": "array"}, "empty_object": {"type": "object"}}}}}], "raw_output": "<|tool▁calls▁begin|><|tool▁call▁begin|>function<|tool▁sep|>test_function\n```json\n{\"string_field\": \"hello\", \"int_field\": 42, \"float_field\": 3.14, \"bool_field\": true, \"null_field\": null, \"array_field\": [\"a\", \"b\", \"c\"], \"object_field\": {\"nested\": \"value\"}, \"empty_array\": [], \"empty_object\": {}}\n```<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [128806, 128808, 8701, 128814, 7958, 64334, 201, 9854, 14479, 201, 24313, 4463, 55291, 3362, 582, 33310, 1760, 582, 650, 55291, 3362, 223, 3180, 14, 582, 15891, 55291, 3362, 223, 21, 16, 929, 14, 582, 20600, 55291, 3362, 3292, 14, 582, 16042, 55291, 3362, 5100, 14, 582, 7386, 55291, 3362, 20584, 67, 1760, 582, 68, 1760, 582, 69, 45390, 582, 10325, 55291, 3362, 28612, 80, 12904, 3362, 582, 5197, 87928, 582, 15566, 30549, 3362, 66517, 582, 15566, 55774, 3362, 26102, 1778, 9854, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3-0324", "revision": "e9b33add76883f293d6bf61f6bd89b497e80e335", "mode": "hf"}, "generation_prompt": "<|Assistant|>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "test_function", "arguments": {"string_field": "hello", "int_field": 42, "float_field": 3.14, "bool_field": true, "null_field": null, "array_field": ["a", "b", "c"], "object_field": {"nested": "value"}, "empty_array": [], "empty_object": {}}}]}, "tags": ["single-call", "numeric-arguments", "nested-json", "x-deepseek-v3"], "notes": "output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": null,
"chat_template_sha256": "22e97ba043dacf9df1f071a9de9d2bb6b0757491f16e96e810834b86e1641286",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3-0324",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804
],
"source": "generation_prompt"
},
"reasoning_detector": null,
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": null,
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3-0324",
"revision": "e9b33add76883f293d6bf61f6bd89b497e80e335",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV3Detector",
"tool_call_parser": "deepseekv3",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
fail deepseek/vllm-v31-text-before-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | one | fail | content: expected 'normal text', got None; tool_calls[0].arguments: expected '{"x": 1}', got '{}' |
expected_match | special | fail | content: expected 'normal text', got None; tool_calls[0].arguments: expected '{"x": 1}', got '{}' |
expected_match | rand:1:8 | fail | content: expected 'normal text', got None |
expected_match | rand:2:8 | fail | content: expected 'normal text', got 'normal' |
expected_match | rand:3:8 | fail | content: expected 'normal text', got None |
expected_match | rand:4:8 | fail | content: expected 'normal text', got None |
expected_match | rand:5:8 | fail | content: expected 'normal text', got None |
stream_equals_nonstream | one | fail | content: nonstream 'normal text', got None; tool_calls[0].arguments: nonstream '{"x": 1}', got '{}' |
stream_equals_nonstream | special | fail | content: nonstream 'normal text', got None; tool_calls[0].arguments: nonstream '{"x": 1}', got '{}' |
stream_equals_nonstream | rand:1:8 | fail | content: nonstream 'normal text', got None |
stream_equals_nonstream | rand:2:8 | fail | content: nonstream 'normal text', got 'normal' |
stream_equals_nonstream | rand:3:8 | fail | content: nonstream 'normal text', got None |
stream_equals_nonstream | rand:4:8 | fail | content: nonstream 'normal text', got None |
stream_equals_nonstream | rand:5:8 | fail | content: nonstream 'normal text', got None |
split_invariance | * | fail | vs one: token (fail): content: one None, got 'normal text'; tool_calls[0].arguments: one '{}', got '{"x":1}' | rand:1:8 (fail): tool_calls[0].arguments: one '{}', got '{"x":1}' | rand:2:8 (fail): content: one None, got 'normal'; tool_calls[0].arguments: one '{}', got '{"x":1}' | rand:3:8 (fail): tool_calls[0].arguments: one '{}', got '{"x":1}' | rand:4:8 (fail): tool_calls[0].arguments: one '{}', got '{"x":1}' | rand:5:8 (fail): tool_calls[0].arguments: one '{}', got '{"x":1}' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/vllm-v31-text-before-call --strategy one --strategy rand:1:8 --strategy rand:2:8 --strategy rand:3:8 --strategy rand:4:8 --strategy rand:5:8 --strategy special --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 6 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: one, special
@@ -1,10 +1,8 @@ { - "content": "normal text", + "content": null, "reasoning_content": null, "tool_calls": [ { - "arguments": { - "x": 1 - }, + "arguments": {}, "name": "foo" }
Strategies: rand:1:8, rand:3:8, rand:4:8, rand:5:8
@@ -1,4 +1,4 @@ { - "content": "normal text", + "content": null, "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": "normal text", + "content": "normal", "reasoning_content": null, "tool_calls": [
Strategies: nonstream, token
Matches the expected parse.
{
"content": "normal text",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"x": 1
},
"name": "foo"
}
]
}
Fixture
Provenance: engine_test, https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv31_tool_parser.py#L25.
Tags: single-call, text-before-call, x-deepseek-v31.
Raw output
normal text<|tool▁calls▁begin|><|tool▁call▁begin|>foo<|tool▁sep|>{"x":1}<|tool▁call▁end|><|tool▁calls▁end|>
Expected parse
{
"content": "normal text",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"x": 1
},
"name": "foo"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/vllm-v31-text-before-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.1", "deepseek-ai/DeepSeek-V3.1-Terminus"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/vllm-project/vllm/blob/ced6857afa0ea7b2e3f0846a62e1394e90f15607/tests/tool_parsers/test_deepseekv31_tool_parser.py#L25", "revision": "ced6857afa0ea7b2e3f0846a62e1394e90f15607", "license": "Apache-2.0", "attribution": "Copyright contributors to the vLLM project"}, "tools": [{"type": "function", "function": {"name": "foo", "parameters": {"type": "object", "properties": {"x": {"type": "integer"}}}}}], "raw_output": "normal text<|tool▁calls▁begin|><|tool▁call▁begin|>foo<|tool▁sep|>{\"x\":1}<|tool▁call▁end|><|tool▁calls▁end|>", "output_token_ids": [13644, 3051, 128806, 128808, 40897, 128814, 24313, 90, 3362, 19, 95, 128809, 128807], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.1", "revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": "normal text", "reasoning_content": null, "tool_calls": [{"name": "foo", "arguments": {"x": 1}}]}, "tags": ["single-call", "text-before-call", "x-deepseek-v31"], "notes": "output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": "deepseek-v3",
"tool_call_parser": "deepseekv31"
},
"chat_encoding_spec": null,
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": "45690185067ea25c073bff2d3e425a45ee2564d2bbf6cdf7d885e139d460b8e0",
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV3ForCausalLM"
],
"model_type": "deepseek_v3"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.1",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": "ReasoningToggleConfig(toggle_param='thinking', default_enabled=False, special_case=None, effort_kwarg=None)",
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.1",
"revision": "c0781d039fb7a1ba2abc4add0bdc293e92d2b8db",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV31Detector",
"tool_call_parser": "deepseekv31",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/sglang-v32-text-before-empty-invoke
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n\n' |
expected_match | rand:4:8 | soft pass | content (whitespace only): expected 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n\n' |
stream_equals_nonstream | rand:4:8 | soft pass | content (whitespace only): nonstream 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n\n' | rand:4:8 (soft_pass): content (whitespace only): one 'Let me get the current date for you.', got 'Let me get the current date for you.\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/sglang-v32-text-before-empty-invoke --strategy rand:4:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 9 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": "Let me get the current date for you.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_date"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": "Let me get the current date for you.", + "content": "Let me get the current date for you.\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:4:8
@@ -1,4 +1,4 @@ { - "content": "Let me get the current date for you.", + "content": "Let me get the current date for you.\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: engine_test, https://github.com/sgl-project/sglang/blob/94602c9c2b7cbdb8efd5c52802dac6a1c180089e/test/registered/unit/function_call/test_function_call_parser.py#L1802.
Tags: single-call, text-before-call, empty-arguments, x-deepseek-v32.
Raw output
Let me get the current date for you. <|DSML|function_calls> <|DSML|invoke name="get_date"> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": "Let me get the current date for you.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_date"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/sglang-v32-text-before-empty-invoke", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/sgl-project/sglang/blob/94602c9c2b7cbdb8efd5c52802dac6a1c180089e/test/registered/unit/function_call/test_function_call_parser.py#L1802", "revision": "94602c9c2b7cbdb8efd5c52802dac6a1c180089e", "license": "Apache-2.0", "attribution": "Copyright SGLang Team"}, "tools": [{"type": "function", "function": {"name": "get_date", "parameters": {"type": "object", "properties": {}}}}], "raw_output": "Let me get the current date for you.\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_date\">\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [5718, 678, 1178, 270, 2573, 5045, 362, 440, 339, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 22993, 3816, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": "Let me get the current date for you.", "reasoning_content": null, "tool_calls": [{"name": "get_date", "arguments": {}}]}, "tags": ["single-call", "text-before-call", "empty-arguments", "x-deepseek-v32"], "notes": "An invoke with no parameter lines (the encoder itself renders an empty line between the tags). output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/sglang-v4-self-closing-invoke
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/engine-tests.jsonl --id deepseek/sglang-v4-self-closing-invoke --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 10 of fixtures/deepseek/engine-tests.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "submit"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: engine_test, https://github.com/sgl-project/sglang/blob/94602c9c2b7cbdb8efd5c52802dac6a1c180089e/test/registered/unit/function_call/test_function_call_parser.py#L2258.
Tags: single-call, empty-arguments, x-self-closing-invoke, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="submit"/> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "submit"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/sglang-v4-self-closing-invoke", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "engine_test", "source_url": "https://github.com/sgl-project/sglang/blob/94602c9c2b7cbdb8efd5c52802dac6a1c180089e/test/registered/unit/function_call/test_function_call_parser.py#L2258", "revision": "94602c9c2b7cbdb8efd5c52802dac6a1c180089e", "license": "Apache-2.0", "attribution": "Copyright SGLang Team"}, "tools": [{"type": "function", "function": {"name": "submit", "parameters": {"type": "object", "properties": {}}}}], "raw_output": "<|DSML|tool_calls>\n<|DSML|invoke name=\"submit\"/>\n</|DSML|tool_calls>", "output_token_ids": [30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 35380, 39278, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "submit", "arguments": {}}]}, "tags": ["single-call", "empty-arguments", "x-self-closing-invoke", "x-deepseek-v4"], "notes": "SGLang's test states 'V4 emits <|DSML|invoke name=\"x\"/> for zero-arg tools'. The official V4 encoder renders an open/close pair instead, and DeepSeek's reference parser rejects this form; kept because the engine reports the model generating it. output_token_ids: tokenizer.encode(raw_output)."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-empty-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-empty-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 5 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_time"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, empty-arguments, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="get_time"> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_time"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-empty-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time. Takes no arguments.", "parameters": {"type": "object", "properties": {}}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_time\">\n\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 20035, 32572, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_time", "arguments": {}}]}, "tags": ["single-call", "empty-arguments", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-marker-in-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-marker-in-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 8 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Write <|DSML|invoke name=\"x\"> to call a tool."
},
"name": "echo"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, marker-in-arguments, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="echo"> <|DSML|parameter name="text" string="true">Write <|DSML|invoke name="x"> to call a tool.</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Write <|DSML|invoke name=\"x\"> to call a tool."
},
"name": "echo"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-marker-in-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "echo", "description": "Echo a string back verbatim.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"echo\">\n<|DSML|parameter name=\"text\" string=\"true\">Write <|DSML|invoke name=\"x\"> to call a tool.</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 18843, 3816, 30, 128793, 41523, 2329, 1281, 2067, 4, 3418, 1281, 11476, 3320, 21750, 818, 128793, 40148, 5406, 2329, 1281, 90, 3320, 304, 1926, 260, 4105, 14020, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "echo", "arguments": {"text": "Write <|DSML|invoke name=\"x\"> to call a tool."}}]}, "tags": ["single-call", "marker-in-arguments", "x-deepseek-v32"], "notes": "The argument contains format-marker text, which the official tokenizer maps to special-token ids. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-numeric-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-numeric-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 6 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, numeric-arguments, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="calculate"> <|DSML|parameter name="x" string="false">-3</|DSML|parameter> <|DSML|parameter name="y" string="false">2.5</|DSML|parameter> <|DSML|parameter name="tolerance" string="false">1e-05</|DSML|parameter> <|DSML|parameter name="exact" string="false">true</|DSML|parameter> <|DSML|parameter name="limit" string="false">null</|DSML|parameter> <|DSML|parameter name="values" string="false">[0, -0.5, 1e+21]</|DSML|parameter> <|DSML|parameter name="code" string="true">007</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-numeric-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "calculate", "description": "Evaluate numbers.", "parameters": {"type": "object", "properties": {"x": {"type": "integer"}, "y": {"type": "number"}, "tolerance": {"type": "number"}, "exact": {"type": "boolean"}, "limit": {"type": ["integer", "null"]}, "values": {"type": "array", "items": {"type": "number"}}, "code": {"type": "string"}}, "required": ["x", "y"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"calculate\">\n<|DSML|parameter name=\"x\" string=\"false\">-3</|DSML|parameter>\n<|DSML|parameter name=\"y\" string=\"false\">2.5</|DSML|parameter>\n<|DSML|parameter name=\"tolerance\" string=\"false\">1e-05</|DSML|parameter>\n<|DSML|parameter name=\"exact\" string=\"false\">true</|DSML|parameter>\n<|DSML|parameter name=\"limit\" string=\"false\">null</|DSML|parameter>\n<|DSML|parameter name=\"values\" string=\"false\">[0, -0.5, 1e+21]</|DSML|parameter>\n<|DSML|parameter name=\"code\" string=\"true\">007</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 93801, 3816, 30, 128793, 41523, 2329, 1281, 90, 4, 3418, 1281, 19836, 3320, 15, 21, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 91, 4, 3418, 1281, 19836, 3320, 20, 16, 23, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 86, 44016, 4, 3418, 1281, 19836, 3320, 19, 71, 15, 2642, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 1289, 651, 4, 3418, 1281, 19836, 3320, 11476, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 39673, 4, 3418, 1281, 19836, 3320, 16042, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15737, 4, 3418, 1281, 19836, 3320, 61, 18, 14, 565, 18, 16, 23, 14, 223, 19, 71, 13, 1602, 63, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 8308, 4, 3418, 1281, 11476, 3320, 17065, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "calculate", "arguments": {"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}}]}, "tags": ["single-call", "numeric-arguments", "x-deepseek-v32"], "notes": "'code' is the STRING \"007\"; numbers, booleans and null must keep their JSON types. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-parallel-two-calls
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n\n' |
expected_match | rand:1:8 | soft pass | content (whitespace only): expected None, got '\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n\n' |
stream_equals_nonstream | rand:1:8 | soft pass | content (whitespace only): nonstream None, got '\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n\n' | rand:1:8 (soft_pass): content (whitespace only): one None, got '\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-parallel-two-calls --strategy rand:1:8 --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 2 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:1:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: parallel-calls, unicode, nested-json, string-escapes, x-deepseek-v32.
Raw output
<|DSML|function_calls>
<|DSML|invoke name="get_weather">
<|DSML|parameter name="city" string="true">Zürich</|DSML|parameter>
<|DSML|parameter name="unit" string="true">c</|DSML|parameter>
</|DSML|invoke>
<|DSML|invoke name="search">
<|DSML|parameter name="query" string="true">café "best"</|DSML|parameter>
<|DSML|parameter name="filters" string="false">{"tags": ["a", "b"], "max": 3}</|DSML|parameter>
</|DSML|invoke>
</|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-parallel-two-calls", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\" string=\"true\">café \"best\"</|DSML|parameter>\n<|DSML|parameter name=\"filters\" string=\"false\">{\"tags\": [\"a\", \"b\"], \"max\": 3}</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 30, 128793, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128793, 41523, 2329, 1281, 12066, 4, 3418, 1281, 11476, 3320, 69, 2797, 619, 582, 21910, 4, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 72, 40332, 4, 3418, 1281, 19836, 3320, 24313, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 24568, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "unicode", "nested-json", "string-escapes", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
soft pass deepseek/v32-reasoning-parallel-text-before
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected "I'll look both up.", got "I'll look both up.\n\n\n\n" |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream "I'll look both up.", got "I'll look both up.\n\n\n\n" |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one "I'll look both up.", got "I'll look both up.\n\n\n\n" |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-reasoning-parallel-text-before --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 11 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": "I'll look both up.",
"reasoning_content": "Two independent lookups: weather and search.",
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": "I'll look both up.", + "content": "I'll look both up.\n\n\n\n", "reasoning_content": "Two independent lookups: weather and search.", "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: parallel-calls, reasoning, reasoning-prefilled, text-before-call, unicode, nested-json, string-escapes, x-deepseek-v32.
Raw output
Two independent lookups: weather and search.</think>I'll look both up.
<|DSML|function_calls>
<|DSML|invoke name="get_weather">
<|DSML|parameter name="city" string="true">Zürich</|DSML|parameter>
<|DSML|parameter name="unit" string="true">c</|DSML|parameter>
</|DSML|invoke>
<|DSML|invoke name="search">
<|DSML|parameter name="query" string="true">café "best"</|DSML|parameter>
<|DSML|parameter name="filters" string="false">{"tags": ["a", "b"], "max": 3}</|DSML|parameter>
</|DSML|invoke>
</|DSML|function_calls>
Expected parse
{
"content": "I'll look both up.",
"reasoning_content": "Two independent lookups: weather and search.",
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-reasoning-parallel-text-before", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "Two independent lookups: weather and search.</think>I'll look both up.\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\" string=\"true\">café \"best\"</|DSML|parameter>\n<|DSML|parameter name=\"filters\" string=\"false\">{\"tags\": [\"a\", \"b\"], \"max\": 3}</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [14959, 8181, 1747, 13953, 28, 9670, 305, 5351, 16, 128799, 43, 5922, 1747, 1952, 890, 339, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 30, 128793, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128793, 41523, 2329, 1281, 12066, 4, 3418, 1281, 11476, 3320, 69, 2797, 619, 582, 21910, 4, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 72, 40332, 4, 3418, 1281, 19836, 3320, 24313, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 24568, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|><think>", "thinking": true, "expected": {"content": "I'll look both up.", "reasoning_content": "Two independent lookups: weather and search.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "reasoning", "reasoning-prefilled", "text-before-call", "unicode", "nested-json", "string-escapes", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": true
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128798
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": true,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": true,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
soft pass deepseek/v32-reasoning-single-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:4:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:4:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:4:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-reasoning-single-call --strategy rand:4:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 10 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.",
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [
Strategies: rand:4:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, reasoning, reasoning-prefilled, x-deepseek-v32.
Raw output
The user wants the current weather in Paris. I'll call get_weather.</think> <|DSML|function_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Paris</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.",
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-reasoning-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "The user wants the current weather in Paris. I'll call get_weather.</think>\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Paris</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [671, 3967, 10059, 270, 2573, 9670, 295, 11111, 16, 342, 5922, 1926, 1178, 65, 50219, 16, 128799, 271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 51119, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|><think>", "thinking": true, "expected": {"content": null, "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "reasoning", "reasoning-prefilled", "x-deepseek-v32"], "notes": "Thinking mode: the prompt ends with <think>, so the output holds only </think>. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": true
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128798
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": true,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": true,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-single-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-single-call --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 1 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Paris</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Paris</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 51119, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-string-false-json
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-string-false-json --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 13 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, nested-json, x-string-false-json, x-deepseek-v32.
Raw output
<|DSML|function_calls>
<|DSML|invoke name="create_event">
<|DSML|parameter name="title" string="true">Design review</|DSML|parameter>
<|DSML|parameter name="when" string="false">{"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}</|DSML|parameter>
<|DSML|parameter name="attendees" string="false">[{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]</|DSML|parameter>
</|DSML|invoke>
</|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-string-false-json", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "when": {"type": "object"}, "attendees": {"type": "array", "items": {"type": "object"}}}, "required": ["title", "when"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"create_event\">\n<|DSML|parameter name=\"title\" string=\"true\">Design review</|DSML|parameter>\n<|DSML|parameter name=\"when\" string=\"false\">{\"start\": \"2026-10-01T09:00:00Z\", \"end\": \"2026-10-01T10:00:00Z\"}</|DSML|parameter>\n<|DSML|parameter name=\"attendees\" string=\"false\">[{\"name\": \"Ana\", \"optional\": false}, {\"name\": \"Bo\", \"optional\": true, \"roles\": [\"notes\"]}]</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 10028, 76740, 3816, 30, 128793, 41523, 2329, 1281, 10212, 4, 3418, 1281, 11476, 3320, 31151, 3862, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 21123, 4, 3418, 1281, 19836, 3320, 24313, 10513, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 3130, 28, 504, 28, 504, 60, 1760, 582, 523, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 553, 28, 504, 28, 504, 60, 4, 24568, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 112191, 5993, 4, 3418, 1281, 19836, 3320, 61, 24313, 2852, 3362, 582, 114991, 1760, 582, 41401, 3362, 5062, 6989, 28612, 2852, 3362, 582, 18056, 1760, 582, 41401, 3362, 3292, 14, 582, 81345, 3362, 20584, 33955, 13747, 37236, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "create_event", "arguments": {"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}}]}, "tags": ["single-call", "nested-json", "x-string-false-json", "x-deepseek-v32"], "notes": "Objects and arrays are JSON inside string=\"false\" parameters. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-text-before-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
expected_match | rand:4:8 | soft pass | content (whitespace only): expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
stream_equals_nonstream | rand:4:8 | soft pass | content (whitespace only): nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' | rand:4:8 (soft_pass): content (whitespace only): one 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-text-before-call --strategy rand:4:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 4 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Strategies: token, rand:4:8
@@ -1,4 +1,4 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current conditions in London.\n\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, text-before-call, x-deepseek-v32.
Raw output
Let me check the current conditions in London. <|DSML|function_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">London</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-text-before-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "Let me check the current conditions in London.\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">London</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [5718, 678, 4085, 270, 2573, 4132, 295, 6693, 339, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128793, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 27571, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": "Let me check the current conditions in London.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "London"}}]}, "tags": ["single-call", "text-before-call", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v32-unicode-emoji
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v32.jsonl --id deepseek/v32-unicode-emoji --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 7 of fixtures/deepseek/v32.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py.
Tags: single-call, unicode, x-deepseek-v32.
Raw output
<|DSML|function_calls> <|DSML|invoke name="translate"> <|DSML|parameter name="text" string="true">こんにちは 🌸 مرحبا — naïve café 👩💻</|DSML|parameter> <|DSML|parameter name="target" string="true">de</|DSML|parameter> </|DSML|invoke> </|DSML|function_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v32-unicode-emoji", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V3.2"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V3.2/blob/a7e62ac04ecb2c0a54d736dc46601c5606cf10a6/encoding/encoding_dsv32.py", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "5e068c2ba2a6e5ebe37a49bb005650c507e7935d77a32f3f7c11ee071498b370", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "translate", "description": "Translate text.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}, "target": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "\n\n<|DSML|function_calls>\n<|DSML|invoke name=\"translate\">\n<|DSML|parameter name=\"text\" string=\"true\">こんにちは 🌸 مرحبا — naïve café 👩💻</|DSML|parameter>\n<|DSML|parameter name=\"target\" string=\"true\">de</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|function_calls>", "output_token_ids": [271, 30, 128793, 8701, 4941, 12548, 1018, 30, 128793, 40148, 5406, 2329, 1281, 77296, 3816, 30, 128793, 41523, 2329, 1281, 2067, 4, 3418, 1281, 11476, 3320, 4549, 7245, 2298, 12457, 2841, 73369, 119, 112125, 53067, 2136, 112752, 57664, 52780, 105, 46088, 23903, 122, 1718, 128793, 41523, 1018, 30, 128793, 41523, 2329, 1281, 28292, 4, 3418, 1281, 11476, 3320, 928, 1718, 128793, 41523, 1018, 1718, 128793, 40148, 5406, 1018, 1718, 128793, 8701, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V3.2", "revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "translate", "arguments": {"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}}]}, "tags": ["single-call", "unicode", "x-deepseek-v32"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v32; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv32",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV32ForCausalLM"
],
"model_type": "deepseek_v32"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V3.2",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128799
],
"source": "generation_prompt"
},
"reasoning_detector": "_DeepSeekV3Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v3",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "LlamaTokenizer",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V3.2",
"revision": "a7e62ac04ecb2c0a54d736dc46601c5606cf10a6",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV32Detector",
"tool_call_parser": "deepseekv32",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-empty-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-empty-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 5 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_time"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, empty-arguments, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="get_time"> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {},
"name": "get_time"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-empty-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_time", "description": "Get the current UTC time. Takes no arguments.", "parameters": {"type": "object", "properties": {}}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_time\">\n\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 20035, 32572, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_time", "arguments": {}}]}, "tags": ["single-call", "empty-arguments", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-marker-in-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-marker-in-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 8 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Write <|DSML|invoke name=\"x\"> inside <|DSML|tool_calls> to call a tool."
},
"name": "echo"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, marker-in-arguments, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="echo"> <|DSML|parameter name="text" string="true">Write <|DSML|invoke name="x"> inside <|DSML|tool_calls> to call a tool.</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"text": "Write <|DSML|invoke name=\"x\"> inside <|DSML|tool_calls> to call a tool."
},
"name": "echo"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-marker-in-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "echo", "description": "Echo a string back verbatim.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"echo\">\n<|DSML|parameter name=\"text\" string=\"true\">Write <|DSML|invoke name=\"x\"> inside <|DSML|tool_calls> to call a tool.</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 18843, 3816, 30, 128825, 41523, 2329, 1281, 2067, 4, 3418, 1281, 11476, 3320, 21750, 818, 128825, 40148, 5406, 2329, 1281, 90, 3320, 6352, 818, 128825, 72461, 4941, 12548, 32, 304, 1926, 260, 4105, 14020, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "echo", "arguments": {"text": "Write <|DSML|invoke name=\"x\"> inside <|DSML|tool_calls> to call a tool."}}]}, "tags": ["single-call", "marker-in-arguments", "x-deepseek-v4"], "notes": "The argument contains format-marker text, which the official tokenizer maps to special-token ids. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-multi-turn-after-tool-result
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:3:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:3:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:3:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-multi-turn-after-tool-result --strategy rand:3:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 10 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": "It is 20C. Now the café search.",
"tool_calls": [
{
"arguments": {
"query": "café Zürich"
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": "It is 20C. Now the café search.", "tool_calls": [
Strategies: rand:3:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": "It is 20C. Now the café search.", "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, multi-turn, unicode, reasoning, reasoning-prefilled, x-deepseek-v4.
Raw output
It is 20C. Now the café search.</think> <|DSML|tool_calls> <|DSML|invoke name="search"> <|DSML|parameter name="query" string="true">café Zürich</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": "It is 20C. Now the café search.",
"tool_calls": [
{
"arguments": {
"query": "café Zürich"
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-multi-turn-after-tool-result", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "It is 20C. Now the café search.</think>\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\" string=\"true\">café Zürich</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [2107, 344, 223, 397, 37, 16, 6583, 270, 57664, 5351, 16, 128822, 271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128825, 41523, 2329, 1281, 12066, 4, 3418, 1281, 11476, 3320, 69, 2797, 619, 125388, 616, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|><think>", "thinking": true, "expected": {"content": null, "reasoning_content": "It is 20C. Now the café search.", "tool_calls": [{"name": "search", "arguments": {"query": "café Zürich"}}]}, "tags": ["single-call", "multi-turn", "unicode", "reasoning", "reasoning-prefilled", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": true
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128821
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": true,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": true,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
soft pass deepseek/v4-numeric-arguments
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-numeric-arguments --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 6 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, numeric-arguments, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="calculate"> <|DSML|parameter name="x" string="false">-3</|DSML|parameter> <|DSML|parameter name="y" string="false">2.5</|DSML|parameter> <|DSML|parameter name="tolerance" string="false">1e-05</|DSML|parameter> <|DSML|parameter name="exact" string="false">true</|DSML|parameter> <|DSML|parameter name="limit" string="false">null</|DSML|parameter> <|DSML|parameter name="values" string="false">[0, -0.5, 1e+21]</|DSML|parameter> <|DSML|parameter name="code" string="true">007</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"code": "007",
"exact": true,
"limit": null,
"tolerance": 1e-05,
"values": [
0,
-0.5,
1e+21
],
"x": -3,
"y": 2.5
},
"name": "calculate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-numeric-arguments", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "calculate", "description": "Evaluate numbers.", "parameters": {"type": "object", "properties": {"x": {"type": "integer"}, "y": {"type": "number"}, "tolerance": {"type": "number"}, "exact": {"type": "boolean"}, "limit": {"type": ["integer", "null"]}, "values": {"type": "array", "items": {"type": "number"}}, "code": {"type": "string"}}, "required": ["x", "y"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"calculate\">\n<|DSML|parameter name=\"x\" string=\"false\">-3</|DSML|parameter>\n<|DSML|parameter name=\"y\" string=\"false\">2.5</|DSML|parameter>\n<|DSML|parameter name=\"tolerance\" string=\"false\">1e-05</|DSML|parameter>\n<|DSML|parameter name=\"exact\" string=\"false\">true</|DSML|parameter>\n<|DSML|parameter name=\"limit\" string=\"false\">null</|DSML|parameter>\n<|DSML|parameter name=\"values\" string=\"false\">[0, -0.5, 1e+21]</|DSML|parameter>\n<|DSML|parameter name=\"code\" string=\"true\">007</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 93801, 3816, 30, 128825, 41523, 2329, 1281, 90, 4, 3418, 1281, 19836, 3320, 15, 21, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 91, 4, 3418, 1281, 19836, 3320, 20, 16, 23, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 86, 44016, 4, 3418, 1281, 19836, 3320, 19, 71, 15, 2642, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 1289, 651, 4, 3418, 1281, 19836, 3320, 11476, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 39673, 4, 3418, 1281, 19836, 3320, 16042, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15737, 4, 3418, 1281, 19836, 3320, 61, 18, 14, 565, 18, 16, 23, 14, 223, 19, 71, 13, 1602, 63, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 8308, 4, 3418, 1281, 11476, 3320, 17065, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "calculate", "arguments": {"x": -3, "y": 2.5, "tolerance": 1e-05, "exact": true, "limit": null, "values": [0, -0.5, 1e+21], "code": "007"}}]}, "tags": ["single-call", "numeric-arguments", "x-deepseek-v4"], "notes": "'code' is the STRING \"007\"; numbers, booleans and null must keep their JSON types. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-parallel-two-calls
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n\n' |
expected_match | rand:1:8 | soft pass | content (whitespace only): expected None, got '\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n\n' |
stream_equals_nonstream | rand:1:8 | soft pass | content (whitespace only): nonstream None, got '\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n\n' | rand:1:8 (soft_pass): content (whitespace only): one None, got '\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-parallel-two-calls --strategy rand:1:8 --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 2 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:1:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: parallel-calls, unicode, nested-json, string-escapes, x-deepseek-v4.
Raw output
<|DSML|tool_calls>
<|DSML|invoke name="get_weather">
<|DSML|parameter name="city" string="true">Zürich</|DSML|parameter>
<|DSML|parameter name="unit" string="true">c</|DSML|parameter>
</|DSML|invoke>
<|DSML|invoke name="search">
<|DSML|parameter name="query" string="true">café "best"</|DSML|parameter>
<|DSML|parameter name="filters" string="false">{"tags": ["a", "b"], "max": 3}</|DSML|parameter>
</|DSML|invoke>
</|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-parallel-two-calls", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\" string=\"true\">café \"best\"</|DSML|parameter>\n<|DSML|parameter name=\"filters\" string=\"false\">{\"tags\": [\"a\", \"b\"], \"max\": 3}</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 30, 128825, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128825, 41523, 2329, 1281, 12066, 4, 3418, 1281, 11476, 3320, 69, 2797, 619, 582, 21910, 4, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 72, 40332, 4, 3418, 1281, 19836, 3320, 24313, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 24568, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "unicode", "nested-json", "string-escapes", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
soft pass deepseek/v4-reasoning-parallel-text-before
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected "I'll look both up.", got "I'll look both up.\n\n\n\n" |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream "I'll look both up.", got "I'll look both up.\n\n\n\n" |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one "I'll look both up.", got "I'll look both up.\n\n\n\n" |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-reasoning-parallel-text-before --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 12 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": "I'll look both up.",
"reasoning_content": "Two independent lookups: weather and search.",
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": "I'll look both up.", + "content": "I'll look both up.\n\n\n\n", "reasoning_content": "Two independent lookups: weather and search.", "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: parallel-calls, reasoning, reasoning-prefilled, text-before-call, unicode, nested-json, string-escapes, x-deepseek-v4.
Raw output
Two independent lookups: weather and search.</think>I'll look both up.
<|DSML|tool_calls>
<|DSML|invoke name="get_weather">
<|DSML|parameter name="city" string="true">Zürich</|DSML|parameter>
<|DSML|parameter name="unit" string="true">c</|DSML|parameter>
</|DSML|invoke>
<|DSML|invoke name="search">
<|DSML|parameter name="query" string="true">café "best"</|DSML|parameter>
<|DSML|parameter name="filters" string="false">{"tags": ["a", "b"], "max": 3}</|DSML|parameter>
</|DSML|invoke>
</|DSML|tool_calls>
Expected parse
{
"content": "I'll look both up.",
"reasoning_content": "Two independent lookups: weather and search.",
"tool_calls": [
{
"arguments": {
"city": "Zürich",
"unit": "c"
},
"name": "get_weather"
},
{
"arguments": {
"filters": {
"max": 3,
"tags": [
"a",
"b"
]
},
"query": "café \"best\""
},
"name": "search"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-reasoning-parallel-text-before", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}, {"type": "function", "function": {"name": "search", "description": "Search the web.", "parameters": {"type": "object", "properties": {"query": {"type": "string"}, "filters": {"type": "object"}}, "required": ["query"]}}}], "raw_output": "Two independent lookups: weather and search.</think>I'll look both up.\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Zürich</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n<|DSML|invoke name=\"search\">\n<|DSML|parameter name=\"query\" string=\"true\">café \"best\"</|DSML|parameter>\n<|DSML|parameter name=\"filters\" string=\"false\">{\"tags\": [\"a\", \"b\"], \"max\": 3}</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [14959, 8181, 1747, 13953, 28, 9670, 305, 5351, 16, 128822, 43, 5922, 1747, 1952, 890, 339, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 60, 5421, 616, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 30, 128825, 40148, 5406, 2329, 1281, 14346, 3816, 30, 128825, 41523, 2329, 1281, 12066, 4, 3418, 1281, 11476, 3320, 69, 2797, 619, 582, 21910, 4, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 72, 40332, 4, 3418, 1281, 19836, 3320, 24313, 44175, 3362, 20584, 67, 1760, 582, 68, 45390, 582, 9047, 3362, 223, 21, 24568, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|><think>", "thinking": true, "expected": {"content": "I'll look both up.", "reasoning_content": "Two independent lookups: weather and search.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Zürich", "unit": "c"}}, {"name": "search", "arguments": {"query": "café \"best\"", "filters": {"tags": ["a", "b"], "max": 3}}}]}, "tags": ["parallel-calls", "reasoning", "reasoning-prefilled", "text-before-call", "unicode", "nested-json", "string-escapes", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": true
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128821
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": true,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": true,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 2,
"version": "0.5.20"
}
soft pass deepseek/v4-reasoning-single-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:4:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:4:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:4:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-reasoning-single-call --strategy rand:4:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 11 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.",
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [
Strategies: rand:4:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, reasoning, reasoning-prefilled, x-deepseek-v4.
Raw output
The user wants the current weather in Paris. I'll call get_weather.</think> <|DSML|tool_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Paris</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.",
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-reasoning-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "The user wants the current weather in Paris. I'll call get_weather.</think>\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Paris</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [671, 3967, 10059, 270, 2573, 9670, 295, 11111, 16, 342, 5922, 1926, 1178, 65, 50219, 16, 128822, 271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 51119, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|><think>", "thinking": true, "expected": {"content": null, "reasoning_content": "The user wants the current weather in Paris. I'll call get_weather.", "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "reasoning", "reasoning-prefilled", "x-deepseek-v4"], "notes": "Thinking mode: the prompt ends with <think>, so the output holds only </think>. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": true
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128821
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": true,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": true,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-single-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-single-call --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 1 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">Paris</|DSML|parameter> <|DSML|parameter name="unit" string="true">c</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "Paris",
"unit": "c"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-single-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">Paris</|DSML|parameter>\n<|DSML|parameter name=\"unit\" string=\"true\">c</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 51119, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 15165, 4, 3418, 1281, 11476, 3320, 69, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "Paris", "unit": "c"}}]}, "tags": ["single-call", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-string-false-json
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-string-false-json --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 14 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, nested-json, x-string-false-json, x-deepseek-v4.
Raw output
<|DSML|tool_calls>
<|DSML|invoke name="create_event">
<|DSML|parameter name="title" string="true">Design review</|DSML|parameter>
<|DSML|parameter name="when" string="false">{"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}</|DSML|parameter>
<|DSML|parameter name="attendees" string="false">[{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]</|DSML|parameter>
</|DSML|invoke>
</|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"attendees": [
{
"name": "Ana",
"optional": false
},
{
"name": "Bo",
"optional": true,
"roles": [
"notes"
]
}
],
"title": "Design review",
"when": {
"end": "2026-10-01T10:00:00Z",
"start": "2026-10-01T09:00:00Z"
}
},
"name": "create_event"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-string-false-json", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "create_event", "description": "Create a calendar event.", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "when": {"type": "object"}, "attendees": {"type": "array", "items": {"type": "object"}}}, "required": ["title", "when"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"create_event\">\n<|DSML|parameter name=\"title\" string=\"true\">Design review</|DSML|parameter>\n<|DSML|parameter name=\"when\" string=\"false\">{\"start\": \"2026-10-01T09:00:00Z\", \"end\": \"2026-10-01T10:00:00Z\"}</|DSML|parameter>\n<|DSML|parameter name=\"attendees\" string=\"false\">[{\"name\": \"Ana\", \"optional\": false}, {\"name\": \"Bo\", \"optional\": true, \"roles\": [\"notes\"]}]</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 10028, 76740, 3816, 30, 128825, 41523, 2329, 1281, 10212, 4, 3418, 1281, 11476, 3320, 31151, 3862, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 21123, 4, 3418, 1281, 19836, 3320, 24313, 10513, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 3130, 28, 504, 28, 504, 60, 1760, 582, 523, 3362, 582, 939, 24, 15, 553, 15, 2616, 54, 553, 28, 504, 28, 504, 60, 4, 24568, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 112191, 5993, 4, 3418, 1281, 19836, 3320, 61, 24313, 2852, 3362, 582, 114991, 1760, 582, 41401, 3362, 5062, 6989, 28612, 2852, 3362, 582, 18056, 1760, 582, 41401, 3362, 3292, 14, 582, 81345, 3362, 20584, 33955, 13747, 37236, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "create_event", "arguments": {"title": "Design review", "when": {"start": "2026-10-01T09:00:00Z", "end": "2026-10-01T10:00:00Z"}, "attendees": [{"name": "Ana", "optional": false}, {"name": "Bo", "optional": true, "roles": ["notes"]}]}}]}, "tags": ["single-call", "nested-json", "x-string-false-json", "x-deepseek-v4"], "notes": "Objects and arrays are JSON inside string=\"false\" parameters. expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-text-before-call
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
expected_match | rand:4:8 | soft pass | content (whitespace only): expected 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
stream_equals_nonstream | rand:4:8 | soft pass | content (whitespace only): nonstream 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' | rand:4:8 (soft_pass): content (whitespace only): one 'Let me check the current conditions in London.', got 'Let me check the current conditions in London.\n\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-text-before-call --strategy rand:4:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 4 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:2:8, rand:3:8, rand:5:8
Matches the expected parse.
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Strategies: token, rand:4:8
@@ -1,4 +1,4 @@ { - "content": "Let me check the current conditions in London.", + "content": "Let me check the current conditions in London.\n\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, text-before-call, x-deepseek-v4.
Raw output
Let me check the current conditions in London. <|DSML|tool_calls> <|DSML|invoke name="get_weather"> <|DSML|parameter name="city" string="true">London</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": "Let me check the current conditions in London.",
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"city": "London"
},
"name": "get_weather"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-text-before-call", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "get_weather", "description": "Get the current weather for a city.", "parameters": {"type": "object", "properties": {"city": {"type": "string"}, "unit": {"type": "string", "enum": ["c", "f"]}}, "required": ["city"]}}}], "raw_output": "Let me check the current conditions in London.\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"get_weather\">\n<|DSML|parameter name=\"city\" string=\"true\">London</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [5718, 678, 4085, 270, 2573, 4132, 295, 6693, 339, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 1133, 65, 50219, 3816, 30, 128825, 41523, 2329, 1281, 37399, 4, 3418, 1281, 11476, 3320, 27571, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": "Let me check the current conditions in London.", "reasoning_content": null, "tool_calls": [{"name": "get_weather", "arguments": {"city": "London"}}]}, "tags": ["single-call", "text-before-call", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
soft pass deepseek/v4-unicode-emoji
expected_match, stream_equals_nonstream, split_invariance
| Check | Strategy | Result | Detail |
|---|---|---|---|
expected_match | token | soft pass | content (whitespace only): expected None, got '\n\n\n' |
expected_match | rand:2:8 | soft pass | content (whitespace only): expected None, got '\n\n' |
stream_equals_nonstream | token | soft pass | content (whitespace only): nonstream None, got '\n\n\n' |
stream_equals_nonstream | rand:2:8 | soft pass | content (whitespace only): nonstream None, got '\n\n' |
split_invariance | * | soft pass | vs one: token (soft_pass): content (whitespace only): one None, got '\n\n\n' | rand:2:8 (soft_pass): content (whitespace only): one None, got '\n\n' |
Minimal repro
uv run canitoolcall run --engine sglang --fixtures fixtures/deepseek/v4.jsonl --id deepseek/v4-unicode-emoji --strategy rand:2:8 --strategy token --observed all
Set up the engine first with scripts/engines/sglang.sh; this run used sglang 0.5.20.
The fixture is line 7 of fixtures/deepseek/v4.jsonl.
Observed vs expected
Identical parses are grouped. Empty strings are shown as null, as in strict comparison.
Strategies: nonstream, one, special, rand:1:8, rand:3:8, rand:4:8, rand:5:8
Matches the expected parse.
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Strategies: token
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n\n", "reasoning_content": null, "tool_calls": [
Strategies: rand:2:8
@@ -1,4 +1,4 @@ { - "content": null, + "content": "\n\n", "reasoning_content": null, "tool_calls": [
Fixture
Provenance: template_render, https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py.
Tags: single-call, unicode, x-deepseek-v4.
Raw output
<|DSML|tool_calls> <|DSML|invoke name="translate"> <|DSML|parameter name="text" string="true">こんにちは 🌸 مرحبا — naïve café 👩💻</|DSML|parameter> <|DSML|parameter name="target" string="true">de</|DSML|parameter> </|DSML|invoke> </|DSML|tool_calls>
Expected parse
{
"content": null,
"reasoning_content": null,
"tool_calls": [
{
"arguments": {
"target": "de",
"text": "こんにちは 🌸 مرحبا — naïve café 👩💻"
},
"name": "translate"
}
]
}
Fixture record (JSONL, ready to vendor into an engine's tests)
{"id": "deepseek/v4-unicode-emoji", "family": "deepseek", "models": ["deepseek-ai/DeepSeek-V4-Flash", "deepseek-ai/DeepSeek-V4-Pro"], "spec_version": "0.1", "provenance": {"kind": "template_render", "source_url": "https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/blob/60d8d70770c6776ff598c94bb586a859a38244f1/encoding/encoding_dsv4.py", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "license": "MIT", "generator": "scripts/fixtures/deepseek/build.py", "template_sha256": "bdbd57c132a1b3725042323d02b98b9d1df28e5f388f134399555d041f5055e0", "attribution": "Copyright (c) 2023 DeepSeek"}, "tools": [{"type": "function", "function": {"name": "translate", "description": "Translate text.", "parameters": {"type": "object", "properties": {"text": {"type": "string"}, "target": {"type": "string"}}, "required": ["text"]}}}], "raw_output": "\n\n<|DSML|tool_calls>\n<|DSML|invoke name=\"translate\">\n<|DSML|parameter name=\"text\" string=\"true\">こんにちは 🌸 مرحبا — naïve café 👩💻</|DSML|parameter>\n<|DSML|parameter name=\"target\" string=\"true\">de</|DSML|parameter>\n</|DSML|invoke>\n</|DSML|tool_calls>", "output_token_ids": [271, 30, 128825, 72461, 4941, 12548, 1018, 30, 128825, 40148, 5406, 2329, 1281, 77296, 3816, 30, 128825, 41523, 2329, 1281, 2067, 4, 3418, 1281, 11476, 3320, 4549, 7245, 2298, 12457, 2841, 73369, 119, 112125, 53067, 2136, 112752, 57664, 52780, 105, 46088, 23903, 122, 1718, 128825, 41523, 1018, 30, 128825, 41523, 2329, 1281, 28292, 4, 3418, 1281, 11476, 3320, 928, 1718, 128825, 41523, 1018, 1718, 128825, 40148, 5406, 1018, 1718, 128825, 72461, 4941, 12548, 32], "tokenizer": {"repo": "deepseek-ai/DeepSeek-V4-Flash", "revision": "60d8d70770c6776ff598c94bb586a859a38244f1", "mode": "hf"}, "generation_prompt": "<|Assistant|></think>", "thinking": false, "expected": {"content": null, "reasoning_content": null, "tool_calls": [{"name": "translate", "arguments": {"text": "こんにちは 🌸 مرحبا — naïve café 👩💻", "target": "de"}}]}, "tags": ["single-call", "unicode", "x-deepseek-v4"], "notes": "expected == DeepSeek's reference parse_message_from_completion_text on this output. Sub-format deepseek-v4; history render of the official encoder."}
Parser configuration
{
"auto_detected": {
"reasoning_parser": null,
"tool_call_parser": null
},
"chat_encoding_spec": "dsv4",
"chat_template_kwargs": {
"thinking": false
},
"chat_template_sha256": null,
"detokenizer": "DetokenizerManager._decode_batch_token_id_output",
"engine": "sglang",
"hf_config": {
"architectures": [
"DeepseekV4ForCausalLM"
],
"model_type": "deepseek_v4"
},
"hf_config_error": null,
"model": "deepseek-ai/DeepSeek-V4-Flash",
"no_stop_trim": false,
"notes": [],
"prompt_tail": {
"ids": [
128804,
128822
],
"source": "generation_prompt"
},
"reasoning_detector": "DeepSeekV4Detector",
"reasoning_effort": null,
"reasoning_enabled": false,
"reasoning_parser": "deepseek-v4",
"separate_reasoning": true,
"skip_special_tokens": false,
"spaces_between_special_tokens": true,
"stop": {
"appended": true,
"finish_reason": "stop",
"id": 1,
"kept_by_engine": false,
"rule": "first stop token of the reference model",
"token": "<|end▁of▁sentence|>"
},
"stream_reasoning": true,
"template_force_reasoning": false,
"template_reasoning_config": null,
"thinking": false,
"tokenizer": {
"class": "TokenizersBackend",
"loader": "sglang.srt.utils.hf_transformers_utils.get_tokenizer(revision=, tokenizer_revision=)",
"repo": "deepseek-ai/DeepSeek-V4-Flash",
"revision": "60d8d70770c6776ff598c94bb586a859a38244f1",
"trust_remote_code": false
},
"tokenizer_mode": "hf",
"tool_call_detector": "DeepSeekV4Detector",
"tool_call_parser": "deepseekv4",
"tool_choice": "auto",
"tools_offered": 1,
"version": "0.5.20"
}
Unsupported fixtures
The adapter declined these fixtures because this engine version has no parser for the family or model.
deepseek/v41-empty-arguments: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-long-arguments: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-marker-in-arguments: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-multi-turn-after-tool-result: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-no-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-numeric-arguments: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-parallel-two-calls: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-reasoning-no-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-reasoning-parallel-text-before: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-reasoning-single-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-single-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-string-false-json: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-text-before-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-truncated-in-reasoning: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-truncated-mid-arguments: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-truncated-second-parallel-call: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-unescaped-string-value: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-unicode-emoji: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/v41-whitespace-string-value: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/vllm-v41-reasoning-text-before-parallel-calls: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'deepseek/vllm-v41-text-before-parallel-calls: SGLang 0.5.20 has no DeepSeek-V4.1 parser: V4.1's spaced DSML markers ('DSML' + U+FF5C + ' calls') appear nowhere in sglang/srt; the deepseekv4 detector only knows V4's 'DSML' + U+FF5C + 'tool_calls'
- pass strict match on every realistic strategy
- soft pass only whitespace differs (normalization
soft-v1) - fail a check failed
- error the harness failed, not the engine's parser
- unsupported the engine has no parser for this family or model