4、在线服务基础:vLLM OpenAI兼容API介绍、启动API服务器(vllm serve命令)、使用curl调用API、理解/v1/completions端点

好,咱们进入在线服务部分。离线批处理搞定了,接下来就是让模型真正跑起来,对外提供API服务。这一章我会带你亲手启动一个vLLM API服务器,然后用curl去调它。说白了,就是让你亲眼看到模型是怎么通过HTTP接口响应请求的。

4.1 为什么需要OpenAI兼容API?

你可能要问:为什么非得兼容OpenAI的API格式?我直接自己写个Flask服务不行吗?

当然可以。但你想过没有,现在市面上几乎所有LLM工具链——LangChain、LlamaIndex、AutoGPT——它们默认调用的都是OpenAI的API格式。如果你自己搞一套,就得让用户改代码、改SDK。我见过太多团队因为API不兼容,集成时踩了一堆坑。

vLLM直接实现了OpenAI的API规范,这意味着:

  • 你现有的OpenAI客户端代码,换个base_url就能用
  • 生态工具开箱即用,不用额外适配
  • 团队迁移成本极低

核心要点:vLLM的API服务器实现了 /v1/completions/v1/chat/completions/v1/embeddings 等端点。本章我们重点讲 /v1/completions,这是最基础的文本补全接口。

4.2 启动API服务器:vllm serve命令

启动服务器其实就一行命令。我个人习惯先指定模型路径和端口,其他参数按需加。

vllm serve /data/models/Qwen2.5-7B-Instruct \
  --port 8000 \
  --host 0.0.0.0 \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.9 \
  --dtype auto

解释一下关键参数:

参数 说明 我的建议
--port 监听端口,默认8000 生产环境别用默认,容易冲突
--host 绑定地址,0.0.0.0表示所有网卡 本地测试用127.0.0.1更安全
--max-model-len 最大输入+输出长度 根据显存调整,别设太大
--gpu-memory-utilization GPU显存利用率 0.85-0.95之间,留点余量
--dtype 模型精度,auto自动选择 显存紧张可以指定float16

小技巧:启动时加上 --enforce-eager 可以禁用CUDA图优化,虽然推理慢一点,但显存占用更低。调试阶段我经常这么干。

启动成功后,你会看到类似这样的日志:

INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000

嗯,看到这个就说明服务器跑起来了。这时候你可以打开浏览器访问 http://localhost:8000/docs,vLLM会自动生成Swagger文档,方便你测试接口。

4.3 使用curl调用API

服务器启动后,咱们用curl发个请求试试。这是最直接的方式,不用写任何代码。

curl http://localhost:8000/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "/data/models/Qwen2.5-7B-Instruct",
    "prompt": "请用一句话解释什么是大语言模型",
    "max_tokens": 100,
    "temperature": 0.7
  }'

返回结果大概长这样:

{
  "id": "cmpl-abc123",
  "object": "text_completion",
  "created": 1700000000,
  "model": "/data/models/Qwen2.5-7B-Instruct",
  "choices": [
    {
      "text": "大语言模型是一种基于深度学习的人工智能模型,通过海量文本数据训练,能够理解和生成自然语言。",
      "index": 0,
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 28,
    "total_tokens": 40
  }
}

注意model字段必须和启动时指定的模型路径完全一致。我曾经因为路径末尾多了一个斜杠,折腾了半小时才找到原因。

4.4 理解/v1/completions端点

这个端点是最基础的文本补全接口。它的核心逻辑就是:你给一段文本,模型接着往下写。

咱们拆解一下请求参数:

  • prompt:输入文本,模型会基于它继续生成
  • max_tokens:最多生成多少个token
  • temperature:控制随机性,0-2之间。0基本确定,1比较随机
  • top_p:核采样,只从概率最高的top_p部分采样
  • stop:遇到这些字符串就停止生成
  • stream:是否流式返回,设为true可以实时看到生成过程

响应里的关键字段:

  • choices[0].text:模型生成的文本
  • choices[0].finish_reason:停止原因,stop表示正常结束,length表示达到max_tokens
  • usage:token用量统计,方便计费或监控

避坑指南:我曾经在生产环境遇到一个问题——用户请求的prompt特别长,超过了模型的上下文窗口。结果模型直接报错。后来我加了个前置检查,如果prompt token数超过max_model_len的80%,就拒绝请求并提示用户缩短输入。

4.5 流式调用:实时看到生成过程

非流式调用要等模型全部生成完才返回,体验不太好。流式调用可以实时看到每个token的生成过程。

curl http://localhost:8000/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "/data/models/Qwen2.5-7B-Instruct",
    "prompt": "写一首关于春天的诗",
    "max_tokens": 200,
    "temperature": 0.8,
    "stream": true
  }'

流式返回的数据是一行一行的:

data: {"id":"cmpl-xyz","object":"text_completion","choices":[{"text":"春","index":0,"finish_reason":null}]}

data: {"id":"cmpl-xyz","object":"text_completion","choices":[{"text":"天","index":0,"finish_reason":null}]}

data: {"id":"cmpl-xyz","object":"text_completion","choices":[{"text":"来","index":0,"finish_reason":null}]}

data: [DONE]

每行都是一个独立的JSON,最后以 [DONE] 结束。前端拿到这些数据后,可以逐字展示,用户体验非常好。

个人经验:流式调用时,记得在客户端做缓冲。因为网络传输可能把多个data包合并成一个,直接解析会出错。我一般用换行符分割,逐行处理。

4.6 本章知识体系

下面这张图帮你理清本章的核心逻辑:

vLLM在线服务核心流程 客户端 curl / Python SDK HTTP请求 vLLM API Server /v1/completions 调度推理 vLLM推理引擎 PagedAttention 返回生成结果 关键参数说明 • prompt: 输入文本 • max_tokens: 最大生成长度 • temperature: 随机性控制 (0-2) • top_p: 核采样参数 • stop: 停止字符串 • stream: 是否流式返回

这张图展示了从客户端发起请求,到vLLM API服务器接收、调度推理引擎执行,最后返回结果的完整链路。你想想看,整个过程其实就三步:发请求、等推理、收结果。但背后vLLM做了大量优化,比如PagedAttention管理显存、连续批处理提高吞吐量,这些我们后面章节会深入讲。

总结一下:这一章我们学会了怎么启动vLLM API服务器,怎么用curl调用 /v1/completions 端点,以及流式和非流式调用的区别。这些都是在线服务的基础,后面的高级特性都建立在这之上。


公众号:蓝海资料掘金营,微信deep3321