我们把 DeepSeek V4 跑上了昇腾 910B:真正难的不是模型启动,而是把 Agent 工具调用跑通
这次部署最大的收获不是“把 DeepSeek V4 跑起来了”。模型部署和Agent 工具调用部署完全不是一回事模型跑起来,只是说明算力和权重链路通了。工具调用跑通,才说明这个模型真的能进入 Agent 系统。模型格式推理框架NPU 后端工具协议parserOpenAI APIAgent 客户端少一个环节,都会出问题。Transformers 不识别 deepseek_v4DSML 泄漏pip i
我们把 DeepSeek V4 跑上了昇腾 910B:真正难的不是模型启动,而是把 Agent 工具调用跑通
这篇文章不想写成那种“复制命令,一路成功”的教程。
因为真实部署根本不是那样。
真实情况是:你以为你在部署一个模型,结果你是在和 模型格式、推理框架、NPU 生态、Docker 容器、Transformers、vLLM-Ascend、OpenClaw、工具调用协议 一起打架。
这次我们搞的是:
DeepSeek-V4-Flash
昇腾 910B × 8
vLLM-Ascend
OpenAI Compatible API
OpenClaw 工具调用
听起来一句话很简单:
在昇腾 910B 上部署 DeepSeek V4,然后接 OpenClaw。
但真正上手以后才知道,这里面每一步都有坑,而且不是小坑,是那种你一脚踩下去,半天都不知道自己掉哪儿了的坑。
一开始我们以为:模型下载下来,vLLM 一跑就完事了
最开始的想法很朴素。
模型下载好了:
/data/models/DeepSeek-V4-Flash
机器也有:
Ascend 910B × 8
每卡 64GB
vLLM-Ascend 也拉好了。
那不就是:
vllm serve /data/models/DeepSeek-V4-Flash
然后起来一个 OpenAI API,完事?
结果第一棒就被打醒了。
日志直接报:
The checkpoint you are trying to load has model type `deepseek_v4`
but Transformers does not recognize this architecture
这句话很关键。它的意思不是“模型坏了”,也不是“显卡不行”,而是:
当前加载链路不认识 deepseek_v4 这个模型结构
也就是说,模型是新模型,但框架生态还没完全跟上。
这个时候很多人会误判:
是不是 transformers 版本低?
是不是 pip install -U transformers 就好了?
是不是模型没下完整?
是不是昇腾不支持?
其实都不是核心。
核心是:昇腾上跑 DeepSeek V4,不能随便拿一个原版权重就上,要用昇腾适配过的版本。
后来我们换成:
DeepSeek-V4-Flash-w8a8-mtp
这才进入了正确路线。
第一个认知:能跑的不是“原版模型”,而是“昇腾适配版模型”
很多人看到 ModelScope 上有:
deepseek-ai/DeepSeek-V4-Flash
就觉得这个肯定能跑。
但在昇腾上,事情不是这么简单。
真正适合我们这台机器的,是:
DeepSeek-V4-Flash-w8a8-mtp
这个名字里有两个关键词:
w8a8
mtp
w8a8 代表它是量化适配版本。mtp 代表它带多 token 预测 / 推理优化相关能力。
更重要的是,它是给 vLLM-Ascend 路线准备的。
我们最后实际跑的是:
/data/models/DeepSeek-V4-Flash-w8a8-mtp
这一步走对以后,模型终于能加载了。
但注意:模型能加载,不等于系统能用。
这是这次部署里最大的感悟。
跑通 API 的那一刻,其实只是刚刚开始
当服务日志里出现:
Application startup complete
那一刻确实挺兴奋。
再一测:
curl http://127.0.0.1:8000/v1/models
有返回。
再测:
curl http://127.0.0.1:8000/v1/chat/completions
也能回复。
这个时候看起来已经成功了。
如果只是做普通对话,这一步确实差不多了。
但我们的目标不是普通聊天。
我们要接的是 OpenClaw,要让它能安装技能、读取文件、调用工具、执行命令。
也就是说,我们要跑的是 Agent 场景。
结果真正的大坑从这里开始。
OpenClaw 一接上,模型开始“说工具话”,但没人听得懂
OpenClaw 一调用,我们看到了类似这样的回复:
<read>
<path>D:~gateway\node_modules\openclaw\skills\skill-vetter-1.0.0\SKILL.md</path>
</read>
还有这种:
<|DSML|tool_calls>
<|DSML|invoke name="exec">
...
</|DSML|invoke>
</|DSML|tool_calls>
第一次看到这个,很容易懵。
因为从模型角度看,它其实不是乱输出。
它是在尝试调用工具。
但问题是:
它输出的是 DSML / XML 风格的工具调用格式,而 OpenClaw 期望的是 OpenAI tool_calls JSON 格式。
所以系统没有把它当工具调用执行,而是把它当普通文本吐出来了。
这就是我们一直说的:
DSML 泄漏
表面现象是模型输出 <read>、<web_fetch>、<tool_calls>。
本质问题是:
模型会调用工具
但推理框架没有把工具调用解析成 OpenAI 标准 tool_calls
这一步特别容易误判。
很多人会说:
模型不行。
OpenClaw 不行。
vLLM 不行。
工具调用不支持。
其实准确说是:
工具调用协议没有对齐
我们试过各种 parser,结果发现默认镜像没有 deepseek_v4
为了解决工具调用,我们开始试 parser。
先试:
--enable-auto-tool-choice
--tool-call-parser deepseek
直接报:
invalid tool call parser: deepseek
日志里列出支持的 parser:
deepseek_v3
deepseek_v31
deepseek_v32
...
没有 deepseek。
那就改成:
--tool-call-parser deepseek_v3
再试:
--tool-call-parser deepseek_v32
这时候服务能起来了。
但问题是,OpenClaw 里仍然可能看到 <read>、<web_fetch> 这种文本泄漏。
后来我们才明白:
deepseek_v32 不是 deepseek_v4
DeepSeek V4 的工具调用标签和 V3.2 不完全一样。
那就试:
--tool-call-parser deepseek_v4
结果又炸了:
invalid tool call parser: deepseek_v4
这时候才真正确认:
当前 vllm-ascend:v0.13.0rc3 默认没有 deepseek_v4 parser。
这不是命令写错,也不是模型路径错。
就是镜像里没有这个功能。
我们也试过升级 vLLM,结果又踩了一个更大的坑
既然 v0.13.0rc3 没有,那是不是升级镜像就好了?
我们试过新版本。
结果发现:昇腾版 vLLM-Ascend 和主线 vLLM 不是完全同步的。
有些主线能力,Ascend 分支并没有及时合入。
更麻烦的是,vLLM 和 vLLM-Ascend 是强绑定的。
我们当时还遇到过一个典型错误:
ImportError: cannot import name 'set_random_seed' from 'vllm.utils.torch_utils'
这个错误的本质就是:
vllm 主库版本
和
vllm-ascend 插件版本
不匹配
这个坑非常致命。
因为它会让你误以为:
可能少装了一个包。
可能 Python 环境坏了。
可能 torch_npu 有问题。
实际上不是。
是你把一套原本匹配好的 Ascend 推理环境拆散了。
所以后面我们总结出来一句话:
昇腾环境不要乱 pip install,不要乱升级 vLLM,不要乱换 Transformers。
尤其是生产环境。
最危险的一步:pip install -e . 差点把环境带沟里
我们拿到 DeepSeek V4 Agentic Support 补丁之后,一开始想当然地执行:
pip install -e .
或者:
pip install -e . --no-deps
看起来很正常,对吧?
Python 项目打完 patch,重新 editable install,一般都是这么干。
结果在 vLLM-Ascend 容器里,这一步非常危险。
因为它会触发 vLLM 的构建流程,进入 CPU backend 编译路径。
日志里出现了:
Target device: cpu
Downloading Arm Compute Library
然后它开始从 GitHub 拉:
ARM-software/ComputeLibrary
最后因为网络问题失败:
Failed to clone repository
这一步我们踩得非常深。
后来才明白:
我们只是改 Python 层的 tokenizer / tool parser / reasoning parser
根本不需要重新编译 vLLM
所以正确做法不是:
pip install -e .
而是:
git apply patch
docker commit
这条经验非常值钱。
因为很多人一看到 patch,第一反应就是重新安装。
但在昇腾容器里,重新安装很可能把原本能跑的环境搞坏。
真正正确的路线:不是编译,而是 patch + commit
最后我们走通的路线其实很清晰。
第一,使用能正常启动的基础镜像:
quay.io/ascend/vllm-ascend:v0.13.0rc3
第二,模型使用:
/data/models/DeepSeek-V4-Flash-w8a8-mtp
第三,先用已有 parser 让容器活着:
--tool-call-parser deepseek_v32
第四,把补丁拷进容器:
docker cp deepseek-v4-agentic-support.patch $CID:/tmp/
第五,在容器里的 vLLM 源码目录打补丁:
cd /vllm-workspace/vllm
git apply --check /tmp/deepseek-v4-agentic-support.patch
git apply /tmp/deepseek-v4-agentic-support.patch
第六,千万不要 pip install。
第七,直接:
docker commit $CID vllm-ascend-deepseek-v4:patched
第八,启动时改成:
--tool-call-parser deepseek_v4
--tokenizer-mode deepseek_v4
--reasoning-parser deepseek_v4
--enable-auto-tool-choice
这才是最终稳定路线。
还有一个很现实的坑:容器和宿主机经常搞混
这次部署里,还有一个特别容易踩的坑:
我到底是在宿主机里?
还是在容器里?
我们多次遇到:
docker: command not found
后来发现,是在容器里执行了 docker 命令。
判断方式很简单:
root@ceshi002:~# 一般是宿主机
root@ceshi002:/workspace# 一般是容器
但有时候容器里的 hostname 也叫 ceshi002,看起来很像宿主机。
所以最稳的方法是:
pwd
ls /
如果看到:
/vllm-workspace
/workspace
大概率就是容器。
如果要打 patch,一定要搞清楚:
patch 文件在宿主机
vLLM 源码在容器里
所以要先:
docker cp ...
再:
docker exec ...
这个看似简单,但实际操作时非常容易乱。
这次最大的感悟:跑通模型不等于跑通 Agent
很多人做大模型部署,会把目标定成:
API 返回 200
但我们这次真正意识到:
API 200 只是第一层成功
真正的 Agent 系统还要看:
tool_choice=auto 能不能工作
tools 能不能被模型理解
模型输出能不能被 parser 解析
parser 能不能转成 OpenAI tool_calls
OpenClaw 能不能接住 tool_calls
工具能不能真正执行
执行结果能不能返回模型
这才是完整链路。
我们中间有一次 API 已经返回 200 了,日志里也有:
POST /v1/chat/completions HTTP/1.1 200 OK
但 OpenClaw 页面上还是输出 <read>。
这就说明:
服务成功了
但 Agent 没成功
这个区别非常关键。
为什么 DeepSeek V4 这个问题会这么绕?
因为 DeepSeek V4 的工具调用不是简单的 JSON。
它更偏向 DSML / XML 风格。
而 OpenAI 生态里,大家更习惯的是:
{
"tool_calls": [
{
"type": "function",
"function": {
"name": "...",
"arguments": "..."
}
}
]
}
所以中间必须有人做翻译。
这个“翻译官”就是:
tool parser
而我们缺的正是:
deepseek_v4 tool parser
没有它,模型输出的是工具调用意图,但系统看不懂。
有了它,模型输出才能被转成标准的 OpenAI tool_calls。
这次部署给我的几个经验
第一,不要迷信“官方支持”这四个字。
官方支持要看清楚:
支持的是哪个镜像?
哪个版本?
哪个分支?
CUDA 还是 Ascend?
主线 vLLM 还是 vLLM-Ascend?
同样叫 vLLM,主线和 Ascend 分支能力可能并不同步。
第二,不要轻易升级依赖。
尤其是这种组合:
torch
torch_npu
vllm
vllm-ascend
transformers
triton-ascend
它们不是普通 Python 包关系,而是一整套推理生态。
你升级一个,可能牵一发动全身。
第三,不要随便 pip install -e .。
在普通 Python 项目里,这没问题。
在 vLLM-Ascend 容器里,这可能直接触发编译,甚至拉外部依赖,最后把环境搞乱。
第四,容器临时修改必须 commit。
你在容器里 patch 了源码,如果不:
docker commit
那一删容器,全没了。
第五,Agent 部署比普通模型部署难一个层级。
普通模型看生成文本。
Agent 看协议、工具、解析器、调用链、返回格式。
如果让我重新部署一次,我会这么做
我不会再从原版模型开始试。
我会直接确认:
是否有 Ascend 适配模型
是否是 w8a8
是否是 mtp
是否有对应 vllm-ascend 镜像
是否有 tool parser 补丁
是否需要 tokenizer-mode
是否需要 reasoning-parser
然后我会直接走:
vllm-ascend:v0.13.0rc3
+
DeepSeek-V4-Flash-w8a8-mtp
+
DeepSeek V4 Agentic Support Patch
+
docker commit
+
deepseek_v4 parser
而不是中间去试:
升级 transformers
升级 vllm
openai parser
pip install -e .
这些路不是完全没意义,但对生产部署来说,成本太高,风险也太大。
最后总结一句
这次部署最大的收获不是“把 DeepSeek V4 跑起来了”。
而是我们真正搞明白了:
模型部署
和
Agent 工具调用部署
完全不是一回事
模型跑起来,只是说明算力和权重链路通了。
工具调用跑通,才说明这个模型真的能进入 Agent 系统。
对于 DeepSeek V4 这种新模型来说,难点不只是参数量,不只是显存,不只是 NPU,而是整个生态链:
模型格式
推理框架
NPU 后端
工具协议
parser
OpenAI API
Agent 客户端
少一个环节,都会出问题。
这次我们从:
Transformers 不识别 deepseek_v4
到:
invalid tool call parser
再到:
DSML 泄漏
再到:
pip install 触发 CPU 编译
再到:
vllm 和 vllm-ascend 版本冲突
最后才走到:
patch + commit + deepseek_v4 parser
这条路踩了很多坑,但也正因为这样,这套经验才有价值。
如果你只是想“看起来跑了”,可能很快。
但如果你想“真的能用”,尤其是接 OpenClaw、接工具、接 Agent,那就必须把这些坑一个一个踩明白。
一句话:
DeepSeek V4 在昇腾上不是不能跑。
真正难的是:让它像一个 Agent 一样可靠地调用工具。
这才是这次部署最值得写出来的地方。
更多推荐




所有评论(0)