DeepSeek 7 月 31 日放出 V4-Flash。我们当晚接进自己的网关,第二天就被一个现象卡住:

同一条 curl,模型换成 deepseek-v4-flash 之后,HTTP 200,没有任何报错,content 是空字符串。

后面挖下去,顺带找到了一个官方文档里没怎么提、但能直接省掉 90% 以上输出成本的参数。先讲坑,再讲这个。

一、复现:200 但 content 为空

curl https://api.deepseek.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-flash",
    "messages": [{"role": "user", "content": "Say OK"}],
    "max_tokens": 10
  }'

返回:

{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "",
      "reasoning_content": "We need answer to user. User says \"Say"
    },
    "finish_reason": "length"
  }],
  "usage": {
    "prompt_tokens": 85,
    "completion_tokens": 10,
    "completion_tokens_details": { "reasoning_tokens": 10 }
  }
}

看这三个数的关系:completion_tokens = 10,其中 reasoning_tokens = 10,content = ""

思考过程把 10 个 token 的预算全吃光了,正文一个字都没轮上。

原因是 V4-Flash 默认开思考。它先写一段推理进 reasoning_content,再写 content。而 max_tokens 限制的是 completion 总量,思考和正文共用同一个池子。预算给小了,模型还没想完就被 length 截断,正文自然是空的。

这跟 V3 时代不一样。老的 deepseek-chat 不带思考,max_tokens: 10 会老老实实吐 10 个 token 正文。很多人代码里的 max_tokens 是当年随手填的小值,模型一换就集体空返回,而且不报错——你在日志里看到的是一片 200。

最直接的解法是把 max_tokens 提到 200 以上:

max_tokens = 200  →  content = "OK",reasoning 72 字符,total_tokens = 106

回答 "Say OK" 这种极短问题,思考部分稳定在 70~90 token。200 是安全下限,正经任务直接给 1000 以上。

二、更好的解法:把思考关掉

如果你的场景根本不需要推理——文本分类、字段抽取、格式转换、意图识别这类——思考纯属浪费钱,因为 reasoning_tokens计入 completion_tokens 按输出价收费的

我试了几个常见写法,实测结果:

"thinking": false                    →  400,报错信息:
                                        thinking: invalid type: boolean
"enable_thinking": false             →  参数被忽略,思考照常
"reasoning_effort": "none"           →  ✅ 生效
"thinking": {"type": "disabled"}     →  ✅ 生效

thinking: false 那个报错很有意思——它说类型错了,不是说参数不存在。顺着这个提示试对象形式,就通了。这是 Anthropic 那套写法,V4 官方说了原生支持 Anthropic 格式,看来参数也一起兼容了。

同一个请求(max_tokens: 200,问题都是 "Say OK")的完整对比:

配置 reasoning_content 字段 completion_tokens reasoning_tokens
默认(不传) 18 16
reasoning_effort: "none" 消失 1
thinking: {"type":"disabled"} 消失 1
reasoning_effort: "high" 29 27

18 → 1,输出 token 降了 94%。

关掉之后 reasoning_content 字段是直接从响应里消失的,不是返回空串,解析代码注意做存在性判断。

用法:

curl https://api.deepseek.com/v1/chat/completions \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-flash",
    "messages": [{"role": "user", "content": "把这句话分类为 正面/负面:这家店服务很差"}],
    "max_tokens": 50,
    "reasoning_effort": "none"
  }'

一句提醒:reasoning_effort 还有 low / high 档。我在 "Say OK" 这种极简任务上测,low 和 high 的思考 token 分别落在 48 和 27,没有呈现出预期的单调关系——样本太小、任务太简单,不足以下结论。想按档位调优的话,请拿你自己的真实 prompt 跑 AB,别信我这两个数。但 none 完全关闭这一点是确定的,字段直接消失,反复测都是 1 个 completion token。

三、另外两件测的时候发现的事

deepseek-chat 已经是 V4 了。

拉官方模型列表:

curl https://api.deepseek.com/models -H "Authorization: Bearer YOUR_KEY"

现在只剩两个真实模型:deepseek-v4-flashdeepseek-v4-pro。老的 deepseek-chatdeepseek-reasoner 还能调,但已经是指向 V4-Flash 的别名。

也就是说,你什么都没改,线上服务已经悄悄换模型了。如果最近发现输出风格变了、延迟变了、或者莫名出现空返回,先确认这件事,别怀疑自己的代码。

定价页脚注里藏着峰谷定价。

官方定价页底部有一行小字:即将采用峰谷定价,高峰时段价格为平时 2 倍,适用所有计费项。高峰是北京时间 09:00-12:00 和 14:00-18:00。

"适用所有计费项"这句要留意——缓存命中输入也翻倍。V4-Flash 缓存命中 0.02 元/百万 token,未命中 1 元/百万,差 50 倍。重度依赖缓存的业务,高峰期成本模型得重算,不能只盯未命中价。

四、如果你在做网关或中间层

这次升级值得补三个防御:

max_tokens 设下限。 用户传小于 200 的值时,对思考型模型自动抬到安全线,至少打个 warning。比事后排查空返回便宜得多。

监控空 content 率。finish_reason == "length"content == "" 的请求单独打点。这个指标抬头,基本就是上游换了思考行为。

别把上游模型 ID 硬编码进业务代码。 这次 deepseek-chat 变别名是平滑的,下次未必。中间加一层映射,改配置就能切。


我们自己的网关(盈算智服)这两天同步了 V4-Flash 元数据,老的 deepseek-chat 保留成别名,老代码零改造;另外做了错峰定价,避开北京时间那两个高峰段同模型更便宜。

为了让人能真上手摸一下而不是只看参数表,免费试用 Key 现在直接给 20 次 deepseek-v4-flash 额度,不用升级、不用信用卡:https://yingsuan.top/api.html?utm_source=csdn&utm_medium=article&utm_campaign=v4flash_pitfall

实时价格这个端点不需要 Key 就能看:https://yingsuan.top/v1/pricing

如果你在 reasoning_effort 的档位上跑出了更靠谱的对比数据,欢迎评论区贴出来。

更多推荐