SGLang——结构化语言模型程序的高效执行
前言
大型语言模型 (LLM) 越来越多地用于需要多次生成调用、高级提示技术、控制流和结构化输入/输出的复杂任务。然而,缺乏用于编程和执行这些应用程序的高效系统。新推出的系统 SGLang 旨在通过提供复杂语言模型程序的高效执行来解决这一问题。SGLang 包含前端语言和运行时。前端使用用于生成和并行控制的原语简化编程,而运行时通过新颖的优化加速执行,例如用于 KV 缓存重用的 RadixAttention 和用于更快结构化输出解码的压缩有限状态机。实验表明,与各种大型语言和多模态模型上的最先进推理系统相比,SGLang 实现了高达 6.4 倍的吞吐量,可处理代理控制、逻辑推理、小样本学习基准、JSON 解码、检索增强生成管道和多轮聊天等任务。
LLM 功能的最新进展扩大了它们的实用性,使它们能够处理更广泛的一般任务并充当自主代理。在这些应用中,LLM 参与多轮规划、推理和与外部环境的交互。这是通过使用工具、多种输入方式和各种提示技术(例如小样本学习、自洽、思维骨架和思维树)来实现的。这些新用例需要多个(通常是相互依赖的)LLM 生成调用,这表明使用多调用结构来完成复杂任务的趋势。
这种转变标志着 LLM 从简单的聊天过渡到更复杂的程序化使用,其中程序安排和控制 LLM 的生成过程。这些程序被称为“语言模型程序”(LM 程序)。高级提示技术和代理工作流属于 LM 程序的范围。LM 程序有两个共同属性:(1) LM 程序通常涉及多个 LLM 调用,这些调用与控制流交织在一起,以完成复杂任务并提高整体质量。(2) LM 程序接收结构化输入并产生结构化输出,从而实现 LM 程序的组合并集成到现有软件系统中。
SGLang 简介
尽管 LM 程序得到了广泛使用,但当前用于表达和执行它们的系统仍然效率低下。SGLang 确定了与高效使用 LM 程序相关的两个主要挑战:
- 编程复杂性:由于 LLM 的非确定性,开发 LM 程序既繁琐又困难。这涉及大量字符串操作、提示的实验性调整、脆弱的输出解析、处理多种输入模式以及实现并行机制。这种复杂性大大降低了即使是简单程序的可读性。
- 执行效率低下:由于冗余计算和内存使用,执行 LM 程序效率低下。最先进的推理引擎经过优化以减少延迟并提高吞吐量,但缺乏对工作负载的直接了解,导致效率低下。一个值得注意的例子是重用键值 (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 推测执行:对于仅使用 API 的模型,例如 OpenAI的GPT-4,SGLang引入API推测执行来优化多调用程序。
使用 SGLang,实现了各种 LLM 应用程序,包括代理控制、逻辑推理、小样本学习基准、JSON 解码、检索增强生成管道、多轮聊天和多模态处理。在 NVIDIA A7G 和 A70 GPU 上对 Llama-8B/7B、Mistral-1.5x7B、LLaVA-v34-10B(图像)和 LLaVA-NeXT-100B(视频)等模型进行了性能测试。实验结果表明,与现有的编程和推理系统(包括 Guidance、vLLM 和 LMQL)相比,SGLang 在各种工作负载、模型和硬件设置中实现了高达 6.4 倍的吞吐量。
SGLang:编程模型和方法
通过一个运行示例介绍了 SGLang 编程模型,描述了其语言原语和执行模式,并概述了运行时优化机会。该模型通过提供灵活且可组合的原语,简化了多调用工作流(例如字符串操作、API 调用、约束规范、并行性)中的繁琐操作。SGLang 是一种嵌入在 Python 中的领域特定语言。下图显示了一个使用分支解决合并提示方法评估关于图像的文章的程序。
该功能 多维评判 接受三个参数: `s`、`path` 和 `essay`.s 管理提示状态,path 是图像文件路径,essay 是文章文本。可以使用以下代码将新字符串和 SGLang 原语附加到状态 s 中执行 += 运算符。首先,该函数将图像和文章添加到提示中。然后它使用 select 检查文章是否与图像相关,并将结果存储在 **s[“相关”]**如果相关,则将提示分为三个副本,以便从不同维度进行并行评估,并使用 gen 将结果存储在 f[“判断”]。接下来,它会合并判断,生成摘要并分配字母等级。最后,它会按照正则表达式约束定义的模式以 JSON 格式返回结果 正则表达式。SGLang 大大简化了这个程序,因为使用类似 OpenAI API 接口的等效程序由于手动字符串操作和并行控制将需要 2.1 倍的代码行数。
SGLang 提供了用于控制提示状态、生成和并行性的原语,可与 Python 语法和库一起使用。以下是原语:
流派: 调用模型来生成结果并将其存储在变量中,变量的名称由其第一个参数指定。它支持“regex”参数,以限制输出遵循正则表达式定义的语法(例如 JSON 模式)。
- 选择:调用模型从列表中选择概率最高的选项。
- += 或 extend:将字符串附加到提示。
- [variable_name]:获取一代的结果。
- fork:创建提示状态的并行分叉。
- join:重新加入提示状态。
- 图像和视频:接收图像和视频输入。
执行 SGLang 程序的最简单方法是通过解释器,其中提示被视为异步流。类似 扩展、生成和选择 提交到流中进行异步执行。这些非阻塞调用允许 Python 代码继续运行而无需等待生成完成,类似于异步启动 CUDA 内核。每个提示都由后台线程中的流执行器管理,从而实现程序内并行性。获取生成结果将阻塞,直到它们准备就绪,确保正确同步。或者,SGLang 程序可以编译为计算图并使用图执行器执行,从而实现更多优化。本文默认使用解释器模式,并在附录 D 中讨论编译器模式结果。SGLang 使用自己的 SGLang Runtime (SRT) 支持开放权重模型,以及 API 模型,例如 OpenAI 和人择模型。
LLM 的编程系统可分为高级(例如 LangChain、DSPy)和低级(例如 LMQL、Guidance、SGLang)。高级系统提供预定义或自动生成的提示,例如 DSPy 的提示优化器。低级系统通常不会更改提示,但允许直接操作提示和原语。SGLang 是一种类似于 LMQL 和 Guidance 的低级系统。下表比较了它们的功能。
SGLang 更注重运行时效率,并带有自己的共同设计的运行时,允许进行新颖的优化。高级语言(例如 DSPy)可以编译为低级语言(例如 SGLang)。稍后将演示如何将 SGLang 作为后端集成到 DSPy 中以提高运行时效率。
上述示例说明了在 9 个时间点上使用 LRU 驱逐策略的 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(图像)在 ActivityNet 上的 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-52.4B 的 RadixAttention 缓存命中率为 34%,Vicuna-74.1B 的 RadixAttention 缓存命中率为 33%。缓存命中来自常见系统消息、经常重复使用的示例图像和多轮聊天历史记录。这平均将 Vicuna-1.7B 的第一个令牌延迟降低了 33 倍。
总结
在本文中,我们讨论了新推出的系统 SGLang,该系统旨在通过提供复杂语言模型程序的高效执行来解决这一问题。SGLang 包含前端语言和运行时。前端使用用于生成和并行控制的原语简化编程,而运行时通过新颖的优化(例如用于 KV 缓存重用的 RadixAttention 和用于更快的结构化输出解码的压缩有限状态机)加速执行。实验表明,与各种大型语言和多模态模型上的最先进推理系统相比,SGLang 实现了高达 6.4 倍的吞吐量,可处理代理控制、逻辑推理、小样本学习基准、JSON 解码、检索增强生成管道和多轮聊天等任务。
原文地址:https://blog.csdn.net/matt45m/article/details/142452074
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!