Skip to content

deepseek-v4-flash reasoning_options omit low, which the API accepts and honors #3962

Description

@johannes-engler-mw

Summary

providers/opencode-go/models/deepseek-v4-flash.toml declares:

[[reasoning_options]]
type = "effort"
values = ["high", "max"]

low is missing. DeepSeek's API accepts it, documents it, and it measurably changes behaviour for this model. Because it isn't declared, opencode never sends it — and since the two values that are declared (high, max) are behaviourally near-identical for v4-flash, the reasoning-effort variant appears to do nothing for this model.

Evidence that low is supported

1. The upstream itself enumerates it. Posting an invalid value to opencode.ai/zen/go/v1/chat/completions returns the provider's own deserializer error:

reasoning_effort: unknown variant `totally-invalid-xyz`,
expected one of `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`

2. DeepSeek documents it. Thinking mode guide: supported values low/high/max, default effort high, and the mapping table gives low → low for deepseek-v4-flash (only deepseek-v4-pro collapses low → high).

3. It measurably differs from the default. Identical request body, only reasoning_effort varied, n=3 each, measuring usage.completion_tokens_details.reasoning_tokens:

reasoning_effort mean reasoning tokens samples
low 879 785, 1308, 544
(field omitted → default) 2542 2460, 2578, 2588
high 2578 2051, 2850, 2833
max 2829 2456, 2827, 3204

Omitting the field lands on ~2542, matching high — consistent with the documented default. low sits 2.9× below that (Welch t = 7.26), so it is a genuine distinct level, not a silent fallback to the default.

Note high vs max is only t = 0.74 — indistinguishable. Those are precisely the two values currently declared, which is why the variant switcher has no observable effect for this model.

Consequence in opencode

opencode drops variant values that aren't declared in reasoning_options. Verified on opencode 1.18.5 by capturing the outgoing request body (provider api URL redirected to a local HTTP server):

CLI flag reasoning_effort sent
--variant max "max"
--variant high "high"
--variant low field absent

So --variant low silently sends nothing and the model runs at its default (high).

Expected

values = ["low", "high", "max"]

Notes

  • deepseek-v4-pro is arguably correct as-is: DeepSeek documents it collapsing low → high, so listing only high/max there is defensible. This report is flash-specific.
  • xhigh should stay unlisted for flash — the docs map xhigh → high for this model, so it would be a duplicate of high.
  • All measurements were taken through the opencode-go gateway rather than DeepSeek's API directly (I don't have a DeepSeek key). That matches the file being changed, but a direct-API confirmation would be worth having if a maintainer has one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions