一、背景
最近在做一个模型适配任务,需要把 CHIH-HUNG/llama-2-13b-FINETUNE5_4w-r16-gate_up_down 这类 Llama-2 13B 模型,部署到 Iluvatar BI-V150 环境,也就是常说的 天垓150 服务器上运行。
这类工作看起来像"把模型拉下来跑一下"这么简单,但真做起来,会遇到几个典型问题:
- 目标机器不是常见的 NVIDIA CUDA 生态,而是 Iluvatar CoreX 环境
- 服务器外网访问能力受限,直接拉 Hugging Face 模型并不稳定
- 模型能不能"跑起来"和模型输出是否"正常可用",是两件不同的事
- 如果后续还要走平台验证或提交驱动包,那么目录结构、入口脚本、交付形式也要一起考虑
这篇文章就把这次完整的适配过程记录下来,给后面做国产 GPU 适配、平台验证、驱动包提交的同学一个参考。
二、目标环境
本次部署的核心环境如下:
- 服务器:天垓150
- GPU:Iluvatar BI-V150
- 运行方式:CoreX 兼容 Docker 容器
- 模型:
CHIH-HUNG/llama-2-13b-FINETUNE5_4w-r16-gate_up_down - 推理封装:Python + Transformers + 本地 HTTP Service
- 目标结果:
- 模型文件完整落地到服务器
- 容器内
check-only自检通过 - 首轮文本生成成功
- 生成可提交的平台 driver package
三、整体思路
这次采用的是一个比较稳的路径:
- 在本地准备好模型适配代码和 CoreX 运行封装
- 由于服务端无法稳定直连 Hugging Face,因此先在可联网机器下载模型
- 再通过断点续传方式把模型镜像到服务器
- 在服务器上通过已有的 CoreX Docker 镜像执行推理
- 补齐服务入口、README 和 driver package 打包脚本
- 最后生成可直接提交的平台 ZIP 包
这个流程的关键点不在"模型代码有多复杂",而在"链路、环境、交付"三件事是否都闭环。
四、实际踩到的坑
1. ModelScope 侧模型标识并不能直接在服务器上拉通
原本预期是直接用 ModelScope 侧地址下载模型,但实测发现,目标模型标识在服务器上的 SDK 或 git 路径并没有顺利打通。
所以后面实际走通的是:
- 在本地可联网环境下载 Hugging Face mirror
- 再镜像到服务器指定目录
这个经验很重要:
很多时候"平台上有地址"不等于"目标机器上能顺利下载"。
2. 不是 SSH 坏了,而是 VPN / 路由链路有问题
中间有一段时间,服务器 22 端口看起来是通的,但一直拿不到正常的 SSH banner。
后面排查发现,不是服务器炸了,而是本机访问 172.28.* 这段私网地址时,流量没有走正确的 VPN 虚拟网卡。
最终恢复后,系统路由里出现了到目标机器的专用路由,SSH 才恢复成标准的 OpenSSH 握手。
这个问题很典型:
Test-NetConnection显示端口通,不代表 SSH 一定可用- 私网服务器能不能连,往往先看 VPN 虚拟网卡和静态路由是否真的生效
3. 大模型传输一定要考虑断点续传
13B 模型不是一个小文件,权重通常是多分片的。
这次远端传输时,前两个分片基本正常,最后一个大分片中途发生过连接重置。
最后解决方式是:
- 先保留已有的
.part续传文件 - 用支持断点续传的方式继续补最后一个 shard
- 分片齐全后再统一改名完成
这个阶段如果不做断点续传,重传成本会非常高。
五、部署目录与运行封装
为了让这个模型后续能方便复用和提交,我把运行逻辑整理成了一个独立目录,核心职责大概分成三层:
1. Runtime 层
负责:
- 自动识别模型目录
- 加载 tokenizer 和 model
- 处理 dtype、device、trust-remote-code 等参数
- 提供环境检查与生成接口
2. CLI / Docker 启动层
负责:
- 在 CoreX Docker 容器里执行推理
- 支持
--check-only - 支持传入 prompt、temperature、top-p、max-new-tokens 等参数
3. Service 层
负责:
- 暴露 HTTP 接口
- 支持健康检查
- 支持文本生成
- 适配后续平台验证时的服务调用方式
六、最终验证结果
部署完成后,我做了两类验证。
1. 环境自检
在服务器上执行 check-only,结果通过,返回核心信息包括:
status: okdevice: cudaresolved_dtype: bfloat16torch_cuda_available: truetorch_cuda_device_count: 16missing_files: []
这说明至少从"模型目录完整性 + CoreX 容器可见 GPU + 推理框架可初始化"这几个维度看,部署已经打通。
2. 首轮推理
接着发起了首轮文本生成请求,推理执行成功,整体耗时在秒级。
这一步的意义是确认:
- 模型不只是"能加载"
- 而是真的已经进入生成流程并返回文本
不过这里也有一个很值得单独强调的点:
首轮推理成功,不代表模型输出质量已经达标。
这次首轮输出存在明显异常内容,说明当前状态更准确地说是:
- "部署成功"
- 但"模型质量还需要继续做 sanity check"
所以在工程上我会把这一步定义为:
运行链路已经打通,可以继续做质量验证和调优
但还不建议直接把当前输出当成正式 benchmark 结果
七、为什么我仍然认为这次部署是成功的
很多同学做模型部署时,容易把"结果好不好"与"系统有没有跑通"混在一起。
其实这两者应该拆开看:
部署成功,意味着什么?
- 模型文件已经完整进入目标机器
- 运行环境依赖齐全
- GPU 可见且推理框架能正常初始化
- 推理命令能执行
- 服务接口能起
- 平台 driver package 能打包
质量验证,意味着什么?
- tokenizer 是否匹配
- checkpoint 是否正确
- chat template 是否适配
- sampling 参数是否合理
- 输出内容是否符合预期
这次我认为"部署成功"已经完成,"质量验证"是下一阶段工作。
八、交付侧的处理
为了方便后续平台验证和提交,这次还补了一个 driver package 打包流程。
核心目标是:
- 不把模型权重打进包里
- 不把日志、账号、密码这类敏感信息打进去
- 只保留平台运行真正需要的文件
最终打包出来的是一个扁平 ZIP,平台解压后可以直接找到:
entrypoint.shserve_llama2_13b_corex.pyllama2_corex_runtime.pyrun_llama2_13b_corex.pyREADME.mdrequirements-non-torch.txt
这种结构对平台校验最友好,也更适合后续交付。
九、一个更实际的经验总结
这次适配里,我觉得最有价值的经验不是某一条命令,而是下面这几点:
1. 先把"能跑起来"作为第一目标
不要一上来就追求结果质量最优。
先把模型加载、容器运行、GPU 可见、自检通过、首轮生成打通,这样后面所有调优才有基础。
2. 大模型传输必须默认会中断
只要模型超过几个 G,就要默认网络会抖、VPN 会断、SSH 会重置。
提前设计断点续传,比事后重传省很多时间。
3. 私网链路问题经常伪装成 SSH 问题
端口通但协议不通、能连上但读不到 banner,这类情况大概率先去看 VPN 和路由,不要一开始就怀疑服务器本身。
4. "模型能生成"不等于"模型已可用"
部署工程上最容易出现的误判就是这一点。
真正可用,还要继续做 prompt、tokenizer、配置、checkpoint 一致性验证。
十、后续准备怎么做
接下来如果继续往下推进,我会优先做这几件事:
- 跑一组固定中英文 prompt 做输出 sanity check
- 复核 tokenizer 与 checkpoint 的匹配关系
- 检查是否需要补 chat template 或 prompt 包装
- 对比不同 dtype、temperature、top-p 下的输出稳定性
- 如果要上平台 benchmark,再补更严格的验证样本
十一、结语
这次在天垓150上部署 Llama-2-13B 的过程,再次说明了一件事:
大模型适配从来不只是"把代码跑起来",而是模型、环境、网络、交付四件事一起闭环。
如果你也在做国产 GPU、Iluvatar CoreX、平台 driver package 或私网服务器上的模型部署,希望这篇复盘能帮你少踩几个坑。
如果后面我把这套流程继续打磨到"输出质量可控"的阶段,也会再补一篇质量验证和调优的实战记录。