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