<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>模型推理 | 林子杨的个人网站</title><link>https://ziyanglin.netlify.app/zh/tags/%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86/</link><atom:link href="https://ziyanglin.netlify.app/zh/tags/%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86/index.xml" rel="self" type="application/rss+xml"/><description>模型推理</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh-Hans</language><lastBuildDate>Mon, 30 Jun 2025 06:00:00 +0000</lastBuildDate><image><url>https://ziyanglin.netlify.app/img/icon-192.png</url><title>模型推理</title><link>https://ziyanglin.netlify.app/zh/tags/%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86/</link></image><item><title>TensorRT深度解析：高性能深度学习推理引擎</title><link>https://ziyanglin.netlify.app/zh/post/tensorrt-documentation/</link><pubDate>Mon, 30 Jun 2025 06:00:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/zh/post/tensorrt-documentation/</guid><description>&lt;h2 id="1-">1. 引言&lt;/h2>
&lt;p>NVIDIA® TensorRT™ 是一个用于在 NVIDIA GPU 上进行高性能深度学习推理的软件开发套件（SDK）。它旨在优化和加速经过训练的神经网络，使其能够在生产环境中以低延迟和高吞吐量的方式运行。TensorRT 接收来自主流深度学习框架（如 TensorFlow、PyTorch、ONNX 等）的模型，通过一系列复杂的优化技术，生成一个高度优化的运行时引擎（Runtime Engine）。&lt;/p>
&lt;p>本文档将深入浅出地介绍 TensorRT 的核心概念、关键特性、工作流程以及最新的功能（包括专门用于加速大语言模型的 TensorRT-LLM），帮助开发者充分利用其强大的性能优势。&lt;/p>
&lt;h2 id="2-">2. 核心概念&lt;/h2>
&lt;p>理解 TensorRT 的核心组件是有效使用它的第一步。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Engine&lt;/strong>: TensorRT 的核心。它是一个经过优化的模型表示，包含了针对特定 GPU 架构和配置（如批量大小、精度）生成的计算图和权重。Engine 是不可修改的，并且是部署的最终产物。&lt;/li>
&lt;li>&lt;strong>Builder (&lt;code>IBuilder&lt;/code>)&lt;/strong>: 这是创建 Engine 的主要接口。Builder 接收一个网络定义，并应用各种优化，最终生成一个针对目标 GPU 的优化计划（Plan），该计划可以被序列化为 Engine。&lt;/li>
&lt;li>&lt;strong>Network Definition (&lt;code>INetworkDefinition&lt;/code>)&lt;/strong>: 这是您用来定义模型结构的地方。您可以从头开始手动构建网络，或者使用 Parser 从模型文件中导入。&lt;/li>
&lt;li>&lt;strong>Parser&lt;/strong>: 用于将来自不同框架的模型（主要是 ONNX 格式）解析并转换为 TensorRT 的网络定义。TensorRT 提供了强大的 ONNX 解析器。&lt;/li>
&lt;li>&lt;strong>Profiler (&lt;code>IProfiler&lt;/code>)&lt;/strong>: 一个可选的接口，允许您在构建过程中收集和查询关于层性能的信息。这有助于调试和理解哪些层是性能瓶颈。&lt;/li>
&lt;li>&lt;strong>Execution Context (&lt;code>IExecutionContext&lt;/code>)&lt;/strong>: 这是执行推理的主要接口。一个 Engine 可以有多个 Execution Context，允许并发执行推理任务。每个上下文都维护自己的输入、输出和状态。&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;模型构建 Offline&amp;quot;
A[原始模型&amp;lt;br&amp;gt;TensorFlow/PyTorch] --&amp;gt; B{ONNX Parser};
B --&amp;gt; C[Network Definition];
C --&amp;gt; D[Builder];
D -- 优化配置 --&amp;gt; E[Optimized Plan];
E --&amp;gt; F((Engine));
end
subgraph &amp;quot;推理部署 Online&amp;quot;
F --&amp;gt; G[Execution Context];
H[输入数据] --&amp;gt; G;
G --&amp;gt; I[输出结果];
end
style F fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#ccf,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;h2 id="3-">3. 关键特性和优化技术&lt;/h2>
&lt;p>TensorRT 的高性能源于其先进的优化技术。&lt;/p>
&lt;h3 id="31--precision-calibration--quantization">3.1. 精度校准与量化 (Precision Calibration &amp;amp; Quantization)&lt;/h3>
&lt;p>TensorRT 支持多种精度进行推理，包括 FP32、FP16、INT8，以及最新的 FP8。其中，INT8 量化是提升性能、降低内存占用的关键技术。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>训练后量化 (Post-Training Quantization, PTQ)&lt;/strong>: 在不重新训练模型的情况下，通过一个校准数据集来确定将 FP32 权重和激活值转换为 INT8 所需的缩放因子。&lt;/li>
&lt;li>&lt;strong>量化感知训练 (Quantization-Aware Training, QAT)&lt;/strong>: 在训练过程中模拟量化操作，使模型对量化误差更具鲁棒性，从而在转换为 INT8 时获得更高的精度。&lt;/li>
&lt;/ul>
&lt;p>您可以使用 &lt;code>QuantizationSpec&lt;/code> 来精确控制哪些层或哪些类型的层需要被量化。&lt;/p>
&lt;pre>&lt;code class="language-python"># 示例：仅量化 'Conv2D' 类型的层
q_spec = QuantizationSpec()
q_spec.add(name='Conv2D', is_keras_class=True)
q_model = quantize_model(model, quantization_mode='partial', quantization_spec=q_spec)
&lt;/code>&lt;/pre>
&lt;h3 id="32--layer--tensor-fusion">3.2. 层与张量融合 (Layer &amp;amp; Tensor Fusion)&lt;/h3>
&lt;p>TensorRT 会智能地将多个独立的层合并成一个单一的、更复杂的层。这减少了 CUDA 内核的启动次数和内存读写，从而显著降低了延迟。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>垂直融合&lt;/strong>: 将连续的、具有相同数据依赖性的层（如 Conv、Bias、ReLU）融合成一个 CBR 层。&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;融合前&amp;quot;
A[Input] --&amp;gt; B(Conv);
B --&amp;gt; C(Bias);
C --&amp;gt; D(ReLU);
D --&amp;gt; E[Output];
end
subgraph &amp;quot;融合后&amp;quot;
A2[Input] --&amp;gt; F((Conv + Bias + ReLU));
F --&amp;gt; E2[Output];
end
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>水平融合&lt;/strong>: 将具有相同输入但执行不同操作的并行层融合在一起。&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;融合前&amp;quot;
A[Input] --&amp;gt; B(Conv A);
A --&amp;gt; C(Conv B);
B --&amp;gt; D[Output A];
C --&amp;gt; E[Output B];
end
subgraph &amp;quot;融合后&amp;quot;
A2[Input] --&amp;gt; F((Conv A + Conv B));
F --&amp;gt; D2[Output A];
F --&amp;gt; E2[Output B];
end
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h3 id="33--kernel-autotuning">3.3. 内核自动调整 (Kernel Auto-Tuning)&lt;/h3>
&lt;p>针对特定的目标 GPU 架构，TensorRT 会从一个包含多种实现的库中，为每个层选择最优的 CUDA 内核。它会根据当前的批量大小、输入尺寸和参数来测试不同的算法和实现，以找到最快的一个。&lt;/p>
&lt;h3 id="34--dynamic-shapes">3.4. 动态形状 (Dynamic Shapes)&lt;/h3>
&lt;p>TensorRT 能够处理输入张量尺寸在运行时可变的模型。在构建 Engine 时，您可以指定一个优化配置文件（Optimization Profile），其中包含输入的最小、最优和最大尺寸。TensorRT 会根据这些信息生成一个可以在指定范围内高效处理任何输入尺寸的 Engine。&lt;/p>
&lt;h3 id="35--plugins">3.5. 插件 (Plugins)&lt;/h3>
&lt;p>对于 TensorRT 原生不支持的自定义或特殊层，您可以通过插件 API (&lt;code>IPluginV2&lt;/code>) 来实现自己的逻辑。这为 TensorRT 提供了极大的扩展性。&lt;/p>
&lt;p>最新的 TensorRT 版本通过装饰器极大地简化了插件的注册过程，特别是对于 Python API。&lt;/p>
&lt;pre>&lt;code class="language-python"># 示例：注册一个简单的元素级加法插件
import tensorrt.plugin as trtp
@trtp.register(&amp;quot;sample::elemwise_add_plugin&amp;quot;)
def add_plugin_desc(inp0: trtp.TensorDesc, block_size: int) -&amp;gt; trtp.TensorDesc:
return inp0.like()
&lt;/code>&lt;/pre>
&lt;h3 id="36--sparsity">3.6. 稀疏性 (Sparsity)&lt;/h3>
&lt;p>TensorRT 支持利用 NVIDIA Ampere 及更高架构 GPU 上的结构化稀疏性特性。如果您的模型权重具有 2:4 的稀疏模式，TensorRT 可以利用稀疏张量核心（Sparse Tensor Cores）来进一步加速计算，性能几乎翻倍。&lt;/p>
&lt;h2 id="4-">4. 工作流程&lt;/h2>
&lt;p>一个典型的 TensorRT 部署流程如下：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant D as 开发者
participant TF as TensorFlow/PyTorch
participant ONNX
participant Poly as Polygraphy
participant TRT as TensorRT (trtexec/API)
participant App as 应用程序
D-&amp;gt;&amp;gt;TF: 训练模型
TF--&amp;gt;&amp;gt;D: 生成训练好的模型
D-&amp;gt;&amp;gt;ONNX: 导出为 ONNX 格式
ONNX--&amp;gt;&amp;gt;D: .onnx 文件
D-&amp;gt;&amp;gt;Poly: 使用 Polygraphy 检查和优化
Poly--&amp;gt;&amp;gt;D: 优化的 .onnx 文件
D-&amp;gt;&amp;gt;TRT: 构建 Engine (FP16/INT8)
TRT--&amp;gt;&amp;gt;D: 生成 .engine 文件
D-&amp;gt;&amp;gt;App: 部署 Engine
App-&amp;gt;&amp;gt;App: 加载 Engine 并创建 Execution Context
loop 推理循环
App-&amp;gt;&amp;gt;App: 准备输入数据
App-&amp;gt;&amp;gt;App: 执行推理
App-&amp;gt;&amp;gt;App: 获取输出结果
end
&lt;/code>&lt;/pre>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>模型导出&lt;/strong>: 从您的训练框架（如 PyTorch 或 TensorFlow）中，将训练好的模型导出为 ONNX 格式。ONNX 是一个开放的模型交换格式，是连接训练和推理的桥梁。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>模型检查与优化 (Polygraphy)&lt;/strong>: 在构建 Engine 之前，强烈建议使用 &lt;strong>Polygraphy&lt;/strong> 工具集来检查、修改和优化您的 ONNX 模型。Polygraphy 是一个功能强大的工具，可以：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>检查模型&lt;/strong>: 显示模型的层、输入输出等信息。&lt;/li>
&lt;li>&lt;strong>常量折叠&lt;/strong>: 预先计算模型中的常量表达式，简化计算图。
&lt;pre>&lt;code class="language-bash">polygraphy surgeon sanitize model.onnx -o folded.onnx --fold-constants
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>比较不同框架的输出&lt;/strong>: 验证 TensorRT 与原始框架（如 ONNX Runtime）的输出是否一致，以排查精度问题。
&lt;pre>&lt;code class="language-bash">polygraphy run model.onnx --trt --onnxrt
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>处理数据依赖形状 (DDS)&lt;/strong>: 识别并为具有数据依赖形状的张量设置上界。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>构建 Engine&lt;/strong>: 使用 &lt;code>trtexec&lt;/code> 命令行工具或 TensorRT 的 C++/Python API 来构建 Engine。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;code>trtexec&lt;/code>&lt;/strong>: 一个方便的命令行工具，用于快速从 ONNX 文件构建 Engine 并进行性能基准测试。
&lt;pre>&lt;code class="language-bash">trtexec --onnx=model.onnx --saveEngine=model.engine --fp16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>API&lt;/strong>: 提供更灵活的控制，例如定义动态形状的优化配置文件、配置插件等。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>部署与推理&lt;/strong>: 将序列化后的 Engine 文件加载到您的应用程序中，并使用 Execution Context 来执行推理。&lt;/p>
&lt;pre>&lt;code class="language-python"># 使用 Polygraphy 的 TrtRunner 进行推理
from polygraphy.backend.trt import TrtRunner, EngineFromBytes
# 加载 Engine
engine = EngineFromBytes(open(&amp;quot;model.engine&amp;quot;, &amp;quot;rb&amp;quot;).read())
with TrtRunner(engine) as runner:
# 准备输入数据
feed_dict = {&amp;quot;input_name&amp;quot;: input_data}
# 执行推理
outputs = runner.infer(feed_dict=feed_dict)
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ol>
&lt;h2 id="5-">5. 最新功能亮点&lt;/h2>
&lt;p>TensorRT 正在快速迭代，以下是一些最新的重要功能：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Polygraphy 工具增强&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>简化的 CLI 语法&lt;/strong>: 允许在单个参数中同时指定脚本和函数名 (&lt;code>my_script.py:my_func&lt;/code>)。&lt;/li>
&lt;li>&lt;strong>改进的输入规范&lt;/strong>: 使用新的列表式语法 (&lt;code>--input-shapes input0:[x,y,z]&lt;/code>) 来避免歧义。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>快速部署插件 (Quickly Deployable Plugins)&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Python API 引入了 &lt;a href="mailto:%60@trtp.register">`@trtp.register&lt;/a>&lt;code>和&lt;/code>@trt.plugin.autotune` 装饰器，使得定义、注册和自动调整插件变得前所未有的简单，无需编写 C++ 代码。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>CUDA 图 (CUDA Graphs)&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>通过 &lt;code>--use-cuda-graph&lt;/code> 标志，TensorRT 可以利用 CUDA Graphs 来捕获整个推理过程，进一步减少 CPU 开销和内核启动延迟，特别适用于模型结构固定的场景。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>FP8 支持&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>在 Hopper 及更高架构的 GPU 上，TensorRT 支持 FP8 推理，为大型语言模型等提供了更高的性能和更低的内存占用。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="6-">6. 附录：常用命令&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>安装 Polygraphy&lt;/strong>:
&lt;pre>&lt;code class="language-bash">python3 -m pip install polygraphy --extra-index-url https://pypi.ngc.nvidia.com
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>构建并安装 TensorRT 开源组件&lt;/strong>:
&lt;pre>&lt;code class="language-bash"># 从源码目录
make install
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>运行 pytest 测试&lt;/strong>:
&lt;pre>&lt;code class="language-bash">pytest --verbose
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h2 id="7-tensorrtllmllm">7. TensorRT-LLM：为大语言模型（LLM）推理而生&lt;/h2>
&lt;p>随着大语言模型（LLM）的规模和复杂性呈指数级增长，传统的推理优化方法面临着前所未有的挑战。为了应对这些挑战，NVIDIA 推出了 TensorRT-LLM，一个专门为加速和优化 LLM 推理而设计的开源库。它构建于 TensorRT 之上，并封装了针对 LLM 的一系列尖端优化技术。&lt;/p>
&lt;h3 id="71--tensorrtllm">7.1. 什么是 TensorRT-LLM?&lt;/h3>
&lt;p>可以把 TensorRT-LLM 看作是 TensorRT 的一个 &amp;ldquo;LLM 专家版本&amp;rdquo;。它提供了一个 Python API，让开发者可以轻松地定义 LLM 模型，并自动应用各种SOTA（State-of-the-Art）优化。最终，它会生成一个高性能的 TensorRT 引擎，可以直接部署。&lt;/p>
&lt;p>与通用 TensorRT 主要处理静态图不同，TensorRT-LLM 专门解决了 LLM 推理中的动态特性，例如：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>自回归生成 (Autoregressive Generation)&lt;/strong>: 每个新生成的 token 都依赖于前面的 token，导致输入序列长度动态变化。&lt;/li>
&lt;li>&lt;strong>巨大的模型规模&lt;/strong>: 模型参数动辄数十亿甚至上千亿，无法单卡部署。&lt;/li>
&lt;li>&lt;strong>庞大的 KV 缓存&lt;/strong>: 推理过程中需要存储大量的键值对（Key-Value Cache），对内存带宽和容量提出极高要求。&lt;/li>
&lt;/ul>
&lt;h3 id="72-">7.2. 核心架构与组件&lt;/h3>
&lt;p>TensorRT-LLM 的架构分为前端和后端：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Python API (&lt;code>tensorrt_llm&lt;/code>)&lt;/strong>: 这是用户交互的主要接口。它以声明式的方式定义模型（类似于 PyTorch），开发者无需关心底层复杂的 TensorRT C++ API。&lt;/li>
&lt;li>&lt;strong>C++ Backend&lt;/strong>: 这是真正执行优化的核心，包含了预先写好的、高度优化的 CUDA 内核、LLM 专属优化 pass 以及一个能够高效处理 LLM 任务的运行时。&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-mermaid">graph TD;
subgraph &amp;quot;前端 (Python API)&amp;quot;
A[Hugging Face / 自定义模型] --&amp;gt;|权重| B(模型定义&amp;lt;br&amp;gt;tensorrt_llm.Module);
B --&amp;gt; C{Builder};
C -- 生成网络和配置 --&amp;gt; D[Network Definition];
end
subgraph &amp;quot;后端 (C++ Runtime)&amp;quot;
D --&amp;gt; E[TensorRT-LLM 优化];
E --&amp;gt; F((LLM 优化版 Engine));
end
subgraph &amp;quot;推理&amp;quot;
F --&amp;gt; G[C++/Python Runtime];
H[输入 Prompts] --&amp;gt; G;
G --&amp;gt; I[输出 Tokens];
end
style F fill:#c9f,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;h3 id="73-llm-">7.3. 关键优化技术（LLM 专属）&lt;/h3>
&lt;p>TensorRT-LLM 的魔力在于其专为 LLM 设计的优化技术。&lt;/p>
&lt;h4 id="731-inflight-batching--continuous-batching">7.3.1. In-Flight Batching (也称 Continuous Batching)&lt;/h4>
&lt;p>&lt;strong>问题&lt;/strong>: 传统的批处理（Static Batching）要求所有请求都等待，直到湊够一个批次再一起处理。由于每个请求的生成长度不同，这会导致大量 GPU 空闲（&amp;ldquo;气泡&amp;rdquo;），因为必须等待批次中最慢的请求完成。&lt;/p>
&lt;p>&lt;strong>解决方案&lt;/strong>: In-Flight Batching 允许服务器在 GPU 运行时动态地加入新的请求，一旦某个请求完成，其占用的计算资源立即被释放并分配给等待队列中的新请求。这极大地提高了 GPU 的利用率和系统的总吞吐量。&lt;/p>
&lt;pre>&lt;code class="language-mermaid">gantt
title GPU 利用率对比
dateFormat X
axisFormat %S
section 静态批处理 (Static Batching)
请求 A: 0, 6
请求 B: 0, 3
请求 C: 0, 5
GPU 等待 : 3, 3
GPU 等待 : 5, 1
section In-Flight Batching
请求 A : 0, 6
请求 B : 0, 3
请求 C : 0, 5
新请求 D : 3, 4
&lt;/code>&lt;/pre>
&lt;h4 id="732-paged-kv-cache--attention">7.3.2. Paged KV Cache &amp;amp; Attention&lt;/h4>
&lt;p>&lt;strong>问题&lt;/strong>: 在自回归生成过程中，KV 缓存会随着序列长度的增加而线性增长，消耗大量显存。传统的做法是为每个请求预分配一个连续的、能容纳最大序列长度的内存块，这导致了严重的内存碎片和浪费。&lt;/p>
&lt;p>&lt;strong>解决方案&lt;/strong>: 受到操作系统虚拟内存分页的启发，TensorRT-LLM 引入了 Paged KV Cache。它将 KV 缓存分割成固定大小的&amp;quot;块&amp;rdquo;（Blocks），并按需分配。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>非连续存储&lt;/strong>: 逻辑上连续的 Token 的 KV 缓存可以存储在物理上不连续的块中。&lt;/li>
&lt;li>&lt;strong>内存共享&lt;/strong>: 对于复杂的场景（如并行采样、Beam Search），不同序列之间可以共享相同的 KV 缓存块（例如共享 Prompt部分的缓存），从而大幅节省内存。&lt;/li>
&lt;li>&lt;strong>优化的 Attention 核&lt;/strong>: TensorRT-LLM 使用了如 FlashAttention、MQA/GQA 等专门优化的 Attention 内核，可以直接操作这些非连续的缓存块，避免了数据拷贝开销。&lt;/li>
&lt;/ul>
&lt;h4 id="733--tensor--pipeline-parallelism">7.3.3. 张量并行与流水线并行 (Tensor &amp;amp; Pipeline Parallelism)&lt;/h4>
&lt;p>对于无法在单个 GPU 上容纳的大型模型，TensorRT-LLM 内置了对张量并行（Tensor Parallelism）和流水线并行（Pipeline Parallelism）的无缝支持。开发者只需在构建时指定并行度（&lt;code>tp_size&lt;/code>, &lt;code>pp_size&lt;/code>），TensorRT-LLM 就会自动处理模型的切分和跨 GPU 的通信。&lt;/p>
&lt;pre>&lt;code class="language-bash"># 示例：构建一个 2 路张量并行的 Llama 模型
python3 examples/llama/convert_checkpoint.py \
--model_dir ./llama-7b-hf \
--output_dir ./tllm_checkpoint_tp2 \
--dtype float16 \
--tp_size 2
&lt;/code>&lt;/pre>
&lt;h4 id="734--fp8int4int8">7.3.4. 先进的量化支持 (FP8/INT4/INT8)&lt;/h4>
&lt;p>LLM 的巨大参数量使其成为量化的理想对象。TensorRT-LLM 支持多种先进的量化方案：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FP8&lt;/strong>: 在 NVIDIA Hopper 及更高架构的 GPU 上，FP8 提供了接近 FP16 的精度，同时显著提升了性能和降低了内存占用。&lt;/li>
&lt;li>&lt;strong>INT8 SmoothQuant&lt;/strong>: 一种同时量化激活值和权重的技术，能在保持较高精度的同时获得 INT8 的加速。&lt;/li>
&lt;li>&lt;strong>INT4/INT8 仅权重化 (Weight-Only Quantization, W4A16/W8A16)&lt;/strong>: 这是一种非常流行的技术，仅将模型权重（参数量最大部分）量化为 INT4 或 INT8，而激活值保持 FP16。这极大地降低了内存占用，同时对精度的影响很小。&lt;/li>
&lt;/ul>
&lt;pre>&lt;code class="language-bash"># 示例：构建一个 INT4 仅权重化量化的模型
python convert_checkpoint.py --model_dir ./gpt-j-6b \
--dtype float16 \
--use_weight_only \
--weight_only_precision int4 \
--output_dir ./trt_ckpt/gptj_int4wo_tp1/
&lt;/code>&lt;/pre>
&lt;h3 id="74-tensorrtllm-">7.4. TensorRT-LLM 工作流程&lt;/h3>
&lt;p>一个典型的 TensorRT-LLM 工作流程如下：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant D as 开发者
participant HF as Hugging Face Hub
participant Conv as convert_checkpoint.py
participant Build as trtllm-build
participant App as 推理应用 (Python/C++)
D-&amp;gt;&amp;gt;HF: 下载模型权重
HF--&amp;gt;&amp;gt;D: model_dir
D-&amp;gt;&amp;gt;Conv: 运行转换脚本 (指定精度、并行度等)
Conv--&amp;gt;&amp;gt;D: 生成 TensorRT-LLM Checkpoint
D-&amp;gt;&amp;gt;Build: 运行构建命令 (指定插件、BatchSize等)
Build--&amp;gt;&amp;gt;D: 生成优化后的 .engine 文件
D-&amp;gt;&amp;gt;App: 加载 Engine 并运行推理
App--&amp;gt;&amp;gt;D: 返回生成结果
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>端到端示例 (以 Llama-7B 为例)&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>转换权重&lt;/strong>:
&lt;pre>&lt;code class="language-bash">git clone https://huggingface.co/meta-llama/Llama-2-7b-hf
python3 examples/llama/convert_checkpoint.py \
--model_dir ./Llama-2-7b-hf \
--output_dir ./tllm_checkpoint_1gpu \
--dtype float16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>构建 Engine&lt;/strong>:
&lt;pre>&lt;code class="language-bash">trtllm-build --checkpoint_dir ./tllm_checkpoint_1gpu \
--output_dir ./trt_engines/llama_7b \
--gpt_attention_plugin float16 \
--gemm_plugin float16
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>&lt;strong>运行推理&lt;/strong>:
&lt;pre>&lt;code class="language-bash">python3 examples/run.py --max_output_len=100 \
--tokenizer_dir ./Llama-2-7b-hf \
--engine_dir=./trt_engines/llama_7b
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ol>
&lt;h3 id="75--api-llm">7.5. 便捷的高层级 API (&lt;code>LLM&lt;/code>)&lt;/h3>
&lt;p>为了进一步简化开发流程，TensorRT-LLM 提供了一个名为 &lt;code>LLM&lt;/code> 的高层级 API。这个接口将模型加载、构建、保存和推理封装成一个简单的类，让开发者在几行代码内就能完成所有操作。&lt;/p>
&lt;pre>&lt;code class="language-python">from tensorrt_llm import LLM
# 1. 初始化 LLM 对象，如果引擎不存在，它会自动从 HuggingFace 模型构建
# 这里会应用所有优化，如 In-Flight Batching, Paged KV-Cache
llm = LLM(
model=&amp;quot;meta-llama/Llama-2-7b-hf&amp;quot;,
tensor_parallel_size=1,
)
# 2. (可选) 保存构建好的引擎以备后用
llm.save(&amp;quot;llama_engine_dir&amp;quot;)
# 3. 运行推理
prompt = &amp;quot;NVIDIA TensorRT-LLM is&amp;quot;
for output in llm.generate([prompt], max_new_tokens=50):
print(output)
&lt;/code>&lt;/pre>
&lt;p>这个高层级 API 是快速原型设计和部署的理想选择。&lt;/p>
&lt;h3 id="76-">7.6. 总结&lt;/h3>
&lt;p>TensorRT-LLM 并非简单地将 TensorRT 应用于 LLM，而是一个从根本上为 LLM 推理重新设计的、包含多种SOTA优化的综合性解决方案。通过 In-Flight Batching、Paged KV-Cache、原生并行支持和先进的量化方案，它能够将 NVIDIA GPU 的硬件性能发挥到极致，为部署高性能、高吞吐量的 LLM 服务提供了坚实的基础。&lt;/p></description></item><item><title>SGLang 技术指南：高性能结构化生成语言框架</title><link>https://ziyanglin.netlify.app/zh/post/sglang-documentation/</link><pubDate>Thu, 26 Jun 2025 01:07:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/zh/post/sglang-documentation/</guid><description>&lt;h2 id="1-sglang-">1. SGLang 简介&lt;/h2>
&lt;p>SGLang (Structured Generation Language) 是一个为大型语言模型（LLM）和视觉语言模型（VLM）设计的高性能服务框架。它的核心目标是解决在实际应用中常见的复杂 LLM 程序所面临的挑战，即在保持灵活性的同时，最大化推理过程的性能。&lt;/p>
&lt;p>传统的 LLM 服务框架（如 vLLM）在处理简单的、一次性的提示（one-shot prompting）时表现出色，但在需要多轮交互、结构化输出、函数调用或控制流的复杂场景下，其性能和易用性会受到限制。SGLang 通过引入一种新颖的前端语言和高效的后端运行时，有效地弥补了这一差距。&lt;/p>
&lt;p>&lt;strong>SGLang 的核心优势包括：&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>卓越的性能：&lt;/strong> SGLang 引入了 &lt;strong>RadixAttention&lt;/strong>，这是一种创新的注意力机制，可以自动、无损地复用键值缓存（KV Cache），从而显著提升了具有复杂提示（如 CoT、ReAct）或多轮对话场景下的推理速度。与 vLLM 等领先框架相比，SGLang 在这些场景下可以实现数倍的吞吐量提升。&lt;/li>
&lt;li>&lt;strong>强大的编程能力：&lt;/strong> SGLang 提供了一种直观的前端语言（DSL），允许开发者使用 Pythonic 的方式来编排复杂的生成任务。你可以轻松地定义变量、使用循环和条件判断、调用外部工具，并将这些逻辑与 LLM 的生成过程无缝集成。这使得构建复杂的 AI Agent、多轮对话系统和结构化数据提取任务变得前所未有的简单。&lt;/li>
&lt;li>&lt;strong>统一的前后端接口：&lt;/strong> SGLang 将前端的编程逻辑与后端的推理服务解耦。前端负责定义&amp;quot;生成什么&amp;rdquo;，后端负责&amp;quot;如何高效生成&amp;rdquo;。这种设计不仅简化了开发流程，还使得 SGLang 能够兼容 OpenAI 的 API 标准，让用户可以轻松地将现有应用迁移到 SGLang 上，立即享受性能红利。&lt;/li>
&lt;li>&lt;strong>灵活的结构化输出：&lt;/strong> SGLang 提供了强大的结构化输出约束功能。无论是通过正则表达式、EBNF 文法还是 JSON Schema，你都可以精确地控制 LLM 的输出格式，确保生成的内容符合预期的结构，这对于需要可靠数据格式的应用至关重要。&lt;/li>
&lt;/ul>
&lt;p>总而言之，SGLang 不仅仅是一个 LLM 推理加速引擎，更是一个完整的、面向复杂生成任务的编程和执行框架。它旨在让开发者能够以一种既高效又直观的方式，充分释放大型语言模型的潜力。&lt;/p>
&lt;h2 id="2-">2. 核心特性&lt;/h2>
&lt;p>SGLang 的强大之处在于其独特的设计，它将直观的前端编程模型与高效的后端执行引擎相结合。以下是其几个核心特性的详细介绍。&lt;/p>
&lt;h3 id="21-radixattention-kv-">2.1 RadixAttention：为复杂提示而生的 KV 缓存优化&lt;/h3>
&lt;p>在处理复杂的 LLM 程序时，例如思维链（Chain-of-Thought）、多轮对话或需要调用工具的 Agent，提示（Prompt）中往往包含大量共享的前缀。传统的注意力机制在处理这些共享前缀时会产生冗余的计算和存储。&lt;/p>
&lt;p>SGLang 引入了 &lt;strong>RadixAttention&lt;/strong>，这是一种新颖的 KV 缓存优化技术。其核心思想是将提示组织成一棵基数树（Radix Tree），并在这个树上执行注意力计算。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>自动共享与复用&lt;/strong>：RadixAttention 能够自动识别并共享不同请求之间的公共前缀，从而避免了重复计算和存储。例如，在多轮对话中，每一轮的对话历史都可以被后续轮次无损地复用。&lt;/li>
&lt;li>&lt;strong>性能提升&lt;/strong>：通过最大化 KV 缓存的复用，RadixAttention 显著减少了内存占用和计算量，从而将吞吐量提升了2到5倍，尤其是在处理长提示或高并发请求时效果更为明显。&lt;/li>
&lt;/ul>
&lt;p>下面是一个 Mermaid 图，用于直观地展示 RadixAttention 如何处理共享前缀的请求：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph &amp;quot;传统方法 (无共享)&amp;quot;
req1[&amp;quot;请求1: 'A B C D'&amp;quot;]
req2[&amp;quot;请求2: 'A B E F'&amp;quot;]
kv1[&amp;quot;KV 缓存: [A, B, C, D]&amp;quot;]
kv2[&amp;quot;KV 缓存: [A, B, E, F]&amp;quot;]
req1 --&amp;gt; kv1
req2 --&amp;gt; kv2
end
subgraph &amp;quot;SGLang RadixAttention&amp;quot;
Root(&amp;quot;Root&amp;quot;) --&amp;gt; A(&amp;quot;Token 'A'&amp;quot;);
A --&amp;gt; B(&amp;quot;Token 'B'&amp;quot;);
B --&amp;gt; C(&amp;quot;Token 'C'&amp;quot;);
B --&amp;gt; E(&amp;quot;Token 'E'&amp;quot;);
C --&amp;gt; D(&amp;quot;Token 'D'&amp;quot;);
E --&amp;gt; F(&amp;quot;Token 'F'&amp;quot;);
style A fill:#9f9
style B fill:#9f9
end
&lt;/code>&lt;/pre>
&lt;p>在上图中，对于两个请求 &lt;code>'A B C D'&lt;/code> 和 &lt;code>'A B E F'&lt;/code>，传统方法会创建两个独立的 KV 缓存。而 RadixAttention 将它们组织成一棵树，共享了公共前缀 &lt;code>'A B'&lt;/code>（绿色节点）的计算和存储，只为不同的部分（C, D, E, F）创建新的分支。这极大地提高了内存和计算效率。&lt;/p>
&lt;h3 id="22-dsl">2.2 统一的前端编程语言（DSL）&lt;/h3>
&lt;p>SGLang 提供了一种富有表现力的领域特定语言（DSL），它深度集成在 Python 中，使得开发者可以用非常自然和直观的方式来构建复杂的生成逻辑。&lt;/p>
&lt;h3 id="sglang-">SGLang 架构概览&lt;/h3>
&lt;p>为了更好地理解 SGLang 的工作方式，我们可以通过下面的流程图来观察其核心架构：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph 用户侧
A[开发者定义 SGLang 程序&amp;lt;br&amp;gt;使用 function 装饰器] --&amp;gt; B{调用 run 方法};
end
subgraph SGLang 前端
B --&amp;gt; C[1. 解析 Python AST&amp;lt;br&amp;gt;分离确定性逻辑和生成指令];
C --&amp;gt; D[2. 构建可移植的&amp;lt;br&amp;gt;SGLang IR 中间表示];
end
subgraph 网络通信
D -- HTTP Request --&amp;gt; E[SGLang 后端服务 SRT];
end
subgraph SGLang 后端 SRT
E --&amp;gt; F[3. 接收 IR 并调度];
F --&amp;gt; G{RadixAttention 引擎};
G --&amp;gt; H[4. 高效执行&amp;lt;br&amp;gt;KV 缓存复用];
H --&amp;gt; I[LLM/VLM 模型];
I --&amp;gt; J[5. 生成结果];
end
subgraph 返回路径
J -- HTTP Response --&amp;gt; K[返回结果给前端];
K --&amp;gt; L[6. 填充状态对象 `s`];
L --&amp;gt; M[用户获得最终结果];
end
style B fill:#f9f,stroke:#333,stroke-width:2px
style E fill:#ccf,stroke:#333,stroke-width:2px
style G fill:#9cf,stroke:#333,stroke-width:2px
&lt;/code>&lt;/pre>
&lt;p>这个图表清晰地展示了 SGLang 如何将前端的编程便利性与后端的高性能执行引擎解耦并结合起来。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Pythonic 控制流&lt;/strong>：你可以在 SGLang 函数中直接使用 &lt;code>if/else&lt;/code>、&lt;code>for&lt;/code> 循环等标准的 Python 控制流语句，来动态地构建提示。&lt;/li>
&lt;li>&lt;strong>生成与逻辑的结合&lt;/strong>：通过 &lt;code>@function&lt;/code> 装饰器和 &lt;code>gen()&lt;/code> 指令，SGLang 将 LLM 的生成过程（&amp;ldquo;不确定性&amp;quot;部分）与程序的确定性逻辑无缝地结合在一起。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>示例：根据条件生成不同的内容&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from sglang import function, system, user, assistant, gen
@function
def tool_use(s, question):
s += system(&amp;quot;You are a helpful assistant.&amp;quot;)
s += user(question)
s += assistant(
&amp;quot;To answer this question, I need to use a &amp;quot;
+ gen(&amp;quot;tool&amp;quot;, choices=[&amp;quot;calculator&amp;quot;, &amp;quot;search engine&amp;quot;])
+ &amp;quot;. &amp;quot;
)
if s[&amp;quot;tool&amp;quot;] == &amp;quot;calculator&amp;quot;:
s += assistant(&amp;quot;The math expression is: &amp;quot; + gen(&amp;quot;expression&amp;quot;))
elif s[&amp;quot;tool&amp;quot;] == &amp;quot;search engine&amp;quot;:
s += assistant(&amp;quot;The key word to search is: &amp;quot; + gen(&amp;quot;word&amp;quot;))
state = tool_use.run(&amp;quot;What is the population of London?&amp;quot;)
print(state[&amp;quot;tool&amp;quot;])
# Output: search engine
print(state[&amp;quot;word&amp;quot;])
# Output: population of London
&lt;/code>&lt;/pre>
&lt;p>在这个例子中，程序首先让 LLM 在 &amp;ldquo;calculator&amp;rdquo; 和 &amp;ldquo;search engine&amp;rdquo; 中选择一个工具，然后根据 LLM 的选择，执行不同的逻辑分支，引导 LLM 生成下一步的内容。&lt;/p>
&lt;h3 id="23-">2.3 强大的结构化输出&lt;/h3>
&lt;p>为了确保 LLM 生成的内容能够被下游程序可靠地解析和使用，SGLang 提供了多种强大的结构化输出约束机制。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>正则表达式（Regex）&lt;/strong>：你可以提供一个正则表达式，强制模型的输出严格匹配该模式。这对于生成特定格式的标识符、数字或简单的文本片段非常有用。&lt;/p>
&lt;pre>&lt;code class="language-python">response = client.chat.completions.create(
model=&amp;quot;deepseek-ai/DeepSeek-R1-Distill-Qwen-7B&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;What is the capital of France?&amp;quot;}],
extra_body={&amp;quot;regex&amp;quot;: &amp;quot;(Paris|London)&amp;quot;},
)
# response.choices[0].message.content 将必然是 &amp;quot;Paris&amp;quot; 或 &amp;quot;London&amp;quot;
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>EBNF 文法&lt;/strong>：对于更复杂的语法结构，你可以使用扩展巴科斯范式（EBNF）来定义一个完整的文法。这使得你可以生成严格遵守特定语法的代码、DSL 或其他结构化文本。&lt;/p>
&lt;pre>&lt;code class="language-python">ebnf_grammar = &amp;quot;&amp;quot;&amp;quot;
root ::= city &amp;quot; is the capital of &amp;quot; country
city ::= &amp;quot;London&amp;quot; | &amp;quot;Paris&amp;quot; | &amp;quot;Berlin&amp;quot; | &amp;quot;Rome&amp;quot;
country ::= &amp;quot;England&amp;quot; | &amp;quot;France&amp;quot; | &amp;quot;Germany&amp;quot; | &amp;quot;Italy&amp;quot;
&amp;quot;&amp;quot;&amp;quot;
response = client.chat.completions.create(
model=&amp;quot;meta-llama/Meta-Llama-3.1-8B-Instruct&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Give me the information of the capital of France.&amp;quot;}],
extra_body={&amp;quot;ebnf&amp;quot;: ebnf_grammar},
)
# response.choices[0].message.content 将会是 &amp;quot;Paris is the capital of France&amp;quot;
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>JSON Schema&lt;/strong>：SGLang 支持使用 JSON Schema 来约束模型生成结构化的 JSON 对象。你可以直接定义 JSON Schema，或者使用 Pydantic 模型来自动生成。这对于需要可靠、可验证的 JSON 输出的 API 和数据处理任务至关重要。&lt;/p>
&lt;pre>&lt;code class="language-python">from pydantic import BaseModel
class CapitalInfo(BaseModel):
name: str
population: int
response = client.chat.completions.create(
model=&amp;quot;deepseek-ai/DeepSeek-R1-Distill-Qwen-7B&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Give me the information and population of the capital of France in the JSON format.&amp;quot;}],
response_format={
&amp;quot;type&amp;quot;: &amp;quot;json_schema&amp;quot;,
&amp;quot;json_schema&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;capital_info&amp;quot;,
&amp;quot;schema&amp;quot;: CapitalInfo.model_json_schema(),
},
},
)
# response.choices[0].message.content 将会是一个符合 CapitalInfo 结构的 JSON 字符串
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h2 id="3-">3. 快速入门&lt;/h2>
&lt;p>本章节将指导你完成 SGLang 的安装、服务启动和基本使用，让你在几分钟内体验到 SGLang 的强大功能。&lt;/p>
&lt;h3 id="31-">3.1 安装&lt;/h3>
&lt;p>SGLang 可以通过 &lt;code>pip&lt;/code> 或更快的 &lt;code>uv&lt;/code> 进行安装。为了获得最佳体验和全部功能，推荐安装 &lt;code>all&lt;/code> 版本。&lt;/p>
&lt;p>&lt;strong>使用 pip:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">pip install --upgrade pip
pip install &amp;quot;sglang[all]&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>使用 uv (推荐，速度更快):&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">pip install uv
uv pip install &amp;quot;sglang[all]&amp;quot;
&lt;/code>&lt;/pre>
&lt;blockquote>
&lt;p>&lt;strong>注意&lt;/strong>: 安装过程可能需要编译 CUDA 内核（如 &lt;code>flashinfer&lt;/code>），请确保你的环境中已正确配置 &lt;code>CUDA_HOME&lt;/code> 环境变量，并且 CUDA 版本与 PyTorch 版本兼容。&lt;/p>
&lt;/blockquote>
&lt;h3 id="32--srt">3.2 启动后端服务 (SRT)&lt;/h3>
&lt;p>安装完成后，下一步是启动 SGLang 的后端服务（SRT, SGLang Runtime）。该服务将加载指定的语言模型，并提供一个与 OpenAI API 兼容的接口。&lt;/p>
&lt;p>在你的终端中运行以下命令：&lt;/p>
&lt;pre>&lt;code class="language-bash">python -m sglang.launch_server --model-path meta-llama/Meta-Llama-3.1-8B-Instruct --host 0.0.0.0 --port 30000
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>参数说明:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>--model-path&lt;/code>: 指定要加载的模型的路径。可以是 Hugging Face Hub 上的模型名称（如本例所示），也可以是本地的模型路径。&lt;/li>
&lt;li>&lt;code>--host&lt;/code>: 服务监听的主机地址。&lt;code>0.0.0.0&lt;/code> 表示允许从任何网络接口访问。&lt;/li>
&lt;li>&lt;code>--port&lt;/code>: 服务监听的端口号。&lt;/li>
&lt;/ul>
&lt;p>服务成功启动后，你将看到类似以下的输出，表示模型已加载并准备好接收请求。&lt;/p>
&lt;pre>&lt;code>INFO: Uvicorn running on http://0.0.0.0:30000 (Press CTRL+C to quit)
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
&lt;/code>&lt;/pre>
&lt;h3 id="33-">3.3 发送第一个请求&lt;/h3>
&lt;p>服务正在运行，现在我们可以通过 OpenAI 的 Python 客户端库来与之交互。&lt;/p>
&lt;p>创建一个名为 &lt;code>test_sglang.py&lt;/code> 的 Python 文件，并填入以下内容：&lt;/p>
&lt;pre>&lt;code class="language-python">import openai
# 初始化客户端，指向我们本地启动的 SGLang 服务
client = openai.Client(
base_url=&amp;quot;http://127.0.0.1:30000/v1&amp;quot;,
api_key=&amp;quot;EMPTY&amp;quot; # SGLang 服务不需要 API Key
)
# 创建一个聊天补全请求
response = client.chat.completions.create(
model=&amp;quot;meta-llama/Meta-Llama-3.1-8B-Instruct&amp;quot;, # 必须与服务加载的模型一致
messages=[
{&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;You are a helpful assistant.&amp;quot;},
{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;What is the capital of France and why is it famous?&amp;quot;},
],
temperature=0.7,
max_tokens=150,
)
# 打印模型的回复
print(response.choices[0].message.content)
&lt;/code>&lt;/pre>
&lt;p>运行这个脚本：&lt;/p>
&lt;pre>&lt;code class="language-bash">python test_sglang.py
&lt;/code>&lt;/pre>
&lt;p>你将看到模型生成的关于巴黎的详细回答。至此，你已经成功地使用 SGLang 完成了一次从服务部署到推理请求的全过程！&lt;/p>
&lt;h2 id="4--sglang-dsl">4. 前端语言 (SGLang DSL)&lt;/h2>
&lt;p>SGLang 的前端语言（DSL）是其易用性的核心。它允许你以声明式的方式定义复杂的生成流程，将 Python 的灵活性与 LLM 的生成能力完美结合。&lt;/p>
&lt;h3 id="41-function-">4.1 &lt;code>@function&lt;/code> 装饰器&lt;/h3>
&lt;p>所有 SGLang 程序都始于一个由 &lt;code>@function&lt;/code> 装饰的 Python 函数。这个装饰器会将一个普通的 Python 函数转换成一个可执行的 SGLang 程序模板。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>状态管理&lt;/strong>：函数的第一个参数（通常命名为 &lt;code>s&lt;/code>）代表了当前的生成状态（state）。它是一个类似字典的对象，用于存储和传递生成过程中产生的所有变量。&lt;/li>
&lt;li>&lt;strong>延迟执行&lt;/strong>：被 &lt;code>@function&lt;/code> 装饰的函数在定义时不会立即执行。相反，它会创建一个可重用的模板。只有当调用 &lt;code>.run()&lt;/code> 或 &lt;code>.run_batch()&lt;/code> 方法时，程序才会真正执行。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>交互流程&lt;/strong>&lt;/p>
&lt;p>整个函数调用的交互流程可以用下面的序列图来表示：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant User as 用户
participant App as 应用 (Python)
participant SGLang as SGLang 服务
participant Tool as 外部工具 (e.g., 天气API)
User-&amp;gt;&amp;gt;+App: &amp;quot;波士顿的天气怎么样？&amp;quot;
App-&amp;gt;&amp;gt;+SGLang: 发送包含 messages 和 tools 的请求
SGLang-&amp;gt;&amp;gt;SGLang: 模型决定调用 get_current_weather
SGLang--&amp;gt;&amp;gt;-App: 返回 tool_calls，包含函数名和参数
App-&amp;gt;&amp;gt;App: 解析 tool_calls
App-&amp;gt;&amp;gt;+Tool: 调用 get_current_weather(city=&amp;quot;Boston&amp;quot;, unit=&amp;quot;fahrenheit&amp;quot;)
Tool--&amp;gt;&amp;gt;-App: 返回天气结果: &amp;quot;68°F&amp;quot;
App-&amp;gt;&amp;gt;+SGLang: 发送包含天气结果的新一轮请求
SGLang-&amp;gt;&amp;gt;SGLang: 模型根据天气结果生成最终回复
SGLang--&amp;gt;&amp;gt;-App: 返回最终的自然语言回复
App--&amp;gt;&amp;gt;-User: &amp;quot;波士顿现在是 68°F。&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>这个序列图清晰地展示了从用户提问到模型决策、工具调用、结果整合，再到最终回复的完整闭环。&lt;/p>
&lt;h3 id="42-">4.2 核心指令&lt;/h3>
&lt;p>在 SGLang 函数内部，你使用一系列指令来构建提示和控制生成流程。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>角色指令&lt;/strong>: &lt;code>system()&lt;/code>, &lt;code>user()&lt;/code>, &lt;code>assistant()&lt;/code>
这些指令用于定义对话的不同部分，符合标准的多轮对话格式。你可以将字符串直接传递给它们。&lt;/li>
&lt;li>&lt;strong>生成指令&lt;/strong>: &lt;code>gen()&lt;/code>
这是 SGLang 中最重要的指令。它告诉 LLM 在当前位置生成文本。
&lt;ul>
&lt;li>&lt;code>s += gen(&amp;quot;variable_name&amp;quot;, ...)&lt;/code>: &lt;code>gen()&lt;/code> 的第一个参数是必需的，它指定了生成结果将存储在状态 &lt;code>s&lt;/code> 中的变量名。&lt;/li>
&lt;li>&lt;code>max_tokens&lt;/code>: 限制生成的最大 token 数量。&lt;/li>
&lt;li>&lt;code>stop&lt;/code>: 定义一个或多个停止字符串。当模型生成这些字符串时，生成过程会提前结束。&lt;/li>
&lt;li>&lt;code>choices&lt;/code>: 提供一个字符串列表，强制模型从这些选项中选择一个进行生成。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>示例：一个完整的前端函数&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from sglang import function, system, user, assistant, gen, set_default_backend, OpenAI
# 设置后端为 SGLang 提供的 OpenAI 兼容服务
set_default_backend(OpenAI(&amp;quot;meta-llama/Meta-Llama-3.1-8B-Instruct&amp;quot;))
@function
def multi_turn_qa(s, question1, question2):
s += system(&amp;quot;You are a helpful assistant.&amp;quot;)
s += user(question1)
s += assistant(gen(&amp;quot;answer1&amp;quot;, max_tokens=128))
s += user(question2)
s += assistant(gen(&amp;quot;answer2&amp;quot;, max_tokens=128))
# 执行 SGLang 程序
state = multi_turn_qa.run(
question1=&amp;quot;What is the capital of the UK?&amp;quot;,
question2=&amp;quot;What is its population?&amp;quot;,
temperature=0.1
)
print(&amp;quot;Answer 1:&amp;quot;, state[&amp;quot;answer1&amp;quot;])
print(&amp;quot;Answer 2:&amp;quot;, state[&amp;quot;answer2&amp;quot;])
&lt;/code>&lt;/pre>
&lt;h3 id="43-">4.3 流式输出&lt;/h3>
&lt;p>对于需要实时反馈的应用，SGLang 支持流式输出。只需在 &lt;code>.run()&lt;/code> 方法中设置 &lt;code>stream=True&lt;/code>，然后迭代返回的状态对象的 &lt;code>.text_iter()&lt;/code> 方法即可。&lt;/p>
&lt;pre>&lt;code class="language-python">state = multi_turn_qa.run(
question1=&amp;quot;Write a short story about a robot.&amp;quot;,
question2=&amp;quot;Continue the story.&amp;quot;,
stream=True
)
for out in state.text_iter(&amp;quot;answer2&amp;quot;):
print(out, end=&amp;quot;&amp;quot;, flush=True)
&lt;/code>&lt;/pre>
&lt;h2 id="5--srt--api-">5. 后端服务 (SRT) 与 API 参考&lt;/h2>
&lt;p>SGLang 的后端，即 SGLang Runtime (SRT)，是一个用 Python 实现的高性能推理服务器。它负责加载模型、管理 KV 缓存（通过 RadixAttention），并处理来自客户端的请求。SRT 提供了两种主要的 API 端点。&lt;/p>
&lt;h3 id="51--api-generate">5.1 原生 API: &lt;code>/generate&lt;/code>&lt;/h3>
&lt;p>这是一个更底层的 API，提供了对生成过程最精细的控制。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Endpoint&lt;/strong>: &lt;code>POST /generate&lt;/code>&lt;/li>
&lt;li>&lt;strong>描述&lt;/strong>: 从给定的文本提示开始生成文本。&lt;/li>
&lt;li>&lt;strong>核心参数&lt;/strong>:
&lt;ul>
&lt;li>&lt;code>text&lt;/code> (string, required): 输入的文本提示。&lt;/li>
&lt;li>&lt;code>sampling_params&lt;/code> (object, optional): 一个包含采样参数的 JSON 对象。
&lt;ul>
&lt;li>&lt;code>temperature&lt;/code> (float): 采样温度。&lt;/li>
&lt;li>&lt;code>max_new_tokens&lt;/code> (int): 最大新生成 token 数。&lt;/li>
&lt;li>&lt;code>stop&lt;/code> (string or list[string]): 停止符。&lt;/li>
&lt;li>&lt;code>json_schema&lt;/code> (string): JSON Schema 字符串，用于约束输出。&lt;/li>
&lt;li>&lt;code>regex&lt;/code> (string): 正则表达式，用于约束输出。&lt;/li>
&lt;li>&lt;code>ebnf&lt;/code> (string): EBNF 文法，用于约束输出。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>stream&lt;/code> (boolean, optional): 是否使用流式传输。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>示例 (使用 &lt;code>requests&lt;/code>)&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-python">import requests
import json
url = &amp;quot;http://127.0.0.1:30000/generate&amp;quot;
data = {
&amp;quot;text&amp;quot;: &amp;quot;The capital of France is&amp;quot;,
&amp;quot;sampling_params&amp;quot;: {
&amp;quot;temperature&amp;quot;: 0,
&amp;quot;max_new_tokens&amp;quot;: 16,
}
}
response = requests.post(url, json=data)
print(response.json())
# {'text': ' Paris.\n\nThe capital of France is Paris. It is the most populous city in', 'meta': ...}
&lt;/code>&lt;/pre>
&lt;h3 id="52-openai--api-v1chatcompletions">5.2 OpenAI 兼容 API: &lt;code>/v1/chat/completions&lt;/code>&lt;/h3>
&lt;p>为了方便迁移和集成，SGLang 提供了与 OpenAI 完全兼容的聊天补全 API。你可以无缝地使用 OpenAI 的官方客户端库。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Endpoint&lt;/strong>: &lt;code>POST /v1/chat/completions&lt;/code>&lt;/li>
&lt;li>&lt;strong>描述&lt;/strong>: 执行聊天式文本生成。&lt;/li>
&lt;li>&lt;strong>核心参数&lt;/strong>:
&lt;ul>
&lt;li>&lt;code>model&lt;/code> (string, required): 模型的名称。&lt;/li>
&lt;li>&lt;code>messages&lt;/code> (list[object], required): 对话消息列表。&lt;/li>
&lt;li>&lt;code>temperature&lt;/code>, &lt;code>max_tokens&lt;/code>, &lt;code>stream&lt;/code>, etc.&lt;/li>
&lt;li>&lt;code>response_format&lt;/code> (object, optional): 用于指定结构化输出，如 &lt;code>{&amp;quot;type&amp;quot;: &amp;quot;json_schema&amp;quot;, &amp;quot;json_schema&amp;quot;: ...}&lt;/code>。&lt;/li>
&lt;li>&lt;code>extra_body&lt;/code> (object, optional): SGLang 特有的扩展参数，如 &lt;code>{&amp;quot;regex&amp;quot;: &amp;quot;...&amp;quot;}&lt;/code> 或 &lt;code>{&amp;quot;ebnf&amp;quot;: &amp;quot;...&amp;quot;}&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>示例 (使用 &lt;code>openai&lt;/code> 库)&lt;/strong>:&lt;/p>
&lt;pre>&lt;code class="language-python">import openai
client = openai.Client(base_url=&amp;quot;http://127.0.0.1:30000/v1&amp;quot;, api_key=&amp;quot;EMPTY&amp;quot;)
response = client.chat.completions.create(
model=&amp;quot;meta-llama/Meta-Llama-3.1-8B-Instruct&amp;quot;,
messages=[{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;List 3 countries and their capitals.&amp;quot;}],
temperature=0,
max_tokens=64,
)
print(response.choices[0].message.content)
&lt;/code>&lt;/pre>
&lt;h2 id="6-">6. 高级用法：函数调用/工具使用&lt;/h2>
&lt;p>SGLang 强大的编程模型使其非常适合构建能够调用外部工具的 AI Agent。这通常通过结构化输出来实现，模型被引导生成一个描述函数调用的特定格式的文本（通常是 JSON）。&lt;/p>
&lt;p>以下是构建一个简单天气查询 Agent 的步骤：&lt;/p>
&lt;p>&lt;strong>1. 定义工具 Schema&lt;/strong>&lt;/p>
&lt;p>首先，使用 JSON Schema 定义你的工具。这告诉模型工具的名称、目的以及需要哪些参数。&lt;/p>
&lt;pre>&lt;code class="language-python">tools = [
{
&amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,
&amp;quot;function&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;get_current_weather&amp;quot;,
&amp;quot;description&amp;quot;: &amp;quot;Get the current weather in a given location&amp;quot;,
&amp;quot;parameters&amp;quot;: {
&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,
&amp;quot;properties&amp;quot;: {
&amp;quot;city&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;The city name&amp;quot;},
&amp;quot;unit&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: [&amp;quot;celsius&amp;quot;, &amp;quot;fahrenheit&amp;quot;]},
},
&amp;quot;required&amp;quot;: [&amp;quot;city&amp;quot;, &amp;quot;unit&amp;quot;],
},
},
}
]
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>2. 引导模型进行函数调用&lt;/strong>&lt;/p>
&lt;p>在发送给模型的 &lt;code>messages&lt;/code> 中，包含一个系统提示，指示模型可以使用这些工具。然后，在 API 调用中传入 &lt;code>tools&lt;/code> 和 &lt;code>tool_choice=&amp;quot;auto&amp;quot;&lt;/code>。&lt;/p>
&lt;pre>&lt;code class="language-python">import json
messages = [
{&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;You are a helpful assistant that can access external tools.&amp;quot;},
{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;What's the weather like in Boston in fahrenheit?&amp;quot;}
]
response = client.chat.completions.create(
model=&amp;quot;meta-llama/Meta-Llama-3.1-8B-Instruct&amp;quot;,
messages=messages,
tools=tools,
tool_choice=&amp;quot;auto&amp;quot;,
)
# 检查模型是否决定调用工具
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
if tool_calls:
# 模型决定调用工具
for tool_call in tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f&amp;quot;Function Call: {function_name}&amp;quot;)
print(f&amp;quot;Arguments: {function_args}&amp;quot;)
# 在这里，你可以实际执行函数调用
# e.g., result = get_current_weather(**function_args)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>输出:&lt;/strong>&lt;/p>
&lt;pre>&lt;code>Function Call: get_current_weather
Arguments: {'city': 'Boston', 'unit': 'fahrenheit'}
&lt;/code>&lt;/pre>
&lt;p>通过这种方式，你可以构建出能够与外部世界交互的、功能强大的 AI 应用。&lt;/p></description></item><item><title>Llama.cpp 技术详解：轻量级大模型推理引擎</title><link>https://ziyanglin.netlify.app/zh/post/llama-cpp-documentation/</link><pubDate>Thu, 26 Jun 2025 01:06:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/zh/post/llama-cpp-documentation/</guid><description>&lt;h2 id="1-">1. 引言&lt;/h2>
&lt;p>Llama.cpp 是一个用 C/C++ 编写的高性能、轻量级的大型语言模型 (LLM) 推理框架。它专注于在消费级硬件上高效运行 LLM，实现了在普通笔记本电脑甚至手机上进行本地推理的可能。&lt;/p>
&lt;p>&lt;strong>核心优势:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>高性能:&lt;/strong> 通过优化的 C/C++ 代码、量化技术和硬件加速支持（如 Apple Metal, CUDA, OpenCL, SYCL），实现了极快的推理速度。&lt;/li>
&lt;li>&lt;strong>轻量级:&lt;/strong> 极低的内存和计算资源消耗，无需昂贵的 GPU 即可运行。&lt;/li>
&lt;li>&lt;strong>跨平台:&lt;/strong> 支持 macOS, Linux, Windows, Docker, Android, 和 iOS 等多种平台。&lt;/li>
&lt;li>&lt;strong>开放生态:&lt;/strong> 拥有活跃的社区和丰富的生态系统，包括 Python 绑定、UI 工具和与 OpenAI 兼容的服务器。&lt;/li>
&lt;li>&lt;strong>持续创新:&lt;/strong> 快速跟进并实现最新的模型架构和推理优化技术。&lt;/li>
&lt;/ul>
&lt;h2 id="2-">2. 核心概念&lt;/h2>
&lt;h3 id="21-gguf-">2.1. GGUF 模型格式&lt;/h3>
&lt;p>GGUF (Georgi Gerganov Universal Format) 是 &lt;code>llama.cpp&lt;/code> 使用的核心模型文件格式，是其前身 GGML 的演进版本。GGUF 是一个专为快速加载和内存映射设计的二进制格式。&lt;/p>
&lt;p>&lt;strong>主要特点:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>统一文件:&lt;/strong> 将模型元数据、词汇表和所有张量（权重）打包在单个文件中。&lt;/li>
&lt;li>&lt;strong>可扩展性:&lt;/strong> 允许在不破坏兼容性的情况下添加新的元数据。&lt;/li>
&lt;li>&lt;strong>向后兼容:&lt;/strong> 保证了对旧版本 GGUF 模型的兼容。&lt;/li>
&lt;li>&lt;strong>内存效率:&lt;/strong> 支持内存映射（mmap），允许多个进程共享同一模型权重，从而节省内存。&lt;/li>
&lt;/ul>
&lt;h3 id="22--quantization">2.2. 量化 (Quantization)&lt;/h3>
&lt;p>量化是 &lt;code>llama.cpp&lt;/code> 的核心优势之一。它是一种将模型权重从高精度浮点数（如 32 位或 16 位）转换为低精度整数（如 4 位、5 位或 8 位）的技术。&lt;/p>
&lt;p>&lt;strong>主要优势:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>减小模型体积:&lt;/strong> 显著降低模型文件的大小，使其更易于分发和存储。&lt;/li>
&lt;li>&lt;strong>降低内存占用:&lt;/strong> 减少了模型加载到内存中所需的 RAM。&lt;/li>
&lt;li>&lt;strong>加速推理:&lt;/strong> 低精度计算通常比高精度计算更快，尤其是在 CPU 上。&lt;/li>
&lt;/ul>
&lt;p>&lt;code>llama.cpp&lt;/code> 支持多种量化方法，特别是 &lt;strong>k-quants&lt;/strong>，这是一种先进的量化技术，能够在保持较高模型性能的同时实现极高的压缩率。&lt;/p>
&lt;h3 id="23-">2.3. 多模态支持&lt;/h3>
&lt;p>&lt;code>llama.cpp&lt;/code> 不仅仅局限于文本模型，它已经发展成为一个强大的多模态推理引擎，支持同时处理文本、图像甚至音频。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>支持的模型:&lt;/strong> 支持如 LLaVA, MobileVLM, Granite, Qwen2.5 Omni, InternVL, SmolVLM 等多种主流多模态模型。&lt;/li>
&lt;li>&lt;strong>工作原理:&lt;/strong> 通常通过一个视觉编码器（如 CLIP）将图像转换为嵌入向量，然后将这些向量与文本嵌入向量一起输入到 LLM 中。&lt;/li>
&lt;li>&lt;strong>使用工具:&lt;/strong> &lt;code>llama-mtmd-cli&lt;/code> 和 &lt;code>llama-server&lt;/code> 提供了对多模态模型的原生支持。&lt;/li>
&lt;/ul>
&lt;h2 id="3-">3. 使用方法&lt;/h2>
&lt;h3 id="31-">3.1. 编译&lt;/h3>
&lt;p>从源码编译 &lt;code>llama.cpp&lt;/code> 非常简单。&lt;/p>
&lt;pre>&lt;code class="language-bash">git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
make
&lt;/code>&lt;/pre>
&lt;p>对于特定硬件加速（如 CUDA 或 Metal），需要使用相应的编译选项：&lt;/p>
&lt;pre>&lt;code class="language-bash"># For CUDA
make LLAMA_CUDA=1
# For Metal (on macOS)
make LLAMA_METAL=1
&lt;/code>&lt;/pre>
&lt;h3 id="32-">3.2. 基本推理&lt;/h3>
&lt;p>编译后，可以使用 &lt;code>llama-cli&lt;/code> 工具进行推理。&lt;/p>
&lt;pre>&lt;code class="language-bash">./llama-cli -m ./models/7B/ggml-model-q4_0.gguf -p &amp;quot;Building a website can be done in 10 simple steps:&amp;quot; -n 400
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>&lt;code>-m&lt;/code>: 指定 GGUF 模型文件的路径。&lt;/li>
&lt;li>&lt;code>-p&lt;/code>: 指定提示（prompt）。&lt;/li>
&lt;li>&lt;code>-n&lt;/code>: 指定要生成的最大 token 数量。&lt;/li>
&lt;/ul>
&lt;h3 id="33-openai-">3.3. OpenAI 兼容服务器&lt;/h3>
&lt;p>&lt;code>llama.cpp&lt;/code> 提供了一个内置的 HTTP 服务器，其 API 与 OpenAI 的 API 兼容。这使得它可以轻松地与 LangChain, LlamaIndex 等现有工具集成。&lt;/p>
&lt;p>启动服务器：&lt;/p>
&lt;pre>&lt;code class="language-bash">./llama-server -m models/7B/ggml-model-q4_0.gguf -c 4096
&lt;/code>&lt;/pre>
&lt;p>然后，你可以像调用 OpenAI API 一样向 &lt;code>http://localhost:8080/v1/chat/completions&lt;/code> 发送请求。&lt;/p>
&lt;h2 id="4-">4. 高级功能&lt;/h2>
&lt;h3 id="41--speculative-decoding">4.1. 投机性解码 (Speculative Decoding)&lt;/h3>
&lt;p>这是一种先进的推理优化技术，通过使用一个小的&amp;quot;草稿&amp;quot;模型来预测主模型的输出，从而显著加速生成速度。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>工作原理:&lt;/strong> 草稿模型快速生成一个 token 序列草稿，然后由主模型一次性验证整个序列。如果验证通过，就可以节省逐个生成 token 的时间。&lt;/li>
&lt;li>&lt;strong>使用方法:&lt;/strong> 在 &lt;code>llama-cli&lt;/code> 或 &lt;code>llama-server&lt;/code> 中使用 &lt;code>--draft-model&lt;/code> 参数指定一个小的、快速的草稿模型。&lt;/li>
&lt;/ul>
&lt;h3 id="42-lora-">4.2. LoRA 支持&lt;/h3>
&lt;p>LoRA (Low-Rank Adaptation) 允许在不修改原始模型权重的情况下，通过训练一个小的适配器来微调模型的行为。&lt;code>llama.cpp&lt;/code> 支持在推理时加载一个或多个 LoRA 适配器。&lt;/p>
&lt;pre>&lt;code class="language-bash">./llama-cli -m base-model.gguf --lora lora-adapter.gguf
&lt;/code>&lt;/pre>
&lt;p>甚至可以为不同的 LoRA 适配器设置不同的权重：&lt;/p>
&lt;pre>&lt;code class="language-bash">./llama-cli -m base.gguf --lora-scaled lora_A.gguf 0.5 --lora-scaled lora_B.gguf 0.5
&lt;/code>&lt;/pre>
&lt;h3 id="43--grammars">4.3. 文法约束 (Grammars)&lt;/h3>
&lt;p>文法约束是一个非常强大的功能，它允许你强制模型的输出遵循特定的格式，例如严格的 JSON 模式。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>格式:&lt;/strong> 使用一种名为 GBNF (GGML BNF) 的格式来定义语法规则。&lt;/li>
&lt;li>&lt;strong>应用:&lt;/strong> 在 API 请求中通过 &lt;code>grammar&lt;/code> 参数提供 GBNF 规则，可以确保模型返回格式正确、可直接解析的 JSON 数据，避免了输出格式错误和繁琐的后处理。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>示例：&lt;/strong> 使用 Pydantic 模型生成 JSON Schema，然后转换为 GBNF，以确保模型输出符合预期的 Python 对象结构。&lt;/p>
&lt;pre>&lt;code class="language-python">import json
from typing import List
from pydantic import BaseModel
class QAPair(BaseModel):
question: str
answer: str
class Summary(BaseModel):
key_facts: List[str]
qa_pairs: List[QAPair]
# 生成 JSON Schema 并打印
schema = Summary.model_json_schema()
print(json.dumps(schema, indent=2))
&lt;/code>&lt;/pre>
&lt;h2 id="5-">5. 生态系统&lt;/h2>
&lt;p>&lt;code>llama.cpp&lt;/code> 的成功催生了一个充满活力的生态系统：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>&lt;a href="https://github.com/abetlen/llama-cpp-python">llama-cpp-python&lt;/a>:&lt;/strong> 最流行的 Python 绑定，提供了与 &lt;code>llama.cpp&lt;/code> 几乎所有功能的接口，并与 LangChain、LlamaIndex 等框架深度集成。&lt;/li>
&lt;li>&lt;strong>&lt;a href="https://ollama.com/">Ollama&lt;/a>:&lt;/strong> 一个将模型打包、分发和运行的工具，底层使用了 &lt;code>llama.cpp&lt;/code>，极大地简化了在本地运行 LLM 的流程。&lt;/li>
&lt;li>&lt;strong>众多 UI 工具:&lt;/strong> 社区开发了大量的图形界面工具，让非技术用户也能轻松地与本地模型进行交互。&lt;/li>
&lt;/ul>
&lt;h2 id="6-">6. 总结&lt;/h2>
&lt;p>&lt;code>llama.cpp&lt;/code> 不仅仅是一个推理引擎，它已经成为推动 LLM 本地化和大众化的关键力量。通过其卓越的性能、对资源的高度优化以及不断扩展的功能集（如多模态、文法约束），&lt;code>llama.cpp&lt;/code> 为开发者和研究人员提供了一个强大而灵活的平台，让他们能够在各种设备上探索和部署 AI 应用，开启了低成本、保护隐私的本地 AI 新时代。&lt;/p></description></item><item><title>vLLM技术详解：高性能LLM推理引擎</title><link>https://ziyanglin.netlify.app/zh/post/vllm-documentation/</link><pubDate>Thu, 26 Jun 2025 01:05:00 +0000</pubDate><guid>https://ziyanglin.netlify.app/zh/post/vllm-documentation/</guid><description>&lt;h2 id="1-vllm-">1. vLLM 简介&lt;/h2>
&lt;p>vLLM 是一个为大型语言模型（LLM）设计的开源推理和服务引擎，以其高吞吐量和内存效率而闻名。在 LLM 服务领域，vLLM 解决了一个核心痛点：传统推理系统在处理 Transformer 模型中注意力机制的键值缓存（KV Cache）时效率低下，导致大量内存被浪费，推理速度受限。&lt;/p>
&lt;p>LLM 推理过程中的内存瓶颈主要源于 KV Cache。这个缓存存储了序列中每个先前 token 的注意力键（Key）和值（Value），以加速后续 token 的生成。然而，KV Cache 的大小是动态变化的，且难以预测，这给内存管理带来了巨大挑战。传统系统（如 HuggingFace Transformers）通常会预先分配一块连续的大内存空间来存储 KV Cache，但这会导致严重的内存碎片化和浪费。&lt;/p>
&lt;p>vLLM 通过引入其核心创新 &lt;strong>PagedAttention&lt;/strong> 机制，从根本上解决了这个问题。&lt;/p>
&lt;h2 id="2-">2. 核心特性与优势&lt;/h2>
&lt;p>vLLM 之所以能在众多 LLM 推理框架中脱颖而出，得益于其以下几个关键特性：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>极高的吞吐量&lt;/strong>：通过 PagedAttention 和持续的批处理（Continuous Batching），vLLM 能够显著提升 GPU 的利用率，其吞吐量比 HuggingFace Transformers 高出数倍，也优于其他主流推理库。&lt;/li>
&lt;li>&lt;strong>高效的内存管理&lt;/strong>：PagedAttention 机制将 KV Cache 划分为非连续的内存块，极大地减少了内存的内部和外部碎片。根据官方数据，它可以节省高达 55% 的内存，这意味着您可以用相同的硬件加载更大的模型或服务更多的并发请求。&lt;/li>
&lt;li>&lt;strong>灵活的解码策略&lt;/strong>：vLLM 支持多种复杂的解码算法，包括并行采样（Parallel Sampling）、波束搜索（Beam Search）和 Top-K/Top-P 采样，可以满足不同应用场景的需求。&lt;/li>
&lt;li>&lt;strong>与 OpenAI API 兼容&lt;/strong>：vLLM 提供了一个与 OpenAI API 完全兼容的服务端点。这意味着您可以将 vLLM 无缝集成到现有的、基于 OpenAI API 构建的应用生态中，只需更改几个配置即可。&lt;/li>
&lt;li>&lt;strong>分布式推理&lt;/strong>：对于无法在单个 GPU 上容纳的超大模型，vLLM 支持张量并行（Tensor Parallelism），可以将模型的权重和计算负载分散到多个 GPU 上，实现高效的分布式推理。&lt;/li>
&lt;li>&lt;strong>流式输出与结构化输出&lt;/strong>：支持流式传输（Streaming）生成的 token，并能通过引导式生成（Guided Generation）产生符合特定格式（如 JSON Schema 或正则表达式）的结构化输出。&lt;/li>
&lt;/ul>
&lt;h2 id="3--pagedattention">3. 核心架构：深入 PagedAttention&lt;/h2>
&lt;p>PagedAttention 是 vLLM 的灵魂，其设计灵感来源于现代操作系统中用于管理虚拟内存的分页（Paging）技术。&lt;/p>
&lt;h3 id="31-">3.1 工作原理&lt;/h3>
&lt;p>在传统方法中，KV Cache 为每个序列存储在连续的内存空间中。这种方式看似简单，但由于不同序列长度差异巨大，会导致严重的内存碎片。&lt;/p>
&lt;p>PagedAttention 则将每个序列的 KV Cache 划分为固定大小的 &lt;strong>块（Blocks）&lt;/strong>。每个块可以存储固定数量 token 的键和值。在推理过程中，vLLM 的核心调度器会根据需要动态地为序列分配这些块。&lt;/p>
&lt;p>这种设计的优势在于：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>消除内部碎片&lt;/strong>：由于块的大小固定，一个序列的最后一个块可能会有少量空间未被使用，但这种浪费远小于为整个序列预留连续内存所造成的浪费。&lt;/li>
&lt;li>&lt;strong>灵活的内存分配&lt;/strong>：块存储在非连续的内存空间中，使得内存管理更加灵活，类似于操作系统管理物理内存页。&lt;/li>
&lt;li>&lt;strong>高效的内存共享&lt;/strong>：PagedAttention 使得在不同序列之间共享 KV Cache 变得异常简单和高效。例如，在并行采样或波束搜索中，多个候选序列都源自同一个提示（Prompt）。vLLM 可以让这些序列共享存储提示部分的 KV 块，只有在生成新 token 时才需要为每个序列分配新的、独立的块。这种&amp;quot;写时复制&amp;rdquo;（Copy-on-Write）的机制极大地降低了复杂解码算法的内存开销。&lt;/li>
&lt;/ol>
&lt;p>下面是一个 Mermaid 图，更直观地展示了 PagedAttention 的内存管理方式：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">graph TD
subgraph Physical_Memory [KV Cache Physical Memory]
direction LR
B1(Block 1)
B2(Block 2)
B3(Block 3)
B4(Block 4)
B5(Block 5)
B6(Block 6)
B7(Block 7)
B8(Block 8)
end
subgraph Logical_View [Sequence Logical View]
direction TB
subgraph Seq1 [Sequence 1]
P1(Prompt) --&amp;gt; T1(Token 1)
end
subgraph Seq2 [Sequence 2]
P2(Prompt) --&amp;gt; T2(Token 1) --&amp;gt; T3(Token 2)
end
subgraph Seq3 [Parallel Sampling]
P3(Prompt) --&amp;gt; T4(Token 1a)
P3 --&amp;gt; T5(Token 1b)
end
end
subgraph Block_Table [Block Table]
direction TB
Map1[&amp;quot;Seq 1: [B1, B5]&amp;quot;]
Map2[&amp;quot;Seq 2: [B2, B6, B8]&amp;quot;]
Map3[&amp;quot;Seq 3a: [B3, B7]&amp;quot;]
Map4[&amp;quot;Seq 3b: [B3, B4]&amp;quot;]
end
Seq1 --&amp;gt; Map1
Seq2 --&amp;gt; Map2
Seq3 --&amp;gt; Map3
Seq3 --&amp;gt; Map4
Map1 --&amp;gt; B1
Map1 --&amp;gt; B5
Map2 --&amp;gt; B2
Map2 --&amp;gt; B6
Map2 --&amp;gt; B8
Map3 --&amp;gt; B3
Map3 --&amp;gt; B7
Map4 --&amp;gt; B3
Map4 --&amp;gt; B4
style B3 fill:#f9f,stroke:#333,stroke-width:2px
linkStyle 8 stroke-width:2px,stroke:green,fill:none;
linkStyle 11 stroke-width:2px,stroke:green,fill:none;
linkStyle 12 stroke-width:2px,stroke:green,fill:none;
&lt;/code>&lt;/pre>
&lt;p>&lt;em>上图说明：&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>KV Cache 物理内存&lt;/strong>：代表 GPU 上非连续的物理内存块。&lt;/li>
&lt;li>&lt;strong>序列逻辑视图&lt;/strong>：代表正在处理的多个请求（序列）。&lt;/li>
&lt;li>&lt;strong>块映射表&lt;/strong>：vLLM 的核心组件，将逻辑上的 token 位置映射到物理内存块。&lt;/li>
&lt;li>&lt;strong>内存共享&lt;/strong>：注意到&amp;quot;并行采样&amp;quot;中的两个分支（3a 和 3b）共享了同一个 Prompt 块（B3），这就是 PagedAttention 高效内存共享的体现。&lt;/li>
&lt;/ul>
&lt;h3 id="32--continuous-batching">3.2 持续批处理 (Continuous Batching)&lt;/h3>
&lt;p>基于 PagedAttention，vLLM 实现了一种更先进的批处理策略——持续批处理。传统的批处理（Static Batching）需要等待批次中所有序列都生成完毕后，才能开始处理下一个批次。而持续批处理则允许在批次中的某个序列完成生成后，立即将新的请求插入到批处理中，从而避免了 GPU 的空闲等待，进一步提升了吞吐量。&lt;/p>
&lt;p>下面通过 Mermaid 序列图对比两种批处理方式：&lt;/p>
&lt;pre>&lt;code class="language-mermaid">sequenceDiagram
participant C as Client
participant S as Server
participant G as GPU
note over C, G: --- Static Batching ---
C-&amp;gt;&amp;gt;S: Request [R1, R2, R3, R4]
S-&amp;gt;&amp;gt;G: Process Batch 1 [R1, R2, R3, R4]
note right of G: All requests process in parallel
G--&amp;gt;&amp;gt;S: Batch 1 Finished
note right of S: Wait for the entire batch to complete
S--&amp;gt;&amp;gt;C: Response [O1, O2, O3, O4]
C-&amp;gt;&amp;gt;S: Request [R5, R6]
S-&amp;gt;&amp;gt;G: Process Batch 2 [R5, R6]
note over C, G: --- Continuous Batching ---
C-&amp;gt;&amp;gt;S: Request [R1, R2, R3, R4]
S-&amp;gt;&amp;gt;G: Process [R1, R2, R3, R4]
G--&amp;gt;&amp;gt;S: R2 Finished
S--&amp;gt;&amp;gt;C: Response O2
C-&amp;gt;&amp;gt;S: New Request R5
S-&amp;gt;&amp;gt;G: Add R5 to queue (GPU is not idle)
note right of G: R1, R3, R4, R5 are now processing
G--&amp;gt;&amp;gt;S: R4 Finished
S--&amp;gt;&amp;gt;C: Response O4
&lt;/code>&lt;/pre>
&lt;h2 id="4-">4. 快速上手指南&lt;/h2>
&lt;p>下面，我们将通过几个简单的步骤来展示如何安装和使用 vLLM。&lt;/p>
&lt;h3 id="41-">4.1 安装&lt;/h3>
&lt;p>您可以使用 &lt;code>pip&lt;/code> 或 &lt;code>uv&lt;/code>（一个更快的包安装工具）来安装 vLLM。推荐使用 &lt;code>uv&lt;/code>，因为它可以自动检测您的 CUDA 版本并安装匹配的 PyTorch 后端。&lt;/p>
&lt;p>&lt;strong>使用 uv (推荐):&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash"># 创建并激活虚拟环境
uv venv
source .venv/bin/activate
# 安装 vLLM
uv pip install vllm --torch-backend=auto
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>使用 pip:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">pip install vllm
&lt;/code>&lt;/pre>
&lt;h3 id="42-">4.2 离线推理&lt;/h3>
&lt;p>使用 &lt;code>vllm.LLM&lt;/code> 类可以非常方便地进行离线推理。&lt;/p>
&lt;pre>&lt;code class="language-python">from vllm import LLM, SamplingParams
# 定义输入提示
prompts = [
&amp;quot;Hello, my name is&amp;quot;,
&amp;quot;The capital of France is&amp;quot;,
&amp;quot;The future of AI is&amp;quot;,
]
# 定义采样参数
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
# 初始化 LLM 引擎 (模型会自动从 Hugging Face 下载)
llm = LLM(model=&amp;quot;facebook/opt-125m&amp;quot;)
# 生成文本
outputs = llm.generate(prompts, sampling_params)
# 打印结果
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f&amp;quot;Prompt: {prompt!r}, Generated text: {generated_text!r}&amp;quot;)
&lt;/code>&lt;/pre>
&lt;h3 id="43--openai-">4.3 启动 OpenAI 兼容服务器&lt;/h3>
&lt;p>vLLM 最强大的功能之一是其内置的 API 服务器。只需一行命令，即可启动一个与 OpenAI API 兼容的服务。&lt;/p>
&lt;pre>&lt;code class="language-bash">vllm serve Qwen/Qwen2.5-1.5B-Instruct
&lt;/code>&lt;/pre>
&lt;p>默认情况下，服务器会在 &lt;code>http://localhost:8000&lt;/code> 上运行。&lt;/p>
&lt;h3 id="44-">4.4 与服务器交互&lt;/h3>
&lt;p>您可以使用 &lt;code>curl&lt;/code> 或 &lt;code>openai&lt;/code> Python 客户端与服务器进行交互。&lt;/p>
&lt;p>&lt;strong>使用 curl:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">curl http://localhost:8000/v1/completions \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-d '{
&amp;quot;model&amp;quot;: &amp;quot;Qwen/Qwen2.5-1.5B-Instruct&amp;quot;,
&amp;quot;prompt&amp;quot;: &amp;quot;San Francisco is a&amp;quot;,
&amp;quot;max_tokens&amp;quot;: 7,
&amp;quot;temperature&amp;quot;: 0
}'
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>使用 OpenAI Python 客户端:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from openai import OpenAI
client = OpenAI(
base_url=&amp;quot;http://localhost:8000/v1&amp;quot;,
api_key=&amp;quot;not-used&amp;quot; # API 密钥不是必需的
)
completion = client.chat.completions.create(
model=&amp;quot;Qwen/Qwen2.5-1.5B-Instruct&amp;quot;,
messages=[
{&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;You are a helpful assistant.&amp;quot;},
{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Who won the world series in 2020?&amp;quot;}
]
)
print(completion.choices[0].message)
&lt;/code>&lt;/pre>
&lt;h2 id="5--serving">5. 模型服务 (Serving)&lt;/h2>
&lt;h3 id="51-">5.1 分布式服务&lt;/h3>
&lt;p>如果模型太大无法放入单个 GPU，您可以使用张量并行将其分布在多个 GPU 上。&lt;/p>
&lt;pre>&lt;code class="language-bash"># 在 4 个 GPU 上启动服务
vllm serve facebook/opt-13b --tensor-parallel-size 4
&lt;/code>&lt;/pre>
&lt;h3 id="52-docker-">5.2 Docker 部署&lt;/h3>
&lt;p>vLLM 提供了官方的 Docker 镜像，可以方便地进行容器化部署。&lt;/p>
&lt;pre>&lt;code class="language-bash">docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env &amp;quot;HUGGING_FACE_HUB_TOKEN=&amp;lt;your-hf-token&amp;gt;&amp;quot; \
-p 8000:8000 \
--ipc=host \
vllm/vllm-openai:latest \
--model mistralai/Mistral-7B-v0.1
&lt;/code>&lt;/pre>
&lt;h2 id="6-">6. 高级功能详解&lt;/h2>
&lt;h3 id="61--structured-outputs">6.1 结构化输出 (Structured Outputs)&lt;/h3>
&lt;p>vLLM 支持多种方式来约束模型的输出格式，这对于需要可靠、可解析输出的应用至关重要。&lt;/p>
&lt;p>&lt;strong>使用 Pydantic 模型生成 JSON:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from pydantic import BaseModel
from openai import OpenAI
client = OpenAI(base_url=&amp;quot;http://localhost:8000/v1&amp;quot;, api_key=&amp;quot;dummy&amp;quot;)
model = client.models.list().data[0].id
class People(BaseModel):
name: str
age: int
completion = client.chat.completions.create(
model=model,
messages=[
{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Generate a JSON with the name and age of one random person.&amp;quot;}
],
response_format={
&amp;quot;type&amp;quot;: &amp;quot;json_schema&amp;quot;,
&amp;quot;json_schema&amp;quot;: {
&amp;quot;name&amp;quot;: &amp;quot;people&amp;quot;,
&amp;quot;schema&amp;quot;: People.model_json_schema()
}
},
)
print(completion.choices[0].message.content)
&lt;/code>&lt;/pre>
&lt;h3 id="62-lora-">6.2 LoRA 支持&lt;/h3>
&lt;p>vLLM 可以在同一个基础模型上高效地服务多个 LoRA 适配器。这对于需要为不同客户或任务提供定制化模型的场景非常有用。&lt;/p>
&lt;p>&lt;strong>启动支持 LoRA 的服务器:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from vllm import LLM
llm = LLM(model=&amp;quot;meta-llama/Llama-2-7b-hf&amp;quot;, enable_lora=True)
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>在请求中指定 LoRA 适配器:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">curl http://localhost:8000/v1/completions \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-d '{
&amp;quot;model&amp;quot;: &amp;quot;sql-lora&amp;quot;, # 指定 LoRA 模型的 ID
&amp;quot;prompt&amp;quot;: &amp;quot;San Francisco is a&amp;quot;,
&amp;quot;max_tokens&amp;quot;: 7
}'
&lt;/code>&lt;/pre>
&lt;h3 id="63--quantization">6.3 量化 (Quantization)&lt;/h3>
&lt;p>量化是一种通过降低模型权重的精度来减小模型大小和内存占用的技术。vLLM 支持多种量化方案，如 AWQ 和 FP8 KV 缓存。&lt;/p>
&lt;p>&lt;strong>启用 FP8 KV 缓存:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-python">from vllm import LLM
llm = LLM(
model=&amp;quot;meta-llama/Llama-2-7b-chat-hf&amp;quot;,
kv_cache_dtype=&amp;quot;fp8&amp;quot;,
calculate_kv_scales=True # 动态计算量化尺度
)
&lt;/code>&lt;/pre>
&lt;h2 id="7-">7. 框架集成&lt;/h2>
&lt;p>vLLM 可以轻松地与 Langchain 和 LlamaIndex 等流行的 LLM 应用框架集成，用于构建复杂的系统，如检索增强生成（RAG）。通常，vLLM 会作为后端提供快速的 LLM 推理和嵌入生成服务。&lt;/p>
&lt;p>&lt;strong>安装相关依赖:&lt;/strong>&lt;/p>
&lt;pre>&lt;code class="language-bash">pip install -U vllm langchain_openai langchain_community
&lt;/code>&lt;/pre>
&lt;p>之后，在 Langchain 中，您可以将 &lt;code>ChatOpenAI&lt;/code> 或 &lt;code>OpenAIEmbeddings&lt;/code> 的 &lt;code>base_url&lt;/code> 指向 vLLM 服务器的地址，即可完成集成。&lt;/p>
&lt;h2 id="8-">8. 总结&lt;/h2>
&lt;p>vLLM 通过其创新的 PagedAttention 架构，成功地解决了 LLM 推理中的内存管理和性能瓶颈，为开发者提供了一个极其高效、灵活且易于使用的推理服务引擎。无论是进行快速的离线实验，还是部署生产级的、高并发的 LLM 服务，vLLM 都展现出了卓越的性能和强大的功能。随着社区的不断发展，vLLM 正在成为 LLM 服务领域的标准工具之一。&lt;/p></description></item></channel></rss>