人工智能
SGLang:结构化语言模型程序的高效执行
大型语言模型(LLM)越来越多地被用于需要多次生成调用、先进的提示技术、控制流和结构化输入/输出的复杂任务。然而,用于编程和执行这些应用程序的高效系统却缺乏。SGLang是一种新引入的系统,旨在通过提供复杂语言模型程序的高效执行来解决这个问题。SGLang由一个前端语言和一个运行时组成。前端通过提供用于生成和并行控制的原语来简化编程,而运行时通过像RadixAttention这样的新型优化来加速执行,用于KV缓存重用和压缩的有限状态机用于更快的结构化输出解码。实验表明,SGLang在各种大型语言和多模态模型上实现了最高6.4×的吞吐量,相比于现有的最先进的推理系统,处理任务如代理控制、逻辑推理、少样本学习基准、JSON解码、检索增强生成管道和多回合聊天。
最近在LLM能力方面的进展扩大了其实用性,使其能够处理更广泛的通用任务,并作为自治代理运行。在这些应用中,LLM参与多轮规划、推理和与外部环境的交互。这是通过工具使用、多个输入模式和各种提示技术(如少样本学习、自一致性、思维框架和思维树)来实现的。这些新用例需要多次、通常依赖的LLM生成调用,表明使用多调用结构来完成复杂任务的趋势。
这种转变标志着从简单聊天到更复杂的程序化使用LLM的转变,在这种使用中,程序调度和控制LLM的生成过程。这些程序被称为“语言模型程序”(LM程序)。先进的提示技术和代理工作流属于LM程序的范畴。LM程序有两个共同的属性:(1)LM程序通常涉及多个LLM调用,伴随着控制流以完成复杂任务并增强整体质量。(2)LM程序接收结构化输入并产生结构化输出,允许LM程序的组合和集成到现有的软件系统中。
在本文中,我们将更深入地探讨SGLang框架,探索其架构,分析其性能,并将其与最先进的框架进行比较。那么让我们开始吧。
SGLang简介
尽管LM程序被广泛使用,但当前用于表达和执行它们的系统仍然效率低下。SGLang确定了两项与LM程序高效使用相关的主要挑战:
- 编程复杂性:开发LM程序很繁琐且困难,主要是由于LLM的非确定性性质。这涉及广泛的字符串操作、实验性提示调整、脆弱的输出解析、处理多个输入模式以及实现并行机制。这种复杂性大大降低了甚至简单程序的可读性。
- 执行效率:执行LM程序效率低下,主要是由于冗余计算和内存使用。最先进的推理引擎,旨在降低延迟和提高吞吐量,缺乏对工作负载的直接了解,导致了显著的低效。一个值得注意的例子是Key-Value(KV)缓存的重用,KV缓存由可用于生成推理的可重用中间张量组成。当前系统缺乏有效的机制来促进KV缓存在共享共同前缀的多个LLM调用之间的重用,导致不必要的计算和浪费的内存。此外,对于结构化输出(如JSON模式)的约束解码是次优的,因为现有的系统只解码一个令牌一次。
为了解决这些挑战,SGLang引入了一种用于LLM的结构化生成语言。核心思想是系统地利用LM程序中的多调用结构以实现高效执行。如以下图所示,SGLang由两个部分组成:前端语言和后端运行时。

前端简化了LM程序的编程,而运行时则加速了其执行。这些部分可以共同工作以获得更好的性能,也可以独立工作。
SGLang是一种嵌入在Python中的特定领域语言,提供用于生成(例如extend、gen、select)和并行控制(例如fork、join)的原语。它与Python的控制流和库兼容,允许用户使用本地Python语法轻松开发先进的提示工作流。SGLang包括一个解释器和一个编译器。解释器将提示状态管理为一个流,并将原语操作提交到流中以进行异步执行,确保对同步和程序内并行的正确控制。另外,SGLang程序可以被跟踪和编译以进行进一步的优化。SGLang的运行时提出了几种新型优化来加速LM程序的执行:
- RadixAttention:该技术实现了KV缓存在多个生成调用之间的自动重用。在现有的推理引擎中,请求的KV缓存在处理后被丢弃,阻止了在多个调用之间的重用并减慢了执行速度。SGLang在一个基数树中维护一个KV缓存的LRU缓存,管理KV缓存作为一个传统缓存,并使用基数树进行高效匹配、插入和驱逐。这允许运行时高效地处理各种重用模式。
- 压缩有限状态机:该技术实现了结构化输出的更快约束解码。现有的系统只遵循下一个令牌的约束,使它们只能一次解码一个令牌。相反,SGLang分析约束并构建一个压缩的有限状态机来表示它们,压缩多令牌路径到单步路径,允许一次解码多个令牌以获得更快的速度。
- API推测执行:对于像OpenAI的GPT-4这样的仅API模型,SGLang引入了API推测执行来优化多调用程序。
使用SGLang,各种LLM应用程序被实现,包括代理控制、逻辑推理、少样本学习基准、JSON解码、检索增强生成管道、多回合聊天和多模态处理。性能被测试在包括Llama-7B/70B、Mistral-8x7B、LLaVA-v1.5-7B(图像)和LLaVA-NeXT-34B(视频)在NVIDIA A10G和A100 GPU上的模型上。实验结果表明,SGLang在广泛的工作负载、模型和硬件设置上实现了最高6.4×的吞吐量,相比于现有的编程和推理系统,包括Guidance、vLLM和LMQL。
SGLang:编程模型和方法
SGLang编程模型通过一个运行示例介绍,描述其语言原语和执行模式,并概述运行时优化机会。该模型简化了多调用工作流中的繁琐操作(例如字符串操作、API调用、约束规范、并行),提供了灵活且可组合的原语。SGLang是嵌入在Python中的特定领域语言。以下图显示了一个使用分支-求解-合并提示方法评估图像的程序。

函数multi_dimensional_judge接受三个参数:`s`、`path`和`essay`。`s`管理提示状态,`path`是图像文件路径,`essay`是文章文本。新的字符串和SGLang原语可以使用+=操作符追加到状态`s`中以进行执行。首先,函数将图像和文章添加到提示中。然后,它使用select检查文章是否与图像相关,并将结果存储在s[“related”]中。如果相关,则提示被分叉为三个副本以进行并行评估,使用gen将结果存储在f[“judgment”]中。接下来,它合并判断、生成摘要并分配字母成绩。最后,它以JSON格式返回结果,遵循由正则表达式约束regex定义的模式。SGLang大大简化了这个程序,因为使用OpenAI API-like接口的等效程序需要2.1×的代码行数,主要是由于手动字符串操作和并行控制。
SGLang提供了用于控制提示状态、生成和并行的原语,可以与Python语法和库一起使用。以下是原语:
gen:调用模型生成并将结果存储在变量中,变量名在其第一个参数中指定。它支持一个`regex`参数来约束输出以遵循由正则表达式定义的语法(例如JSON模式)。
- select:调用模型从列表中选择最高概率选项。
- +=或extend:将字符串追加到提示中。
- [变量名]:检索生成的结果。
- fork:创建提示状态的并行分支。
- join:重新连接提示状态。
- image和video:接受图像和视频输入。
执行SGLang程序的最简单方法是通过解释器,其中提示被视为异步流。像extend、gen和select这样的原语被提交到流中以进行异步执行。这些非阻塞调用允许Python代码在生成完成之前继续运行,类似于异步启动CUDA内核。每个提示由一个流执行器在后台线程中管理,实现程序内并行。检索生成结果将阻塞,直到它们准备好,确保正确的同步。或者,SGLang程序可以被编译为计算图并使用图执行器执行,允许进行更多优化。本文默认使用解释器模式,并在附录D中讨论编译器模式的结果。SGLang支持使用其自己的SGLang运行时(SRT)和API模型(如OpenAI和Anthropic模型)进行开权重模型。
LLM的编程系统可以被归类为高级(例如LangChain、DSPy)和低级(例如LMQL、Guidance、SGLang)。高级系统提供预定义或自动生成的提示,例如DSPy的提示优化器。低级系统通常不会改变提示,但允许直接操纵提示和原语。SGLang是一种低级系统,类似于LMQL和Guidance。以下表格比较了它们的功能。

SGLang更侧重于运行时效率,并带有自己的协同设计运行时,允许进行新型优化。高级语言(例如DSPy)可以被编译为低级语言(例如SGLang)。在DSPy中将SGLang用作后端以获得更好的运行时效率的集成在后面被演示。

上面的示例说明了RadixAttention在九个时间点上的操作,展示了基数树在响应不同请求时的动态演化。这些请求包括两个聊天会话、一个少样本学习查询批次和自一致性采样。每个树边都带有一个标签,表示子字符串或令牌序列。节点被着色以反映不同的状态:绿色表示新添加的节点,蓝色表示在时间点访问的缓存节点,红色表示已被驱逐的节点。
步骤1:基数树最初是空的。
步骤2:服务器处理一个传入的用户消息“Hello”并用LLM输出“Hi”作出响应。系统提示“你是一个有帮助的助手”,用户消息“Hello!”和LLM回复“Hi!”被合并到树中作为一个单一的边,连接到一个新节点。
步骤3:一个新提示到达,服务器在基数树中找到提示的前缀(即对话的第一回合),并重用其KV缓存。新回合被追加到树中作为一个新节点。
步骤4:一个新的聊天会话开始。步骤3中的节点被分割为两个节点,以允许两个聊天会话共享系统提示。
步骤5:第二个聊天会话继续。但是,由于内存限制,步骤4中的一个节点必须被驱逐。新回合被追加到步骤4中剩余的节点之后。
步骤6:服务器接收到一个少样本学习查询,处理它,并将其插入到树中。根节点被分割,因为新查询与现有节点没有共同的前缀。
步骤7:服务器接收到一批额外的少样本学习查询。这些查询共享相同的少样本示例集,因此步骤6中的一个节点被分割以实现共享。
步骤8:服务器接收到来自第一个聊天会话的新消息。它驱逐第二个聊天会话中的所有节点,因为它们是最近最少使用的。
步骤9:服务器接收到一个请求,用于为步骤8中的问题采样更多答案,可能是用于自一致性提示。为了为这些请求腾出空间,多个节点被驱逐。
这个例子展示了RadixAttention如何处理不同请求对节点的动态分配和驱逐,确保KV缓存的高效重用和内存管理。
SGLang:评估和结果
在开权重模型上的结果
延迟和吞吐量结果如下图所示。SGLang提高了最高6.4×的吞吐量,并降低了最高3.7×的延迟。这些改进是由于KV缓存重用、单个程序内并行的利用以及更快的约束解码所致。

在这些基准测试中,缓存命中率从50%到99%不等。图13(附录)列出了所有基准测试的实现和最优缓存命中率,表明SGLang的缓存感知调度在平均上接近96%的最优命中率。

在具有张量并行的更大模型上的结果
更大的模型Mixtral-8x7B和Llama-70B被测试在相同的基准测试上,使用张量并行,结果如下图所示。在更大的模型上,SGLang的优化表现出类似的趋势,表明其优化对更大的模型具有良好的泛化性。由于Guidance和LMQL缺乏对张量并行的高效实现,因此它们被省略。

多模态模型的结果
SGLang对多模态模型具有原生的支持,使用图像和视频原语。该论文中的优化与多模态模型兼容。对于RadixAttention,计算输入图像的哈希并将其用作基数树中的键,允许重用相同图像的图像令牌的KV缓存。LLaVA-v1.5-7B(图像)在llava-bench-in-the-wild上运行,LLaVA-NeXT-34B(视频)在ActivityNet上运行。由于这些模型不被其他基准系统很好地支持,因此使用了Hugging Face Transformers中模型作者的原始实现作为基准。如以下表所示,SGLang在这些基准测试中提供了最高6×的吞吐量。在llava-bench-in-the-wild中,同一图像的多个问题被处理,SGLang运行时重用了KV缓存。

生产部署
SGLang已被部署在Chatbot Arena中,以服务开权重模型。由于某些模型的流量较低,因此每个模型只有一个SGLang工作者。一个月后,LLaVA-Next-34B的RadixAttention缓存命中率为52.4%,Vicuna-33B的缓存命中率为74.1%。缓存命中来自常见的系统消息、频繁重用的示例图像和多回合聊天历史。这种情况降低了Vicuna-33B的首令牌延迟,平均降低了1.7×。

最后的想法
在本文中,我们讨论了SGLang,一种新引入的系统,旨在通过提供复杂语言模型程序的高效执行来解决这个问题。SGLang由一个前端语言和一个运行时组成。前端通过提供用于生成和并行控制的原语来简化编程,而运行时通过新型优化来加速执行,例如RadixAttention用于KV缓存重用和压缩的有限状态机用于更快的结构化输出解码。实验表明,SGLang在各种大型语言和多模态模型上实现了最高6.4×的吞吐量,相比于现有的最先进的推理系统,处理任务如代理控制、逻辑推理、少样本学习基准、JSON解码、检索增强生成管道和多回合聊天。












