「AI Agent 全栈开发 50 讲」——从本地模型部署到多智能体系统,一年省 87 万 第6节
2026/9/10 2:28:09 网站建设 项目流程

第 06 课 | 高性能推理:vLLM 部署与 OpenAI 兼容接口

Ollama 好用,但它是「单线程」的——一次只能处理一个请求。当你跑多 Agent 系统的时候,4 个 Agent 同时发请求,Ollama 就只能排队。vLLM 就是来解决这个问题的:高并发、高吞吐、生产级推理引擎。


为什么需要 vLLM

前两节课我们用 Ollama 跑起了本地模型,体验不错。但 Ollama 有一个明显的局限:它是一次只处理一个请求的

当你跑一个简单的对话时,这没问题。但当你在后面构建多 Agent 系统时,问题就来了——4 个 Agent 同时向模型发请求,Ollama 只能一个一个处理,其他 3 个得排队等着。

这就好比一个餐厅只有一个厨师,不管来了多少客人,菜只能一道一道做。客人少的时候没问题,客人一多就全堵住了。

vLLM就是来解决这个问题的。它是一个高性能的 LLM 推理引擎,核心特性包括:

  • 连续批处理(Continuous Batching):动态合并多个请求,一起处理
  • PagedAttention:高效利用显存,支持更长的上下文
  • 高吞吐量:比 Ollama 快 2-4 倍(特别是在并发场景下)
  • OpenAI 兼容 API:代码几乎不用改,切换后端就行

打个比方:如果 Ollama 是一个厨师,vLLM 就是一个厨房——多个厨师同时做菜,还能动态调整谁先做谁后做。

对于我们的教程来说,前期开发用 Ollama 就够了。但当你开始跑多 Agent 系统(场景三)的时候,vLLM 的高并发能力就派上用场了。


vLLM 核心特性

先简单了解 vLLM 的两个核心技术。你不需要成为专家,但理解它们有助于你做出正确的架构选择。

PagedAttention

传统的 LLM 推理会把整个 KV Cache(注意力机制的中间结果)放在连续的显存空间里。但显存是稀缺资源,连续的显存空间更难找。

PagedAttention 借鉴了操作系统虚拟内存的思想:把 KV Cache 分成固定大小的「页」,不需要连续存储。这样显存利用率大幅提升,能支持更长的上下文和更大的批处理。

连续批处理

传统批处理是等一个批次的所有请求都完成后,才开始处理下一个批次。如果批次里有一个请求特别长,其他请求就得等它完成。

连续批处理更聪明:它动态地把新请求加入正在处理的批次,把已完成的请求移出。这样 GPU 始终在满负荷工作,吞吐量大幅提升。

vLLM 连续批处理

请求 1 + 2 + 3
一起处理
总耗时 6s

Ollama 单请求

请求 1
处理 5s

请求 2
处理 5s

请求 3
处理 5s

图 1:Ollama 单请求 vs vLLM 连续批处理


安装 vLLM

vLLM 的安装比 Ollama 稍微复杂一点,因为它需要 CUDA 环境。

首先确认你的 NVIDIA 驱动和 CUDA 版本:

nvidia-smi

看输出里的CUDA Version字段,应该是 12.x 以上。

然后安装 vLLM:

uv pip install vllm

如果你遇到安装问题,可能是因为 Windows 上 vLLM 的支持不如 Linux 完善。vLLM 官方主要支持 Linux,Windows 上可能需要通过 WSL2 来运行。

如果你的 Windows 环境安装 vLLM 有困难,不用担心——Ollama 已经足够支撑我们学完大部分课程。vLLM 主要在后期的多 Agent 高并发场景才体现出优势。你可以先把 Ollama 用熟,后面需要 vLLM 的时候再装。


启动 vLLM 服务

安装成功后,启动 vLLM 服务:

python-m vllm.entrypoints.openai.api_server \--model Qwen/Qwen2-7B-Instruct \--host 0.0.0.0 \--port 8000 \--max-model-len 8192 \--gpu-memory-utilization 0.85

参数说明:

  • --model:模型名称(vLLM 会自动从 HuggingFace 下载)
  • --host 0.0.0.0:监听所有网络接口
  • --port 8000:服务端口
  • --max-model-len 8192:最大上下文长度
  • --gpu-memory-utilization 0.85:显存使用率上限(留 15% 给系统)

服务启动后,vLLM 会提供一个 OpenAI 兼容的 API,地址是http://localhost:8000

验证一下:

curl http://localhost:8000/v1/models

如果返回模型列表,就说明服务启动成功了。


用 Python 调用 vLLM

vLLM 的 API 和 Ollama 几乎一样——都是 OpenAI 兼容格式。这意味着你之前写的调用代码,几乎不用改就能用。

# vllm_chat.py - 用 Python 调用 vLLM# AI Agent 全栈开发 50 讲 - 第 06 课importrequestsdefchat_vllm(prompt:str,model:str="Qwen/Qwen2-7B-Instruct")->str:"""调用 vLLM 的 OpenAI 兼容 API"""url="http://localhost:8000/v1/chat/completions"payload={"model":model,"messages":[{"role":"user","content":prompt}],"temperature":0.7,}response=requests.post(url,json=payload,timeout=120)response.raise_for_status()result=response.json()returnresult["choices"][0]["message"]["content"]defmain():reply=chat_vllm("用 3 句话总结一下 AI Agent 的核心价值。")print(f"vLLM 回复:\n{reply}")if__name__=="__main__":main()

看到了吗?代码和第 4 课的ollama_chat.py几乎一模一样,只是 URL 从localhost:11434变成了localhost:8000。这就是 OpenAI 兼容 API 的好处——切换后端几乎零成本。


性能对比:vLLM vs Ollama

我们用脚本测试一下 vLLM 和 Ollama 的性能差异。

# vllm_benchmark.py - vLLM vs Ollama 性能对比# AI Agent 全栈开发 50 讲 - 第 06 课importrequestsimporttimeimportconcurrent.futuresdefsingle_request(url:str,model:str,prompt:str)->dict:"""单次请求测试"""payload={"model":model,"messages":[{"role":"user","content":prompt}],"temperature":0.7,}start=time.time()response=requests.post(url,json=payload,timeout=120)elapsed=time.time()-start content=response.json()["choices"][0]["message"]["content"]tokens=len(content)/2return{"elapsed":round(elapsed,2),"tokens_per_second":round(tokens/elapsed,1),}defconcurrent_requests(url:str,model:str,prompt:str,n:int=5)->dict:"""并发请求测试"""start=time.time()withconcurrent.futures.ThreadPoolExecutor(max_workers=n)asexecutor:futures=[executor.submit(single_request,url,model,prompt)for_inrange(n)]results=[f.result()forfinfutures]total_elapsed=time.time()-start avg_tps=sum(r["tokens_per_second"]forrinresults)/len(results)return{"total_elapsed":round(total_elapsed,2),"avg_tokens_per_second":round(avg_tps,1),"requests":n,}defmain():prompt="用 200 字介绍一下人工智能的发展历程。"print("="*60)print(" vLLM vs Ollama 性能对比")print("="*60)# 测试配置configs=[{"name":"Ollama (Qwen2 7B)","url":"http://localhost:11434/v1/chat/completions","model":"qwen2:7b"},{"name":"vLLM (Qwen2 7B)","url":"http://localhost:8000/v1/chat/completions","model":"Qwen/Qwen2-7B-Instruct"},]forconfiginconfigs:print(f"\n[{config['name']}]")# 单请求测试try:result=single_request(config["url"],config["model"],prompt)print(f" 单请求:{result['elapsed']}s,{result['tokens_per_second']}tokens/s")exceptExceptionase:print(f" 单请求: [错误]{e}")# 并发测试(5 个并发)try:result=concurrent_requests(config["url"],config["model"],prompt,n=5)print(f" 5 并发: 总耗时{result['total_elapsed']}s, 平均{result['avg_tokens_per_second']}tokens/s")exceptExceptionase:print(f" 5 并发: [错误]{e}")if__name__=="__main__":main()

在我的 RTX 3090 上,测试结果如下:

测试项OllamavLLMvLLM 提升
单请求速度~45 tokens/s~50 tokens/s+11%
5 并发总耗时~25 秒~7 秒3.6x
5 并发平均速度~9 tokens/s~36 tokens/s4x

关键发现:

  1. 单请求速度:vLLM 比 Ollama 略快,但差距不大(+11%)。
  2. 并发场景:vLLM 的优势非常明显。5 个并发请求,vLLM 的总耗时只有 Ollama 的 1/3.6,平均速度是 Ollama 的 4 倍。

这就是连续批处理的威力。当多个请求同时到达时,vLLM 能把它们合并成一个批次一起处理,GPU 利用率大幅提升。


Ollama vs vLLM:如何选择

你的场景是什么?

本地开发/个人使用?

生产部署/多 Agent?

用 Ollama
简单、快速、够用

需要高并发?

用 vLLM
高吞吐、低延迟

Ollama 也行
简单优先

图 2:Ollama vs vLLM 选择决策树

维度OllamavLLM
安装难度简单(一行命令)中等(需要 CUDA)
使用难度简单中等
单请求速度略好
并发能力弱(串行处理)强(连续批处理)
适用场景本地开发、个人使用生产部署、多 Agent
Windows 支持一般(建议 WSL2)

我的推荐

  • 开发阶段:用 Ollama。简单、快速、够用。
  • 生产部署:用 vLLM。高并发、高吞吐、更稳定。
  • 教程学习:前期用 Ollama,后面多 Agent 场景再切换到 vLLM。

统一 LLM 客户端设计

为了让代码能在 Ollama 和 vLLM 之间无缝切换,我们设计一个统一的 LLM 客户端。

# llm_client.py - 统一 LLM 客户端# AI Agent 全栈开发 50 讲 - 第 06 课importrequestsfromconfigimportLLM_BACKEND,LLM_MODEL,LLM_BASE_URL,LLM_API_KEYclassLLMClient:"""统一的 LLM 客户端,支持 Ollama 和 vLLM"""def__init__(self,backend:str=None,model:str=None,base_url:str=None):self.backend=backendorLLM_BACKEND self.model=modelorLLM_MODEL self.base_url=base_urlorLLM_BASE_URL self.api_key=LLM_API_KEYdefchat(self,messages:list,temperature:float=0.7)->str:"""发送聊天请求 Args: messages: 消息列表 [{"role": "user", "content": "..."}] temperature: 温度参数 Returns: 模型回复文本 """url=f"{self.base_url}/chat/completions"headers={}ifself.api_keyandself.api_key!="ollama":headers["Authorization"]=f"Bearer{self.api_key}"payload={"model":self.model,"messages":messages,"temperature":temperature,}response=requests.post(url,json=payload,headers=headers,timeout=120)response.raise_for_status()result=response.json()returnresult["choices"][0]["message"]["content"]def__repr__(self):returnf"LLMClient(backend={self.backend}, model={self.model})"defmain():# 创建客户端(自动读取配置)client=LLMClient()print(f"客户端:{client}")# 测试对话messages=[{"role":"system","content":"你是一个专业的市场分析师。"},{"role":"user","content":"用 2 句话总结 AI Agent 的核心价值。"}]reply=client.chat(messages)print(f"\n回复:\n{reply}")if__name__=="__main__":main()

这个客户端通过配置文件自动选择后端。想切换 Ollama 和 vLLM?只需要改.env文件里的LLM_BASE_URL

# 用 OllamaLLM_BASE_URL=http://localhost:11434/v1# 用 vLLMLLM_BASE_URL=http://localhost:8000/v1

代码完全不用改。这就是统一接口设计的好处。


小结与预告

这节课我们学习了 vLLM——一个生产级的高性能推理引擎。

核心收获:

  1. vLLM 的优势:连续批处理、PagedAttention、高并发
  2. 性能对比:并发场景下 vLLM 比 Ollama 快 3-4 倍
  3. 统一客户端:封装了 LLMClient,支持 Ollama 和 vLLM 无缝切换

现在你有了两个推理引擎可选:Ollama 适合开发,vLLM 适合生产。后面的课程中,我们会根据场景灵活切换。

下一节课,我们会把 Ollama、vLLM、OpenAI API 统一封装成一个客户端,通过配置文件一键切换。这是整个教程的基础设施——后面所有的 Agent 调用都通过这个客户端完成。

我们下一课见。


系列教程导航

上一篇:第 05 课 | 模型量化与优化:让 14B 模型也能流畅运行

下一篇:第 07 课 | 统一 LLM 客户端:本地与云端 API 无缝切换

本系列共 50 课,持续更新中。关注我不迷路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询