vLLM结构化输出(Guided Decoding)

简介

vLLM 的结构化输出特性是通过“引导式解码”(Guided Decoding)实现的,这一功能允许模型在生成文本时遵循特定的格式约束,例如 JSON 模式或正则表达式,从而确保生成的内容符合预期的结构化要求。

后端引擎

启动vLLM时,可以指定--guided-decoding-backend参数来设置引导式编码的具体实现引擎,最新版本默认使用的是xgrammar。可以有以下三种选择:

  • outlines-dev/outlines
  • mlc-ai/xgrammar
  • noamgat/lm-format-enforcer

优势

  1. 输出结果符合预期,不需要额外的兼容逻辑。不使用引导式编码时,模型的输出通常无法控制,导致生成的内容通常需要额外的处理逻辑去兼容,且无法兼容所有情况。
  2. 性能更好。不使用引导式编码时,模型有可能生成与你预期格式无关的token,导致整理耗时较大。

如何使用

chat completion接口的extra_body可以指定输出的格式。

分类任务

示例代码使用guided_choice引导模型生成指定的分类

from openai import OpenAI
client = OpenAI(base_url="http://localhost:8000/v1",api_key="-",
)completion = client.chat.completions.create(model="Qwen/Qwen2.5-3B-Instruct",messages=[{"role": "user", "content": "Classify this sentiment: vLLM is wonderful!"}],extra_body={"guided_choice": ["positive", "negative"]},
)
print(completion.choices[0].message.content)

正则格式

示例代码使用guided_regex引导模型生成邮箱格式的输出

completion = client.chat.completions.create(model="Qwen/Qwen2.5-3B-Instruct",messages=[{"role": "user","content": "Generate an example email address for Alan Turing, who works in Enigma. End in .com and new line. Example result: alan.turing@enigma.com\n",}],extra_body={"guided_regex": "\w+@\w+\.com\n", "stop": ["\n"]},
)
print(completion.choices[0].message.content)

JSON格式

示例代码使用guided_json引导模型生成json格式输出(使用pydantic只是为了得到json schema,你也可以手动提供json schema)

from pydantic import BaseModel
from enum import Enumclass CarType(str, Enum):sedan = "sedan"suv = "SUV"truck = "Truck"coupe = "Coupe"class CarDescription(BaseModel):brand: strmodel: strcar_type: CarTypejson_schema = CarDescription.model_json_schema()completion = client.chat.completions.create(model="Qwen/Qwen2.5-3B-Instruct",messages=[{"role": "user","content": "Generate a JSON with the brand, model and car_type of the most iconic car from the 90's",}],extra_body={"guided_json": json_schema},
)
print(completion.choices[0].message.content)

EBNF语法格式

EBNF 是 Extended Backus-Naur Form(扩展巴科斯-诺尔范式) 的缩写,它是一种用于描述上下文无关语法的标准化表示法。EBNF 是 BNF 的扩展版本,比 BNF 更加简洁和易读,广泛用于定义编程语言、协议以及其他形式化语言的语法规则。

示例代码使用guided_grammar用于指导生成符合特定规则(SQL 查询格式)的语言结构。

simplified_sql_grammar = """?start: select_statement?select_statement: "SELECT " column_list " FROM " table_name?column_list: column_name ("," column_name)*?table_name: identifier?column_name: identifier?identifier: /[a-zA-Z_][a-zA-Z0-9_]*/
"""completion = client.chat.completions.create(model="Qwen/Qwen2.5-3B-Instruct",messages=[{"role": "user","content": "Generate an SQL query to show the 'username' and 'email' from the 'users' table.",}],extra_body={"guided_grammar": simplified_sql_grammar},
)
print(completion.choices[0].message.content)

实现原理

结构化输出流程图

构建logits_processor

这里以xgrammar作为示例,使用transformers进行模型推理时,只需要在generate方法的入参,指定logits_processor就行。

import xgrammar as xgr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfigdevice = "cuda"  # Or "cpu", etc.
model_name = "meta-llama/Llama-3.2-1B-Instruct"
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float32, device_map=device
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
config = AutoConfig.from_pretrained(model_name)# 1. 组装inputs
messages = [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": "Introduce yourself in JSON briefly."},
]
texts = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
model_inputs = tokenizer(texts, return_tensors="pt").to(model.device)# 2. 获取compiled grammar
tokenizer_info = xgr.TokenizerInfo.from_huggingface(tokenizer, vocab_size=config.vocab_size)
grammar_compiler = xgr.GrammarCompiler(tokenizer_info)
compiled_grammar = grammar_compiler.compile_builtin_json_grammar()
# Other ways: provide a json schema string
# compiled_grammar = grammar_compiler.compile_json_schema(json_schema_string)
# Or provide an EBNF string
# compiled_grammar = grammar_compiler.compile_grammar(ebnf_string)# 3. generate时,指定compiled_grammar作为logits_processor
xgr_logits_processor = xgr.contrib.hf.LogitsProcessor(compiled_grammar)
generated_ids = model.generate(**model_inputs, max_new_tokens=512, logits_processor=[xgr_logits_processor]
)
generated_ids = generated_ids[0][len(model_inputs.input_ids[0]) :]
print(tokenizer.decode(generated_ids, skip_special_tokens=True))

屏蔽

logits_processor的内部处理逻辑大致如下:

# 1. 初始化grammar matcher,并实例化一个bitmask
matcher = xgr.GrammarMatcher(compiled_grammar)
token_bitmask = xgr.allocate_token_bitmask(1, tokenizer_info.vocab_size)# 模型 LLM 推理过程,logits 为模型的推理结果
for logits in LLM.inference(**model_inputs)# 2. 使用 GrammarMatcher 计算 bitmask 并应用到 logits 上matcher.fill_next_token_bitmask(token_bitmask)xgr.apply_token_bitmask_inplace(logits, token_bitmask.to(logits.device))# 3. 获取下一个token id (使用softmax得到概率值,再根据具体的取样算法获取最终生成的token_id)probs = torch.softmax(logits, dim=-1).cpu().numpy()next_token_id = np.random.choice(list(range(full_vocab_size)), p=probs)# 4. 更新 GrammarMatcher 的状态assert matcher.accept_token(next_token_id), f"Invalid token: {next_token_id}"# 5. 检查终止条件if next_token_id == tokenizer.eos_token_id:break# 6. 将 token_id 转换为 token 并返回next_token = tokenizer.decode([next_token_id])[0]  # 根据实际的 tokenizer 转换 token_id 为 tokenyield next_token  # 逐步返回每个生成的 token

总结

语言模型的输出由模型的推理结果(logits)通过采样或其他策略生成。在结构化生成场景中,GrammarMatcher 实例化一个 bitmask ,对模型的生成过程进行约束,确保输出符合预定义的语法规则(如 JSON 格式或特定语言的 EBNF 语法)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

部署SenseVoice

依赖 Conda cuda pythor 查看GPU版本-CSDN博客 创建虚拟conda环境 conda create --name deeplearn python3.10 conda activate deeplearn git clone https://github.com/FunAudioLLM/SenseVoice.git cd SenseVoice pip install -r requirements.txt pip install gradio pip …

基于51单片机(STC32G12K128)和8X8彩色点阵屏(WS2812B驱动)的小游戏《贪吃蛇》

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、定时器02、矩阵按键模块3、8X8彩色点阵屏 四、主函数总结 系列文章目录 前言 《贪吃蛇》,一款经典的、怀旧的小游戏,单片机入门必写程序。 以《贪吃蛇》为载体,熟悉各种屏幕…

关于flinkCDC监控mysql binlog时,datetime类型自动转换成时间戳类型问题

flinkCDC监控mysql binlog时,datetime类型自动转换成时间戳类型 问题解决1.自定义转换器类2.代码引用 结果 问题 flink版本:1.18.1,mysql版本:8.0.40 使用FlinkCDC的MySqlSource 连接mysql,对于datetime 类型字段&…

SwiftUI 撸码常见错误 2 例漫谈

概述 在 SwiftUI 日常撸码过程中,头发尚且还算茂盛的小码农们经常会犯这样那样的错误。虽然犯这些错的原因都很简单,但有时想要快速准确的定位它们却并不容易。 况且这些错误还可能在模拟器和 Xcode 预览(Preview)表现的行为不甚…

【Unity】 HTFramework框架(五十八)【进阶篇】资源及代码热更新实战演示(Deployment + HybridCLR)

更新日期:2025年1月2日。 Github源码:[点我获取源码] 索引 资源及代码热更新实战演示运行演示Demo1.克隆项目工程2.更新子模块3.打开项目4.打开入口场景5.设置远端资源服务器地址6.导入HybridCLR7.初始化HybridCLR8.发布项目9.部署资源版本10.运行Exe11.…

(五)人工智能进阶:基础概念解释

前面我们介绍了人工智能是如何成为一个强大函数。接下来,搞清损失函数、优化方法和正则化等核心概念,才能真正驾驭它! 1. 什么是网络模型? 网络模型就像是一个精密的流水线工厂,由多个车间(层&#xff0…

初学STM32 --- 外部SRAM

SRAM简介 静态随机存取存储器(Static Random-Access Memory,SRAM) 1M字节容量的SRAM芯片XM8A51216为例介绍。 SRAM特性: 高速:具有最高访问速度15ns 低功耗:80MHz时55mA,待机电流 20mA TTL电平兼容 …

Zabbix:自动发现功能讲解,包括网络发现、自动注册、低级别自动发现以及案例分享。

ZBX:自动发现功能讲解 视频讲解:Zabbix 自动发现网络发现概述操作方法 自动注册概述操作方法 低级别自动发现概述工作原理及工作流程案例1,base进程监控要求:步骤: 案例2,磁盘IO监控要求:步骤&a…

Windows上安装Go并配置环境变量(图文步骤)

前言 1. 本文主要讲解的是在windows上安装Go语言的环境和配置环境变量; Go语言版本:1.23.2 Windows版本:win11(win10通用) 下载Go环境 下载go环境:Go下载官网链接(https://golang.google.cn/dl/) 等待…

#端云一体化开发# #HarmonyOS Next#《说书人》鸿蒙原生基于角色的对话式文本编辑开发方案

1、写在前面 过去的一百年里,在“编程”的这个行业诞生之初,人们采用面向过程的方式进行开发,但是,伴随着程序规模的日益增大,程序的复杂度也随之增加,使用结构化编程方法来管理复杂的程序逻辑变得越来越困…

xadmin后台首页增加一个导入数据按钮

xadmin后台首页增加一个导入数据按钮 效果 流程 1、在添加小组件中添加一个html页面 2、写入html代码 3、在urls.py添加导入数据路由 4、在views.py中添加响应函数html代码 <!DOCTYPE html> <html lang

【AimRT】现代机器人通信中间件 AimRT

目录 一、什么是AimRT二、AimRT与ROS22.1 定位与设计2.2 组成与通信方式对比 三、AimRT基本概念3.1 Node、Pkg 和 Module3.2 Protocol、Channel、Rpc 和 Filter3.3 App模式 和 Pkg模式3.4 Executor3.5 Plugin 一、什么是AimRT AimRT 是智元机器人公司自主研发的一款机器人通信…

mysql系列7—Innodb的redolog

背景 本文涉及的内容较为底层&#xff0c;做了解即可&#xff0c;是以前学习《高性能Mysql》和《mysql是怎样运行的》的笔记整理所得。 redolog(后续使用redo日志表示)的核心作用是保证数据库的持久性。 在mysql系列5—Innodb的缓存中介绍过&#xff1a;数据和索引保存在磁盘上…

C++【内存管理】

C/C中程序的内存划分&#xff1a; 栈&#xff1a;又称堆栈&#xff0c;存放非静态的局部变量、函数参数、返回值等等&#xff0c;栈是向下增长的。内存映射段&#xff1a;是高效的&#xff29;&#xff0f;&#xff2f;映射方式&#xff0c;用于装载一个共享的动态内存库。用户…

手机租赁平台开发助力智能设备租赁新模式

内容概要 手机租赁平台开发&#xff0c;简单说就是让你用得起高大上的智能设备&#xff0c;不管是最新款的手机、平板&#xff0c;还是那些炫酷的智能耳机&#xff0c;这个平台应有尽有。想要体验但又不希望花大钱&#xff1f;那你就找对地方了&#xff01;通过灵活的租赁方案…

【开源免费】基于SpringBoot+Vue.JS校园社团信息管理系统(JAVA毕业设计)

本文项目编号 T 107 &#xff0c;文末自助获取源码 \color{red}{T107&#xff0c;文末自助获取源码} T107&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

【鸿蒙NEXT】鸿蒙里面类似iOS的Keychain——关键资产(@ohos.security.asset)实现设备唯一标识

前言 在iOS开发中Keychain 是一个非常安全的存储系统&#xff0c;用于保存敏感信息&#xff0c;如密码、证书、密钥等。与 NSUserDefaults 或文件系统不同&#xff0c;Keychain 提供了更高的安全性&#xff0c;因为它对数据进行了加密&#xff0c;并且只有经过授权的应用程序才…

使用npm包的工程如何引入mapboxgl-enhance/maplibre-gl-enhance扩展包

作者&#xff1a;刘大 前言 在使用iClient for MapboxGL/MapLibreGL项目开发中&#xff0c;往往会对接非EPSG:3857坐标系的地图&#xff0c;由于默认不支持&#xff0c;因此需引入mapboxgl-enhance/maplibre-gl-enhance扩展包。 在使用Vue等其他框架&#xff0c;通过npm包下载…

应急指挥系统总体架构方案

引言 应急指挥系统总体架构方案旨在构建一个高效、智能的应急管理体系&#xff0c;以应对自然灾害、事故灾难等突发事件&#xff0c;保障人民生命财产安全。 背景与挑战 近年来&#xff0c;安全生产形势严峻&#xff0c;自然灾害事故频发&#xff0c;对应急指挥系统的要求越…

如何用CSS3创建圆角矩形并居中显示?

在网页设计中&#xff0c;圆角矩形因其美观和现代感而被广泛使用&#xff0c;居中显示元素也是一个常见的需求。今天&#xff0c;我们将学习如何使用CSS3的border-radius属性来创建圆角矩形&#xff0c;并将其居中显示在页面上。 如果你正在学习CSS&#xff0c;那么这个实例将非…