你是不是也有这种感觉:明明花了大价钱买了GPU,跑起大模型来却慢得像蜗牛?别人能同时接100个请求,你接10个就开始报错?别急,今天这篇文章就是给你“抄作业”的——从部署到压测,再到给模型的能力打分,一条龙全讲明白。
一、为什么你的大模型跑得慢?—— 显存里藏着的“浪费”
我们先想一个问题:大模型在回答你问题的时候,它在做什么?
简单说,它是一个字一个字往外蹦的。每次生成下一个字,都要回头看一眼之前说过的所有字(这叫“注意力机制”)。为了让模型不用每次重新算一遍,它会把这些“记忆”存下来,放到一块叫 KV Cache 的区域。
问题来了:传统方法(比如Hugging Face自带的生成方式)给每个请求提前占好一整块连续的内存。就好比你一个人去电影院,非要把一整排座位都占上,说“万一我朋友来了呢”。结果大部分座位空着,别人想坐也坐不了。
这就造成了两个后果:
-
显存利用率低
:可能只用了30%,剩下的都浪费了。
-
并发能力差
:来几个请求就把显存占满了,后面的只能排队。
所以,你需要的不是更贵的显卡,而是一个更聪明的“调度员”——vLLM。
二、vLLM:一个能让你的GPU“物尽其用”的推理引擎
vLLM 是加州大学伯克利分校团队开发的开源项目,现在已经是大模型推理的标配之一。它的核心思想就两个,特别容易理解。
2.1 PagedAttention:像拼积木一样管理显存
vLLM 不再给每个请求预留一大块连续显存,而是把显存切成很多小块(就像一页一页的纸)。一个请求来了,它需要几页就分配几页,而且这些页可以不连续存放,通过一张“目录”(页表)来找到它们。
打个比方:传统方法像你租房子,必须整租一套,哪怕你只住一间;vLLM像按天住青旅,来一个人开一个床位,走了立刻腾出来给别人。
结果就是:同样的显存,能同时服务更多请求。官方数据说,最高能让吞吐量(每秒处理的请求数)提升24倍。这不是玄学,是实实在在的工程优化。
2.2 Continuous Batching:让GPU永远不闲着
你有没有遇到过这种情况:食堂打饭,必须等一整个班的人到齐了才开饭,结果有人慢吞吞,全班都得等。
传统批处理就是这个毛病:必须攒够一批请求才一起算,一旦有个请求特别长(比如要写2000个字的回答),整个批次就被它拖慢了,GPU在那干等。
vLLM的连续批处理,就像流水线:每个请求独立处理,哪个完成了就立刻从队列里拉一个新的进来。GPU永远有活干,利用率自然就上去了。
三、动手部署:一行命令跑起一个OpenAI风格的API
很多教程让你配一堆环境、写一堆代码,vLLM不用。你只要装好,然后一行命令就能启动一个和OpenAI完全兼容的API服务。
第一步:装环境
conda create -n vllm_env python=3.11
conda activate vllm_env
pip install vllm
第二步:启动服务
假设你已经有一个训练好的模型(比如Qwen3-8B),放在 /root/autodl-tmp/models/Qwen3-8B-sft-all 目录下。执行:
vllm serve /root/autodl-tmp/models/Qwen3-8B-sft-all \
--served-model-name Qwen3-8B-sft-all \
--max-model-len 32K
解释一下:
-
serve:告诉vLLM我要起一个API服务。
-
第一个路径:你的模型文件夹。
-
--served-model-name:对外暴露的模型名字,调用的时候要用这个。
-
--max-model-len 32K:允许最大上下文长度(32K就是32768个token,约2万多汉字)。
启动成功后,你会看到类似 Uvicorn running on http://localhost:8000 的提示。这就说明服务已经就绪了。
第三步:后台运行(生产环境必用)
nohup vllm serve /root/autodl-tmp/models/Qwen3-8B-sft-all \
--served-model-name Qwen3-8B-sft-all \
--max-model-len 32K > vllm.log 2>&1 &
nohup 让它不会因为你关掉终端而停止,日志输出到 vllm.log 文件。
四、调用服务:三种方式,任你挑选
服务跑起来了,怎么用呢?很简单,vLLM提供了和OpenAI一模一样的接口,所以你用任何支持OpenAI的客户端都能调。
4.1 用curl快速测试
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3-8B-sft-all",
"messages": [
{"role": "system", "content": "你是个乐于助人的助理。"},
{"role": "user", "content": "我的猫死了,我很难过。"}
]
}'
你会看到模型返回一段安慰你的话。
4.2 用Python的OpenAI库
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1/",
api_key="none" # vLLM默认不校验key,占个位就行
)
response = client.chat.completions.create(
model="Qwen3-8B-sft-all",
messages=[
{"role": "user", "content": "量子计算会威胁比特币吗?"}
]
)
print(response.choices[0].message.content)
是不是和调用真正的OpenAI一模一样?无缝切换。
4.3 用LangChain
很多做AI应用的人喜欢用LangChain,vLLM也完美支持。
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="Qwen3-8B-sft-all",
base_url="http://localhost:8000/v1/",
api_key="none",
temperature=0
)
response = llm.invoke("用一句话解释什么是PagedAttention")
print(response.content)
五、光跑起来还不够:你的模型到底能扛多大压力?
服务跑通了,但你肯定想知道:它能同时服务多少人?首字响应快不快?每秒能吐多少个字?
这就需要做压力测试。别一听“压测”就觉得复杂,用阿里魔搭社区的 EvalScope 工具,一行命令全搞定。
安装压测模块:
pip install 'evalscope[perf]'
发起压测:
evalscope perf \
--url "http://127.0.0.1:8000/v1/chat/completions" \
--parallel 5 \
--model Qwen3-8B-sft-all \
--number 20 \
--api openai \
--dataset openqa \
--stream
参数说明,我用人话翻译一下:
参数 | 意思 |
--parallel 5 | 同时开5个“虚拟用户”去问模型 |
--number 20 | 总共问20次(5个用户,每人问4轮) |
--dataset openqa | 用一套现成的问答集当考题 |
--stream | 模拟打字机效果,一个字一个字返回 |
跑完之后,你会看到一张结果表。我帮你解读最重要的几个指标:
指标 | 白话解释 |
Output token throughput (tok/s) | 模型每秒能吐出多少个字。越高说明回答越快。 |
Time to first token (s) | 你问完问题,模型多久才蹦出第一个字。这是体验的关键——如果超过1秒,用户就会觉得“卡”。 |
Average latency (s) | 从你发问到拿到完整回答的总耗时。 |
Succeed requests | 成功多少个。如果失败率很高,说明服务扛不住这个并发。 |
举个例子,如果你跑出来 Time to first token 是0.2秒,Output token throughput 是100 tok/s,那就相当不错了。
六、模型“智商”够不够?—— 用EvalScope给它打个分
压测测的是速度和并发能力。但你的模型回答得准不准、逻辑强不强、会不会胡说八道,那是另一个维度的问题,需要能力评估。
EvalScope 内置了海量考试题,比如:
-
MMLU
:考模型的综合知识(像高考文综)
-
GSM8K
:小学数学应用题
-
HumanEval
:写代码的能力
-
IFEval
:能不能听明白复杂指令
专门针对Qwen3模型,魔搭社区还整理了一个 modelscope/EvalScope-Qwen3-Test 数据集,把这些考题打包好了。
跑评估只需要几行Python代码:
from evalscope import TaskConfig, run_task
task_cfg = TaskConfig(
model='Qwen3-8B-sft-all',
api_url='http://127.0.0.1:8000/v1/chat/completions',
eval_type='service',
datasets=['data_collection'],
dataset_args={
'data_collection': {
'dataset_id': 'modelscope/EvalScope-Qwen3-Test',
'filters': {'remove_until': '</think>'} # 过滤掉模型内部的思考过程
}
},
generation_config={
'max_tokens': 30000, # 允许模型输出很长(比如复杂推理)
'temperature': 0.6, # 采样温度,Qwen官方推荐值
'top_p': 0.95,
},
limit=200 # 先测200条,省时间
)
run_task(task_cfg=task_cfg)
跑完后,EvalScope会给出每个科目的得分,比如MMLU 85分、GSM8K 92分……你就能清楚地知道模型哪里强、哪里弱。
想看漂亮的可视化报告? 安装可视化模块:
pip install 'evalscope[app]'
evalscope_app
如果是远程服务器(比如云主机),用SSH隧道把端口映射到本地:
ssh -CNg -L 7860:127.0.0.1:7860 root@你的服务器地址 -p 你的端口
然后浏览器打开 http://localhost:7860,就能看到一个酷炫的看板,所有成绩一目了然。
七、一个小窍门:专门测“思考型”模型的效率
最近很多模型(比如DeepSeek-R1、QwQ)会先输出一大段思考过程,然后再给答案。这种模式虽然准确率高了,但有时候会“过度思考”——明明10个字能说清,非要绕2000个字。
EvalScope 专门为这种模型设计了一个思考效率指标:
-
推理Token数
:模型在 标签内写了多少字。
-
首次正确Token位置
:正确答案最早出现在第几个字。
-
Token效率
:正确答案出现得越早,效率越高。
这样你就能判断:你的模型是不是在“装模作样地思考”,还是真的在高效推理。
八、总结:一套组合拳,让大模型又快又准
我们来回顾一下今天的“三板斧”:
-
用vLLM部署
:一行命令启动高并发、高吞吐的推理服务,解决“跑得慢”的问题。
-
用EvalScope压测
:量化服务的并发能力、首字延迟、吞吐量,解决“能不能扛住”的问题。
-
用EvalScope评估
:用标准考题给模型智商打分,解决“回答得好不好”的问题。
这三步做完,你的大模型应用就具备了生产可用的基础。无论是做AI客服、代码助手,还是内容生成,你都能自信地说:我知道它能跑多快,也知道它有多聪明。
希望这篇文章能帮你少踩一些坑。如果你在实操中遇到问题,欢迎留言讨论,我会尽量解答。