Skip to content

common/chat: fix DeepSeek V4 parsing/encoding - #25891

Closed
tarruda wants to merge 10 commits into
ggml-org:masterfrom
tarruda:dsv4-encoding-fixes
Closed

common/chat: fix DeepSeek V4 parsing/encoding#25891
tarruda wants to merge 10 commits into
ggml-org:masterfrom
tarruda:dsv4-encoding-fixes

Conversation

@tarruda

@tarruda tarruda commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Overview

Align DSv4 parsing/encoding to the official implementation here: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/tree/main/encoding. Main user visible fixes:

  • Better performance in coding agents
  • Batched/parallel tool calls (which is done in the offical API)
  • Support for max effort thinking, which is implemented by handling template kwarg reasoning_effort == "max"
  • Support for --reasoning-preserve. In the official DSv4 encoding, the drop_thinking option controls this. Here we translate to "preserve_thinking" for --reasoning-preserve compatibility.
  • No more seeing unparsed tool calls (<DSML...) in thinking blocks, that usually halts an agentic coding session.

Additional information

To do this, I've had to opt-out of the autoparser. AFAICT Deepseek is different enough in how it handles tool calls within <think> blocks to require this, but I could be missing something. (cc @pwilkin @aldehir @fairydreaming @am17an)

This fixes Deepseek V4 Flash for agentic multi-turn usage for me.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: Yes Codex wrote most of the code. I have reviewed and tested this with pi coding harness.

@github-actions github-actions Bot added testing Everything test related jinja parser Issues related to the jinja parser labels Jul 19, 2026
@fairydreaming

Copy link
Copy Markdown
Collaborator

@tarruda What benchmark do you recommend for testing DeepSeek V4 chat template?

@tarruda

tarruda commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@fairydreaming I don't use anything scientific, but there's a personal test that I have been using a lot to evaluate local models. It is an investigation of llama.cpp codebase that is fully detailed in this issue description.

@tarruda
tarruda marked this pull request as ready for review July 19, 2026 22:29
@tarruda
tarruda requested review from a team, CISC and pwilkin as code owners July 19, 2026 22:29
@drrros

drrros commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Testing this branch, parallel tool call seems to work fine in pi agent.

@aldehir aldehir left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's pretty sloppy.

I say split this up into a separate v4 function and remove all code that exists outside of it, except for the template/test/cap changes.

Comment thread common/chat-peg-parser.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/chat.cpp Outdated
Comment thread common/jinja/caps.cpp
@tarruda

tarruda commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

It's pretty sloppy.

I did say it was mostly LLM written, so thank you for confirming that. I'm totally fine with closing and letting someone else with actual understanding of how things work here deal with this. Truth be told: If I continue, all I'm going to do is pass your comments to Codex. If that is not acceptable I can close this immediately.

@aldehir

aldehir commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

I personally don't mind, especially since I don't have the hardware to run this model. That said, @pwilkin is probably the better person to review since he can.

tarruda added 2 commits July 20, 2026 06:59
Add dedicated DeepSeek V4 handling for its DSML tool format, reasoning
modes, and structured responses while retaining V3.2 compatibility.

- Opt V4 templates out of differential autoparsing and use the specialized
  DSML parser.
- Parse reasoning and DSML tool calls incrementally from streamed output.
- Recognize DSML tool calls encountered before the reasoning end marker.
- Encode typed and empty arguments and sort results by tool-call order.
- Validate required and unique arguments in arbitrary order with linear parser
  construction.
- Support Max reasoning, preserved thinking history, and chat-mode
  continuations.
- Inject response schemas and allow raw JSON or tool calls for structured
  output.
- Expand V4 prompt, parser, grammar, and reconstruction coverage.

These changes align DSv4 parsing/encoding to the official implementation here:
https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash/tree/main/encoding

Assisted-by: Codex
@tarruda
tarruda marked this pull request as draft July 20, 2026 10:05
@tarruda
tarruda force-pushed the dsv4-encoding-fixes branch from 16cfdcf to 290898e Compare July 20, 2026 10:06
@tarruda

tarruda commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

@aldehir as promised: I used codex to address your review. Since #25544 is still open I have rebased this branch on top of it and marked it as draft.

@tarruda

tarruda commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

@aldehir I'm curious about #25544: The main reason I understood it was necessary to opt out of the autoparser was because it was possible to invoke tools without ending the <think> block. Does #25544 allows the autoparser to work correctly here by using <DSML... tool marker as a thinking end delimiter?

@aldehir

aldehir commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Does #25544 allows the autoparser to work correctly here by using <DSML... tool marker as a thinking end delimiter?

I think we'll need a bit more experimentation to figure out how to integrate it with the autoparser. It won't work OOTB at the moment, so using it in a dedicated parser (or two) will help show us what that might look like.

@am17an

am17an commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Just FYI I also faced an issue where the model just outputted plain DSML in the output. So there does seem to be some issue here, but I'm not able to reproduce reliably.

@tarruda

tarruda commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Just FYI I also faced an issue where the model just outputted plain DSML in the output. So there does seem to be some issue here, but I'm not able to reproduce reliably.

Were you able to reproduce it in this branch? Codex did manage to reproduce a regression and fix it in this branch. IIRC this was the test that reproduced it:

        tst.test(
               "Let me check the time\n\n"
               "<|DSML|tool_calls>\n"
               "<|DSML|invoke name=\"get_time\">\n"
               "<|DSML|parameter name=\"city\" string=\"true\">Tokyo</|DSML|parameter>\n"
               "</|DSML|invoke>\n"
               "</|DSML|tool_calls>\n"
               "</think>")
            .enable_thinking(true)
            .reasoning_format(COMMON_REASONING_FORMAT_DEEPSEEK)
            .tools({ get_time_tool })
            .expect_reasoning("Let me check the time")
            .expect_tool_calls({ { "get_time", R"({"city": "Tokyo"})", {} } })
            .run();

I had a similar experience where it would sometimes cause this in the middle of an agentic session, but after that fix I didn't see it again.

@pwilkin

pwilkin commented Jul 22, 2026

Copy link
Copy Markdown
Member

FYI the DeepSeek4 dedicated parser fixes are finally merged :)

@tarruda

tarruda commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

FYI the DeepSeek4 dedicated parser fixes are finally merged :)

Closing it then. There are still two things missing from the template:

  • max effort reasoning
  • structured output instructions

But since it is only template tweaks, it doesn't need to go to llama.cpp

@tarruda tarruda closed this Jul 22, 2026
@tarruda
tarruda deleted the dsv4-encoding-fixes branch July 22, 2026 12:06
@tarruda

tarruda commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@pwilkin also: the --reasoning-preserve mechanic doesn't seem to be working with the version of the template in #25414

@pwilkin

pwilkin commented Jul 22, 2026

Copy link
Copy Markdown
Member

@tarruda yeah that's because of the wrong variable name, did a quick PR to fix it.

@tarruda
tarruda restored the dsv4-encoding-fixes branch July 28, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jinja parser Issues related to the jinja parser server testing Everything test related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants