ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

vLLM启动后如何调用API?接口清单、OpenAI兼容用法与排障指南

vLLM启动后如何调用API?接口清单、OpenAI兼容用法与排障指南 很多人第一次部署 vLLM 都会经历这样一个瞬间屏幕上滚过一大段日志最后出现 “Application startup complete”服务确实起来了但你站在终端前突然不知道下一步该干嘛——这个 HTTP 服务到底暴露了哪些接口用 curl 怎么调Python 代码怎么写为什么老是报 model not found这篇文章就围绕 “vLLM 启动后的 API 接口” 做一次系统梳理把接口清单、每个接口的用法、启动参数和接口行为的对应关系、以及我在部署开源模型时踩过的坑一次说清楚。内容以 vLLM 和 API 接口为主线适合刚把 vLLM 跑起来、但对接口层还不熟的开发者。1. vLLM 启动后到底对外开放了哪些入口1.1 本质一个小型 HTTP 推理服务先讲一个很多人忽略的事实vLLM 启动后并不只是一个“命令行工具”它本质上是一个常驻的 HTTP 推理服务。你可以把 vLLM 想象成一家刚开门的饭店启动日志是开门营业的动作而 API 接口就是菜单来消费的“顾客”是各类客户端程序——curl、Python SDK、企业内部系统、以及各种 AI 应用框架。默认情况下vLLM 监听 8000 端口所有端点都挂在/v1/这个路径前缀下。这个设计不是随便定的它是 OpenAI 兼容协议的标准布局。换句话说vLLM 并不是发明了一套“自己专属”的 API而是把 OpenAI 的接口规范搬到本地推理引擎上。所以你在网上找 vLLM 接口文档时很多时候可以直接参考 OpenAI API 文档绝大多数字段都能对上。这一点非常重要因为它决定了你的集成成本如果你的项目已经用过 OpenAI 的接口切换到 vLLM 时只需要改一个 base_url 和一个 api_key 占位符代码几乎不用动。1.2 接口全景清单我根据自己的使用经验把 vLLM 默认提供的主要接口整理成一张表接口路径请求方法作用典型使用场景/v1/chat/completionsPOST多轮对话补全聊天机器人、Agent、客服问答/v1/completionsPOST纯文本续写补全代码补全、文章续写、结构化文本生成/v1/embeddingsPOST文本向量化RAG 检索、语义相似度计算/v1/modelsGET查询当前已加载模型列表客户端动态发现模型名称/healthGET健康检查探针负载均衡、容器编排探活/metricsGETPrometheus 指标导出监控吞吐、显存、延迟/tokenizePOST文本分词调试 Token 计数、估算请求长度顺带提一句部分版本或扩展模块还会提供/v1/score、/v1/rerank之类的专用端点但这些要看具体镜像和启动参数不是所有部署都默认带。普通部署先把上面这张表吃透就够用了。1.3 为什么是 OpenAI 兼容而不是自创协议有人可能会问vLLM 性能做得这么好为什么不顺手定义一套自己的 API 规范我的理解是兼容性本身就是 vLLM 成功的关键因素之一。已有的 OpenAI SDK 可以直接接入Python、Node.js、Java 客户端生态都能复用企业内部从商业 API 迁移到本地 vLLM 时代码改动量小到可以忽略LangChain、Dify、FastGPT 这些上层应用框架都按 OpenAI 协议封装vLLM 天然适配。换句话说vLLM 选择了“站在巨人的肩膀上”。这带来的直接好处是如果你部署的是 DeepSeek 或 Qwen 这类开源权重模型你可以像调用云上大模型一样调用本地服务而且数据不出内网。2. 主力接口 /v1/chat/completions从请求到响应的完整拆解2.1 请求体里每个字段的作用/v1/chat/completions是绝大多数场景下最常用的接口。一个典型的请求体长这样{ model: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B, messages: [ {role: system, content: 你是专业的技术助手回答尽量简洁。}, {role: user, content: 解释一下 vLLM 的 PagedAttention 机制} ], temperature: 0.7, top_p: 0.9, max_tokens: 1024, stream: false }逐个字段拆开看model必须和服务启动时加载的模型名保持一致具体规则后面单独讲messages多轮对话的历史消息数组每个元素包含role和content。role常见是system、user、assistant系统提示词负责设定人设和约束用户消息是实际提问助手消息则用于多轮对话的上下文temperature控制随机性数值越大越发散越小越稳定。做代码生成我会压到 0.2 以下做创意写作可以给到 0.8 以上top_p核采样参数和 temperature 配合使用一般保持默认即可max_tokens限制单次生成的最大输出长度不只是保护服务端显存也是保护你的钱包——虽然本地没有按 token 计费但无限生成会拖垮并发stream是否流式返回。这里建议大家生产环境务必开 true。2.2 curl 调用实录与返回结构先来一条最直接的 curl 命令验证接口curl -s http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B, messages: [{role: user, content: 你好用一句话介绍 vLLM}], max_tokens: 64 }返回的 JSON 结构大致是{ id: chatcmpl-xxx, object: chat.completion, choices: [ { index: 0, message: { role: assistant, content: vLLM 是一个高性能的大模型推理服务引擎。 }, finish_reason: stop } ], usage: { prompt_tokens: 17, completion_tokens: 12, total_tokens: 29 } }新手最容易搞错的地方是真正的内容在choices[0].message.content里外面还包了好几层。另外usage字段非常有用它会告诉你每次请求消耗了多少 token做成本统计和长度排查都靠它。2.3 Python 调用不用自己拼 JSON用 curl 验证完接口实际业务里推荐直接用 OpenAI 官方 SDK代码更简洁from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000/v1, api_keyEMPTY ) resp client.chat.completions.create( modeldeepseek-ai/DeepSeek-R1-Distill-Qwen-7B, messages[ {role: system, content: 你是严谨的算法工程师。}, {role: user, content: 帮我写一段 Python 快排} ], temperature0.3 ) print(resp.choices[0].message.content)这里有个细节必须说明api_key写成EMPTY不是乱填。OpenAI 的 SDK 强制要求这个字段存在而 vLLM 默认不校验鉴权所以随便填一个非空字符串就能过。真正重要的是base_url一定要指向http://localhost:8000/v1这个/v1前缀不能漏。如果你在启动 vLLM 时加了--api-key参数那么这里就要填你设置的实际密钥否则会收到 401 错误。这一点在接入公网或跨部门共享服务时尤其要注意。2.4 流式输出的正确打开方式当生成长文本时建议务必使用流式。非流式请求要等模型把全部 token 生成完才返回一个几百字的长回答可能要等几十秒而流式模式下第一个 token 通常在几百毫秒内就能到达用户看到的是逐字输出的过程体感完全不一样。resp client.chat.completions.create( modeldeepseek-ai/DeepSeek-R1-Distill-Qwen-7B, messages[{role: user, content: 写一篇 500 字的短文}], streamTrue ) for chunk in resp: delta chunk.choices[0].delta if delta and delta.content: print(delta.content, end, flushTrue)vLLM 的流式接口遵循 SSEServer-Sent Events规范每一行数据以data:开头最后以data: [DONE]结束。用 OpenAI SDK 时这些细节都被封装好了但如果你自己在写 HTTP 客户端就需要按 SSE 格式解析。这也是我建议直接用官方 SDK 的原因之一。3. 别只盯着对话接口补全、嵌入、模型查询与健康探针3.1 /v1/completions 的适用场景很多人打开 vLLM 接口文档第一眼只看到/v1/chat/completions。实际上/v1/completions在很多场景下更直接——它不要求messages数组只需要一个prompt字符串模型会沿着这段文本继续生成curl -s http://localhost:8000/v1/completions \ -H Content-Type: application/json \ -d { model: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B, prompt: def fibonacci(n):, max_tokens: 64 }适合它的场景包括代码补全、日志异常后的续写、模板填充、数据增强类的生成任务。不过要注意如果启动时加载的是纯对话模型部分版本默认禁用补全接口反过来如果启动时指定了--task embed那么对话和补全接口都会不可用。所以开工前先确认一下服务支持哪些路由。3.2 /v1/embeddings部署向量模型的专用通道Embedding 模型在 vLLM 里的接口相对独立。最近很多人用官方镜像 vllm/vllm-openai:v0.27.1 加载 Qwen3-Embedding-0.6B 这类向量模型启动命令大致是这样docker run --gpus all -p 8000:8000 \ vllm/vllm-openai:v0.27.1 \ --model Qwen/Qwen3-Embedding-0.6B \ --task embed注意这里多了一个--task embed它会明确告诉 vLLM 当前加载的是嵌入模型而不是对话模型。如果漏了这个参数启动阶段可能能过但调用/v1/embeddings时却可能返回不支持该操作的错误。调用方式如下curl http://localhost:8000/v1/embeddings \ -H Content-Type: application/json \ -d { model: Qwen/Qwen3-Embedding-0.6B, input: [vLLM 接口实践, 本地大模型部署] }返回的data[0].embedding是一个长度固定的浮点数组维度由模型本身决定。做 RAG 时把这些向量存进向量数据库查询时召回相似片段再交给对话模型生成答案整个链路只需要 vLLM 的两个接口就能闭环。3.3 /v1/models 与 /health客户端和运维都依赖的入口调试接口时我最先敲的命令永远是这两条。第一条是查看模型列表curl -s http://localhost:8000/v1/models | jq .返回结果里有data[0].id这个 id 就是服务对外暴露的模型名。请求体里的model字段必须以它为准。很多“model not found”的报错根源就是这里没对上。第二条是健康检查curl -s http://localhost:8000/health如果服务正常会立即返回 JSON 格式的{status: ok}。这条探活路径不经过模型推理所以响应非常快适合挂到负载均衡或容器探针上。你在 Docker Compose 或 K8s 里配置存活探针直接用这条路径最稳。3.4 /metrics看得见的性能状态还有一个容易忽略的接口是/metrics它以 Prometheus 文本格式暴露服务指标包括吞吐、延迟分布、显存占用、当前排队请求数等。生产环境排障时我会先看这里的指标再下结论——比如响应突然变慢先看是不是并发排队数上来了而不是直接怀疑模型出了问题。4. 启动参数如何改变接口行为模型命名、Docker 与 CUDA 版本4.1 served-model-name 是接口和启动参数之间的桥梁这是本次要说的核心细节之一。vLLM 请求体里的model字段并不直接等于“模型在 HuggingFace 上的路径”而是等于启动时的服务名。如果你启动时只写了--model没有加--served-model-name那么请求里的model必须写完整的模型路径比如Qwen/Qwen2.5-7B-Instruct。如果你加了vllm serve Qwen/Qwen2.5-7B-Instruct --served-model-name qwen那么客户端请求里只需要写model: qwen即可。这个功能在实际部署中很有用。比如你把 DeepSeek 蒸馏模型部署成服务希望对外统一叫deepseek-r1而不是暴露一长串 HuggingFace 路径用--served-model-name就能实现。顺便也能避免模型路径意外变更连累到调用方。4.2 Docker 部署时接口地址与端口映射通过 Docker 跑 vLLM 时需要区分容器端口和宿主机端口。下面这条命令是把宿主机 8000 映射到容器 8000docker run --gpus all -p 8000:8000 \ vllm/vllm-openai:v0.27.1 \ --model Qwen/Qwen2.5-7B-Instruct这种情况下容器内和宿主机都是http://localhost:8000。如果改成-p 9999:8000那么宿主机上访问地址就变成http://localhost:9999但容器内部通信时仍用 8000。很多人在服务器上开端口后仍然连不上先检查是不是端口映射或云安全组的入站规则没放行。还有一个常见问题是 Windows 用户想在本地体验 vLLM。vLLM 原生主要支持 LinuxWindows 上一般通过 WSL2 加 Docker Desktop 跑GPU 直通要求 WSL2 后端接口访问方式和 Linux 一致。社区版部署时资源调度会有一些限制但接口层的行为没有区别。4.3 CUDA 版本和驱动对接口可用性的影响搜索里经常看到“cuda128 vllm”这类关键词。实际上 vLLM 对 CUDA 运行库和 GPU 驱动版本比较敏感不同镜像构建依赖的 CUDA 版本不同。如果驱动版本低于镜像要求启动时会报 “CUDA driver version is insufficient” 或类似错误。对于接口层来说这类问题通常表现为服务还没起来端口完全不通或者看似起来了第一次请求推理直接报内部错误。排查顺序建议是先跑nvidia-smi看驱动再看镜像要求的 CUDA 版本最后看启动日志里有没有显存分配失败。我的经验是只要保证驱动版本不低于镜像要求CUDA 容器内依赖基本不用手动装。真正容易出问题的是多 GPU 机器上的显存分配比如两张卡一张被其他进程占满了vLLM 默认用所有可见 GPU就容易 OOM。4.4 并发和显存参数影响接口表现想让接口在生产环境更稳定有几个启动参数值得关注--max-model-len限制模型的最大上下文长度。如果你的业务场景输入不会超过 4K token就不要默认给模型 32K 的上下文省下大量显存--max-num-seqs限制并发请求的序列数防止突发流量把显存打爆--gpu-memory-utilization控制显存占用的上限默认 0.9留一点余量给后续其他进程--api-key可选的接口鉴权参数。接口层看到的很多超时和 OOM往往不是接口本身的问题而是这些启动参数没有按实际场景约束好。5. 接口调不通的典型排障链路5.1 从健康检查到模型列表的黄金三步接口报错时我建议按“从近到远”的顺序排查不要一头扎进代码里先探活curl http://localhost:8000/health。不通就查服务状态、端口监听、防火墙再看模型curl http://localhost:8000/v1/models。确认请求里的model和返回的id完全一致再跑最小请求把max_tokens设成 16messages只放一条user消息排除大上下文和长生成干扰。这三步走完90% 的问题都能定位。5.2 常见报错对照表现象很可能的原因解决方向连接被拒绝服务没启动 / 端口映射错误 / 防火墙拦截检查日志、端口监听、安全组404 路由不存在端点拼错或服务未启用该类型对照接口清单确认路由400 model not found请求里的模型名和 served-model-name 不一致查/v1/models拿到准确 id400 context 超限输入超过max-model-len增大上下文或压缩输入401 无效鉴权客户端 api-key 与启动参数不一致检查--api-key或统一写 EMPTY显存不足并发过高或单请求超长调低并发、缩小上下文、限制 max_tokens首次请求极慢模型还在预热 / 权重未完全加载耐心等待用健康检查确认就绪响应超时非流式长生成开启流式、提高客户端超时5.3 一个真实排障案例Embedding 模型返回 model not found有一次我用 vllm/vllm-openai:v0.27.1 镜像加载 Qwen3-Embedding-0.6B启动很顺利但调用/v1/embeddings时一直报 model not found。我用/v1/models查了模型列表发现返回的id是Qwen/Qwen3-Embedding-0.6B没错请求里也填的这个仍然报错。后来看了完整日志才发现问题出在--task embed没有生效——旧版本镜像里这个参数的位置写错了导致服务其实是用默认任务加载的模型/v1/embeddings虽然存在但模型任务类型对不上于是被判定无效。重新调整参数顺序再启动问题消失。这个案例给我们的教训是接口层面的报错不一定在接口里找原因启动日志和任务类型往往才是真正的源头。6. 从“调通接口”到“接入业务”几个落地姿势6.1 把 vLLM 接口当作 OpenAI 后端的无缝替代vLLM 接口最实用的点在于本地部署的模型可以直接当作云上大模型的平替。你只需要设置两个环境变量export OPENAI_BASE_URLhttp://localhost:8000/v1 export OPENAI_API_KEYEMPTY之后你项目里所有基于 OpenAI SDK 的代码会自动把请求发到本地 vLLM而不再发往云端。这对于不想把业务数据外传、又想用成熟 SDK 生态的团队来说是一个低成本高收益的路径。所谓“免费的大模型 API 接口”本质上就是这么回事——模型权重自己管算力自己出接口开销为零。6.2 vLLM 和 Ollama、LM Studio、SGLang 怎么选搜索热词里经常把 vLLM、Ollama、LM Studio、SGLang 放在一起比较。我的选型原则很简单个人笔记本上快速体验、想图形化操作选 Ollama 或 LM Studio轻量、省心企业级部署、追求高吞吐和并发能力选 vLLM它对显存的管理和调度做得更细需要更激进的性能优化、对特定模型结构有调优需求可以关注 SGLang接口同样兼容 OpenAI 协议。vLLM 的优势在于“生产级”不是“最易用”。所以如果你卡在单机体验阶段先用 Ollama 跑通业务逻辑再迁移到 vLLM 做正式部署这个路径其实很平滑两边核心接口形态是兼容的。6.3 实战参考用 vLLM 两个接口搭一个极简 RAG 闭环下面这段代码演示了如何同时使用 chat 和 embedding 接口完成一次简单的检索问答from openai import OpenAI client OpenAI(base_urlhttp://localhost:8000/v1, api_keyEMPTY) def embed_text(text): resp client.embeddings.create( modelQwen/Qwen3-Embedding-0.6B, inputtext ) return resp.data[0].embedding def ask_question(context, question): resp client.chat.completions.create( modeldeepseek-ai/DeepSeek-R1-Distill-Qwen-7B, messages[ {role: system, content: 请基于提供的资料回答问题。}, {role: user, content: f资料{context}\n问题{question}} ] ) return resp.choices[0].message.content实际生产里嵌入向量会预计算并存入向量库查询时先召回再拼 prompt。vLLM 在这里扮演的角色就是同时承担“检索侧的向量化”和“生成侧的对话补全”两种能力。当你的部署规模变大接口层依然保持单入口这也是它适合做基础设施的原因。最后再分享一个经验本地 vLLM 默认不做鉴权如果你把它绑到了公网 IP 上任何能访问该端口的人都能免费调用你的显卡。我的习惯是内网使用加--api-key对外暴露一定套一层反向代理同时设置请求速率限制。另外每次部署完先用一个 16 token 的最小请求验证链路再进正式压测这能省下大量排障时间。
返回列表