简介:面向国产化大模型应用落地场景,这份资源提供基于华为昇腾推理服务器和Atlas300IPro加速卡部署Dify平台的完整可运行源码。压缩包共2个文件,主要包含inscode工程配置与html说明文档,整体仅4KB,却精炼覆盖环境准备、MindIE推理引擎部署、Embedding与Rerank接口验证、Dify v0.8.2安装配置等核心要点。inscode文件便于快速导入运行工程,html页面则直观展示部署过程和运行效果,二者配合可大幅缩短复现路径。已有86人浏览学习,适合正在做昇腾适配、Dify私有化部署或信创AI平台验证的开发者直接参考。借助源码与说明,读者可快速掌握Dify部署全流程中的关键操作与常见排错思路,了解Qwen2.5-7B在双卡环境下的实际运行表现和显存占用情况,从而减少从零摸索带来的试错成本,加速国产化硬件上大模型应用的落地进程。 我接手的那台 Atlas 800 推理服务器,在机房里吃灰了整整两周。驱动、固件、CANN 都装好了,MindIE 也能把 Qwen 跑起来,但业务方一直在问:应用工作台在哪?总不能每次让前端直接对着裸模型接口写代码。于是我把 Dify 平台接到昇腾底座上,整理出一套可以直接跑的完整方案。这篇不写虚的,把可运行源码、核心配置、踩坑记录全部摊开,给同样手里握着 Atlas 机器、想快速落地 LLMOps 的同学一条能直接照抄的路。
先说结论:Dify 本身不需要跑在 NPU 上,昇腾算力通过“模型推理服务”这一层喂给 Dify。看懂这句话,后面所有配置都好理解了。
1. 昇腾环境里跑 Dify,先想清楚算力在哪一层
1.1 Dify 究竟是什么角色
Dify 是开源 LLMOps 平台,聊天助手、Agent、工作流、RAG、数据分析这些能力做得非常顺手,模型接入、提示词管理、知识库、工具调用、日志观测都被集成在一个可视化界面里。
用我自己的话说,Dify 是“模型之上的应用层”,它负责编排和调度,不负责大模型前向推理。这一点非常关键,因为很多人一听“昇腾部署 Dify”,第一反应是给 Dify 容器装 CANN、改 PyTorch 代码,让 Dify 的 Python 服务在 NPU 上跑。方向一开始就错了。Dify 的前端、API、Worker、Sandbox、数据库服务全是常规容器负载,它只需要通过网络去调用一个模型接口,至于这个接口背后是 NVIDIA 显卡还是昇腾 NPU,Dify 根本感知不到。
1.2 昇腾算力的正确位置
真实请求链路是这样的:
| 链路层 | 组件 | 昇腾上的角色 |
|---|---|---|
| 应用编排层 | Dify Web / API / Worker / Sandbox | 普通容器,不碰 NPU |
| 模型接入层 | OpenAI-API-compatible | 桥:把昇腾推理服务伪装成 OpenAI API |
| 推理引擎层 | vLLM-Ascend / MindIE | 在 NPU 上做真正的模型推理 |
| 芯片层 | Atlas 300I Duo / Atlas 800T A2 | 算力来源 |
Dify 的模型供应商机制支持任何 OpenAI 兼容接口。昇腾上的 vLLM-Ascend 或者 MindIE 都对外暴露/v1/chat/completions,对 Dify 来说,这就是一个“换了底座和地址的 OpenAI”。你只需要在 Dify 控制台把 Base URL 指向昇腾推理服务,API Key 填任意占位字符串,模型名称填昇腾上部署的模型名,整条链路就通了。
1.3 正确部署顺序
先起 Dify 本体,包括 PostgreSQL、Redis、API、Worker、Web、Sandbox,再在 Atlas 机器上起模型服务,最后在 Dify 控制台把 Base URL 指过去。
这个顺序有讲究。如果先配模型再接平台,一旦出问题,你根本分不清是 Dify 配置错了,还是推理服务没起来。先把两头各自验证通,再接中间,一次成功的概率会高很多。我自己第一次做的时候就是先在一个裸容器里把 vLLM-Ascend 跑通,curl 验证完模型接口,才开始碰 Dify。
2. 环境准备:驱动、CANN、容器运行时,版本和挂载一步都不能错
2.1 先认清手里是哪一类昇腾硬件
“昇腾系列有哪些 GPU”这个问题被问过太多次。先纠正叫法:昇腾的算力芯片不叫 GPU,叫 NPU。常见型号差别很大,直接影响你能跑什么规模的模型。
| 型号 | 形态 | 显存 | 适合场景 |
|---|---|---|---|
| Atlas 300I Duo | 半高推理卡 | 16GB / 48GB 版本 | 7B~13B 模型推理 |
| Atlas 300V Pro | 视频/视觉推理卡 | 较小 | 视频解码、CV 场景,不适合长文本 LLM |
| Atlas 800 推理服务器(型号 9000) | 整机,插多张 300I Duo | 按卡累计 | 企业级并发推理 |
| Atlas 800T A2 训练服务器 | 训练整机 | 单卡 64GB 级别 | 大模型训练,也适合 14B 以上推理 |
我实测用的是 Atlas 800 推理服务器,两张 300I Duo 48GB。跑 Qwen2.5-7B-Instruct 非常从容,max-model-len 给到 8192 也不紧张,单卡并发处理 20 个左右请求问题不大。
2.2 版本配套宁可多查一遍
昇腾软件栈的版本要求比 NVIDIA 严格得多。驱动、固件、CANN、torch_npu、容器运行时必须在一个配套表里面,否则装出来会非常诡异:有时驱动能看见卡,但 CANN 一申请显存就报错;有时 CANN 版本没问题,但 docke 容器里挂载设备路径不对,又浪费半天。
我用的组合是驱动/固件 23.0.6 + CANN 8.0.RC1。拿到机器先验证:
npu-smi info cat /usr/local/Ascend/ascend-toolkit/latest/version.cfgnpu-smi info能看到卡的状态和显存总量,version.cfg能看到 CANN 版本。新机器开箱后,第一件事就是去昇腾社区官网查“驱动-固件-CANN 配套表”,别嫌麻烦,这一步帮你省下后面至少两天的排查时间。
2.3 容器里必须能看到 NPU,否则后面全白搭
Docker 默认不会把 NPU 设备映射进容器。华为提供了 ascend-docker-runtime,装好之后执行docker info | grep -i runtime,能看到一个叫ascend的 runtime。
如果没有这个 runtime,就必须在docker run时手动带设备和目录:
docker run --rm \ --device=/dev/davinci0 \ --device=/dev/davinci_manager \ --device=/dev/hisi_hdc \ --device=/dev/devmm_svm \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ -v /usr/local/dcmi:/usr/local/dcmi \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ ascend/vllm-ascend:latest \ npu-smi info先跑通这条最小命令,再进下一步。如果容器里看不到davinci0,说明设备挂载或 runtime 有问题,这时候去排查 Dify 没有任何意义。
提示:宿主机上
npu-smi正常不代表容器里正常。容器缺设备映射时,最常见的报错是No such file or directory或Can't open device。
3. 模型服务层:用 vLLM-Ascend 拉起 OpenAI 兼容接口
3.1 为什么选 vLLM-Ascend,而不是 MindIE
MindIE 是华为原生的推理引擎,性能和昇腾硬件贴合度都很高,但配置流程明显更重:权重要转换、版本要严格对应、文档相对分散。vLLM-Ascend 是社区在标准 vLLM 上加的 Ascend 后端,使用习惯和 NVIDIA 生态几乎一致,出了问题也更容易在社区里找到答案。
如果目标是“赶紧把 Dify 跑起来”,vLLM-Ascend 是更顺的路。MindIE 更适合在生产环境做极致性能优化。不过两者对 Dify 来说没有任何区别,都是 OpenAI 兼容 API,后面 Base URL 的端口不一样而已。
3.2 装环境、下模型、起服务
准备一个 Python 3.10 环境:
conda create -n vllm-ascend python=3.10 -y conda activate vllm-ascend pip install vllm==0.8.4 vllm-ascend==0.8.4注意,vllm-ascend 对 CANN 版本有要求,装之前先看它的 release 说明。我这边 CANN 8.0.RC1 配合这两个版本没有问题。
模型用 ModelScope 下载,内网服务器拉取速度快:
pip install modelscope modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /data/models/Qwen2.5-7B-Instruct然后启动推理服务:
export ASCEND_RT_VISIBLE_DEVICES=0 vllm serve /data/models/Qwen2.5-7B-Instruct \ --host 0.0.0.0 \ --port 8000 \ --dtype bfloat16 \ --max-model-len 8192 \ --gpu-memory-utilization 0.9 \ --tensor-parallel-size 1参数解读:
ASCEND_RT_VISIBLE_DEVICES=0:指定进程用哪张卡,作用类似CUDA_VISIBLE_DEVICES。--dtype bfloat16:昇腾对 BF16 支持依赖 CANN 版本,老版本或部分边缘推理卡不支持时就改成float16。--gpu-memory-utilization 0.9:默认就是 0.9。7B 模型 BF16 权重约 14GB,48GB 卡上模型加 KV Cache 完全够。16GB 小卡要往下调,同时缩短--max-model-len。--tensor-parallel-size 1:单卡先跑通,多卡并行要处理 HCCL 通信,排障顺序不要反。
3.3 验证模型服务
curl http://localhost:8000/v1/models curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen2.5-7B-Instruct", "messages": [{"role": "user", "content": "你好"}] }'返回正常的 completion 结果,说明模型服务已经能对外服务了。到这一步,昇腾侧的核心链路就通了,接下来可以安心部署 Dify。
4. Dify 平台部署:裁剪后的最小可运行 compose
4.1 为什么裁剪官方 compose
官方 docker compose 里服务非常多,API、Worker、Web、PostgreSQL、Redis、Sandbox、SSRF 代理、Plugin Daemon、向量库,样样都有。新手直接照搬,容易出现某个服务版本冲突,或者一堆根本用不上的组件占用资源。
我这边裁剪出一套最小闭环:PostgreSQL、Redis、Sandbox、SSRF Proxy、Plugin Daemon、Migration、API、Worker、Web。向量存储先用pgvector,后续要接外部 Qdrant 再改配置。镜像版本以官方当前最新 release 为准,这里用 1.10.1 作为示例。
4.2 可运行 docker-compose
version: "3.9" x-common-env: &common-env DB_HOST: postgres DB_PORT: 5432 DB_USERNAME: dify DB_PASSWORD: dify DB_DATABASE: dify REDIS_HOST: redis REDIS_PORT: 6379 SECRET_KEY: change-me-to-a-long-random-string VECTOR_STORE: pgvector CODE_EXECUTION_ENDPOINT: http://sandbox:8194 CODE_EXECUTION_API_KEY: dify-sandbox SSRF_PROXY_HTTP_URL: http://ssrf_proxy:3128 SSRF_PROXY_HTTPS_URL: http://ssrf_proxy:3128 PLUGIN_DAEMON_URL: http://plugin_daemon:5002 PLUGIN_DAEMON_KEY: change-me-plugin-key PLUGIN_DAEMON_REQUEST_TIMEOUT: 120 services: postgres: image: postgres:15-alpine environment: POSTGRES_USER: dify POSTGRES_PASSWORD: dify POSTGRES_DB: dify volumes: - pg_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U dify"] interval: 5s timeout: 5s retries: 10 restart: always redis: image: redis:7-alpine volumes: - redis_data:/data restart: always sandbox: image: langgenius/dify-sandbox:latest environment: API_KEY: dify-sandbox GIN_MODE: release restart: always ssrf_proxy: image: langgenius/dify-ssrf-proxy:latest restart: always plugin_daemon: image: langgenius/dify-plugin-daemon:0.0.9 environment: DB_PLUGIN_HOST: postgres DB_PLUGIN_PORT: 5432 DB_PLUGIN_USERNAME: dify DB_PLUGIN_PASSWORD: dify DB_PLUGIN_DATABASE: dify REDIS_PLUGIN_HOST: redis REDIS_PLUGIN_PORT: 6379 PLUGIN_DAEMON_KEY: change-me-plugin-key PLUGIN_DAEMON_PORT: 5002 ports: - "5002:5002" restart: always migration: image: langgenius/dify-api:1.10.1 depends_on: postgres: condition: service_healthy redis: condition: service_started environment: *common-env command: ["flask", "db", "upgrade"] restart: "no" api: image: langgenius/dify-api:1.10.1 depends_on: postgres: condition: service_healthy redis: condition: service_started migration: condition: service_completed_successfully environment: <<: *common-env MODE: api ports: - "5001:5001" volumes: - storage:/app/api/storage restart: always worker: image: langgenius/dify-api:1.10.1 depends_on: postgres: condition: service_healthy redis: condition: service_started migration: condition: service_completed_successfully environment: <<: *common-env MODE: worker volumes: - storage:/app/api/storage restart: always web: image: langgenius/dify-web:1.10.1 depends_on: - api ports: - "3000:3000" restart: always volumes: pg_data: redis_data: storage:启动命令很简单:
mkdir -p /opt/dify-ascend cd /opt/dify-ascend vim docker-compose.yml docker compose up -d docker compose ps如果本地 Docker Compose 版本比较老,不支持condition: service_completed_successfully,就先去掉 migration 依赖,手动执行docker compose exec api flask db upgrade,再启动 api 和 worker。
4.3 Dify 和模型服务怎么通信
Compose 里的 Dify 各服务在默认 bridge 网络里。vLLM-Ascend 如果在宿主机上直接跑,Dify 容器访问宿主机局域网 IP 即可;如果模型服务跑在另一台 Atlas 机器上,Dify 容器访问那台机器的局域网 IP 即可。
注意:Base URL 千万别写
localhost。容器里没有宿主机意义上的 localhost,写了必挂。我见过太多人卡在这个问题上。
5. 接入昇腾模型:控制台配置 OpenAI-API-compatible
5.1 添加模型供应商
登录 Dify 控制台,进入“设置 → 模型供应商”,添加OpenAI-API-compatible类型的供应商。要填的字段如下:
| 字段 | 值 |
|---|---|
| Base URL | http://192.168.1.100:8000/v1 |
| API Key | 任意字符串,例如 ascend-local |
| 模型类型 | LLM |
| 模型名称 | Qwen2.5-7B-Instruct |
填写之后点“测试”,连接成功就可以保存。
这个配置的本质就是让 Dify 把昇腾推理服务当成一个 OpenAI 兼容的第三方平台。API Key 填什么不重要,因为 vLLM-Ascend 默认不校验,但它要求这个字段非空,所以给一个占位字符串即可。
5.2 先跑通一个最小聊天应用
创建一个“聊天助手”应用,在提示词编排页面右上角把模型切到刚接入的昇腾模型,发送消息。如果正常返回,这条“昇腾推理 → Dify 编排 → 用户对话”的链路就算通了。
到这里,整个部署已经成功。但实际使用中,你大概率不只是想要一个聊天框,而是想基于昇腾模型的能力,做一个真正能落地的应用。
5.3 升级成数据分析 Agent
很多人搜“dify 搭建数据分析平台”,其实昇腾上的大模型完全能撑起这个场景。做法是:在 Dify 创建一个 Agent 应用,给 Agent 添加一个 SQL 执行工具,把数据库连接信息配好,然后用户用自然语言提问,模型负责把问题转成 SQL、执行查询、总结结果。
这套方案跑在 Atlas 上,模型本地部署、数据不出内网,对数据敏感场景很有价值。部署步骤不会因为加了 Agent 而变化,模型还是那一个,工具调用由 Dify 的 Agent 编排机制接管,昇腾推理服务只负责生成 token,不需要知道自己正在帮用户写 SQL。
6. 实测踩坑:从 NPU 设备映射到对话 400,四个高频问题
6.1 坑一:Dify 容器里访问不到模型服务
表现:模型供应商测试失败,但宿主机上 curl vLLM 接口完全正常。
排查链路:
- 宿主机执行
curl http://localhost:8000/v1/models,返回正常。 docker compose exec api curl http://127.0.0.1:8000/v1/models,连接失败。- 意识到
localhost和127.0.0.1在容器里只代表 Dify 容器自身,不是宿主机。 - 把 Base URL 改成
http://<宿主机局域网IP>:8000/v1,测试通过。
这个坑跟昇腾关系不大,但在异构部署里非常典型。记住一条规则:容器里的localhost永远只代表容器自身。
6.2 坑二:容器里看不到 NPU 卡
表现:vLLM-Ascend 启动时报davinci0不存在,或者容器内执行npu-smi info没有任何输出。
排查链路:
- 宿主机执行
npu-smi info,正常显示卡信息,说明驱动没问题。 - 执行
docker info | grep -i runtime,发现没有 ascend runtime。 - 安装 ascend-docker-runtime,并在启动容器时指定
--runtime ascend。 - 容器内再执行
npu-smi info,一切正常。
教训:不要在容器启动参数上省时间。先跑一个最小验证镜像,确认容器内能看到 NPU,再去跑 vLLM、Dify 这些上层应用,否则问题会被层层包装成各种莫名其妙的报错。
6.3 坑三:vLLM-Ascend 启动时显存不够
表现:启动时报No available memory for the cache,或者模型起来了但对话一长就报超长。
排查链路:
npu-smi info查看单卡 HBM 总量和当前占用。- 估算权重占用:7B BF16 约 14GB,14B BF16 约 28GB。
- 如果 48GB 卡连一个 7B 都跑不起来,检查
ASCEND_RT_VISIBLE_DEVICES是否指向了一张已经被别的进程占用的卡。 - 适当缩小
--max-model-len,比如从 8192 降到 4096,KV Cache 占用会明显降低。
经验是:先保证模型服务自身有余量,再谈并发。7B 模型在 48GB 单卡上开 8K context,留 0.9 的显存利用率,日常测试完全够用;真要上生产,再根据并发峰值做压测。
6.4 坑四:连接成功但对话报 400
表现:模型供应商测试通过,应用内对话却报 400 或者一直转圈。
排查链路:
- 执行
docker compose logs -f api,日志里大概率有上游推理服务返回的 4xx 信息。 - 检查 Dify 里填的“模型名称”和 vLLM 端实际部署的模型名是否一致。
- 检查请求 token 数是否超过 vLLM 的
--max-model-len。 - 在生产环境中,建议给 vLLM 显式指定
--served-model-name Qwen2.5-7B-Instruct,Dify 里填同样的名称,两个服务之间的模型名就永远对齐了。
这四个坑基本覆盖了我第一次打通昇腾 Dify 链路时遇到的主要问题。解决之后,整条链路稳了很多,后面就是按团队加权限、接企业知识库、做更复杂的 Agent 编排这些业务层面的演进,已经不属于部署链路的范畴。
最后分享一个生产小技巧:把 vLLM-Ascend 的启动命令封装成一个 systemd unit,机器重启后自动拉起。Dify 那边只要 Base URL 不变,模型供应商配置就完全不用动。昇腾 Dify 这套组合跑起来之后,团队里不懂部署的人也能通过界面搭 Agent,这才是平台化部署真正的价值。
本文还有配套的精品资源,点击获取