1. 为什么我偏要在ModelArts上跑部署和微调,而不是继续用本地GPU
1.1 本地部署看起来很省钱,真跑起来全是隐形成本
这两周我刚把公司几个大模型的部署和微调任务全部迁到华为云ModelArts上,从在线推理到LoRA微调都完整跑通了一遍。如果你也在纠结“大模型到底放哪跑、微调怎么搞”,这篇文章应该能帮你省掉不少试错时间。
先说我自己为什么会从本地GPU搬到ModelArts。以前团队有两台单卡A6000的机器,大家排队跑实验,环境动不动就被搞坏。后来买了一张A100回来,发现驱动、CUDA、容器网络、用户权限全要自己管,装一次环境就得折腾一两天。最崩溃的一次是凌晨两点要部署一个7B模型做线上验证,发现另一名同事正在用同一张卡跑训练,直接把显存打满了。
这种“本地部署看起来很便宜”的错觉,只有在真正跑起来才会被击碎。本地单卡只适合做小规模实验,一旦涉及多模型并行、多人协作、线上稳定服务、升级回滚,就需要考虑资源池、版本管理、监控告警和自动扩容。ModelArts作为华为云上的一站式AI平台,把这些东西都收敛到了控制台里,我可以把精力放在模型本身,而不是底层K8s和GPU驱动上。
1.2 ModelArts的差异化能力:模型管理、在线服务、训练作业一体
ModelArts最吸引我的地方,不是单纯的“有GPU可以租”,而是它把模型管理、训练任务、在线服务串联成了一条完整链路。
比如模型部署,传统方式是自己买服务器、装Docker、起服务、配负载均衡。在ModelArts上,模型文件放在OBS里,AI应用可以做成一个带版本号的部署单元,然后一键创建在线服务。训练作业也一样,我把训练代码和数据放到OBS,ModelArts自动拉起资源执行任务,日志和输出模型再回到OBS。整个过程非常契合团队协作:数据、模型、代码都沉淀在云上,而不是某个人的笔记本里。
实际用下来的另一个感受是,ModelArts的推理服务支持自动扩容。以前本地部署,流量高了只能人工加卡,流量低了卡还是空转。ModelArts可以设置最小实例数和最大实例数,按GPU利用率或请求指标触发扩容。这一点对线上业务太重要了,尤其是大模型这种成本大头,不能让实例闲着烧钱。
1.3 什么场景建议留在本地/自建
ModelArts不是银弹,有些场景还是留在本地更合理。比如数据完全不能出内网、要求极致低延迟、必须离线运行的业务,用公有云就不太合适。华为云也有专属资源池和私有化方案,但成本和管理复杂度会明显上升。
我的判断标准很简单:如果只是调试代码、跑小规模实验,本地单卡可以;如果要做正式业务,且允许数据上云,ModelArts能省掉大量运维时间;如果数据敏感或网络隔离要求极高,那就老老实实做私有化部署,不要强行上公有云。云上云下各有取舍,关键在于把“模型训练部署”这件事的可维护性放在第一位。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 在ModelArts上完成一次大模型在线部署,要经过哪几步
2.1 把模型搞到OBS里:下载、转换、上传一条龙
模型部署的第一步不是打开ModelArts,而是先把模型文件准备好。目前大部分开源模型都托管在HuggingFace或ModelScope上,比如Qwen2.5、DeepSeek、Llama3.1系列。我一般会用ModelScope的SDK或命令行工具下载,因为国内网络拉HuggingFace速度相对慢,ModelScope更稳。
下载完模型后,最好先检查目录结构是否完整。一个典型的模型目录里应该有config.json、tokenizer.json、tokenization_*.json、多个model-*.safetensors分片文件。有时还会缺generation_config.json,可能导致后续推理时生成长度、采样参数不对,所以下载后建议先跑一段本地推理验证。
确认没问题后,用obsutil把整个模型目录传到OBS桶里:
bash复制obsutil cp ./Qwen2.5-7B-Instruct obs://my-bucket/models/Qwen2.5-7B-Instruct -r -f
-r表示递归上传,-f表示强制覆盖。上传大模型时推荐开并行,命令里可以加-j 16之类的参数,能明显提高速度。模型文件动辄十几GB,网络不稳定容易中断,建议用obsutil的断点续传机制,或在有稳定网络的云服务器上执行上传。
2.2 创建AI应用:镜像、模型路径、健康检查缺一不可
模型上传到OBS之后,接下来在ModelArts控制台找到“AI应用”,点击创建。这里需要重点配置三样东西:模型来源、推理镜像、健康检查。
模型来源选择“从OBS导入”,把刚才的模型路径填进去。如果用的是ModelArts预置的推理镜像,控制台会自动识别模型框架;如果模型比较新或需要自定义依赖,最好用自定义镜像。我自己习惯自己写Dockerfile,基础镜像用PyTorch官方镜像,再加transformers、vllm或fastapi等依赖,最终把推理服务打进镜像。
ModelArts的在线服务会要求容器监听指定端口,常见的是8080。Dockerfile里一定要暴露这个端口:
dockerfile复制FROM pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
WORKDIR /app
COPY . /app
RUN pip install fastapi uvicorn transformers vllm
EXPOSE 8080
CMD ["python", "server.py"]
健康检查接口也很关键。ModelArts会定时请求你的/health,如果返回非200,实例会被判定为不健康并反复重启。我见过同事因为忘了实现这个接口,服务在“启动中-异常-重启”之间循环了一下午。最简单的做法是在server.py里加一个路由:
python复制@app.get("/health")
def health():
return {"status": "ok"}
2.3 配置在线服务:实例数、GPU规格、环境变量
AI应用创建好后,下一步是部署成在线服务。这里要选择资源池和GPU规格。ModelArts的公共资源池里有NVIDIA V100/A100/A800,也有华为自研的Ascend卡;Ascend 910B在搞国产化适配时很常用,但某些模型算子可能没优化好,需要跑一键迁移。如果追求省心,我建议先用N卡跑通,再考虑昇腾。
实例数不建议一上来就配太高。先配1个最小实例,确认推理无异常,再打开自动扩容。环境变量也很必要,比如MODEL_PATH告诉服务加载哪个模型,MAX_MODEL_LEN控制最大上下文长度,TENSOR_PARALLEL_SIZE决定用几张卡做张量并行。7B模型一般单卡就能跑,70B这种大模型通常需要多卡并行,环境变量配置错了会直接启动失败。
部署完成后,ModelArts会给一个在线服务调用地址。第一次调用前,先看看日志确认模型加载完成,别急着发请求。大模型冷启动加载权重可能要3-5分钟,属于正常现象。
2.4 调用在线服务:IAM鉴权与流式输出
模型服务跑起来后,调用方式分两种:一种是直接用ModelArts生成的API地址加上IAM Token;另一种是配置了API Key后走密钥鉴权。
IAM Token获取方式:
bash复制curl -X POST https://iam.myhuaweicloud.com/v3/auth/tokens \
-H "Content-Type: application/json" \
-d '{
"auth": {
"identity": {
"methods": ["password"],
"password": {
"user": { "name": "your_user", "password": "your_password", "domain": { "name": "your_domain" } }
}
}
}
}'
返回的响应头X-Subject-Token就是Token。调用服务时带上Authorization: Bearer $TOKEN即可。如果你用的是OpenAI兼容协议,通常只需要把请求格式稍微调整一下。
流式输出对客服、对话类场景很重要。ModelArts在线服务本身可以透传SSE流,前提是后端推理服务实现了/v1/chat/completions里的stream=true分支。我之前遇到过一个问题:在线服务在网关层有响应超时限制,长对话如果完全等推理完再返回,很容易被掐断;改成流式输出后,Token一个个往外吐,连接不会被误杀。客户端也要处理text/event-stream格式,不能把整段响应当成普通JSON。
3. 动微调之前,先把这三个问题想清楚
3.1 先分清微调、RAG和提示词工程分别解决什么问题
很多人一看到“大模型效果不好”,第一反应就是“微调”。但很多情况下,微调根本不是最优解。我遇到过不少提问:“AI客服用了模型效果差,是不是应该微调?”这背后其实要分清三个层级:
- 提示词工程:不改变模型,只是设计Prompt、System Message、few-shot示例。
- RAG(检索增强生成):把外部知识检索出来拼进上下文,让模型基于文档回答。
- 模型微调:通过训练数据调整模型参数,改变模型的行为模式、输出格式、领域能力。
提示词工程最便宜,适合规则类、风格类的调整;RAG适合“模型不知道”的知识类问题,比如企业内部文档、产品FAQ;微调适合“模型能做到但做不好”的深层行为问题,比如必须按固定JSON结构输出、必须说某种风格的话。
以客服机器人为例,我之前实践下来的顺序是:先用Prompt写清楚角色和回答边界,再接入RAG检索产品手册,如果仍然不满足,比如语气、合规话术太死板,最后才考虑微调。一上来就微调,数据质量不高的话会把模型原有的通用能力带偏。
3.2 基座模型选型:7B还是13B,Qwen还是DeepSeek还是LLaMA
基座模型决定了微调效果的上限。如果业务以中文为主,我优先推荐Qwen系列,比如Qwen2.5-7B-Instruct或Qwen2.5-14B-Instruct,中文理解稳定,指令跟随好。代码生成场景可以考虑DeepSeek系列,它有较强的代码能力,但目前部分版本的协议和商业友好度需要确认。如果团队希望与国际开源生态更紧密,Llama3.1也不错,但需要重点做中文词表扩充和中文语料验证。
关于参数量,7B模型在单卡上运行和微调都比较友好,效果对于客服、文档问答、中等难度信息抽取基本够用。13B-14B模型效果更强,但显存需要更大,成本随之增加。70B级别需要多卡并行,不建议普通小团队直接上,先用小模型验证业务效果,再考虑升级。
还有一类是垂直模型,比如开源的中医大模型、法律大模型。直接拿垂直模型微调可能更快,但需要确认其基座和训练语料是否与你的业务匹配。不要因为看到“开源领域大模型”就盲目使用,先拿自己的测试集跑一遍基座效果,再决定要不要在此基础上微调。
3.3 训练数据怎么组织:Alpaca还是ShareGPT
数据格式对微调效果的影响非常大。最常用的是Alpaca格式和ShareGPT格式。
Alpaca格式适合单轮指令:
json复制{
"instruction": "把下面的句子翻译成英文",
"input": "今天天气真不错。",
"output": "The weather is really nice today."
}
ShareGPT格式适合多轮对话:
json复制[
{"from": "human", "value": "你好,帮我查一下退款流程"},
{"from": "gpt", "value": "好的,请提供您的订单号"}
]
千万不要把原始日志直接丢进去。我见过最典型的错误是:语料里充满了“客服:……用户:……”之类的半结构文本,没有转成标准instruction格式,微调后模型输出乱接。数据清洗的核心是保证instruction指令明确、output是期望的标准答案,宁缺毋滥。几千条高质量数据可能比几万条带噪数据效果好得多。
3.4 LoRA/QLoRA显存估算:7B、13B、70B分别要多大卡
很多人问“LoRA微调需要多少显存”,这个问题不能只看模型参数量。模型加载本身要占显存,还要留出前向计算、反向传播、优化器状态的空间。LoRA的好处是只训练少量低秩矩阵,显存占用比全参数微调低很多,但基座模型的权重和激活值仍然很占空间。
我自己实测下来的经验值大致如下:
| 模型规模 | 微调方式 | 典型显存需求 | 适合的GPU |
|---|---|---|---|
| 7B/8B | LoRA(FP16) | 18-24GB | 单张A100 40G / 4090 24G |
| 7B/8B | QLoRA(4bit) | 10-14GB | 单张3090/4090 |
| 13B/14B | LoRA(FP16) | 36-48GB | 单张A100 80G / 两张24G |
| 13B/14B | QLoRA(4bit) | 18-24GB | 单张A100 40G / 4090 |
| 70B | QLoRA(4bit) | 约50-80GB | 多卡或A100 80G多张 |
这只是一个估算,实际训练时还受max_length、batch_size、gradient_accumulation_steps影响。max_length只要稍微一长,显存曲线立刻上去了。建议先设一个小batch_size跑一个step,用nvidia-smi观察显存占用,再逐步调大,比任何公式都靠谱。
4. 用ModelArts跑LoRA微调:从Notebook到训练作业
4.1 环境准备:创建开发环境实例,克隆LLaMA-Factory
在ModelArts里微调,最简单的方式是创建一个Notebook开发环境。选择GPU规格,比如“NVIDIA A100 80G”,挂载一个OBS桶或EVS盘。启动后,在终端里把训练框架克隆下来:
bash复制git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e .
LLaMA-Factory对新手来说确实友好,支持LoRA、QLoRA、全参数微调,也支持多种模型。如果你的模型在ModelArts环境里下载不方便,可以提前把模型放到OBS,再在Notebook里用obsutil同步下来。
开发环境适合调试代码、处理数据、跑小规模实验。但训练任务可能要跑几个小时甚至更久,Notebook窗口一关训练就断了。所以正式微调我建议走ModelArts的“训练作业”,而不是一直挂在Notebook里。
4.2 数据上传与config.yaml配置
先把清洗好的数据上传到OBS,然后在训练作业里把它当输入路径。LLaMA-Factory的数据集注册方式很明确:在data/dataset_info.json里加一条映射。
比如我的客服数据集叫customer_service.json,内容是多轮对话ShareGPT格式,就在dataset_info.json里加:
json复制"customer_service": {
"file_name": "customer_service.json",
"formatting": "sharegpt",
"columns": {
"messages": "messages"
},
"tags": {
"role_tag": "from",
"content_tag": "value",
"user_tag": "human",
"assistant_tag": "gpt"
}
}
然后写一个训练用的YAML配置:
yaml复制model_name_or_path: /models/Qwen2.5-7B-Instruct
dataset: customer_service
template: qwen
finetuning_type: lora
lora_rank: 8
lora_alpha: 16
lora_target: q_proj,v_proj
output_dir: /output/qwen-lora
per_device_train_batch_size: 2
gradient_accumulation_steps: 8
learning_rate: 2.0e-4
num_train_epochs: 3
max_length: 2048
logging_steps: 10
save_steps: 500
lora_rank默认8,lora_alpha一般为rank的两倍,这是经验值。lora_target选q_proj,v_proj是常见配置,也能加入更多模块。max_length我建议先从2048开始,不要一上来就4096,否则显存很容易爆。
4.3 训练作业配置:规格、日志路径、启动命令
训练作业的好处是任务跑在独立资源池里,不会因为你关闭浏览器而中断。我在ModelArts控制台创建训练作业时,选好镜像和GPU规格,训练输入指向OBS里的数据集路径,训练输出指向OBS里保存checkpoint的路径,启动命令写:
bash复制cd /opt/LLaMA-Factory && llamafactory-cli train config.yaml
注意把模型和数据路径都映射到容器内绝对路径。ModelArts训练作业默认会从OBS下载输入到本地,训练完成后再把输出回传OBS,所以配置里的路径一定要写容器内路径,不能写OBS路径。
日志路径也建议单独指定,这样模型训练过程中有任何报错,都能在ModelArts的日志页面直接看到,不用登录容器。训练结束后,输出目录里会看到adapter_model.safetensors等LoRA权重文件。
4.4 训练参数里最容易翻车的几个地方
我在调参时最容易翻车的地方有三个:学习率、序列长度、batch size。
学习率太大,loss会炸,尤其LoRA微调常用学习率在1e-4到3e-4之间,不要给到1e-3。序列长度太长,显卡直接OOM,表现为日志突然中断,容器被杀。batch size太大也一样,但可以用gradient_accumulation_steps来模拟大batch,而不必堆高显存占用。
训练过程中观察loss不是越低越好,关键看验证集效果。我见过loss降到0.4但回答变得特别机械的情况,因为你可能过拟合到训练集了。建议训练时留一部分验证数据,每个epoch结束做一次生成测试,直接看回答质量。
另外,如果使用QLoRA,加载4bit量化模型时部分模型和bitsandbytes版本有兼容性问题,会报QuantizeModel相关的错误。建议用LLaMA-Factory官方镜像或固定版本组合,减少环境兼容性痛苦。
5. 微调完成后,怎么把模型无缝切到在线服务
5.1 合并LoRA权重并导出
训练完成得到的是LoRA adapter,不是完整模型。如果要把它部署到ModelArts在线服务,最简单的方式是合并权重,导出成完整的模型目录。
LLaMA-Factory提供了导出命令:
bash复制llamafactory-cli export \
--model_name_or_path /models/Qwen2.5-7B-Instruct \
--adapter_name_or_path /output/qwen-lora \
--template qwen \
--finetuning_type lora \
--export_dir /output/qwen2.5-7b-customer-service \
--export_size 4 \
--export_legacy_format false
导出后,先把模型目录跑一个本地推理冒烟测试,确认回答符合微调预期,再上传到OBS,部署新的AI应用版本。
如果你不想合并,也可以选择在推理服务启动时动态加载adapter。但这样做容器镜像和启动脚本复杂度更高,而且每次模型版本切换都依赖外部权重路径,不利于版本管理。我一般推荐合并导出,简单可靠。
5.2 创建新AI应用版本,灰度替换旧服务
在ModelArts的AI应用页面,可以在旧版本基础上创建新版本,模型来源指向刚刚上传的OBS路径。创建好之后,不一定要直接替换线上服务,可以先部署一个独立在线服务做验证,调用几个典型问题,确认回答正常。
ModelArts在线服务支持灰度发布。如果只有一个服务,可以通过调整实例权重,比如旧版本占用90%流量、新版本占用10%流量,观察一段时间。新服务没有严重问题后,再把流量全部切到新版本。这个过程我在实际项目里反复用,能极大降低“微调后某些通用能力下降”带来的线上风险。
5.3 压测与调优:并发、显存、延迟、成本
部署上线后,建议做一轮压测。自写一个并发脚本,模拟真实用户请求,观察几个核心指标:首Token延迟、平均生成速度、GPU显存占用、GPU利用率。
如果并发高了显存放不下,常见手段是调低max_num_seqs或max_model_len,减少同时处理的序列数。vLLM部署时,--max-model-len也会影响显存预分配。ModelArts在线服务实例的内存规格是固定的,模型加载后显存不够一定会报OOM,所以部署前先用之前的显存估算经验判断需要多大的卡。
成本方面,最有效的手段是自动扩容策略。业务低谷时把实例数缩到1,高峰时自动扩容到3-5个。同时ModelArts有按需计费和包周期计费,长期稳定运行的实例建议买包周期,短期实验按需跑。
6. 这一路踩过的坑,按概率排序
6.1 OBS权限不通,微调和部署都白搭
这是我最常遇到的问题。Notebook或训练作业在访问OBS时,如果当前子账号没有对应的OBS权限,会报类似AccessDenied的错误。解决办法是在华为云IAM里给子账号添加OBS OperateOnly权限,或者在ModelArts的委托配置中确认是否设置了“OBS桶与对象读写权限”。权限没配好,模型都拉不下来,后面的操作全卡在第一步。
6.2 健康检查失败导致服务一直重启
之前说过,健康检查接口必须返回200。但有时候接口本身没问题,启动时模型没加载完,健康检查已经开始了,服务在模型加载完成前就被判定异常。解决办法有两个:要么启动命令里等模型加载完成后再启动Uvicorn;要么把健康检查的延迟和失败阈值调大,给模型冷启动留足时间。
6.3 端口监听错误,服务显示“已创建”但调用超时
ModelArts在线服务默认要求容器监听8080端口。如果Dockerfile或启动脚本里监听的是8000或其他端口,服务会显示为运行中,但实际上请求完全不通。这个坑特别隐蔽,因为本地测试时你可能直接docker run -p 8000:8000,一切正常,但一放到ModelArts就超时。启动参数里务必监听0.0.0.0:8080。
6.4 模型加载慢、镜像拉取超时,反复启动失败
大模型文件大,镜像也不小。如果上传模型到OBS时路径层级不对,或者镜像没有提前推送至SWR,ModelArts创建实例时拉取和下载的时间可能超时。我建议把推理镜像提前推送到华为云SWR镜像仓库,部署时直接选SWR里的镜像,离线场景速度更稳定。大模型权重上传到与ModelArts同一个Region的OBS桶,也能明显减少下载延迟。
6.5 微调后通用能力下降
这是个很经典的问题:在业务数据上微调之后,模型回答业务问题变好了,但常识、逻辑、泛化能力下降。通常原因是数据太单一、学习率太高、训练轮次太多。解决办法是控制数据量,2万条以内先跑2-3轮,定期在通用测试集上评估。同时可以在训练数据里掺入一部分通用指令数据,保持模型基础能力。
6.6 成本爆炸,GPU利用率却很低
大模型部署后最大的隐形杀手是“实例空转”。如果只配置了最小实例数而不设置自动休眠,服务会7x24小时占着GPU,就算没有任何请求,费用也照收。我自己的习惯是:测试环境用完立即删除在线服务;生产环境开启缩容策略,设置空闲超过一定时间自动缩到最小实例,或直接用按量付费配合流量调度。
最后分享一个我长期用的习惯:所有模型、数据、训练配置都先在本地小规模跑通,再上ModelArts。云上虽然省心,但每次训练和部署都涉及真实成本,迭代一次烧掉几百块很正常。先把数据质量、参数配置在本地用小模型验证好,再把完整方案迁到ModelArts,既省钱又省心。这样一套流程走下来,从模型部署到微调上线,差不多一天内就能完成一次完整闭环。
