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.…

SpringCloud源码分析-nacos与eureka

一、高版本为什么优先用nacos 如果用alibaba springcloud,那么就是阿里的技术体系。nacos属于阿里的原生技术栈,所以阿里更偏向于用nacos作为服务发现注册。 二、对比分析 Spring Cloud Alibaba 推荐使用 Nacos 作为服务发现和配置管理的首选组件&…

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

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

级联配准learning

1.定义 级联配准(Cascade Registration)是一种在图像处理、计算机视觉等领域广泛应用的技术。它主要用于将不同视角、不同模态或者不同时间获取的图像进行精确的对齐,并且是通过多个阶段(级联)的处理来逐步优化配准的精…

初学STM32 --- 外部SRAM

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

leetcode hot 100 前k个高平元素

347. 前 K 个高频元素 已解答 中等 相关标签 相关企业 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 class Solution(object):def topKFrequent(self, nums, k):""":type nums: Lis…

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/) 等待…

python3.x支持,但python2.7不支持的语法

python3.x支持,但python2.7不支持的语法 1.属性访问的问题&#xff1a; 你可能是在 params 中直接使用了某个对象的属性&#xff0c;而不是该属性的值。在你提供的信息中&#xff0c;<slot wrapper next of instance objects> 指的是一个对象的槽位&#xff08;slot wra…

开源GTKSystem.Windows.Forms框架:C# Winform跨平台运行深度解析

开源GTKSystem.Windows.Forms框架&#xff1a;C# Winform跨平台运行深度解析 一、跨平台框架的崛起 1.1 跨平台技术的现状与需求 在当今快速发展的科技时代&#xff0c;软件开发的需求日益多样化。随着移动设备和操作系统的不断涌现&#xff0c;开发者面临着前所未有的挑战&…

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

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

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;数据和索引保存在磁盘上…

Swift Combine 学习(二):发布者 Publisher

Swift Combine 学习&#xff08;一&#xff09;&#xff1a;Combine 初印象Swift Combine 学习&#xff08;二&#xff09;&#xff1a;发布者 PublisherSwift Combine 学习&#xff08;三&#xff09;&#xff1a;Subscription和 SubscriberSwift Combine 学习&#xff08;四&…

Win11清除安全中心保护历史记录全攻略

Win11清除安全中心保护历史记录全攻略 在Windows 11操作系统中,安全中心作为守护系统安全的重要防线,扮演着举足轻重的角色。它不仅实时监控系统的安全状态,还详细记录各类安全事件,为用户提供全面的安全保障。然而,随着系统的长期使用,这些安全记录可能会逐渐累积,占用…