实用约束解码入门指南
本文介绍了实用约束解码(也称结构化生成或引导解码),这是一种在token选择阶段强制大型语言模型(LLM)严格遵循指定数据模式、语法或正则表达式的工程策略。通过构建有限状态机,在推理前将约束编译为白名单,对logits向量进行掩码,使得模型只能生成符合约束的token。文章还介绍了当前最流行的实现库——outlines,并通过一个Python示例展示了如何使用Pydantic模型约束LLM输出JSON。
实用约束解码(也称为结构化生成或引导解码)是一种工程策略,旨在强制大型语言模型(LLM)在生成文本时严格遵循指定的数据模式、语法或正则表达式。与传统的“信任式”生成不同,约束解码将提示和文本生成视为一个交织的程序,通过锁定关键字符,让模型在约束内填充内容。其核心机制是在推理前构建一个有限状态机,将目标约束(如Python的Pydantic模型)编译成白名单。在每一步生成新token时,有限状态机评估当前状态并给出允许的token列表,然后对LLM的原始logits向量进行掩码,将白名单外的token的logit设为负无穷。之后,模型在幸存token上正常进行softmax归一化和采样(考虑温度、top-p等参数),最终选择最可能的token。
尽管需要对整个词汇表进行掩码操作,但现代Python库通过预编译词汇表,大大降低了延迟开销。目前,outlines库被认为是实现约束解码的黄金标准。它允许用户定义Pydantic模型、JSON模式或正则表达式,并将其传递给封装后的预训练模型,从而限制模型输出的自由度。
以下是一个使用outlines库的代码示例:首先通过pip install outlines[transformers]安装库,然后定义一个继承自Pydantic BaseModel的UserProfile类,包含name、age和is_active字段。接着加载TinyLlama模型和分词器,使用outlines.from_transformers封装模型,最后调用模型并传入提示和结构约束。模型输出严格的JSON对象,如{"name": "John", "age": 34, "is_active": true}。
约束解码的优势包括:100%保证正确语法,消除代码中的解析需求;大幅节省prompt中的token,不再需要few-shot示例;使小型模型(如1B参数)也能可靠地生成结构化数据,促进小模型的普及。然而,它也有局限性:如果模型需要回答无法回答的问题,但模式强制输出整数,模型会照做,从而失去诚实性;首次运行Pydantic模式时,构建有限状态机可能需要数秒冻结,导致首次推理显著变慢。
总之,实用约束解码为LLM驱动的应用提供了一种可靠的方法,确保输出符合预期格式。通过outlines等工具,开发者可以轻松实现结构化生成,提高系统的稳定性和效率。