尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

基于阿里云函数计算部署Qwen大模型:Serverless推理实战指南

基于阿里云函数计算部署Qwen大模型:Serverless推理实战指南 1. 项目概述为什么选择函数计算部署大模型最近在折腾大语言模型本地部署的朋友估计都绕不开一个核心痛点资源门槛。无论是Qwen2.5-7B还是更大的14B、32B模型动辄十几GB的显存需求直接把大部分个人开发者的显卡挡在了门外。就算用CPU推理那缓慢的速度和巨大的内存占用也基本告别了“快速验证想法”的可能性。云端GPU实例按小时计费成本又让人肉疼。正是在这种背景下“零配置部署”和“Serverless函数计算”的组合成为了一个极具吸引力的新思路。这个项目的核心就是利用阿里云函数计算Function Compute这类Serverless服务来一键部署并运行像Qwen3.5这样的顶级开源大模型。它的魅力在于“零配置”——你不需要关心服务器规格、系统环境、依赖冲突甚至不需要懂Docker。你只需要准备好模型文件和一个符合规范的函数代码剩下的扩容、运维、流量分发全部交给云平台。对于算法工程师、全栈开发者或者只是想快速体验、对外提供API接口的创业者来说这无疑是一条捷径。我最初尝试这个方案是为了给一个内部知识库问答系统快速搭建一个后备的推理服务。自建服务的维护成本太高而直接调用商业化API又存在数据隐私和长期成本的顾虑。函数计算按调用次数和资源使用量计费的模式在流量波谷时期成本可以极低完美匹配了我们的需求。经过几轮实测从代码上传到服务上线最快可以在5分钟内完成真正做到了“开箱即用”。2. 核心思路拆解Serverless如何“扛住”大模型把一个大模型塞进函数计算听起来有点“小马拉大车”的感觉。传统的函数计算场景是处理一个HTTP请求、转换一张图片执行时间短内存消耗小。而大模型推理是计算密集型和内存密集型任务这二者如何结合关键在于对函数计算能力的重新认识以及一些巧妙的设计。2.1 函数计算的“重型”能力与冷启动挑战现在的云函数服务早已不是当年的“轻量级”选手。以阿里云函数计算为例它支持最高32GB内存、16核vCPU的实例规格并且实例的存活时间可以自定义最长24小时。这意味着我们完全可以在一个足够强大的函数实例内部预加载好一个十几GB的模型。当请求到来时直接在这个已加载好模型的“热实例”中进行推理延迟可以做到很低。这里最大的挑战是“冷启动”。当一个请求到来而系统没有现成的、已加载模型的实例时就需要启动一个新实例。这个过程包括拉取函数代码和层Layer、启动容器、安装依赖、下载并加载模型。对于大模型仅下载和加载模型就可能需要数分钟这是用户无法接受的。解决方案的核心思路是“保活”与“镜像加速”预留实例通过配置预留实例让平台始终保持一定数量的、已初始化完成的实例处于待命状态彻底消除冷启动。但这会产生持续的费用适合有稳定基线流量的场景。镜像加速与自定义运行时将模型和所有依赖打包成一个完整的Docker镜像推送到容器镜像服务。函数计算可以直接从镜像启动省去了在实例内部下载和解压模型的时间冷启动速度大幅提升。这是我们本次实践的主要方式。模型分片与延迟加载对于超大规模模型可以考虑在函数初始化时只加载部分核心组件或者利用模型并行技术将不同层分配到多个函数实例上。但这会显著增加架构复杂性对于Qwen3.5-14B这个量级单实例加载仍是性价比最高的方案。2.2 架构设计从单次调用到持续服务我们的目标不是运行一次推理就结束而是提供一个稳定的HTTP API服务。因此函数的设计模式至关重要。我们采用“事件函数”包装“HTTP触发器”的模式函数本身是一个接收HTTP请求事件并返回HTTP响应的处理器。在函数初始化阶段initializer我们执行加载模型、初始化tokenizer等耗时操作。这些初始化代码只会在实例冷启动时执行一次。之后该实例处理的所有请求都复用已加载好的模型对象。一个典型的工作流如下开发者将模型文件如.safetensors或.bin和推理代码打包成Docker镜像。镜像被推送至阿里云容器镜像仓库ACR。在函数计算控制台创建函数选择“自定义容器镜像”作为运行时并指向ACR中的镜像。配置HTTP触发器获得一个公网可访问的URL。当第一个请求触发函数时平台拉取镜像并启动容器执行初始化代码加载模型冷启动。模型加载完毕后处理第一个请求并返回结果。该实例会保留一段时间根据配置期间到来的新请求均被路由至此“热实例”实现低延迟推理。当一段时间无请求后实例被回收。下一个请求将触发新的冷启动。注意模型文件必须放在镜像内或者挂载高速共享存储如NAS。绝对不要在每次函数调用时从对象存储如OSS下载模型那将导致每次调用都是分钟级的延迟完全不可用。3. 实操详解一步步构建Qwen3.5推理函数理论讲完我们进入实战环节。我将以部署Qwen2.5-7B-Instruct模型为例展示从零到一的全过程。选择7B版本是因为它在函数计算提供的资源范围内例如16GB内存运行得比较从容适合演示。3.1 环境准备与模型获取首先你需要在本地准备一个Docker构建环境并安装好Docker引擎。同时确保拥有一个阿里云账号并开通了函数计算FC、容器镜像服务ACR和文件存储NAS可选用于加速镜像构建的服务。第一步获取模型文件。你可以从魔搭社区ModelScope或Hugging Face下载Qwen2.5-7B-Instruct的模型权重。这里以ModelScope为例使用其官方Python库可以非常方便地下载。# 安装 modelscope pip install modelscope # 在Python脚本中下载模型 from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2.5-7B-Instruct, cache_dir./model)执行后模型文件会下载到本地的./model目录。这里包含了模型权重.safetensors、配置文件config.json和分词器文件等。第二步编写推理函数代码。创建一个项目目录例如qwen-fc。在目录内创建以下文件app.py- 主函数入口import json import logging from transformers import AutoModelForCausalLM, AutoTokenizer import torch # 初始化全局变量将在initializer中赋值 model None tokenizer None def initializer(context): 函数实例初始化钩子。冷启动时执行一次。 global model, tokenizer logger logging.getLogger() logger.info(开始加载模型...) model_dir /mnt/auto/model # 模型在镜像中的挂载路径 # 加载tokenizer tokenizer AutoTokenizer.from_pretrained( model_dir, trust_remote_codeTrue ) # 设置padding token如果tokenizer没有的话 if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token # 加载模型根据内存情况选择精度 # 方案A全精度加载需要约14GB GPU显存或等量CPU内存 # model AutoModelForCausalLM.from_pretrained( # model_dir, # torch_dtypetorch.float16 if torch.cuda.is_available() else torch.float32, # device_mapauto, # trust_remote_codeTrue # ) # 方案B使用int8量化大幅减少内存占用约8GB model AutoModelForCausalLM.from_pretrained( model_dir, load_in_8bitTrue, # 启用8bit量化 device_mapauto, trust_remote_codeTrue ) # 方案C使用4bit量化内存占用更小约4-5GB但可能损失更多精度 # from transformers import BitsAndBytesConfig # quantization_config BitsAndBytesConfig(load_in_4bitTrue) # model AutoModelForCausalLM.from_pretrained( # model_dir, # quantization_configquantization_config, # device_mapauto, # trust_remote_codeTrue # ) model.eval() # 切换到评估模式 logger.info(模型加载完毕) def handler(environ, start_response): 函数请求处理器。 global model, tokenizer # 1. 解析请求 try: request_body_size int(environ.get(CONTENT_LENGTH, 0)) except (ValueError): request_body_size 0 request_body environ[wsgi.input].read(request_body_size) if not request_body: response json.dumps({error: 请求体为空}) status 400 Bad Request else: try: data json.loads(request_body.decode(utf-8)) prompt data.get(prompt, ) max_new_tokens data.get(max_new_tokens, 512) temperature data.get(temperature, 0.7) except json.JSONDecodeError: response json.dumps({error: 无效的JSON格式}) status 400 Bad Request else: # 2. 执行推理 with torch.no_grad(): inputs tokenizer(prompt, return_tensorspt, paddingTrue).to(model.device) generated_ids model.generate( **inputs, max_new_tokensmax_new_tokens, temperaturetemperature, do_sampleTrue, pad_token_idtokenizer.pad_token_id, eos_token_idtokenizer.eos_token_id ) output tokenizer.decode(generated_ids[0], skip_special_tokensTrue) # 只返回新生成的部分 response_text output[len(prompt):].strip() response json.dumps({response: response_text}) status 200 OK # 3. 构造HTTP响应 response_headers [(Content-type, application/json; charsetutf-8)] start_response(status, response_headers) return [response.encode(utf-8)] # WSGI Server适配函数计算HTTP触发器通过WSGI协议调用 def main(environ, start_response): return handler(environ, start_response)requirements.txt- Python依赖transformers4.40.0 torch2.3.0 modelscope1.19.0 accelerate0.30.0 bitsandbytes0.43.0 # 如果需要4/8bit量化 sentencepiece # Qwen分词器可能需要的依赖Dockerfile- 容器镜像构建文件# 使用带有CUDA的PyTorch基础镜像如果使用CPU推理可换为cpu版本 FROM pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime # 设置工作目录 WORKDIR /app # 复制依赖列表和代码 COPY requirements.txt . COPY app.py . # 安装Python依赖使用国内镜像加速 RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ # 创建一个目录用于挂载模型模型将通过NAS或直接打包进镜像的方式提供 RUN mkdir -p /mnt/auto/model # 声明函数计算的初始化入口和HTTP服务入口 # 函数计算会寻找这两个特定的环境变量 ENV FC_SERVER_PORT9000 ENV FC_SERVER_PATH/app/app.py # 暴露端口函数计算会覆盖此设置但保留以示规范 EXPOSE 9000 # 启动命令使用内置的fc-daemon适配器 CMD [python3, /app/app.py]3.2 镜像构建、推送与函数部署现在我们有了模型文件、代码和Dockerfile。接下来需要将它们整合并部署。方案一模型打包进镜像适合模型较小或变更不频繁将下载好的./model整个目录复制到qwen-fc项目目录中。修改Dockerfile增加复制模型的指令# ... 前面的内容不变 ... COPY ./model /mnt/auto/model # ... 后面的内容不变 ...构建并推送镜像# 登录阿里云容器镜像服务ACR docker login --username你的用户名 registry.cn-hangzhou.aliyuncs.com # 构建镜像注意最后的点号 docker build -t registry.cn-hangzhou.aliyuncs.com/你的命名空间/qwen-inference:1.0 . # 推送镜像 docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/qwen-inference:1.0方案二模型挂载NAS适合模型巨大或需要频繁更新在阿里云上创建一个文件存储NAS并创建一个文件系统。将模型文件上传到NAS的某个挂载点例如/share/model。在函数计算创建函数时配置NAS挂载。将NAS的/share/model目录挂载到容器的/mnt/auto/model。Dockerfile中无需复制模型直接构建不包含模型的基础镜像即可。这样可以实现模型与代码的解耦更新模型时无需重新构建和推送镜像。在函数计算控制台部署进入函数计算控制台创建服务例如qwen-service。在服务下创建函数选择“使用自定义运行时创建”。在“函数代码”配置中选择“镜像”方式并填入你推送的镜像地址。在“环境配置”中设置合适的实例规格。对于Qwen2.5-7B-Instruct的int8量化版建议至少选择8GB内存的实例。如果使用全精度或更大的模型需要16GB或32GB。设置“实例并发度”为1。对于大模型推理每个实例同一时间最好只处理一个请求避免内存溢出。设置“初始化超时时间”为一个较大的值例如600秒给模型加载留足时间。配置HTTP触发器设置好鉴权方式如“匿名访问”用于测试。如果使用NAS方案在此处添加NAS挂载配置。创建函数。等待片刻即可在触发器详情中获得一个公网访问的URL。4. 性能调优与成本控制实战部署成功只是第一步要让服务稳定、高效且经济还需要进行细致的调优。4.1 冷启动优化与实例管理冷启动是Serverless大模型服务的头号敌人。除了使用自定义镜像还有以下实战技巧设置预留实例Provisioned Instances这是解决冷启动最彻底的方法。在函数配置中可以设置预留实例数为1或更多。平台会预先初始化好指定数量的实例并保持活跃请求会直接路由到这些“热”实例上实现零冷启动延迟。代价是这些实例会持续产生计费即使没有请求。适合对延迟极度敏感、且有稳定基线流量的生产环境。定时触发器预热一个成本更低的方案是配置一个定时触发器Cron例如每5分钟触发一次函数。这个触发执行一个空的或轻量的请求目的是让至少一个实例保持“热”状态。你需要修改handler函数使其能识别这种“预热请求”并快速返回而不执行完整的模型推理。def handler(environ, start_response): # 检查是否为预热请求例如通过特定的header或path if environ.get(HTTP_X_FC_WARMUP, ) true: status 200 OK response json.dumps({status: warmed up}) response_headers [(Content-type, application/json)] start_response(status, response_headers) return [response.encode(utf-8)] # ... 正常的推理逻辑 ...然后在阿里云定时触发器配置中为请求添加一个自定义Header如X-FC-Warmup: true。优化镜像体积镜像越小拉取越快。使用Alpine等轻量级基础镜像清理pip缓存使用多阶段构建都能有效缩减镜像体积从而缩短冷启动的“镜像拉取”阶段。4.2 推理性能与资源规格选择函数计算的计费与配置的内存大小强相关。选择合适的内存规格是一门平衡艺术。内存与vCPU的关联在函数计算中内存和vCPU是成比例分配的。例如选择4096MB内存通常会获得相应的计算能力。对于大模型推理内存是首要瓶颈必须确保足够加载模型。量化技术的威力如前文代码所示使用bitsandbytes库进行8bit或4bit量化能将模型内存占用降低50%甚至75%。对于Qwen2.5-7B全精度fp16约需14GBint8约需8GBint4仅需约4-5GB。量化会带来轻微的质量损失但对于很多应用场景是可接受的。强烈建议从int8量化开始尝试它在精度和资源消耗间取得了很好的平衡。实测选型不要凭感觉猜测。部署后使用压力测试工具如wrk或locust模拟并发请求观察函数的执行时长和内存使用率可在函数计算控制台监控查看。目标是让内存使用率在峰值时达到规格的70%-80%既不留太多浪费也不至于因偶尔的波动导致OOM内存溢出错误。4.3 成本估算与监控Serverless的成本模型是“按量付费”主要包括调用次数费每百万次请求几元钱通常很低。资源使用量费核心成本。计算公式为(配置内存) * (执行时长)。执行时长从收到请求到函数返回为止单位为GB-秒。实例空闲费容易被忽略的成本。函数实例在执行完毕后不会立即销毁会有一个“空闲保留期”通常几分钟。在这期间即使没有处理请求也会按配置内存收取少量费用。这也是为什么要避免频繁冷启动的另一个原因——短时间内的多次冷启动会产生多个实例的空闲费。成本控制策略设置最大实例数防止因异常流量导致的无限扩容而产生天价账单。根据业务最大预期并发设置一个安全上限。合理设置超时时间根据模型推理的典型耗时例如生成512个token大约需要10-30秒设置一个略大于此值的函数超时时间如60秒。避免因个别超长请求占用实例过久。使用性能监控密切关注函数的平均执行时长和内存使用率。如果发现执行时长异常增加可能是模型响应变慢或代码有问题需要优化。如果内存使用率长期低于50%可以考虑降低内存规格以节省成本。5. 常见问题排查与进阶技巧在实际操作中你几乎一定会遇到下面这些问题。这里是我踩过坑后的经验总结。5.1 部署与运行问题速查表问题现象可能原因排查步骤与解决方案函数创建失败报错“镜像拉取失败”1. 镜像地址错误或私有镜像未授权。2. 镜像体积过大拉取超时。1. 检查镜像地址拼写确保函数计算服务所在地域与ACR地域一致并为服务授予ACR拉取权限。2. 优化Dockerfile减小镜像体积。在ACR控制台检查镜像层大小。函数调用超时日志显示在initializer阶段卡住1. 模型加载时间超过初始化超时时间默认30秒。2. 从网络位置如OSS下载模型速度过慢。1. 将函数“初始化超时时间”延长至300-600秒。2.确保模型已在镜像内或挂载的NAS中避免运行时下载。函数执行失败报错“CUDA out of memory”1. 配置的内存/显存不足。2. 实例并发度1多个请求共享同一实例导致内存累积。1. 升级函数实例规格增加内存。启用模型量化int8/int4。2.将“实例并发度”设置为1确保每个实例同一时刻只处理一个推理请求。请求响应慢日志显示每次调用都执行initializer冷启动频繁。实例在空闲期后被回收。1. 实施“定时触发器预热”方案。2. 对于生产环境考虑配置“预留实例”。3. 检查是否流量过于稀疏可适当增加函数的“最小实例数”如果平台支持为0但配合预热。HTTP请求返回413错误或畸形响应1. 请求体或响应体超过函数计算默认限制通常请求体6MB响应体6MB。2. WSGI响应格式不正确。1. 在函数计算服务配置中调整“请求体大小”和“响应体大小”限制。2. 确保handler函数返回的响应格式符合WSGI规范即[response_body.encode(utf-8)]。中文输出乱码或生成质量差1. Tokenizer加载不正确未设置trust_remote_codeTrue。2. 生成参数如temperature设置不合理。1. 确认加载tokenizer时传入了trust_remote_codeTrue。2. 调整temperature控制随机性、top_p核采样等参数。对于严肃问答可降低temperature至0.1。5.2 进阶技巧打造生产级API服务基础的推理函数跑通后你可以考虑以下增强措施让它更接近一个真正的生产服务添加API网关虽然函数计算自带HTTP触发器但功能较简单。在前端套一层API网关可以轻松实现认证鉴权如API Key、流量控制、访问日志、自定义域名等高级功能。将API网关的端点指向你的函数计算HTTP触发器URL即可。实现流式输出Streaming对于生成长文本的场景让用户等待几十秒再看到全部结果体验很差。可以利用Server-Sent Events (SSE) 实现token-by-token的流式返回。这需要修改函数代码使其支持分块输出。注意函数计算的响应超时限制需要相应延长。集成向量数据库实现RAG单纯的模型对话能力有限。你可以在同一个函数内或通过另一个函数集成Chroma、Milvus等向量数据库。在初始化阶段加载向量索引在handler中先进行向量检索再将检索到的上下文与用户问题一起送给模型生成即可构建一个强大的私有知识库问答系统。建立CI/CD流水线将模型、代码、Dockerfile纳入Git管理。利用云效或GitHub Actions等工具设置自动化流水线。当代码更新时自动构建新的Docker镜像推送到ACR并更新函数计算中的函数版本或别名实现自动化部署。多模型管理与路由一个服务想支持多个模型可以在函数内根据请求参数动态加载不同的模型但要注意内存限制。更优雅的方案是使用函数计算的别名和灰度发布功能。为Qwen2.5-7B和Qwen2.5-14B分别部署一个函数版本然后通过一个路由函数或API网关根据策略将请求分发到不同版本实现灵活的模型管理和A/B测试。将Qwen3.5这样的大家伙塞进函数计算并不是什么黑魔法本质上是云原生技术和模型优化技术结合的一次巧妙实践。它最大的价值在于极致地简化了运维让我们这些关心算法和应用的人能把精力从繁琐的环境配置、服务监控中解放出来。当然它并非银弹冷启动、成本精细控制和超大规模模型的部署仍然是需要持续权衡和优化的课题。但对于中小规模的模型应用、快速原型验证、或间歇性使用的服务场景这无疑是一条值得深入探索的捷径。我自己的几个内部工具和演示项目已经稳定运行了数月节省的运维精力远超预期。如果你也在为模型部署的资源问题头疼不妨就从这里开始亲手试一次。
返回列表