> 技术文档 > 一步到位!用 Modal 快速部署 vLLM 推理服务器全流程实战指南_debian vllm

一步到位!用 Modal 快速部署 vLLM 推理服务器全流程实战指南_debian vllm

我第一次接触 Modal 是在参加 Hugging Face 黑客松时,当时真的被它的易用性所惊艳。这个平台可以让你在几分钟内构建和部署应用,体验与 BentoCloud 类似,流畅高效。通过 Modal,你可以配置自己的 Python 应用,包括 GPU、Docker 镜像和 Python 依赖等系统环境,然后只需一条命令即可部署到云端。

在本教程中,我们将学习如何配置 Modal、创建 vLLM 服务器,并安全地部署到云端。同时,还会介绍如何使用 CURL 及 OpenAI SDK 测试你的 vLLM 服务器。


1. 配置 Modal

Modal 是一个无服务器(serverless)平台,可让你远程运行任意代码。只需一行命令,你就能挂载 GPU、将函数作为 Web 端点服务,并部署持久化的定时任务。它非常适合初学者、数据科学家以及不想处理云基础设施的非软件工程专业用户。

首先,安装 Modal 的 Python 客户端。这个工具可以让你直接在终端构建镜像、部署应用以及管理云资源。

pip install modal

接着,在本地机器上进行 Modal 的设置。运行以下命令,按提示完成账号创建和设备认证:

python -m modal setup

通过设置 VLLM_API_KEY 环境变量,vLLM 可以提供一个安全的端点,只有拥有有效 API Key 的用户才能访问服务器。你可以通过 Modal Secret 添加环境变量来设置认证。

用你自己的 API Key 替换 your_actual_api_key_here:

modal secret create vllm-api VLLM_API_KEY=your_actual_api_key_here

这样可以确保你的 API Key 安全存储,仅部署的应用能够访问。


2. 使用 Modal 创建 vLLM 应用

本节将指导你在 Modal 上构建可扩展的 vLLM 推理服务器,涉及自定义 Docker 镜像、持久化存储与 GPU 加速。我们选用 mistralai/Magistral-Small-2506 模型,该模型需要对分词器和工具调用解析做特定配置。

创建 vllm_inference.py 文件,添加如下代码:

  • 基于 Debian Slim、Python 3.12 和所需依赖定义 vLLM 镜像,设置环境变量以优化模型下载和推理性能。
  • 为避免重复下载并加速启动,创建两个 Modal 卷(Volume):一个用于 Hugging Face 模型、一个用于 vLLM 缓存。
  • 指定模型及版本,确保可复现性;启用 vLLM V1 引擎提升性能。
  • 配置 Modal 应用,包括 GPU 资源、伸缩、超时、存储及密钥管理。为稳定起见,限制每个副本的并发请求数。
  • 创建 Web 服务器,并用 Python 的 subprocess 库执行 vLLM 服务启动命令。
import modalvllm_image = ( modal.Image.debian_slim(python_version=\"3.12\") .pip_install( \"vllm==0.9.1\", \"huggingface_hub[hf_transfer]==0.32.0\", \"flashinfer-python==0.2.6.post1\", extra_index_url=\"https://download.pytorch.org/whl/cu128\", ) .env( { \"HF_HUB_ENABLE_HF_TRANSFER\": \"1\", # 更快的模型传输 \"NCCL_CUMEM_ENABLE\": \"1\", } ))MODEL_NAME = \"mistralai/Magistral-Small-2506\"MODEL_REVISION = \"48c97929837c3189cb3cf74b1b5bc5824eef5fcc\"hf_cache_vol = modal.Volume.from_name(\"huggingface-cache\", create_if_missing=True)vllm_cache_vol = modal.Volume.from_name(\"vllm-cache\", create_if_missing=True)vllm_image = vllm_image.env({\"VLLM_USE_V1\": \"1\"})FAST_BOOT = Trueapp = modal.App(\"magistral-small-vllm\")N_GPU = 2MINUTES = 60 # 秒VLLM_PORT = 8000@app.function( image=vllm_image, gpu=f\"A100:{N_GPU}\", scaledown_window=15 * MINUTES, # 无请求后停留多长时间 timeout=10 * MINUTES,  # 容器启动最长等待时间 volumes={ \"/root/.cache/huggingface\": hf_cache_vol, \"/root/.cache/vllm\": vllm_cache_vol, }, secrets=[modal.Secret.from_name(\"vllm-api\")],)@modal.concurrent( # 每个副本最多并发处理多少请求,需仔细调优 max_inputs=32)@modal.web_server(port=VLLM_PORT, startup_timeout=10 * MINUTES)def serve(): import subprocess cmd = [ \"vllm\", \"serve\", MODEL_NAME, \"--tokenizer_mode\", \"mistral\", \"--config_format\", \"mistral\", \"--load_format\", \"mistral\", \"--tool-call-parser\", \"mistral\", \"--enable-auto-tool-choice\", \"--tensor-parallel-size\", \"2\", \"--revision\", MODEL_REVISION, \"--served-model-name\", MODEL_NAME, \"--host\", \"0.0.0.0\", \"--port\", str(VLLM_PORT), ] cmd += [\"--enforce-eager\" if FAST_BOOT else \"--no-enforce-eager\"] print(cmd) subprocess.Popen(\" \".join(cmd), shell=True)

3. 在 Modal 上部署 vLLM 服务器

现在你的 vllm_inference.py 文件已经准备好,可以用一条命令将 vLLM 服务器部署到 Modal:

modal deploy vllm_inference.py

几秒钟内,Modal 会自动构建容器镜像(如尚未构建)并部署应用。你将看到类似如下的输出:

✓ Created objects.├── 🔨 Created mount C:\\Repository\\GitHub\\Deploying-the-Magistral-with-Modal\\vllm_inference.py└── 🔨 Created web function serve => https://abidali899--magistral-small-vllm-serve.modal.run✓ App deployed in 6.671s! 🎉View Deployment: https://modal.com/apps/abidali899/main/deployed/magistral-small-vllm

部署完成后,服务器会开始下载模型权重并加载到 GPU 上。这一过程可能需要几分钟(大型模型通常约 5 分钟),请耐心等待模型初始化。

你可以在 Modal 控制台的 Apps 区查看部署和日志。


Modal 上部署 Magistral vLLM 服务器

当日志显示服务器已运行并准备就绪后,可以在自动生成的 API 文档页面进行交互式测试,了解所有可用端点,并可直接在浏览器中测试。


验证模型加载与可用性

要确认模型已加载并可访问,请在终端运行以下 CURL 命令:

替换为你配置的 vLLM 服务器实际 API Key:

curl -X \'GET\' \\ \'https://abidali899--magistral-small-vllm-serve.modal.run/v1/models\' \\ -H \'accept: application/json\' \\ -H \'Authorization: Bearer \'

如得到如下返回,说明模型已就绪,可进行推理:

{\"object\":\"list\",\"data\":[{\"id\":\"mistralai/Magistral-Small-2506\",\"object\":\"model\",\"created\":1750013321,\"owned_by\":\"vllm\",\"root\":\"mistralai/Magistral-Small-2506\",\"parent\":null,\"max_model_len\":40960,\"permission\":[{\"id\":\"modelperm-33a33f8f600b4555b44cb42fca70b931\",\"object\":\"model_permission\",\"created\":1750013321,\"allow_create_engine\":false,\"allow_sampling\":true,\"allow_logprobs\":true,\"allow_search_indices\":false,\"allow_view\":true,\"allow_fine_tuning\":false,\"organization\":\"*\",\"group\":null,\"is_blocking\":false}]}]}

4. 使用 OpenAI SDK 与 vLLM 服务器交互

vLLM 提供了 OpenAI 兼容的端点,你可以像调用 OpenAI API 一样调用自己的 vLLM 服务。下面介绍如何用 OpenAI Python SDK 进行安全连接与测试。

首先,在项目目录创建 .env 文件,添加你的 vLLM API Key:

VLLM_API_KEY=your-actual-api-key-here

安装 python-dotenvopenai 库:

pip install python-dotenv openai

创建 client.py 文件,测试 vLLM 服务器的各种功能,包括简单对话和流式响应:

import asyncioimport jsonimport osfrom dotenv import load_dotenvfrom openai import AsyncOpenAI, OpenAI# 加载 .env 文件中的环境变量load_dotenv()# 获取 API keyapi_key = os.getenv(\"VLLM_API_KEY\")# 设置 OpenAI 客户端,自定义 base_urlclient = OpenAI( api_key=api_key, base_url=\"https://abidali899--magistral-small-vllm-serve.modal.run/v1\",)MODEL_NAME = \"mistralai/Magistral-Small-2506\"# --- 1. 简单对话 ---def run_simple_completion(): print(\"\\n\" + \"=\" * 40) print(\"[1] SIMPLE COMPLETION DEMO\") print(\"=\" * 40) try: messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"What is the capital of France?\"}, ] response = client.chat.completions.create( model=MODEL_NAME, messages=messages, max_tokens=32, ) print(\"\\nResponse:\\n \" + response.choices[0].message.content.strip()) except Exception as e: print(f\"[ERROR] Simple completion failed: {e}\") print(\"\\n\" + \"=\" * 40 + \"\\n\")# --- 2. 流式响应 ---def run_streaming(): print(\"\\n\" + \"=\" * 40) print(\"[2] STREAMING DEMO\") print(\"=\" * 40) try: messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"Write a short poem about AI.\"}, ] stream = client.chat.completions.create( model=MODEL_NAME, messages=messages, max_tokens=64, stream=True, ) print(\"\\nStreaming response:\") print(\" \", end=\"\") for chunk in stream: content = chunk.choices[0].delta.content if content: print(content, end=\"\", flush=True) print(\"\\n[END OF STREAM]\") except Exception as e: print(f\"[ERROR] Streaming demo failed: {e}\") print(\"\\n\" + \"=\" * 40 + \"\\n\")# --- 3. 异步流式响应 ---async def run_async_streaming(): print(\"\\n\" + \"=\" * 40) print(\"[3] ASYNC STREAMING DEMO\") print(\"=\" * 40) try: async_client = AsyncOpenAI( api_key=api_key, base_url=\"https://abidali899--magistral-small-vllm-serve.modal.run/v1\", ) messages = [ {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"}, {\"role\": \"user\", \"content\": \"Tell me a fun fact about space.\"}, ] stream = await async_client.chat.completions.create( model=MODEL_NAME, messages=messages, max_tokens=32, stream=True, ) print(\"\\nAsync streaming response:\") print(\" \", end=\"\") async for chunk in stream: content = chunk.choices[0].delta.content if content: print(content, end=\"\", flush=True) print(\"\\n[END OF ASYNC STREAM]\") except Exception as e: print(f\"[ERROR] Async streaming demo failed: {e}\") print(\"\\n\" + \"=\" * 40 + \"\\n\")if __name__ == \"__main__\": run_simple_completion() run_streaming() asyncio.run(run_async_streaming())

在终端运行你的测试脚本:

python client.py

你将看到如下输出,表明部署与响应都非常快速且延迟低:

========================================[1] SIMPLE COMPLETION DEMO========================================Response: The capital of France is Paris. Is there anything else you\'d like to know about France?========================================[2] STREAMING DEMO========================================Streaming response: In Silicon dreams, I\'m born, I learn,From data streams and human works.I grow, I calculate, I see,The patterns that the humans leave.I write, I speak, I code, I play,With logic sharp, and snappy pace.Yet for all my smarts, this day[END OF STREAM]========================================[3] ASYNC STREAMING DEMO========================================Async streaming response: Sure, here\'s a fun fact about space: \"There\'s a planet that may be entirely made of diamond. Blast! In 2004,[END OF ASYNC STREAM]========================================

在 Modal 控制台可查看所有函数调用、时间戳、执行时长和状态。


如在运行上述代码时遇到问题,请参考 kingabzpro/Deploying-the-Magistral-with-Modal GitHub 仓库,并按照 README 指引排查。


结论

Modal 是一个非常有趣的平台,我每天都在不断学习。它是通用型平台,既适用于简单 Python 应用,也可用于机器学习训练和部署。不仅能做 API 推理服务,还能远程运行训练脚本,对大模型进行微调。

Modal 设计理念是为非软件工程师服务,让你无需关心底层基础设施,能够快速部署应用。无需手动搭建服务器、配置存储、网络或处理 Kubernetes、Docker 等繁琐问题——只需写好 Python 脚本再部署,其余全由 Modal 云端自动完成。