gpt-4o-2024-08-06
在談 Structured Outputs 之前,我們先來看看這個名為 gpt-4o-2024-08-06 的新模型,在輸入與輸出的 token 費用上,$5.00 / 1M input tokens 相對於 gpt-4o 降價了 50%,$10.00 / 1M output tokens 相對於 gpt-4o 降了 33.33%,同時輸出 token 的最大數量也擴展到了16k 的長度,一如往常 LLM 持續卷的趨勢,各家迭代推出更新且更強的模型反而在使用上的成本卻更加便宜。
Structured Outputs
在去年的開發者大會上,OpenAI 推出了 JSON 模式,這對想要用他們的模型開發穩定應用程式的工程師來說是個好工具。不過呢,雖然 JSON 模式確實讓模型在產生合格 JSON 輸出方面更可靠了,但它還是無法保證模型的回應會完全符合特定的結構。今天 OpenAI 在 API 中推出一個全新功能:結構化輸出。這個功能可以確保模型產生的輸出會百分之百符合開發者提供的 JSON 結構定義。要把沒有結構的資料轉成有結構的資料,這可說是現在 AI 應用中最重要的用途之一。開發者們用 OpenAI 的 API 來打造功能強大的助手,這些助手可以透過呼叫函式來抓取資料、回答問題,還能提取結構化資料來輸入,甚至建立多步驟的智慧工作流程,讓 AI 模型能夠採取行動。
以前,開發者們總是得用開源工具、各種提示,還要一遍又一遍地重試,才能確保模型輸出的格式符合他們系統的需求。現在,結構化輸出徹底解決了這個問題。它不只限制了 OpenAI 的模型必須符合開發者提供的結構定義,還訓練他們的模型更懂得理解複雜的結構。OpenAI 測試了模型在遵循複雜 JSON 結構方面的表現,結果相當驚人。他們最新的模型 gpt-4o-2024-08-06
搭配結構化輸出功能,竟然拿到了滿分 100 分!相較之下,舊版的 gpt-4-0613
只有不到 40 分。
那麼,要怎麼用這個結構化輸出功能呢?OpenAI 在 API 裡提供了兩種方式:
第一種是透過『Function Calling』。只要在開發者定義函式的時候,把 strict
這個選項設為 true
,就可以啟用結構化輸出了。這個功能支援的模型還滿多的,包括 gpt-4-0613
、gpt-3.5-turbo-0613
以及之後的所有版本。開啟這個功能後,模型輸出就會乖乖聽話,完全符合開發者定義的工具結構。
第二種方式是使用 response_format
參數的新選項。現在,開發者可以直接提供一個 JSON Schema,透過 json_schema
這個新選項來實現。這個方法特別適合那些不是呼叫工具,而是要模型直接用結構化方式回應使用者的情況。不過要注意,這個功能目前只支援 OpenAI 最新的幾個 gpt-4o 模型,包括今天剛推出的 gpt-4o-2024-08-06
和 gpt-4o-mini-2024-07-18
。只要開發者在使用 response_format
的時候把 strict
設為 true
,模型的輸出就會完全符合他們提供的 schema。
這兩種方法讓開發者們有了更多選擇,可以根據自己的需求來決定要怎麼實現結構化輸出。無論他們選哪一種,都能讓 AI 模型的輸出更加精準,更符合他們的期望。
安全,永遠是 OpenAI 最看重的事情。所以呢,就算他們推出了這個新的結構化輸出功能,他們還是會嚴格遵守現有的安全政策,讓 AI 模型有權利拒絕那些不安全的要求。不過 OpenAI 也知道,開發者們希望開發過程能夠更簡單一點。所以他們在 API 的回應中加了一個新的 refusal
字串值。有了這個值,開發者就可以很輕鬆地用程式來判斷:模型是拒絕回答了呢?還是產生了符合要求的輸出?
當然啦,如果回應裡沒有拒絕訊息,而且模型的回應也沒有被中途打斷(這個可以從 finish_reason
看出來),那麼開發者就可以放心了。在這種情況下,模型一定會乖乖地產生符合開發者提供的模式的有效 JSON。簡單來說,OpenAI 就是想讓開發過程更順暢,但同時又不犧牲安全性。
除了之前提到的用途,開發者們其實還有很多有趣的方式來運用 OpenAI 的模型產生結構化的資料。OpenAI 舉了一個例子:
想像一下,要是能根據使用者的意圖來即時生成使用者介面,那該有多酷?這並不是天方夜譚。
使用 OpenAI 的結構化輸出功能,開發者就能打造出能自動生成程式碼或使用者介面的應用程式。更厲害的是,只要用同一個 response_format
,就能根據不同的使用者輸入,變出各式各樣的介面來。
這樣的應用真的很有意思,因為它讓軟體變得更聰明、更懂得適應使用者的需求。想像一下,以後的 App 可能會自動根據使用者的喜好來調整介面,是不是很酷?這就是 AI 為我們的數位世界帶來的新可能性。
再來看看結構化輸出的兩個超實用的應用:
首先,想像一下,如果能讓 AI 模型在給出最終答案之前,先把思考過程「說」出來,那會怎麼樣?沒錯,這就像是讓 AI 在回答問題時,先在草稿紙上打打草稿。這樣不只能讓 AI 的回答更加精準,使用者還能一窺 AI 的「腦袋」裡在想些什麼!這種方法可以大大提升 AI 回答的品質,讓人們更信任它的結論。
再來,OpenAI 談到如何從一堆雜亂無章的資料中找出重點。比方說,某人參加完一個冗長的會議,有一大堆雜亂的筆記。現在,人們可以指示 AI 模型從這些筆記中自動整理出待辦事項、截止日期,甚至任務分配。這簡直就像是有了一個超級效率的助理,幫人們把重要資訊都整理得井井有條!
這兩個應用都顯示了結構化輸出的強大威力。它不僅讓 AI 的回答更加清晰有條理,還能幫人們從看似雜亂的資訊中提煉出精華。這樣一來,不管是解決複雜問題,還是處理日常瑣事,AI 都能成為人們得力的幫手。
Under the hood
為了提升 AI 模型在生成符合 JSON Schema 結構化數據方面的可靠性,OpenAI 採取了兩項創新策略。首先,他們對最新的 gpt-4o-2024-08-06
模型進行了特殊訓練,使其能夠理解複雜的數據結構,並精確地生成符合要求的輸出。這項訓練使得模型在基準測試中取得了 93% 的優異成績。
然而,AI 模型的行為本質上帶有不確定性。即使性能大幅提升,仍未能完全滿足開發者在構建穩健應用程式時對可靠性的嚴格要求。有鑑於此,OpenAI 進一步採用了一種基於工程學的確定性方法,對模型的輸出進行了嚴格限制。這種方法確保了輸出結果的 100% 可靠性,為開發者提供了更穩定、更可預測的工具。
Constrained decoding
OpenAI 的方法基於一種稱為約束採樣或約束解碼的技術。默認情況下,當對模型進行採樣以產生輸出時,它們是完全不受約束的,可以從詞彙表中選擇任何標記作為下一個輸出。這種靈活性是導致模型犯錯的原因;例如,它們通常可以在任何時候自由地採樣大括號標記,即使這樣做不會產生有效的 JSON。為了強制產生有效的輸出,OpenAI 約束他們的模型只能使用根據提供的模式有效的標記,而不是所有可用的標記。
在實踐中實現這種約束可能具有挑戰性,因為在模型輸出的整個過程中,有效的標記是不同的。假設有以下模式:
{
"type": "object",
"properties": {
"value": { "type": "number" }
},
"required": ["value"],
"additionalProperties": false
}
在輸出開始時有效的標記包括 {
、{"
、{\n
等。然而,一旦模型已經抽樣了 {"val
,那麼 {
就不再是有效 token。因此,OpenAI 需要實現動態 Constrained decoding,並在每個 token 生成後確定哪些標記是有效的,而不是在回應開始時就預先確定。
為此,OpenAI 將提供的 JSON Schema 轉換為 context-free grammar(CFG)。文法是定義語言的一組規則,而 CFG 是符合特定規則的文法。可以將 JSON 和 JSON Schema 視為具有規則來定義語言中什麼是有效的特定語言。就像在英語中沒有動詞的句子是無效的一樣,在 JSON 中有尾隨逗號是無效的。
因此,對於每個 JSON Schema,OpenAI 計算一個代表該模式的文法,並預處理其組件,使其在模型抽樣期間易於訪問。這就是為什麼使用新模式的第一個請求會產生 latency penalty 的原因:他們必須預處理模式以生成這個可以在抽樣期間高效使用的產物。
在抽樣過程中,每個 token 之後,OpenAI 的推理引擎將根據先前生成的 token 和文法中指示下一個有效 token 的規則來確定哪些 token 可以產生下一個。然後他們使用這個 token 列表來遮罩下一個抽樣步驟,這有效地將無效 token 的機率降低到 0。因為他們已經預處理了模式,OpenAI 可以使用暫存的數據結構來高效地執行此操作,並且延遲開銷最小。
AI 的『語言學習』難題:為何選擇 CFG?
在教 AI 『說人話』的過程中,工程師們面臨著一個有趣的選擇:是要教它背誦固定的句型(就像使用有限狀態機,FSM),還是要教它理解語言的深層結構(使用上下文無關文法,CFG)?
OpenAI 的工程師們選擇了後者,原因頗為巧妙。想像一下,如果一個人在學習一門新語言,只是死記硬背一些常用句子,他可能應付日常對話沒問題。但如果要他理解或創作一首複雜的詩,他可能就會不知所措。這就是 FSM 方法的局限性——它像是教 AI 背誦句子,而不是真正理解語言結構。
相比之下,CFG 方法就像是教 AI 理解語法規則。這使得 AI 不僅能應付簡單的對話,還能理解和生成複雜的語言結構,比如那些包含多層嵌套或遞迴的句子。在計算機的世界裡,這相當於能夠處理複雜的數據結構,如深度嵌套的 JSON 文件。
OpenAI 的這個選擇,使得他們的 AI 模型具備了處理更複雜、更靈活的語言和數據結構的能力。這不僅體現在技術上的優越性,更意味著 AI 在實際應用中能夠應對更多樣化、更複雜的場景。
簡而言之,OpenAI 選擇了一條看似更艱難,但潛力更大的路徑。這就像是培養一個精通語言的翻譯家,而不僅僅是一個會背誦幾句外語的導遊。這種方法雖然在初期可能更具挑戰性,但長遠來看,它為 AI 開啟了更廣闊的應用前景。
結構化輸出功能:使用須知
OpenAI 的結構化輸出功能雖然強大,但也有一些值得注意的限制和特點:
- 資料類型限制:它只能處理特定類型的 JSON Schema。這樣做是為了確保其最佳運作狀態。
- 初次處理延遲:第一次使用新的 schema 時,它需要一定時間進行處理,可能需要幾秒到一分鐘不等。後續使用則會顯著加快。
- 安全性考量:如果判斷某個請求不安全,它會直接拒絕執行。
- 輸出可能不完整:如果達到設定的字數限制,它可能會中止輸出,留下未完成的內容。
- 準確性有限:雖然結構會符合規範,但內容可能仍有錯誤,特別是在處理複雜的數學問題時。
- 並行處理能力不足:它不能很好地處理並行的函數調用。
- 數據保留問題:使用這個功能時,OpenAI 可能會保留一些數據,不符合零數據保留政策。
OpenAI 的結構化輸出功能現已全面開放使用,為開發者提供更多可能性和更高的性價比。
總結
Structured Outputs 現已支援 OpenAI 的各種主力模型,包括最新的 GPT-4 系列和廣受歡迎的 GPT-3.5 系列。無論開發者使用 Chat completion API、Assistant API,還是 Batch API,均可使用結構化輸出功能。此外,該功能還支援視覺輸入,為多模態應用開闢了新的發展空間。
在成本方面,最新的 ‘gpt-4o-2024-08-06’ 模型不僅功能更強,價格也大幅下調。與之前的版本相比,輸入成本減少了 50%,輸出成本降低了 33%。這意味著開發者可以以更低的成本獲得更出色的性能。