實用約束解碼入門指南
本文介紹了實用約束解碼(也稱結構化生成或引導解碼),這是一種在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等工具,開發者可以輕鬆實現結構化生成,提高系統的穩定性和效率。