banner
约 4,200 字
14 分钟

DeepSeek V4 昇腾部署与 Claude Code Agent 工作流实践

摘要

本文整理 DeepSeek V4 Flash 在 8 卡昇腾环境中的 vLLM-Ascend 部署、OpenAI 兼容接口验收与压力测试流程,并以 Claude Code 的项目记忆、计划模式和 Hooks 为例,构建可控的 AI Coding 工作流。重点不在固定命令,而在版本锁定、参数约束、验收闭环和代码质量控制。

DeepSeek V4 昇腾部署与 Claude Code Agent 工作流实践

写在前面

这个项目包含两条相互关联但不应混淆的工程链路。第一条是将 DeepSeek-V4-Flash-w8a8-mtp 部署到 8 卡昇腾环境,通过 vLLM-Ascend 暴露 OpenAI 兼容接口,并完成接口、NPU 状态与压力测试验收。第二条是将 Claude Code 放入实际开发流程,用 CLAUDE.md、Plan Mode 和 Hooks 把代码修改纳入可审阅、可验证的工作流。

两条链路的连接点是本地推理服务提供模型能力,编码 Agent 提供任务编排和工具调用能力。但资料没有给出 Claude Code 直连本地服务的完整代理或配置文件,因此本文不把二者的直连写成既成事实,而是把它标记为需要按实际协议完成的接入步骤。

全文按总分结构展开:先说明整体架构和版本边界,再拆解昇腾部署、服务验收和 Claude Code 工作流,最后用 Hooks 自动格式化案例说明如何把模型能力接入可控的软件工程过程。

模块

解决的问题

可验证输出

昇腾部署

在国产算力上运行量化后的 DeepSeek V4 Flash

可启动的 vLLM-Ascend 服务

服务验收

确认模型、接口、设备和并发链路有效

/v1/models、对话接口、npu-smi、基准测试

Claude Code

让 Agent 先理解项目、再执行修改

CLAUDE.md、Plan Mode、工具调用

Hooks

将格式化或检查固化为工具生命周期动作

文件编辑后的自动 Prettier 输出

项目概览

项目

内容

推理模型

DeepSeek-V4-Flash-w8a8-mtp

硬件目标

Atlas 800 A2,64 GB × 8;或 Atlas 800 A3,128 GB × 8

推理框架

vLLM-Ascend,容器化部署

并行方式

Tensor Parallelism,张量并行(TP)= 8;启用 Expert Parallelism,专家并行(EP)

服务接口

OpenAI 兼容的 /v1/models/v1/chat/completions

验收工具

npu-smihccn_toolvllm bench serve

编码工作流

CLAUDE.md 项目记忆、Plan Mode、PostToolUse Hooks

代表性案例

编辑 JavaScript 文件后自动执行 Prettier 格式化

w8a8 表示 Weight 8-bit Activation 8-bit,权重与激活均采用 8 位量化;mtp 表示 Multi-Token Prediction,多 Token 预测,用于推测解码。它们决定了部署的模型形态,不能用原始模型权重或任意推理镜像替换。

一、整体架构:部署、验收与编码工作流

整体系统分为部署验收面和编码控制面。前者负责把模型稳定地变成可调用服务,后者负责把 Agent 的行为约束在项目上下文、计划审阅和质量检查之内。

DeepSeek V4 昇腾部署与 Claude Code 工作流整体架构(图由AI辅助绘制)
DeepSeek V4 昇腾部署与 Claude Code 工作流整体架构(图由AI辅助绘制)

图 1:模型服务与编码 Agent 的两条工作链路。虚线表示需要按实际协议完成的模型接入,不代表资料中已经给出了可直接复用的连接配置(图由AI辅助绘制)。

这张图有两个工程含义。第一,部署成功不等价于编码 Agent 可用,模型服务必须先通过接口和设备验收。第二,模型能回答问题也不等于代码修改可靠,Agent 还需要项目记忆、计划过程和工具后检查共同约束。

二、昇腾部署的前提:先锁定兼容组合

2.1 模型、硬件与镜像必须作为一个组合验证

资料使用 DeepSeek-V4-Flash-w8a8-mtp,目标硬件是单节点 8 卡 Atlas 800 A2 或 A3。当前官方 vLLM-Ascend 文档同样将该量化模型列为这两类 8 卡节点的部署对象,但镜像标签、CANN 版本和个别启动参数会随发行版本调整。[^1]

昇腾部署的模型、镜像与硬件前提
昇腾部署的模型、镜像与硬件前提

图 2:部署前需要同时确认模型形态、镜像版本与硬件规格。来源:项目部署说明。

资料中的示例使用 quay.io/ascend/vllm-ascend:v0.13.0rc3deepseekv4 相关镜像标签。该信息只适用于对应版本线,不能在新环境中直接视为通用版本。当前官方文档已经存在新的稳定版本和新的模型专用镜像示例,部分原先通过环境变量启用的能力也可能迁移到 additional-config。[^1][^2]

因此,部署前应先固定四项信息:模型权重名称、NPU 型号和显存规格、CANN 与驱动版本、vLLM-Ascend 镜像或发布分支。只有这四项匹配后,再讨论服务参数和性能调优。

2.2 宿主机检查的目标是排除分布式硬件问题

容器启动前,必须确认设备可见、链路健康且通信配置一致。下面的检查覆盖了模型服务最依赖的三个层次:NPU 状态、HCCN 网络和设备 IP。

bash
# 1. 查看 8 张 NPU 的健康状态、温度和显存占用
npu-smi info

# 2. 检查每张卡的通信链路与网络健康状态
for i in {0..7}; do
  hccn_tool -i "$i" -link -g
  hccn_tool -i "$i" -net_health -g
done

# 3. 确认 HCCN 配置与每张卡的 IP
cat /etc/hccn.conf
for i in {0..7}; do
  hccn_tool -i "$i" -ip -g
done

这一步的通过条件不是单卡能被识别,而是 8 张卡都处于健康状态,HCCN 链路无异常,且 IP 与集群配置一致。TP=8 和 EP 同时依赖设备间通信;任何一张卡或一条链路异常都可能在模型加载或首个请求时暴露。

2.3 容器负责隔离版本,模型目录负责持久化

容器化部署中,模型目录应挂载到宿主机持久路径,例如 /data/models;NPU 设备节点、驱动库、npu-smi 和 HCCN 工具也需要映射进容器。--net=host 能避免额外网络转发,--shm-size=32g 为多进程加载和共享内存预留空间。

这里的关键原则是不要在已匹配的镜像内部随意 pip install 或升级 vLLM。推理框架、CANN、torch-npu 和模型专用算子之间存在严格的版本关系。若需要升级,应整体切换到官方支持的镜像和版本矩阵,而不是只替换其中一个 Python 包。[^2]

三、启动服务:先解释参数,再写命令

3.1 服务参数对应三类资源约束

启动命令中的参数可以分为并行拓扑、显存与上下文、调度与功能三类。将它们混在一起调节,通常会导致无法定位 OOM、低吞吐或接口能力缺失的原因。

参数组

代表参数

作用

调整代价

并行拓扑

--tensor-parallel-size 8--enable-expert-parallel

决定 8 卡如何分摊权重和专家

对通信链路、设备数量和版本兼容性敏感

显存与上下文

--max-model-len--gpu-memory-utilization--max-num-seqs

决定 KV Cache,Key-Value 缓存的上限

上下文与并发增大都会增加显存压力

调度与缓存

--max-num-batched-tokens--enable-chunked-prefill--enable-prefix-caching

提升混合请求下的吞吐与缓存复用

需要根据真实负载重新压测

模型专用能力

--quantization ascend--speculative-config、工具调用与推理解析参数

启用昇腾量化、MTP 与模型协议适配

参数名和支持范围与版本绑定

资料中的启动命令将最大上下文设为 135168,并发设为 16,显存利用率设为 0.92,TP 设为 8,同时开启 EP、分块预填充、前缀缓存、异步调度和 MTP。下面保留主干参数,模型解析器和编译参数应以当前版本的模型专用文档为准:

bash
vllm serve /data/models/DeepSeek-V4-Flash-w8a8-mtp \
  --served-model-name ds \
  --tensor-parallel-size 8 \
  --enable-expert-parallel \
  --quantization ascend \
  --max-model-len 135168 \
  --max-num-batched-tokens 4096 \
  --max-num-seqs 16 \
  --gpu-memory-utilization 0.92 \
  --block-size 128 \
  --enable-chunked-prefill \
  --enable-prefix-caching \
  --async-scheduling \
  --speculative-config '{"num_speculative_tokens": 1, "method": "mtp"}' \
  --port 8000

该命令表达的是配置关系,不应脱离版本直接复制。资料的启动命令写的是 --max-num-batched-tokens 4096,参数说明表又给出 8192,两者不一致。实际部署应以最终运行配置文件或启动日志为准,并把该值连同并发、输入长度和输出长度记录进压测报告。

3.2 环境变量只解决已知问题,不应成为盲目堆叠项

OMP_NUM_THREADSPYTORCH_NPU_ALLOC_CONFHCCL_BUFFSIZEUSE_MULTI_BLOCK_POOL 等环境变量分别作用于 CPU 辅助线程、NPU 内存分配、集合通信缓冲与内存池。它们不是性能开关的集合,而是在出现具体瓶颈时才有意义。

建议先使用模型专用文档给出的最小环境,再分层增加设置:先保证模型可加载,再确认单请求能返回,随后观察多卡利用率,最后根据压测数据调节批处理和缓存。当前 vLLM-Ascend 功能矩阵将 TP、EP、W8A8 量化、异步输出与推测解码列为可用能力,但组合支持仍需以对应模型页面为准。[^3]

四、服务验收:接口、设备与压测必须同时通过

服务启动日志出现 Application startup complete 仅说明 Web 服务已监听端口,不能证明模型路由、8 卡并行和接口协议全部正确。验收至少应覆盖以下三层。

4.1 第一层:模型与接口可用

bash
# 模型注册检查
curl http://localhost:8000/v1/models

# 最小对话请求
curl http://localhost:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "ds",
    "messages": [{"role": "user", "content": "你好,请用一句话介绍自己"}],
    "max_tokens": 100,
    "temperature": 0.7
  }'

第一个请求检查模型是否以 served-model-name 注册,第二个请求检查 OpenAI 兼容的聊天端点能否完成一次端到端生成。两者缺一不可:只看到模型列表不能证明推理图构建成功,只返回 HTTP 200 也不能证明响应内容来自正确模型。

4.2 第二层:NPU 并行行为可观察

接口调用、NPU 监控与压力测试
接口调用、NPU 监控与压力测试

图 3:服务验收同时包含对话接口、npu-smi 监控和 vllm bench serve 压力测试。来源:项目部署说明。

在请求执行期间运行 npu-smi infowatch -n 2 npu-smi info,观察 8 卡是否被正确使用。这里关注的是设备参与情况、显存曲线和异常状态,而不是仅看某一时刻的利用率峰值。若只有部分设备工作,优先检查 TP、EP、设备映射和 HCCN 配置,而不是先调整批处理参数。

4.3 第三层:压测结果需要带条件解释

资料给出的基准场景使用随机数据集,输入长度 1024 Token,输出长度 128 Token,请求数 100,最大并发 8

bash
vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model /data/models/DeepSeek-V4-Flash-w8a8-mtp \
  --served-model-name ds \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 128 \
  --num-prompts 100 \
  --max-concurrency 8

基准测试至少应记录吞吐量、平均延迟、首 Token 时间和 P99 延迟,并同时记录模型版本、镜像版本、NPU 规格、上下文长度、并发和参数配置。当前材料没有提供上述命令的实际输出,因此本文只把它作为验收方案,不给出吞吐或延迟结论。

五、常见问题的定位顺序

5.1 模型架构无法识别

transformers 报告不认识 deepseek_v4 时,先确认权重路径是否确实指向适配的 DeepSeek-V4-Flash-w8a8-mtp,再检查镜像与模型教程是否来自同一版本线。只有在模型来源可信且官方说明要求时,才使用 --trust-remote-code,因为它允许执行远程仓库提供的模型代码。

5.2 容器中看不到 NPU

先在容器中检查设备数量,再检查设备文件和宿主机驱动映射:

bash
python3 -c "import torch; import torch_npu; print(torch.npu.device_count())"
ls -la /dev/davinci*

预期设备数为 8。若不满足,问题发生在容器设备映射、驱动挂载或运行时权限层,而不是模型参数层。

5.3 显存不足

OOM 的常见触发因素是最大上下文、并发和 KV Cache 同时过大。定位时按以下顺序降低单项:--max-model-len--max-num-seqs--gpu-memory-utilization,每次只修改一个变量并重新记录结果。直接同时缩小所有参数虽然能快速启动,但无法得到可复用的容量边界。

六、Claude Code:把模型能力放进受约束的开发流程

6.1 CLAUDE.md 提供项目级长期记忆

Claude Code 的 /init 可以在项目中建立 CLAUDE.md。它不应重复 README,而应记录 Agent 无法从目录结构稳定推断的信息:模块边界、启动与测试命令、编码规范、禁止修改的区域、关键依赖和验收条件。官方文档将 /init 定义为初始化项目说明的命令;新版交互流程还可引导配置 Skills、Hooks 和个人记忆。[^4]

一个可维护的 CLAUDE.md 至少应覆盖以下内容:

区域

应写入的信息

项目结构

入口、核心模块、接口与数据流

开发命令

安装、运行、测试、格式化和构建命令

修改约束

不可破坏的接口、权限和数据边界

质量要求

测试范围、格式化工具、提交前检查

领域上下文

业务术语、模型限制、已知问题

6.2 Plan Mode 先建立理解,再申请修改

面对陌生项目或重构任务,Plan Mode 允许 Agent 读取文件、运行探索性命令并提交计划,但不会直接修改源文件。当前 Claude Code 文档支持用 Shift+Tab/plan 进入该模式,计划完成后再由用户选择执行方式。[^5]

它适合三类任务:梳理遗留模块调用链、评估跨文件重构影响、生成测试和迁移方案。其价值不在于多一层交互,而是将问题理解、改动方案和实际写入分离,使用户能在代码变更前检查 Agent 的假设。

6.3 本地模型接入需要单独验证协议与能力

本地 vLLM-Ascend 服务提供的是 OpenAI 兼容接口,Claude Code 的模型连接则需要匹配其实际支持的提供方、认证和协议配置。资料提到可用配置切换工具管理 Claude Code 或 Codex 的环境,但没有提供完整的本地端点接入配置。

因此,正确的验证顺序是先完成本地 /v1/chat/completions 调用,再确认客户端或代理能否把请求按协议转发到该端点,最后测试工具调用、长上下文、流式输出和失败重试。只有这四类行为均符合预期,才能把本地模型视为 Claude Code 工作流中的可用后端。

七、Hooks 案例:把代码格式化从习惯变成机制

7.1 场景与目标

案例使用一个未格式化的 test.js 文件。目标不是验证模型生成代码的能力,而是验证 Agent 每次编辑后都能触发确定性的质量动作。这里选择 Prettier,是因为输入和输出直观,且结果可以独立于模型质量验证。

Claude Code 的 Hooks 配置可以放在项目的 .claude/settings.json 中。PostToolUse 在工具执行后触发,matcher 用于筛选触发的工具名称。官方文档也将项目级 .claude/settings.json 定义为可共享的 Hooks 配置位置。[^6]

Claude Code 的 PostToolUse Hooks 配置
Claude Code 的 PostToolUse Hooks 配置

图 4:编辑或写入文件后触发格式化命令的项目级 Hooks 配置。来源:项目 Hooks 示例。

7.2 配置逻辑与更稳妥的写法

示例的核心逻辑是:当 EditWrite 完成时,读取 Hook 输入中的文件路径,再调用 npx prettier --write。当前 Hooks 文档以 JSON 标准输入传递工具参数,下面的写法显式从输入中读取路径,避免把格式化失败静默吞掉:[^6]

JSON
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "file=$(jq -r '.tool_input.file_path'); test -n \"$file\" && npx prettier --write \"$file\""
          }
        ]
      }
    ]
  },
  "permissions": {
    "allow": ["Bash(npx prettier *)"]
  }
}

这段配置的输入是 Claude Code 工具调用的 JSON,输出是被格式化后的目标文件,需要环境中已安装 jq。它适用于确定性、低风险的后处理,例如格式化、静态检查和生成局部文档;不适合在 PostToolUse 中执行数据库迁移、删除文件或提交代码,因为工具已经完成,后置 Hook 无法撤销前面的副作用。

7.3 结果与边界

PostToolUse Hooks 触发后的格式化结果
PostToolUse Hooks 触发后的格式化结果

图 5:Hooks 触发 Prettier 后,test.js 的空格、缩进和分号被统一。来源:项目 Hooks 示例。

结果证明的是自动格式化链路已生效,而不是代码逻辑正确。格式化只能保证风格一致,不能替代类型检查、单元测试、集成测试或人工审阅。更合理的质量链路是:编辑后执行格式化,提交前执行静态检查和测试,对高风险命令在 PreToolUse 中增加显式限制。

八、工程结论与后续改进

这个项目的可复用价值不在某一个模型参数,而在建立了从运行环境到 Agent 行为的双层约束。

部署层面,应将模型、量化方式、昇腾硬件、CANN、镜像和启动参数视为一个版本化集合;服务层面,应把模型注册、对话接口、NPU 使用和带条件的压力测试组合成验收闭环;编码层面,应让 CLAUDE.md 提供上下文、Plan Mode 提供审阅点、Hooks 承担确定性质量动作。

现有材料仍有三项边界。第一,镜像标签和部分参数随版本变化,部署前必须回到对应版本的官方模型页核验。第二,基准测试只有命令和条件,没有实际输出,无法据此比较吞吐或延迟。第三,本地模型与 Claude Code 的连接配置未给出,不能将架构图中的虚线接入视为已完成实现。

后续可以补充三类真实证据:固定版本下的 vllm bench serve 输出和 NPU 监控截图,不同上下文与并发组合的容量边界表,以及本地后端接入 Claude Code 后的工具调用与代码任务对比。这样文章可以从部署方法整理进一步升级为可复现的系统评估记录。

END