1. AI Infra 与 Agent 技能全景拆解
搞 AI Infra 和 Agent 开发这几年,我最大的感受就是:技能栈的广度比深度更让人头疼。你可能花了两周把 vLLM 的 PagedAttention 原理啃透了,结果一上手发现连 Docker 镜像里带不带模型权重都搞不清楚;你刚把 SGLang 的 RadixAttention 调通,转头又遇到 Agent 执行到一半报execution terminated due to error。这不是你能力不行,而是这个领域本身就横跨了推理引擎、模型服务、Agent 编排、环境配置、性能调优好几个层面,每个层面都有自己的坑。
这篇内容我打算把自己从零搭建 AI Infra 和 Agent 系统过程中积累的技能点做一次系统整理。核心覆盖 vLLM、SGLang、PyTorch 三大推理与训练基座,同时延伸到 Agent 框架选型、部署实操、性能排查这些实际工作中绕不开的环节。不管你是刚接触 AI Infra 的新手,还是已经能跑通 vLLM 部署但想深入理解 EngineCore 与 Scheduler 交互流程的老手,都能从里面找到对自己有用的东西。我会尽量把每个技术点的“为什么”讲清楚,而不是只丢一堆命令让你复制粘贴。
1.1 为什么这三个东西总是被放在一起聊
vLLM、SGLang、PyTorch 这三个名字经常出现在同一个技术讨论里,但它们的定位其实完全不同。PyTorch 是地基,负责张量计算、自动求导、GPU 调度这些底层能力;vLLM 和 SGLang 是建在地基上的推理服务框架,负责把训练好的模型高效地跑起来对外提供服务。很多人搞混是因为它们都涉及“跑模型”这件事,但 PyTorch 更偏向训练和实验,vLLM/SGLang 更偏向生产环境的高吞吐推理。
我见过不少团队在选型时纠结“到底用 vLLM 还是 SGLang”,其实这个问题本身就问错了。正确的问法是:你的业务场景对吞吐、延迟、并发、模型架构的支持需求是什么。vLLM 的强项在于 PagedAttention 带来的显存利用率和连续批处理能力,适合高并发在线服务;SGLang 的 RadixAttention 在前缀共享场景下优势明显,适合多轮对话、Agent 这类有大量重复前缀的负载。两者不是替代关系,而是互补关系。
1.2 技能整理的逻辑框架
我把整个技能体系分成四层来梳理,从下往上依次是:
| 层级 | 覆盖内容 | 核心技能点 |
|---|---|---|
| 基础环境层 | PyTorch 安装、CUDA 配置、Docker 环境 | torch 版本匹配、CUDA 兼容性、镜像构建 |
| 推理引擎层 | vLLM、SGLang 部署与调优 | 引擎架构、调度策略、显存管理 |
| Agent 编排层 | Agent 框架、工具调用、记忆管理 | 框架选型、执行流程、错误处理 |
| 运维排查层 | 性能监控、问题定位、版本管理 | 日志分析、性能回归、版本锁定 |
这个分层不是绝对的,实际工作中经常需要跨层排查问题。比如 Agent 执行报错,可能是 Agent 框架的逻辑问题,也可能是 vLLM 推理超时导致的,还可能是 PyTorch 版本和 CUDA 不匹配引发的底层异常。跨层排查能力才是真正拉开差距的地方。
2. PyTorch 环境配置与版本管理实战
PyTorch 的安装看起来简单,pip install torch一行命令的事,但实际踩过的坑能写满一页纸。我见过太多人卡在torch.cuda.__init__.py报错上,也见过因为 torch 版本和 CUDA 版本不匹配导致 GPU 完全用不了的案例。这一章把 PyTorch 环境配置的核心要点拆开讲。
2.1 版本匹配的底层逻辑
PyTorch 的版本选择不是“越新越好”,而是要跟你的 CUDA 驱动版本、GPU 型号、Python 版本三者对齐。核心逻辑是这样的:NVIDIA 驱动决定支持的 CUDA 最高版本,CUDA 版本决定能装哪个 PyTorch 构建版本,PyTorch 版本又决定了支持的 Python 版本范围。
举个例子,你机器上的 NVIDIA 驱动是 525 版本,它最高支持 CUDA 12.0。那你就不能装需要 CUDA 12.1 的 PyTorch 构建。这时候你有两个选择:升级驱动,或者降级 PyTorch 到支持 CUDA 12.0 的版本。我一般建议优先升级驱动,因为新驱动向下兼容旧 CUDA 版本,灵活性更高。
具体版本对应关系可以这样查:
# 查看当前驱动支持的 CUDA 版本 nvidia-smi # 输出右上角会显示 "CUDA Version: 12.x" # 这个版本是驱动支持的最高 CUDA 版本,不是已安装的 CUDA 版本然后去 PyTorch 官网的 previous versions 页面找对应构建。比如你要装 torch 2.1.0 + CUDA 12.1 的组合:
pip3 install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu121注意:
--index-url后面的 cu121 必须和你的 CUDA 版本严格对应,写错了会装成 CPU 版本或者直接报找不到包。
2.2 常见安装报错与排查
d:\comfyui_image\python\lib\site-packages\torch\cuda\__init__.py:180: UserWarning这个报错我见过太多次了。这个警告通常出现在 Windows 环境下,核心原因是PyTorch 找不到可用的 CUDA 运行时。可能的情况有三种:一是装成了 CPU 版本的 torch;二是 CUDA 版本和 torch 构建不匹配;三是环境变量里 CUDA_PATH 指向了错误的目录。
排查步骤我一般按这个顺序来:
- 先确认装的是不是 GPU 版本:
python -c "import torch; print(torch.cuda.is_available())",返回 False 就是有问题 - 检查 torch 版本和 CUDA 版本:
python -c "import torch; print(torch.version.cuda)",如果输出 None 说明是 CPU 版本 - 检查 CUDA 安装:
nvcc --version,如果命令不存在说明 CUDA Toolkit 没装或者没加到 PATH - 检查环境变量:
echo $CUDA_PATH(Linux)或echo %CUDA_PATH%(Windows)
还有一个容易被忽略的点:conda 环境和 pip 环境的冲突。如果你用 conda 装了 pytorch,又用 pip 装了另一个版本,两个版本会打架。我建议统一用一个包管理器,要么全 conda,要么全 pip,别混着来。
2.3 多版本共存与隔离方案
实际工作中经常需要同时维护多个项目,每个项目依赖不同的 torch 版本。这时候虚拟环境隔离是必须的,但光靠 venv 或 conda 还不够,因为 CUDA 版本是系统级的,虚拟环境管不了。
我的做法是:用 conda 管理 Python 层面的隔离,用 Docker 管理 CUDA 层面的隔离。具体来说,日常开发用 conda 创建独立环境,每个环境装对应版本的 torch;需要严格隔离 CUDA 版本时,用 Docker 镜像,每个镜像固定一个 CUDA + torch 组合。
# conda 环境创建示例 conda create -n project_a python=3.10 conda activate project_a pip install torch==2.1.0 --index-url https://download.pytorch.org/whl/cu121 # 另一个项目用不同版本 conda create -n project_b python=3.11 conda activate project_b pip install torch==2.4.0 --index-url https://download.pytorch.org/whl/cu124实操心得:conda 环境切换后一定要重新验证
torch.cuda.is_available(),因为有时候环境变量会残留上一个环境的配置,导致看起来切换了实际没生效。
3. vLLM 推理引擎深度解析与部署实操
vLLM 是目前最主流的开源推理引擎之一,核心卖点是 PagedAttention 和连续批处理。但很多人只停留在“能跑起来”的层面,对内部的 EngineCore、Scheduler、Executor 交互流程一知半解。这一章我把 vLLM 的架构拆开讲,同时给出可直接复现的部署方案。
3.1 vLLM 核心架构:EngineCore 与 Scheduler 交互流程
vLLM 的架构可以类比成一个餐厅的运作模式。EngineCore 是餐厅经理,负责整体协调;Scheduler 是调度员,决定哪些请求先做、哪些排队;Executor 是后厨团队,实际执行计算任务。三者之间的交互流程决定了整个系统的吞吐和延迟表现。
具体来说,当一个请求进来时,流程是这样的:
- 请求到达 EngineCore:EngineCore 接收来自 API Server 的请求,做初步的格式校验和 tokenization
- Scheduler 介入调度:Scheduler 根据当前 GPU 显存状态、正在处理的序列数量、请求优先级,决定这个请求是立即执行还是排队等待
- Executor 执行计算:被调度的请求进入 Executor,Executor 负责实际的模型前向计算,包括 attention 计算、KV Cache 读写
- 结果返回 EngineCore:计算完成后结果回传 EngineCore,再通过 API Server 返回给客户端
这个流程里最关键的是Scheduler 的调度策略。vLLM 默认用的是连续批处理(Continuous Batching),跟传统的静态批处理不同,它不需要等一个批次的所有请求都完成才处理下一批,而是每生成一个 token 就重新评估一次批次组成。这样做的好处是短请求不会被长请求拖累,GPU 利用率更高。
Scheduler 在做决策时会考虑几个核心因素:
- 显存水位:当前 KV Cache 占用了多少显存,还剩多少可以分配给新请求
- 序列长度:请求的 prompt 长度和预期生成长度,决定需要多少 KV Cache 空间
- 抢占策略:显存不够时,是拒绝新请求还是抢占低优先级请求的资源
注意:vLLM 新版本在调度策略上有调整,部分版本出现了性能下降的情况。如果你从旧版本升级后发现吞吐下降,可以先回退到稳定版本,或者调整
--max-num-seqs和--max-num-batched-tokens参数来适配新调度逻辑。
3.2 Docker 部署 vLLM 完整流程
Docker 部署是目前最推荐的方式,环境隔离干净,迁移方便。我以部署 Qwen 系列模型为例,把完整流程走一遍。
首先拉取镜像。vLLM 官方镜像的命名规则是vllm/vllm-openai:版本号,比如vllm/vllm-openai:v0.27.1。这个镜像不包含模型权重,模型需要在启动时挂载或者从网络下载。
# 拉取指定版本镜像 docker pull vllm/vllm-openai:v0.27.1 # 启动容器,挂载本地模型目录 docker run --runtime nvidia --gpus all \ -v /path/to/your/models:/models \ -p 8000:8000 \ --ipc=host \ vllm/vllm-openai:v0.27.1 \ --model /models/Qwen2.5-7B-Instruct \ --served-model-name qwen2.5-7b \ --max-model-len 8192 \ --gpu-memory-utilization 0.9几个关键参数的解释:
--ipc=host:共享主机 IPC 命名空间,vLLM 多进程通信需要,不加可能报共享内存错误--max-model-len:最大序列长度,根据模型支持的长度和显存大小调整--gpu-memory-utilization:GPU 显存利用率上限,默认 0.9,显存紧张时可以降到 0.8--served-model-name:对外暴露的模型名称,调用 API 时用这个名字
如果模型不大,也可以让 vLLM 自动从 HuggingFace 下载,但生产环境我强烈建议提前下载好模型挂载进去,避免容器启动时因为网络问题卡住。
3.3 部署 Qwen3-Embedding 与 DeepSeek 的差异化配置
不同模型对推理引擎的要求不一样。Embedding 模型和生成式模型的部署配置差异很大,不能一套参数走天下。
Qwen3-Embedding-0.6B 这类 Embedding 模型,特点是模型小、吞吐要求高、不需要生成长文本。部署时重点调这几个参数:
docker run --runtime nvidia --gpus all \ -v /models:/models \ -p 8000:8000 \ --ipc=host \ vllm/vllm-openai:v0.27.1 \ --model /models/Qwen3-Embedding-0.6B \ --task embedding \ --max-model-len 512 \ --gpu-memory-utilization 0.5--task embedding是关键,告诉 vLLM 这是 Embedding 任务,走不同的处理路径。--max-model-len可以设小一点,Embedding 输入通常不会太长。
DeepSeek 这类大模型,部署时显存是主要瓶颈。以 DeepSeek-V2-Lite 为例,FP16 精度下大概需要 32GB 显存,如果显存不够可以考虑量化版本:
docker run --runtime nvidia --gpus all \ -v /models:/models \ -p 8000:8000 \ --ipc=host \ vllm/vllm-openai:v0.27.1 \ --model /models/DeepSeek-V2-Lite-Chat \ --tensor-parallel-size 2 \ --max-model-len 4096 \ --gpu-memory-utilization 0.95 \ --enforce-eager--tensor-parallel-size 2表示用两张卡做张量并行,适合单卡显存不够的情况。--enforce-eager关闭 CUDA Graph,省一点显存但会牺牲一些性能,显存极度紧张时可以用。
3.4 vLLM 性能调优与版本选择
vLLM 的版本迭代很快,不同版本之间的性能表现可能有明显差异。我整理了一个版本选择的参考思路:
| 场景 | 推荐版本策略 | 原因 |
|---|---|---|
| 生产环境稳定优先 | 锁定已知稳定版本,不追新 | 新版本可能引入性能回归 |
| 新模型支持 | 用最新版本 | 新模型架构需要新版本支持 |
| 显存紧张 | 尝试较新版本 | 新版本通常有显存优化 |
| 多卡部署 | 选择社区验证过的版本 | 多卡并行的问题更多 |
性能调优的核心参数就那几个,但每个都值得反复调:
--max-num-seqs:最大并发序列数,调大吞吐上升但延迟可能增加--max-num-batched-tokens:单批次最大 token 数,影响批处理效率--gpu-memory-utilization:显存利用率,0.9 是默认值,可以微调到 0.95--enable-chunked-prefill:开启分块预填充,长 prompt 场景下能降低首 token 延迟
实操心得:调参时一次只改一个参数,改完跑一轮基准测试,记录吞吐和延迟变化。同时改多个参数你根本不知道是哪个起了作用。
4. SGLang 与 vLLM 的选型对比与实战
SGLang 和 vLLM 经常被拿来比较,但我觉得与其争论谁更好,不如搞清楚什么场景该用谁。这一章从架构差异、性能表现、适用场景三个维度做对比,并给出 SGLang 的部署实操。
4.1 RadixAttention 与 PagedAttention 的本质差异
vLLM 的 PagedAttention 解决的是KV Cache 显存碎片化问题。传统方式下每个请求的 KV Cache 需要连续显存空间,浪费严重;PagedAttention 把 KV Cache 分成固定大小的块,像操作系统管理内存页一样管理显存,利用率大幅提升。
SGLang 的 RadixAttention 解决的是前缀重复计算问题。在多轮对话、Agent 工具调用这类场景下,不同请求往往有大量相同的前缀(比如 system prompt、历史对话)。RadixAttention 用基数树(Radix Tree)来组织 KV Cache,相同前缀只计算一次,后续请求直接复用。
打个比方:PagedAttention 像是一个高效的仓库管理员,把货物(KV Cache)分门别类放好,不浪费货架空间;RadixAttention 像是一个聪明的图书管理员,发现很多人借同一本书的前几章,干脆把前几章复印好放在前台,谁来都直接给复印件。
这两个机制不是互斥的,理论上可以结合,但目前两个框架各走各的路线。选型的核心判断标准是:你的负载有没有大量重复前缀。有,选 SGLang;没有或者前缀重复率低,选 vLLM。
4.2 SGLang 部署实操与参数配置
SGLang 的部署方式和 vLLM 类似,也支持 Docker 和 pip 两种方式。我用 pip 方式演示,因为 SGLang 的 Docker 镜像更新频率不如 vLLM 高。
# 安装 SGLang pip install "sglang[all]" # 启动服务 python -m sglang.launch_server \ --model-path /models/Qwen2.5-7B-Instruct \ --port 30000 \ --host 0.0.0.0 \ --tp-size 1 \ --mem-fraction-static 0.85 \ --max-running-requests 128关键参数说明:
--tp-size:张量并行大小,跟 vLLM 的--tensor-parallel-size对应--mem-fraction-static:静态显存分配比例,SGLang 会预留一部分显存给 KV Cache--max-running-requests:最大并发请求数,类似 vLLM 的--max-num-seqs
SGLang 还支持一些 vLLM 没有的特性,比如RadixAttention 的前缀缓存默认开启,以及结构化输出的原生支持。如果你的 Agent 需要模型输出严格的 JSON 格式,SGLang 的结构化输出比 vLLM 的 guided decoding 用起来更顺手。
4.3 什么场景该选 SGLang 而不是 vLLM
根据我的实际使用经验,这几个场景 SGLang 优势明显:
多轮对话系统。每轮对话都包含之前的完整历史,前缀重复率极高。SGLang 的 RadixAttention 能把首 token 延迟降低 50% 以上,这个提升在用户体验上是质变的。
Agent 工具调用。Agent 在执行任务时,system prompt 和工具定义部分是完全固定的,每次调用都重复。SGLang 能缓存这部分前缀,减少重复计算。
批量推理任务。如果一批请求共享相同的 prompt 模板,只是变量部分不同,SGLang 的前缀复用能大幅提升吞吐。
反过来,这几个场景 vLLM 更合适:
单轮问答。没有前缀复用空间,vLLM 的 PagedAttention 在显存管理上更成熟。
高并发短请求。vLLM 的连续批处理在短请求场景下调优空间更大。
生态兼容性要求高。vLLM 的社区更大,跟其他工具的集成更完善,遇到问题更容易找到解决方案。
4.4 两个框架的混合部署思路
实际生产环境中,不一定非要二选一。我见过一些团队的做法是:用 vLLM 做通用推理服务,用 SGLang 专门服务 Agent 和多轮对话场景。两个服务独立部署,通过路由层根据请求特征分发。
这种混合架构的好处是各取所长,坏处是运维复杂度上升。如果团队人手有限,建议先聚焦一个框架,把它的性能调优做到极致,再考虑引入第二个。
5. Agent 开发核心技能与框架选型
Agent 是这两年最热的方向之一,但很多人在框架选型上就卡住了。LangChain、AutoGPT、Hermes Agent、Pi Agent……名字一大堆,到底该用哪个?这一章我把 Agent 开发的核心技能点拆开讲,同时给出框架选型的判断框架。
5.1 Agent 架构的核心组件
不管用什么框架,一个 Agent 系统的核心组件就那几个:
规划模块。Agent 需要把用户的高层指令拆解成可执行的步骤。比如用户说“帮我分析这份销售数据并生成报告”,Agent 需要拆成“读取数据→清洗数据→计算指标→生成图表→撰写报告”这几步。
工具调用模块。Agent 需要调用外部工具来完成任务,比如搜索引擎、代码执行器、API 接口。工具调用的核心是函数签名定义和参数解析,这部分做不好 Agent 就会频繁调错工具。
记忆模块。Agent 需要记住之前的对话和操作历史。短期记忆通常放在上下文里,长期记忆需要向量数据库或者结构化存储。记忆管理做不好,Agent 要么“失忆”要么上下文爆炸。
执行循环。Agent 的核心是一个循环:观察当前状态→规划下一步→执行动作→观察结果→判断是否完成。这个循环的终止条件设计很关键,设计不好要么死循环要么提前退出。
5.2 主流 Agent 框架对比与选型建议
| 框架 | 核心特点 | 适合场景 | 学习曲线 |
|---|---|---|---|
| LangChain | 生态最全,组件丰富 | 快速原型、复杂编排 | 中等 |
| Hermes Agent | 桌面端友好,配置简单 | 个人助手、本地部署 | 低 |
| Pi Agent | 轻量,专注核心循环 | 学习原理、定制开发 | 低 |
| AutoGPT | 自主性强,适合探索 | 研究、实验 | 高 |
选型的核心判断标准是:你的 Agent 需要多复杂的编排。如果只是简单的“调用模型→解析输出→调用工具”循环,用 Pi Agent 或者自己写一个循环就够了,引入 LangChain 反而增加复杂度。如果需要复杂的多 Agent 协作、条件分支、循环嵌套,LangChain 的 LangGraph 会更合适。
注意:Agent 框架的版本迭代非常快,API 经常变。选型时不要只看功能列表,要看最近三个月的更新频率和社区活跃度。一个半年没更新的框架,即使功能再全也不建议用在生产环境。
5.3 Agent 记忆管理与安全防护
Agent 记忆管理是实际开发中最容易出问题的环节。我踩过的坑包括:上下文太长导致推理变慢、记忆检索不准确导致 Agent 答非所问、记忆写入冲突导致数据不一致。
我的做法是分层管理记忆:
- 工作记忆:当前对话的上下文,放在 prompt 里,控制在模型上下文窗口的 70% 以内
- 短期记忆:最近几轮对话的摘要,用向量数据库存储,按相关性检索
- 长期记忆:用户偏好、历史任务结果等结构化数据,用关系数据库存储
安全方面,Agent 的记忆系统是一个容易被忽视的攻击面。如果 Agent 的记忆可以被外部输入污染,攻击者就能通过注入恶意记忆来操控 Agent 行为。A-MemGuard 这类主动防御框架的思路值得参考:对写入记忆的内容做来源验证和内容过滤,对读取记忆的操作做权限控制。
5.4 Agent 执行报错排查实录
agent execution terminated due to error这个报错太常见了,但它的信息量几乎为零。我一般按这个顺序排查:
- 看完整日志。这个报错通常只是最外层的包装,真正的错误信息在更下面的日志里。找
Traceback或者Caused by关键字。 - 检查工具调用。Agent 执行失败最常见的原因是工具调用出错。检查工具的参数格式、返回值格式是否符合预期。
- 检查推理服务。如果 Agent 依赖 vLLM 或 SGLang 做推理,确认推理服务是否正常响应。推理超时也会导致 Agent 报这个错。
- 检查上下文长度。上下文超长会导致模型输出异常,进而让 Agent 解析失败。打印一下实际发送给模型的 prompt 长度。
- 检查循环终止条件。如果 Agent 陷入死循环,最终会因为达到最大步数而终止,报错信息可能就是这个。
我整理了一个速查表:
| 报错现象 | 可能原因 | 排查方法 |
|---|---|---|
| 执行立即终止 | 工具定义格式错误 | 检查工具 schema 是否符合框架要求 |
| 执行到一半终止 | 推理服务超时 | 查看推理服务日志,检查超时配置 |
| 间歇性终止 | 上下文超长 | 打印 prompt 长度,检查截断逻辑 |
| 特定任务终止 | 工具返回值解析失败 | 打印工具原始返回值,检查解析代码 |
6. 跨层问题排查与性能优化经验
前面几章分别讲了 PyTorch、vLLM、SGLang、Agent,但实际工作中遇到的问题往往是跨层的。这一章分享几个典型的跨层问题排查案例,以及我总结的性能优化经验。
6.1 推理服务性能下降的排查思路
vLLM 新版本性能下降是社区经常讨论的问题。遇到这种情况,我按这个顺序排查:
第一步,确认基准。用相同的模型、相同的请求负载,在旧版本和新版本上各跑一轮基准测试。不要凭感觉说“变慢了”,要有数据。
第二步,检查调度参数。新版本可能改了默认的调度参数。对比新旧版本的--max-num-seqs、--max-num-batched-tokens默认值,看是否有变化。
第三步,检查 CUDA Graph。vLLM 默认开启 CUDA Graph 来加速推理,但某些模型或某些版本下 CUDA Graph 可能导致性能下降。试试加--enforce-eager关闭它,看性能是否恢复。
第四步,检查显存管理。新版本的显存管理策略可能变了。用nvidia-smi观察推理过程中的显存占用曲线,看是否有异常波动。
第五步,回退版本。如果以上都排查不出问题,回退到已知稳定的版本,等新版本修复后再升级。
6.2 多卡部署的常见坑
多卡部署(张量并行)能解决单卡显存不够的问题,但引入的复杂度也不小。我踩过的坑包括:
NCCL 通信超时。多卡之间通过 NCCL 通信,如果网络配置有问题或者某张卡负载过高,会报 NCCL timeout。解决办法是调整NCCL_TIMEOUT环境变量,或者检查是否有其他进程占用了 GPU。
负载不均衡。张量并行下,如果模型层分配不均匀,会出现一张卡忙死、另一张卡闲死的情况。vLLM 和 SGLang 都会自动做层分配,但某些模型架构下自动分配效果不好,需要手动调整。
显存碎片化。多卡环境下显存碎片化问题更严重,因为每张卡都要维护自己的 KV Cache。开启 PagedAttention 能缓解,但不能完全解决。定期重启推理服务是个简单有效的办法。
6.3 版本锁定与升级策略
AI Infra 领域的版本管理是个头疼问题。我的策略是生产环境锁定版本,开发环境跟进最新。
生产环境用 Docker 镜像锁定所有依赖版本,包括 vLLM、PyTorch、CUDA、Python。镜像打好标签,记录每个版本的组合。升级时先在开发环境验证,确认没问题再更新生产镜像。
开发环境可以激进一些,跟进最新版本,提前发现兼容性问题。但要注意不要在生产环境直接 pip install --upgrade,这个操作的风险太高了。
我维护了一个版本兼容性表格,记录每个验证过的版本组合:
| vLLM 版本 | PyTorch 版本 | CUDA 版本 | 验证状态 | 备注 |
|---|---|---|---|---|
| v0.27.1 | 2.4.0 | 12.4 | 稳定 | 当前生产使用 |
| v0.28.0 | 2.5.0 | 12.4 | 测试中 | 新模型支持更好 |
| v0.26.0 | 2.3.0 | 12.1 | 稳定 | 旧项目使用 |
实操心得:每次升级前,用相同的基准测试跑一轮,记录吞吐、延迟、显存占用三个指标。只有三个指标都不劣于旧版本,才考虑升级。
6.4 监控与告警体系搭建
生产环境的推理服务需要监控,不然出了问题只能等用户反馈。我一般监控这几个指标:
- 请求延迟:P50、P95、P99 分位数,看长尾延迟
- 吞吐量:每秒处理的 token 数或请求数
- GPU 利用率:计算利用率和显存利用率
- 错误率:请求失败的比例,按错误类型分类
- 队列长度:等待处理的请求数,反映系统压力
监控工具用 Prometheus + Grafana 就够了,vLLM 和 SGLang 都暴露了 Prometheus 格式的指标。告警规则根据业务需求设,我一般设这几个:
- P99 延迟超过阈值持续 5 分钟
- 错误率超过 1% 持续 3 分钟
- GPU 显存利用率超过 95% 持续 10 分钟
- 队列长度超过阈值持续 5 分钟
告警不是越多越好,太多告警会导致告警疲劳,真正重要的问题反而被忽略。每个告警都要有明确的处理动作,没有处理动作的告警不如不设。
7. 学习路线与技能进阶建议
最后聊一下学习路线。AI Infra 和 Agent 这个领域变化太快,没有一劳永逸的学习方案,但有一些原则性的东西可以分享。
7.1 从使用者到贡献者的进阶路径
我观察到的进阶路径大概是这样的:
第一阶段,会用。能按照文档把 vLLM 或 SGLang 跑起来,能部署一个简单的 Agent,遇到常见报错能自己排查。这个阶段重点是动手,不要只看文档,要实际跑起来。
第二阶段,会调。能根据业务场景调整推理参数,能优化 Agent 的 prompt 和工具定义,能定位性能瓶颈。这个阶段重点是理解原理,知道每个参数背后的逻辑。
第三阶段,会改。能修改推理引擎的源码来适配特殊需求,能自己实现 Agent 框架的核心组件,能贡献代码到开源社区。这个阶段重点是读源码,从 issue 和 PR 里学习。
第四阶段,会设计。能设计整个 AI Infra 架构,能做技术选型和容量规划,能预判技术趋势。这个阶段重点是积累经验,多跟同行交流,多复盘项目。
7.2 值得深入的方向
如果你已经过了“会用”的阶段,这几个方向值得深入:
推理引擎的调度算法。vLLM 和 SGLang 的调度策略还有很多优化空间,特别是在异构负载场景下。理解调度算法不仅能帮你调优,还能让你在选型时更有判断力。
Agent 的记忆与规划。这是 Agent 领域最核心也最难的问题。如何让 Agent 记住关键信息、如何让 Agent 做出合理的规划,目前还没有特别成熟的方案,值得深入研究。
多模态推理。随着多模态模型越来越普及,如何高效地做多模态推理是个新问题。vLLM 和 SGLang 都在跟进,但成熟度还不如纯文本推理。
推理服务的成本优化。GPU 成本是 AI 应用的大头,如何在保证性能的前提下降低成本,是每个团队都关心的问题。量化、蒸馏、投机采样这些技术都值得研究。
7.3 我个人的一些体会
搞 AI Infra 这几年,我最大的体会是:不要追求把所有东西都学会,要追求把关键东西学透。vLLM、SGLang、PyTorch、Agent 框架,每个都深不见底,你不可能全部精通。找到你业务最依赖的那一两个,深入下去,其他的了解基本用法就够了。
另一个体会是:动手比看文档重要一百倍。我见过太多人把 vLLM 的论文读了好几遍,但连最基本的部署都没跑过。文档和论文能帮你理解原理,但真正的经验只能从动手实践中来。遇到报错不要怕,每个报错都是学习的机会。
最后一个体会是:保持跟进但不要焦虑。这个领域每天都有新东西出来,你不可能全部跟上。我的做法是关注几个核心项目的更新,其他的等用到的时候再学。技术是学不完的,但核心原理是相通的,把基础打牢,学新东西就快。
最后分享一个小技巧:建一个自己的知识库,记录每次踩坑和解决方案。我用的是 Obsidian,每次遇到问题解决后就记一条,标注日期、环境、问题现象、排查过程、解决方案。半年下来积累了上百条,再遇到类似问题直接搜知识库,效率高很多。