Deepseek V3.1 本地化部署实践
前言
DeepseekV3.1 已经发布,这是一个混合模型,同时支持 Thinking
和 Nonthinking
两种推理模式。这对于缺卡的小玩家而言无疑是个重大利好。这意味着原先我们需要 2 套硬件资源来运行的 V3 + R1 的租户,现在只需要一套硬件就可以运行了。我们只需要在资源不足时给他扩容即可,这无疑带来了更大的灵活性(比如在低峰期间就可以拆出一些卡来做其他测试了,手动狗头)。
DeepseekV3.1 的模型结构和 DeepseekV3
保持一致,所以本地部署沿用 V3
的方案即可拉起模型。
当然这并不意味着可以无缝迁移到 V3.1
,我们至少要解决以下几个问题。
Thinking 模式切换
DeepseekV3.1
是一个混合模型,默认工作在 NonThinking
模式下,激活 Thinking
模式需要显示输入参数。
在 huggingface.co
的 card
里,他给了这样一个 example
:
这个意思是在 tokenizer.apply_chat_template
调用中,通过 thinking
参数来控制当前的工作模式。
对于推理框架提供的 OpenAI
兼容接口而言,无论 vllm
还是 sglang
,都支持 chat_template_kwargs
参数,这个参数的作用就相当于在tokenizer.apply_chat_template
中传入的指定的参数。
例如在 qwen3
里,他给的 example 是这样的:
那对于拉起的 qwen3
接口,传入这样的参数即可关闭 qwen3
的 thinking
模式
对于 DeepseekV3.1
而言,这里自然传入以下参数来开启 thinking
模式即可
模型封装
通过调用推理框架拉起的 OpenAI
兼容接口,并传入 "chat_template_kwargs": {"thinking": true}
参数,我们确实可以实现动态的切换模型的工作模式。然而对于终端用户而言,chat_template_kwargs
的对于用户而言显然太底层
和太灵活
了,用户可能传入其他预期之外的参数,这可能会带来一些意想不到的问题,也可能存在一些风险。并且不同的模型的 thinking
开关参数不一致,对用户而言也并不方便。
对于生产环境而言,可以参考 百炼 的方式,将开启 thinking
的参数统一封装为一致的参数,比如 enable_thinking
,这样用户在调用时,只需要传入 enable_thinking
参数即可,而不需要知道底层的 chat_template_kwargs
,也无法传入其他的参数。
也可以参考 Deepseek 的方式,依然将 thinking
模型和 NonThinking
模式拆分为两个模型。这样用户通过调整传入 model
来改变对应的模型,这个方案也考虑了兼容性,可能会更有好一些。ChatECNU 采用的就是这个模式。
reasoning-parser
Deepseek
作为第一个支持思维链的开源模型,其设计的 reasoning_content
目前已然成为了 thinking
模型的 API 接口标准。但对于模型本身的输出而言,思考部分本质上是和正文部分一起输出的,只是带上了不同的标记而已,具体的格式则与模型的 chat_template
有关。主流推理框架如 vllm
和 sglang
则都提供了 --reasoning-parser
参数,将思考部分解析到 reasoning_content
中。
而 DeepseekV3.1
的 chat_template
相对 Deepseek-R1
和 Deepseek-V3
都产生了很大的变动,因此如果继续沿用原有的解析器,比如在 sglang
中沿用 --reasoning-parser deepseek-r1
,则会产生错误解析,比如在 thinking
模式关闭的时候,会错误的将 NonThinking
的内容也解析到 reasoning_content
中。类似这个 #9457 issue 所提到的现象。
sglang
的支持见这个 #9464 PR。
vllm
的支持见这个 #23437 PR。
tools call parser
和 reasoning
的 parse
一样, 工具调用的部分也是由 chat_template
中的标记来决定的。DeepseekV3.1
的工具调用也做了相当多的调整,因此这里仍然需要一个新的 parser
来进行处理,才能够正确的实现 tools_call
功能。
sglang
的支持见这个 #9446 PR。
vllm
的支持见这个 #23545 PR。
和 Deepseek V3/R1
不同的是,DeepseekV3.1
仅在 NonThinking
模式下支持工具调用。
性能测试
完成上述的准备后,我们就可以做本地化的部署了。sglang
最新的 v0.5.1.post3-cu126
已经合入了上述的所有 PR,跑这个版本即可。核心变化是 --reasoning-parser
,--tool-call-parser
和 --chat-template
部分。
以下是在我们在一台 8 卡 H20 上的运行示例:
我们用 vllm
的 benchmark
来对 sglang
做了一个性能测试,128 并发,1k 的输入输出长度:
性能指标和 v3
差不多,这是符合预期的,毕竟架构没有太大的变化。
Anthropic 兼容 API
kimi ,glm,deepseek 都开始支持 Anthropic 标准的 API,Claude Code 的影响力恐怖如斯。
我们华东师范大学也支持 Anthropic 兼容 API 了,采取的是 proxy 方案。我们修改了claude-code-proxy 这个项目,让他支持对每个用户自己的 API KEY
来进行鉴权,详见 #37 这个 PR。
不过好消息是 vllm
和 sglang
都有支持 anthorpic api
的 PR 了,例如 #21313 和 #8149,将来可能切换到原生支持是更好的选择。
极你太美
万万没想到的是,DeekseekV3.1 引起的最大热度竟然是极你太美。具体可以看知乎这个提问下的相关回答:如何评价 DeepSeek V3.1 模型输出 Token 会被随机替换为「极」?
我们针对这个事情也做了一些测试,结论大概是这样:
在数据构造的场景里,持续的规律性长文本输出确实会让 DS 懵逼,并开始输出 极。
出现 极 的情况和输出的长度相关,在比较低的输出长度下不会出现这个问题。所以在数据构造的场景里,分批来构造就可以规避掉 极。
调整 temperature, top_p 等参数恐怕作用不大。在 logprobs 里很多场景 极 直接出现在了第一位。降低 temperature 和 top_p 搞不好是反而出来的更多了。
通过提示词可以一定程度缓解,但无法完全避免。
写作,代码,提问等场景里,只要不涉及持续的规律性的文本构造,即便是超长文本输出也基本上不会出现这个问题。
详见这里 聊聊Deepseek V3.1的极你太美
参考资料
以上
版权声明: 本文为 InfoQ 作者【冯骐】的原创文章。
原文链接:【http://xie.infoq.cn/article/ed5ceb70a3224ab8f3f3139b0】。
本文遵守【CC BY-SA】协议,转载请保留原文出处及本版权声明。
评论