當下,大模型領(lǐng)域已然步入 “百模大戰(zhàn)” 時期,形形色色的大模型如雨后春筍般不斷涌現(xiàn)。那么,若我們打算學(xué)習大模型的 API,是否真的需要逐一去鉆研呢?答案無疑是否定的。
盡管大模型的數(shù)量極為可觀,然而就編程接口層面而言,它們大體上頗為相似。用編程領(lǐng)域的專業(yè)表述來講,即便各模型的內(nèi)部實現(xiàn)千差萬別,但其接口卻基本保持一致。所以,只要深入研習其中一個模型的 API,掌握其他 API 對于我們而言也并非難事,能夠較為迅速地入門上手。
既然確定要展開學(xué)習,那自然需要設(shè)定一個具體的學(xué)習目標。在此,我選定的是 OpenAI API。之所以做出這樣的抉擇,首要原因便是 GPT 模型在行業(yè)內(nèi)所產(chǎn)生的深遠影響力,眾多后來者在設(shè)計自身 API 時,或多或少都會對其予以參考借鑒。
此外,還有一個極為關(guān)鍵的因素,OpenAI API 幾乎已成為行業(yè)內(nèi)公認的事實標準。在當下的眾多項目中,許多都傾向于提供與 OpenAI API 相兼容的接口。甚至存在一些具有中間件特性的項目,無論其后臺實際接入的是何種模型,面向自身用戶所提供的均為 OpenAI 兼容的 API。鑒于如此這般的行業(yè)現(xiàn)狀,倘若僅打算學(xué)習一個 API,那么 OpenAI API 顯然是不二之選。
OpenAI API
為了讓你有一個直觀的感受,我們來看一個具體的例子:
復(fù)制curl https://api.openai.com/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer $OPENAI_API_KEY" -d '{ "model": "gpt-4o", "messages": [ {"role": "user", "content": "寫一首關(guān)于AI的詩"} ] }'
在了解具體內(nèi)容之前,我們先從整體上看一下這個 API。雖然我們的主要工作是面向大模型進行編程,但 Open AI API 其實提供了許多功能,比如:Text Generation:生成和處理文本Embeddings:文本轉(zhuǎn)向量Speech to Text:語音轉(zhuǎn)文本Image Generation:生成圖像Vision:處理圖像輸入……
這些不同的接口是通過不同的路徑進行區(qū)分。這里看到的 /v1/chat/completions 就是我們常用的大模型的編程接口。除了各種強大的功能,OpenAI API 還有兩個關(guān)鍵的參數(shù)是各個接口統(tǒng)一的,一個是訪問地址,一個是 API Key。
訪問地址之所以需要被單獨提及,原因在于實際運用該 API 之際,我們并非總是徑直訪問 OpenAI API。有可能是借助他人所提供的兼容 API,亦或是通過代理途徑所給予的訪問方式??偠灾覀兯\用的地址會有所不同,所以需要專門進行配置。
而 API Key 的概念則相對容易理解,不同的 Key 主要用于區(qū)分不同的用戶。從上述實例中能夠清晰地看出,此 Key 是被寫在 HTTP 訪問的頭部信息之中。
倘若我們采用的是 OpenAI 所提供的程序庫,那么這兩個參數(shù)既能夠借助程序來設(shè)定,也可以通過命令行來進行設(shè)置。以下即為使用命令行設(shè)置的相關(guān)示例:
復(fù)制export OPENAI_API_BASE="your_api_base_here" export OPENAI_API_KEY="your_api_key_here"
有了這些通用的知識,接下來,我們來具體關(guān)注一下最核心的大模型編程接口。
Chat Completions
大模型編程接口所對應(yīng)的路徑為 /v1/chat/completions 。在此路徑中,“v1” 代表的是版本編號,而該接口被命名為 “聊天補全”?!把a全” 這一名稱恰好與我們之前所闡述的 GPT 工作原理相互呼應(yīng)。實際上,OpenAI 起初擁有一個單純執(zhí)行補全功能的接口,然而在 ChatGPT 迅速走紅之后,聊天形式逐漸成為主流應(yīng)用模式,于是 “聊天補全” 接口便成為了我們重點關(guān)注且廣泛使用的核心接口。
新舊兩種補全 API 之間最為顯著的區(qū)別在于,舊版 API 所接收傳入的是一個單一的提示詞,而新版 API 接收傳入的則是一個消息列表。
請求
我們來看看這個接口的具體內(nèi)容。作為一個 HTTP 請求,它分為請求和應(yīng)答兩個部分。我們先來看請求。請求的參數(shù)非常多,我們會做一個通覽。有一點需要提示一下,你學(xué)習到這篇內(nèi)容時,可能與最新的 OpenAI API 文檔對不上,因為這個 API 本身也在不斷的演化過程中,它會不斷地增刪參數(shù)。為了方便你理解,我把請求參數(shù)劃分成四類:
- 核心參數(shù)
- 工程參數(shù)
- 工具參數(shù)
- 模型參數(shù)
核心參數(shù)
首先來看最為核心的兩個參數(shù),它們在之前的示例中已然有所呈現(xiàn)。
其一為 “model”,此參數(shù)用于指定與哪一個模型進行交互溝通,在相關(guān)示例里所采用的便是 “gpt - 4o” 模型。
其二是 “messages”,它代表著發(fā)送給模型的消息,這里的消息呈現(xiàn)為一個列表形式,簡單來講,可將其視作一個包含歷史消息的列表,其目的在于為模型提供更為豐富的上下文信息。
每條消息通常由兩個主要部分構(gòu)成:“角色(role)” 和 “內(nèi)容(content)”。其中 “內(nèi)容” 較為直觀,即消息自身所包含的具體信息。而對于常規(guī)對話場景而言,“角色” 主要分為 “系統(tǒng)(system)” 和 “用戶(user)”??梢岳斫鉃殚_發(fā)者所設(shè)置的相關(guān)內(nèi)容對應(yīng) “系統(tǒng)” 角色,而用戶提出的問題則屬于 “用戶” 角色。有時,我們還會把大模型所生成的消息添加進去,例如在聊天歷史記錄中,這類消息的角色即為 “助理(assistant)”。
除了上述這兩個關(guān)鍵參數(shù)之外,還有三個常用參數(shù)。
“temperature”,其概念在之前已經(jīng)有所提及,主要用于設(shè)定大模型回復(fù)的確定性程度。當該值越小,表明回復(fù)的確定性越強;反之,值越大,則意味著回復(fù)的隨機性越強。
“max_completion_tokens”,它表示大模型生成應(yīng)答時的最大 token 數(shù)量。由于大模型生成內(nèi)容通常依據(jù) token 數(shù)量來計費,所以對 “max_completion_tokens” 進行合理限制是一種有效控制成本的方式。不過,也不能將其設(shè)置得過大,因為每個模型內(nèi)部實際上都存在自身的最大限制,當我們所設(shè)置的限制值超出其內(nèi)部限制時,模型將會忽略我們的設(shè)置。值得注意的是,該字段曾被命名為 “max_tokens”,所以在許多地方,包括一些參考 OpenAI 設(shè)計的框架之中,仍然能夠看到 “max_tokens” 的存在。
“stream”,此參數(shù)用于確定是否需要流式應(yīng)答。流式應(yīng)答的主要作用在于提升聊天過程中的響應(yīng)速度,關(guān)于這部分內(nèi)容將會在下一講中展開詳細探討。
需要特別指出的是,對于不同的模型,這些參數(shù)的取值范圍可能會存在差異。例如不同模型各自擁有其特定的 “max_tokens” 取值范圍。此外,鑒于眾多服務(wù)供應(yīng)商提供了兼容的 OpenAI API,即便是相同的參數(shù),其取值范圍也可能不盡相同。比如在 OpenAI API 里,“temperature” 的取值范圍是從 0 到 2,其默認值為 1,然而對于某些兼容模型而言,其取值范圍或許會有所變化,具體情況需要依據(jù)相關(guān)文檔來確定。
通過以上梳理,我們對大模型編程中最核心的參數(shù)有了較為清晰的認識。在常規(guī)聊天場景下,多數(shù)情況中我們所進行調(diào)節(jié)的便是這些參數(shù)。接下來,我們將進一步探討其他參數(shù)。
工程參數(shù)
在請求參數(shù)之中,存在一部分是基于工程目的而設(shè)立的。
首先是 “user” 參數(shù),它代表著終端用戶標識。這一參數(shù)由我們作為開發(fā)者提供給 OpenAI,其主要用途在于實現(xiàn)對 API 濫用情況的監(jiān)控與檢測,并且其監(jiān)控的精細程度能夠具體到單個用戶個體層面。
接著是 “n” 參數(shù),該參數(shù)用于指定針對每條輸入消息生成回復(fù)的數(shù)量。盡管從表面上看,設(shè)置此參數(shù)能夠獲取更多的生成內(nèi)容,但由于生成內(nèi)容是需要計費的,所以在沒有特殊需求的情況下,建議不要對這個參數(shù)進行額外設(shè)置。
還有 “response_format” 參數(shù),即應(yīng)答格式。在默認狀態(tài)下,此接口僅僅生成文本內(nèi)容。然而在開發(fā)過程中,我們常常會用到 JSON 格式。對于獲取 JSON 格式的輸出,我們既可以借助提示詞要求大模型進行返回,也能夠通過設(shè)置 “response_format” 參數(shù)使 API 直接返回 JSON 格式,具體的操作方法可以參考 OpenAI 的結(jié)構(gòu)化輸出相關(guān)內(nèi)容。
不過需要說明的是,這些參數(shù)雖然存在被使用的可能性,但在實際應(yīng)用中真正用到它們的機會并不多。例如,若發(fā)現(xiàn)某個用戶存在濫用 API 的行為,我們通常不會將其相關(guān)信息傳遞給 OpenAI,而是自行在本地進行處理。再比如,盡管 OpenAI 支持 JSON 格式輸出,但考慮到模型的兼容性問題,我們可能仍然會傾向于選擇使用提示詞的方式,讓大模型直接返回所需內(nèi)容。
工具參數(shù)
在當下,除了用于常規(guī)的聊天場景之外,大模型還有一種較為常見的應(yīng)用方式,那便是構(gòu)建 Agent。Agent 有著十分重要的用途,其中關(guān)鍵的一點在于它能夠拓展大模型的能力邊界,使其可以完成更多類型的任務(wù),像查詢天氣、搜索網(wǎng)頁這類操作都涵蓋在內(nèi)。那么,大模型是如何知曉自己能夠做這些事情的呢?即通過工具參數(shù)來進行傳遞。
這里的 “工具” 這一說法其實是經(jīng)過改進之后的稱呼,之所以進行這樣的改進,主要是為了與社區(qū)的習慣保持一致。最開始的時候,它被稱作 “函數(shù)(Function)”。之所以要特別說明這一點,是因為在部分資料當中,我們依然能夠看到 “函數(shù)” 這種表述方式。并且在 API 文檔里也存在 “函數(shù)” 相關(guān)內(nèi)容,只不過目前已經(jīng)被標記為廢棄狀態(tài)了。
工具參數(shù)里最常用的是這兩個:
對于 “tools” 參數(shù),它代表著模型能夠調(diào)用的工具列表。在該列表中的每一個工具均包含 “type”(類型)與 “function”(函數(shù))這兩個組成部分。
就當前而言,“type” 所表示的工具類型僅有 “function” 這一種。
而 “function” 的主要作用在于告知模型該函數(shù)的調(diào)用方式,它涵蓋了 “description”(函數(shù)的描述)、“name”(函數(shù)名)以及 “parameters”(函數(shù)參數(shù))這些要素。
另外,“tool_choice” 參數(shù)則用于確定如何調(diào)用工具。當參數(shù)值為 “none” 時,意味著不調(diào)用任何工具;若參數(shù)值為 “auto”,則表示由模型自行決定是生成消息還是調(diào)用工具;而參數(shù)值為 “required” 時,則表明必須調(diào)用工具。此外,該參數(shù)值還可以是一個對象形式,例如,如下這行代碼便是告知模型需要調(diào)用指定的這個工具。
復(fù)制{"type": "function", "function": {"name": "my_function"}}
模型參數(shù)
若上述所提及的部分參數(shù)還算比較易于理解,僅通過參數(shù)名便能知曉其大致用途的話,那么還有相當多的參數(shù)看起來則令人頗為費解,就比如 “frequency_penalty”。實際上,這些參數(shù)通常并非是供開發(fā)應(yīng)用的工程師使用的,我們可以將其視為是為模型開發(fā)者所準備的,所以,我把它們歸到了模型參數(shù)的類別之中。大家對此僅作簡單了解即可,待日后真有需要用到它們的時候,再深入探究也為時不晚。
先來說說 “seed”,即種子值。種子值的設(shè)立主要是為了解決可重復(fù)輸出的問題。具體而言,如果采用相同的種子值并且搭配相同的參數(shù),那么所生成的輸出結(jié)果理應(yīng)是完全一致的。從開發(fā)的角度來看,我們可以將這種現(xiàn)象理解為緩存操作。
接著是 “stop”,也就是停止序列。它的作用在于告知大模型,在生成文本的進程中,一旦遇到停止序列,便立即停止生成文本。
再看 “frequency_penalty”(頻率懲罰)和 “presence_penalty”(存在懲罰)。這兩個參數(shù)主要是用于降低內(nèi)容重復(fù)出現(xiàn)的概率,這也是它們名稱中都帶有 “懲罰” 二字的原因。二者的區(qū)別在于,“frequency_penalty” 是依據(jù)一個 token 在已生成文本里出現(xiàn)的頻率來進行計算的,而 “presence_penalty” 則是根據(jù)一個 token 是否已經(jīng)出現(xiàn)過進行計算。
“l(fā)ogit_bias”,即 logit 偏差。這里的 logit 是統(tǒng)計學(xué)中的一個函數(shù)。該參數(shù)的作用是在 logit 函數(shù)計算過程中對計算結(jié)果進行調(diào)整,其主要目的是改變某些 token 出現(xiàn)的可能性。例如,當我們不希望某些詞匯出現(xiàn)在最終結(jié)果中時,便可以借助此參數(shù)來實現(xiàn)。
“l(fā)ogprobs”:它用于確定是否返回對數(shù)概率。正如我們之前所提到的,大模型生成每個 token 都是有相應(yīng)概率的。若設(shè)置了此參數(shù),就能夠?qū)⑦@些概率以對數(shù)的形式返回。對于大模型開發(fā)人員而言,這有助于他們進行調(diào)試工作。
“top_logprobs”:該參數(shù)用于設(shè)定返回每個位置最有可能返回的 token 數(shù)量。在調(diào)試大模型時,除了想要知曉概率信息之外,有時我們還希望了解排名較為靠前的 token 都有哪些。通過設(shè)置這個參數(shù),就能夠讓大模型返回這些排名靠前的 token。
最后是 “top_p”:這是另一種采樣方式,與 “temperature” 相對應(yīng)。我們之前闡述過,“temperature” 決定了大模型如何選取下一個 token,而 “top_p” 則是另外一種采樣策略,即從概率排名靠前的若干 token 中進行選擇。在實際使用過程中,選擇 “top_p” 和 “temperature” 其中之一即可。