使用 vLLM 部署 Qwen2.5-Coder 代码模型服务
本文介绍如何使用自定义 vLLM 镜像部署 Qwen2.5-Coder-14B 代码模型服务。该方案适合代码生成、代码解释、脚本改写和轻量代码审查。
信息
本文以 Qwen2.5-Coder-14B 为示例。若改用更大模型或量化模型,请根据模型说明调整 GPU 规格、模型路径和 vLLM 参数。
推荐配置
| 配置项 | 建议 |
|---|---|
| 推理类型 | 推理服务 |
| 资源类型 | 包年包月资源或 Spot 资源 |
| GPU 起步配置 | A100、H100、H800、H200;不建议将 RTX 4090 作为 BF16 权重的默认配置 |
| 推理引擎 | vLLM |
| 镜像 | 使用自定义 vLLM 镜像 |
| 模型文件 | /infini-data/Qwen2.5-Coder-14B 或共享高性能存储中的 Qwen2.5-Coder-14B 模型目录 |
| 监听端口 | 8000 |
| 监控端口 | 8000 |
警告
Qwen2.5-Coder-14B 的 BF16 权重和 KV Cache 会占用较多显存。若使用单卡规格启动失败,请先降低 --max-model-len 和 --max-num-seqs,或改用更大显存、更多 GPU 的规格。
准备自定义镜像
如果平台预置镜像中的 vLLM 版本不能满足要求,建议使用镜像中心构建自定义镜像。
打开镜像中心。
参考使用 uv 的 vLLM Dockerfile构建镜像。
构建完成后,在创建推理服务时选择该自定义镜像。
警告
请勿在推理服务启动命令中临时安装 vLLM 或下载大型依赖。应在镜像中固定推理框架版本。
准备模型路径
本文启动命令默认读取:
/infini-data/Qwen2.5-Coder-14B/infini-data/ 是平台公共数据的容器内挂载路径,用于只读访问平台维护的公共模型和数据集。公共数据仅在部分可用区提供;创建推理服务时,还需要在存储配置中勾选挂载公共数据,容器内才会出现该路径。
如果当前可用区没有公共数据,或公共数据中没有目标模型,请将模型放在共享高性能存储中,并在创建推理服务时挂载到容器内路径。例如:
/mnt/models/Qwen2.5-Coder-14B随后在启动命令中把 MODEL_PATH 改为实际路径。
创建推理服务
进入推理服务创建页。
按以下方式填写关键配置:
- 推理类型:选择推理服务。
- 资源类型:选择包年包月资源或 Spot 资源。使用 Spot 资源时,请确认调用方具备超时、重试或降级策略。
- 实例规格:优先选择 A100、H100、H800 或 H200 单卡规格。如果需要更长上下文或更高并发,可选择更大显存或多卡规格。
- 镜像:选择已构建的 vLLM 自定义镜像。
- 存储:挂载公共数据或包含模型文件的共享高性能存储。
- 内网配置:监听端口填写
8000。如需 LLM 场景业务监控,监控端口也填写8000。
启动命令
以下命令会启动 OpenAI 兼容的 vLLM 服务。若模型路径不同,请修改 MODEL_PATH。
#!/bin/bash
set -euo pipefail
export PYTHONUNBUFFERED=1
export MODEL_PATH="${MODEL_PATH:-/infini-data/Qwen2.5-Coder-14B}"
export SERVED_MODEL_NAME="${SERVED_MODEL_NAME:-Qwen2.5-Coder-14B}"
exec vllm serve "${MODEL_PATH}" \
--host 0.0.0.0 \
--port 8000 \
--dtype bfloat16 \
--tensor-parallel-size 1 \
--served-model-name "${SERVED_MODEL_NAME}" \
--max-model-len 16384 \
--gpu-memory-utilization 0.85 \
--max-num-seqs 32 \
--shutdown-timeout 60信息
--shutdown-timeout 需要 vLLM v0.18.0 或更高版本。本文推荐的自定义 vLLM Dockerfile 已使用更新的稳定版本。如果改用较旧预置镜像,请删除该参数或先确认 vLLM 版本。
调用验证
推理服务运行后,按以下顺序验证服务。
Step 1 获取调用地址和认证方式
- 进入推理服务详情页。
- 点击调用,复制推理服务调用地址。
- 如果使用外网访问,请准备 API Key。默认情况下,请求需要使用
Authorization: Bearer <API Key>。 - 如果创建服务时将 Auth Header 配置为
X-Infini-Auth,请把下面示例中的AuthorizationHeader 改为X-Infini-Auth。
将地址和 API Key 写入环境变量:
export BASE_URL="<推理服务调用地址>"
export API_KEY="<API Key>"信息
如果调用地址末尾已经包含 /,下面命令中的路径拼接可能出现双斜线。通常不影响 HTTP 调用,但建议把 BASE_URL 末尾的 / 去掉。
Step 2 检查 OpenAI 兼容接口是否可用
先调用 /v1/models。这一步用于确认地址、认证和服务进程是否可用。
curl -X GET "${BASE_URL}/v1/models" \
-H "Authorization: Bearer ${API_KEY}"如果返回中能看到 Qwen2.5-Coder-14B,说明服务已经暴露 OpenAI 兼容接口。如果返回 401 或 403,请检查 API Key 和 Auth Header。如果连接失败,请确认服务状态、外网访问开关和监听端口。
Step 3 发送代码生成请求
使用较短的 max_tokens 做第一次代码生成验证。
curl -X POST "${BASE_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_KEY}" \
--data '{
"model": "Qwen2.5-Coder-14B",
"messages": [
{
"role": "user",
"content": "请写一个 FastAPI /healthz 接口,返回 JSON:{\"status\":\"ok\"}。"
}
],
"temperature": 0,
"max_tokens": 1024
}'如果返回中包含 choices[0].message.content,说明模型已能正常生成代码。
Step 4 发送代码解释请求
再发送一条代码解释请求,确认模型能发现简单代码问题。
curl -X POST "${BASE_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_KEY}" \
--data '{
"model": "Qwen2.5-Coder-14B",
"messages": [
{
"role": "user",
"content": "下面的 Python 函数有什么问题?\\n\\n```python\\ndef top_item(items):\\n counts = {}\\n for item in items:\\n counts[item] += 1\\n return max(counts, key=counts.get)\\n```"
}
],
"temperature": 0,
"max_tokens": 1024
}'模型应能指出 counts[item] += 1 在 key 不存在时会报错,并建议使用 dict.get、defaultdict 或 Counter。
Step 5 排查常见调用问题
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
401 或 403 | API Key 错误,或 Header 名称与服务配置不一致 | 检查 API Key;确认使用 Authorization 还是 X-Infini-Auth |
| 连接超时或连接失败 | 服务未运行、外网访问未开启、地址复制错误 | 查看服务状态和调用地址;确认监听端口为 8000 |
返回 model not found | 请求中的 model 与 --served-model-name 不一致 | 确认启动命令中的 SERVED_MODEL_NAME,或把请求中的 model 改为实际名称 |
| 服务异常或重启 | 模型路径错误、显存不足、镜像版本不匹配 | 查看实例日志;先降低 --max-model-len 或换更大显存规格 |
常见调整
- 显存不足:先将
--max-model-len调低到8192,或降低--max-num-seqs。 - 需要更长上下文:优先选择 H100、H800、H200 或更多 GPU,再逐步调大
--max-model-len。 - 需要更高吞吐:先完成单实例压测,再调整实例数量、GPU 规格和 vLLM 并发参数。
- 服务停止或升级时请求被切断:确认启动命令使用
exec,并阅读优化推理服务启动命令。