過去一年有關大模型應用構建的干貨經驗之戰術篇
過去一年,大模型應用以前所未有之勢從出現到繁榮。LLM應用從原型展示向生產落地演進。近日,Oreilly刊發了由 Eugene Yan, Bryan Bischof等人撰寫的大模型總結性文章《What We Learned from a Year of Building with LLMs?》,由于作者們背景各不相同,有獨立咨詢顧問(Hamel Husain,Jason Liu),有研究人員(Shreya Shankar),還有科技公司AI團隊領袖(Eugene Yan,Bryan Bischof),以及AI領域布道師(Charles Frye),這使得文章內容更為全面深入。他們從戰術、運營和戰略三個部分展開解讀了自己過去一年有關LLM應用開發與運營的全方位經驗。
一、戰術篇
本部分探討有關提升質量和可靠性的提示技巧、構建檢索增強生成(RAG)、應用流程工程( flow engineering)以及評估和監控的最佳實踐和常見陷阱,進而構建穩健的LLM應用。
提示技巧
在開發新應用時,建議首先考慮提示技術。提示的重要性往往容易被人低估或高估。它被低估是因為,正確的提示技巧若使用得當,可以帶來意想不到的成效。而其被高估,則是因為,即便是基于提示的應用,也需要圍繞提示進行大量的工程設計才能確保良好的運行。
盡可能利用基礎的提示技術獲取最大收益
一些提示技巧在各種模型和任務上一直有助于提升性能:n-shot 提示 + 上下文學習, chain-of-thought, 以及提供相關資源。
通過n-shot提示進行的上下文學習的思路是向LLM提供一些示例,利用這些示例展示了任務過程并將輸出與用戶期望對齊。
一些建議:
- 如果n太低,模型可能會過度依賴這些特定示例,損害其泛化能力。作為一個經驗法則,目標是n ≥ 5。不要害怕高達幾十個的n。
- 示例應代表預期輸入分布。如果你正在構建一個電影摘要器,包括不同類型的樣本,大致按照期望在實踐中看到的比例。
- 不一定需要提供完整的輸入-輸出對。在許多情況下,僅僅提供所需輸出的示例就足夠了。
- 如果正在使用一個支持工具調用( tool use)的LLM,n-shot示例也應使用希望Agent使用的工具。
在chain-of-thought (CoT)提示中,鼓勵大語言模型在返回最終回答之前解釋它的思考過程。把它想象成為大語言模型提供一個草稿本,這樣它就不必全部在內存中完成。原始方法是簡單地添加短語“讓我們一步一步來思考”作為指令的一部分。然而,我們發現讓CoT更具體,通過額外的一兩個句子增加具體性,通常能顯著減少幻覺率。例如,當讓一個LLM總結會議紀要時,可以明確相關步驟,例如:
- 首先,在草稿本上列出關鍵決策、后續事項及相關負責人。
- 然后,檢查草稿本中的細節與記錄是否事實一致。
- 最后,將關鍵點整合成簡明的摘要。
最近,出現一些有關COT技術是否有效的質疑(Chain of Thoughtlessness? An Analysis of CoT in Planning(https://arxiv.org/abs/2405.04776)),以及使用COT 進行推理時究竟發生了什么,存在著明顯的爭論。但無論如何,這是一個值得嘗試的技術。
提供相關資源是擴展模型知識庫、減少幻覺和增加用戶信任的強大機制。這通常通過檢索增強生成 (RAG) 來完成,為模型提供它可以直接利用的文本片段是一種必不可少的技巧。提供相關資源時,僅僅包含它們是不夠的;別忘了告訴模型優先使用它們,直接引用它們,有時還要提及哪些資源不足。這些都有助于將Agent基于知識庫作出響應。
結構化輸入和輸出
構建結構化的輸入和輸出有助于模型更好地理解輸入,以及可靠地輸出以便于與下游系統集成。向輸入添加序列化格式可以給模型提供更多線索以理解上下文中Token和附加元數據(如類型)的特定Token之間的關系,或將請求與模型訓練數據中的類似示例關聯。
例如,互聯網上關于編寫SQL的許多問題都是通過指定SQL schema開始的。因此,可能期望有效的Text-to-SQL提示應包括結構化的schema定義。
結構化輸出具有類似的目的,但它也簡化了整合到系統的下游組件中。Instructor 和Outlines 對于結構化輸出很有幫助。(如果正在導入LLM API SDK,使用Instructor; 如果正在導入Huggingface以用于自托管模型,使用 Outlines。)結構化輸入清晰地表達任務,并類似于訓練數據的格式化,增加了提升輸出更好的可能性。
當使用結構化輸入時,要意識到每種LLM都有它們自己的偏好。Claude偏好xml,而GPT偏愛Markdown和JSON。使用XML,甚至可以通過提供一個響應標簽來預填Claude的響應,就像這樣。
messages=[
{
"role": "user",
"content": """Extract the <name>, <size>, <price>, and <color>
from this product description into your <response>.
<description>The SmartHome Mini
is a compact smart home assistant
available in black or white for only $49.99.
At just 5 inches wide, it lets you control
lights, thermostats, and other connected
devices via voice or app—no matter where you
place it in your home. This affordable little hub
brings convenient hands-free control to your
smart devices.
</description>"""
},
{
"role": "assistant",
"content": "<response><name>"
}
]
編寫“單一職責”的小提示
在軟件開發中,有一個常見的反模式“全能型對象”(God Object),也就是指那種幾乎包攬所有功能的類或函數。在編寫提示(Prompt)時,這一概念同樣適用。最開始,編寫提示往往是簡明扼要的:寫下幾句指示語,舉幾個例子,接著事情就可以開展了。不過,隨著我們試圖提高程序性能,處理越來越多的特殊情況,提示中的復雜性也在不知不覺中增長。這意味著需要更多的指示語和更復雜的邏輯推理,還要加入許多例子。就這樣,一段原本簡短的提示竟變成了一個長達 2,000 Token 的龐然大物。更令人頭痛的是,它對那些更常見、更簡單的情況的處理效果還不如以前那樣好了!
在努力讓系統和代碼保持簡潔的同時,在創建提示方面也應該堅持這一原則。就以會議紀要為例,可以將它拆解成幾個步驟:
1. 將關鍵決策、待辦事項以及責任承擔者提取出來,并整理成結構化的格式。
2. 核對提取出的信息,確保其與原始會議記錄的內容保持一致。
3. 基于已結構化的信息,生成一個簡練的摘要。
如此一來,就可將一個復雜的提示拆分成了多個簡單、專注并且容易理解的小提示。分開處理這些提示之后,也就能夠逐一迭代和評估它們。
優化上下文
重新審視必須向 Agent 提供多少上下文信息。學習米開朗基羅,不是堆砌,而是精簡。RAG 被廣泛用于整合所有可能相關的信息片段,但關鍵在于如何從中提煉出必要內容?
把發送給模型的最終提示——全部上下文、元提示(meta-prompting)以及 RAG 結果——單獨放在一張白紙上閱讀,能有效幫助重新審視上下文配置。這種方法會幫助發現了文中的冗余、自我矛盾及格式問題。
另一個重要的優化點在于上下文的結構安排。將文檔以“袋子模型(bag-of-docs)”的形式呈現對人幫助不大,不應默認它對 Agent同樣有效。應深思熟慮地組織上下文結構,明確突出不同部分之間的關系,盡可能地簡化信息抽取過程。
信息檢索/RAG
除了提示之外,另一個引導LLM的有效方法是在提示中提供知識。這會將LLM建立在提供的上下文中,然后用于上下文學習。這就是所謂的檢索增強生成 (RAG)。實踐者發現 RAG 在提供知識和提高輸出方面非常有效,同時與微調相比,它需要更少的努力和成本。RAG 的效果取決于檢索到的文檔的相關性、密度和細節。
檢索增強生成(RAG)的輸出質量取決于檢索到的文檔的質量,而文檔質量可以從以下幾個方面考慮。
第一個也是最明顯的指標是相關性。這通常通過排名指標量化,例如平均倒數排名 (MRR) 或歸一化折現累積增益 (NDCG)。MRR 評估系統在排序列表中將第一個相關結果排名的效果,而 NDCG 則考慮所有結果的相關性及其位置。它們衡量系統在將相關文檔排得更高,而將不相關文檔排得更低方面的效果。例如,如果我們要檢索用戶摘要來生成電影評論摘要,我們會希望將特定電影的評論排得更高,同時排除其他電影的評論。
與傳統的推薦系統類似,檢索到的項目的排名將對 LLM 在下游任務中的表現產生重大影響。為了衡量這種影響,運行一個基于 RAG 的任務,但將檢索到的項目打亂 - RAG 輸出的表現如何?
其次,還需要考慮信息密度。如果兩篇文檔同樣相關,應該優先考慮更簡潔、包含更少無關細節的文檔。回到電影例子,可以認為電影劇本和所有用戶評論在廣義上都是相關的。但是,最高評分的評論和編輯評論可能在信息密度方面更高。
最后,考慮文檔中提供的細節程度。假設要構建一個 RAG 系統,從自然語言生成 SQL 查詢。可以簡單地提供包含列名的表格架構作為上下文。但是,如果包含列描述和一些代表性值呢?額外的細節可以幫助 LLM 更好地理解表格的語義,從而生成更準確的 SQL。
不要忘記關鍵字搜索;將其作為基準并用于混合搜索。
鑒于基于向量檢索的 RAG 演示如此流行,人們很容易忘記或忽視信息檢索領域數十年的研究和解決方案。
盡管如此,embedding無疑是一種強大的工具,但它并不是萬能的。首先,雖然embedding擅長捕捉高層次的語義相似性,但在處理更具體的、基于關鍵字的查詢時,比如用戶搜索姓名(如 Ilya)、縮略語(如 RAG)或 ID(如 claude-3-sonnet)時,嵌入式可能會顯得力不從心。基于關鍵字的搜索,如 BM25,就是為此而明確設計的。經過多年的基于關鍵字的搜索,用戶可能已經認為這是理所當然的,如果他們期望檢索的文檔沒有被返回,他們可能會感到沮喪。
其次,使用關鍵字檢索可以更直觀地了解檢索到文檔的原因--可以查看與查詢相匹配的關鍵字。相比之下,基于嵌入的檢索就不那么容易理解了。最后,由于 Lucene 和 OpenSearch 等系統經過數十年的優化和實戰檢驗,關鍵詞搜索的計算效率通常更高。
在大多數情況下,混合搜索的效果最好:關鍵詞匹配用于明顯的匹配,嵌入式搜索用于同義詞、超義詞和拼寫錯誤,以及多模態搜索(如圖像和文本)。Shortwave 分享了他們如何構建 RAG 管道(https://www.shortwave.com/blog/deep-dive-into-worlds-smartest-email-ai/),包括查詢重寫、關鍵詞 + 嵌入檢索和排序。
對于新知識,優先考慮 RAG 而不是微調
RAG 和微調都可以用來將新信息整合到LLM中,并提升特定任務的性能。那么,應該先嘗試哪個呢?
最近的研究表明,RAG 可能更勝一籌。一項研究將 RAG 與無監督微調(也稱為持續預訓練)進行了比較,并在 MMLU 的一個子集和當前事件上評估了兩種方法。他們發現,對于訓練過程中遇到的知識以及全新的知識,RAG 的性能始終優于微調。在另一篇論文中,他們將 RAG 與農業數據集上的監督微調進行了比較。同樣地,RAG 帶來的性能提升比微調更大,尤其是對于 GPT-4(參見論文的表格 20)。
除了性能提升之外,RAG 還具有幾個實際優勢。首先,與持續預訓練或微調相比,更新檢索索引更容易,也更便宜!其次,如果檢索索引中存在包含有毒或有偏見內容的問題文檔,可以輕松地刪除或修改這些文檔。
此外,RAG 中的 R (檢索)提供了對文檔檢索方式的更細粒度的控制。例如,如果我們為多個組織托管 RAG 系統,通過對檢索索引進行分區,可以確保每個組織只能檢索到自己索引中的文檔。這可以確保不會無意中將一個組織的信息暴露給另一個組織。
長文本模型并不會讓 RAG 過時
Gemini 1.5 提供了高達 1000 萬個標記的上下文窗口,有些人開始質疑 RAG 的未來。
雖然長上下文對于分析多個文檔或與 PDF 聊天等用例來說是一個改變游戲規則的功能,但關于 RAG 即將消亡的傳言都被大大夸大了。
首先,即使上下文窗口有 1000 萬個 token,仍然需要一種方法來選擇信息輸入模型。其次,除了狹窄的“大海撈針”評估之外,還沒有看到令人信服的數據表明模型可以有效地推理如此大的上下文。因此,如果沒有好的檢索(和排序),可能會讓模型被干擾因素所淹沒,甚至可能會用完全不相關的信息填充上下文窗口。
最后是成本。Transformer 的推理成本隨著上下文長度呈二次方增長(或在空間和時間上都呈線性增長)。僅僅因為存在一個模型可以在回答每個問題之前讀取你組織的整個 Google Drive 內容,并不意味著這是一個好主意。可以類比一下如何使用 RAM:仍然從磁盤讀取和寫入,即使存在 RAM 達到數十 TB 的計算實例。
所以,不要急著把你的 RAG 扔進垃圾桶。即使上下文窗口的大小不斷增大,這種模式仍然會很有用。
微調和優化工作流(Workflow)
提示引導LLM只是第一步。為了充分利用它們,需要跳出單一提示的局限,擁抱工作流。例如,如何將一個復雜的任務分解成多個更簡單的任務?微調或緩存何時有助于提高性能并降低延遲/成本?下面分享一些經過驗證的策略和真實世界的例子,幫助優化和構建可靠的 LLM 工作流。
逐步的多輪“流程”可以帶來巨大的提升。我們已經知道,將一個大型提示分解成多個較小的提示,可以獲得更好的結果。AlphaCodium 就是一個例子:通過從單一提示切換到多步驟工作流程,他們將 GPT-4 在 CodeContests 上的準確率(pass@5)從 19% 提高到 44%。詳細閱讀:??微軟、OpenAI大佬暗示LLM應用開發范式遷移:從Prompt Engineering到Flow Engineering??。該工作流程包括:
- 反思問題
- 在公開測試集上進行推理
- 生成可能的方案
- 對可能的方案進行排序
- 生成合成測試集
- 在公開測試集和合成測試集中反復迭代方案。
目標明確的小任務最適合作為Agent或流程提示。雖然不強制要求每個Agent提示都請求結構化輸出,但是,結構化輸出對于與編排Agent與環境互動的任何系統的接口都有很大幫助。
一些嘗試:
- 一個明確的規劃步驟,盡可能嚴格規定。考慮提供預定義的計劃供選擇。
- 將原始的用戶提示改寫成Agent提示。注意,這個過程是有損失的!
- 以Chain、DAG 和狀態機的Agent行為;不同的依賴關系和邏輯關系可能更適合不同的規模,也可能不那么適合。能否從不同的任務架構中優化性能?
- 規劃驗證;規劃可以包括如何評估其他Agent響應的說明,以確保最終組裝能很好地協同工作。
- 具有固定上游狀態的提示工程--確保Agent提示是根據之前可能發生的情況的變體集合進行評估的。
優先采用確定性的工作流
雖然 Agent可以動態地響應用戶請求和環境,但它們的非確定性本質使得它們難以部署。Agent執行的每個步驟都有失敗的可能性,而從錯誤中恢復的可能性很小。因此,代理成功完成多步任務的可能性隨著步驟數量的增加而呈指數級下降。結果,構建Agent的團隊發現很難部署可靠的Agent。
一種很有前景的方法是讓Agent系統生成確定性的計劃,然后以結構化、可重復的方式執行這些計劃。在第一步中,給定一個高級目標或提示,Agent會生成一個計劃。然后,該計劃以確定性的方式執行。這使得每個步驟都更加可預測和可靠。好處包括:
- 生成的計劃可以作為少量樣本,用于提示或微調。
- 確定性執行使系統更加可靠,因此更易于測試和調試。此外,故障可以追溯到計劃中的特定步驟。
- 生成的計劃可以表示為有向無環圖(DAG),與靜態提示相比,它更容易理解和適應新情況。
最成功的Agent構建者可能是那些在管理初級工程師方面經驗豐富的人,因為生成計劃的過程類似于我們如何指導和管理初級工程師。我們給初級工程師明確的目標和具體的計劃,而不是含糊不清的開放式指示,我們也應該對我們的Agent做同樣的事情。
最終,構建可靠、可工作的Agent的關鍵可能在于采用更結構化、確定性的方法,以及收集數據來改進提示和微調模型。沒有這些,我們將構建出可能在某些時候工作得異常好的Agent,但平均而言,會讓用戶失望,從而導致用戶保留率低。
除了溫度(temperature)之外,如何獲得更多樣化的輸出
假設你的任務需要 LLM 輸出的多樣性。也許你正在編寫一個 LLM 管道,根據用戶之前購買的商品列表來推薦商品。當你多次運行提示時,你可能會注意到生成的推薦結果過于相似——所以你可能會在 LLM 請求中增加溫度參數。
簡單來說,增加溫度參數會使 LLM 響應更加多樣化。在采樣時,下一個標記的概率分布變得更加平坦,這意味著通常不太可能出現的標記會被更多地選中。盡管如此,在增加溫度時,你可能會注意到與輸出多樣性相關的某些故障模式。例如,目錄中一些可能很合適的商品可能永遠不會被 LLM 輸出。如果這些商品在訓練時非常有可能遵循提示,那么同一批商品可能會在輸出中過度表示。如果溫度過高,你可能會得到引用不存在的商品(或胡言亂語!)的輸出。
換句話說,增加溫度并不能保證 LLM 會從你期望的概率分布(例如,均勻隨機)中采樣輸出。盡管如此,我們還有其他技巧來增加輸出多樣性。最簡單的方法是調整提示中的元素。例如,如果提示模板包含一個項目列表,例如歷史購買記錄,每次將這些項目插入提示時對其進行隨機排序會產生顯著影響。
此外,保留一個最近輸出的簡短列表有助于防止冗余。在推薦商品的例子中,通過指示 LLM 避免推薦來自這個最近列表的商品,或者通過拒絕并重新采樣與最近建議相似的輸出,可以進一步使響應多樣化。另一個有效的策略是改變提示中使用的措辭。例如,加入類似“選擇用戶會經常使用并喜歡的商品”或“選擇用戶可能會推薦給朋友的商品”這樣的短語可以轉移焦點,從而影響推薦商品的多樣性。
緩存作用被低估
緩存無需對相同輸入重新計算響應,從而節省了成本,消除了生成延遲。此外,如果某個回復之前已被屏蔽,我們就可以提供經過審核的回復,從而降低提供有害或不適當內容的風險。
一種直接的緩存方法是為正在處理的項目使用唯一的 ID,例如我們正在總結新文章或產品評論。當收到請求時,我們可以檢查緩存中是否已經存在摘要。如果存在,我們可以立即返回;如果不存在,我們就生成、保護并提供摘要,然后將其存儲在緩存中,以備將來的請求。
對于更開放的查詢,我們可以借鑒搜索領域的技術,后者也利用緩存來處理開放式輸入。自動完成和拼寫糾正等功能也有助于規范用戶輸入,從而提高緩存命中率。
何時微調
在某些任務中,即使是設計最巧妙的提示也會有不足之處。例如,即使經過大量的提示工程設計,系統可能仍然無法返回可靠、高質量的輸出。如果是這樣,就有必要針對特定任務對模型進行微調。
最佳實踐:
- Honeycomb 的自然語言查詢助手:最初,"programming manual "是在提示中提供的,同時還提供了 n 個示例供用戶在上下文中學習。雖然效果不錯,但對模型進行微調后,特定領域語言的語法和規則輸出效果更好。地址:https://www.honeycomb.io/blog/introducing-query-assistant
然而,微調雖然有效,但代價也很大。需要對微調數據進行標注,對模型進行微調和評估,并最終對模型進行部署管理。因此,要考慮較高的前期成本是否值得。如果通過提示可以實現 90% 的目標,那么微調可能就不值得投入。不過,如果決定進行微調,為了降低收集人工標注樣本的成本,可以在合成數據上生成并進行微調,或者在開源數據上進行微調。
評估與監督
評估 LLM 可能是一個雷區。LLM 的輸入和輸出是任意文本,我們為其設定的任務也多種多樣。然而,嚴謹周到的評估至關重要--OpenAI 的技術領袖就從事評估工作并對個別評估提出反饋意見絕非偶然。
評估 LLM 應用程序需要多種定義和還原:它可以是簡單的單元測試,也可以更像是可觀測性,還可能只是數據科學。我們發現所有這些觀點都很有用。在下面的章節中,我們將就構建評估 和監控pipeline的重要性提供一些經驗。
從真實的輸入/輸出樣本中創建一些基于斷言的單元測試
創建單元測試(即斷言),其中包含來自生產的輸入和輸出樣本,并基于至少三個標準對輸出進行預期。雖然三個標準可能看起來是任意的,但這是一個實用的開始數字;更少的標準可能表明你的任務沒有得到充分定義或過于開放,就像一個通用聊天機器人。這些單元測試或斷言應該由pipeline中的任何更改觸發,無論它是編輯提示、通過 RAG 添加新上下文還是其他修改。這篇寫作用例中給出了一個基于斷言的測試示例(https://hamel.dev/blog/posts/evals/#step-1-write-scoped-tests)。
考慮從指定要包含或排除在所有響應中的短語或想法的斷言開始。還要考慮檢查以確保單詞、項目或句子計數在一定范圍內。對于其他類型的生成,斷言看起來可能不同。執行評估(Execution-evaluation)是評估代碼生成的一種強大方法,其中你運行生成的代碼并確定運行時的狀態是否足以滿足用戶請求。
舉例來說,如果用戶需要一個名為 foo 的新函數,那么在執行Agent生成的代碼后,foo 應該是可調用的!執行評估所面臨的一個挑戰是,Agent代碼離開運行時的形式經常與目標代碼略有不同。將斷言 "放寬 "到任何可行答案都能滿足的絕對最弱假設是有效的。
最后,按照客戶的預期使用產品(即 "dogfooding")可以深入了解真實世界數據中的失敗類型。這種方法不僅有助于識別潛在的弱點,還能提供有用的生產樣本,并將其轉換為 evals。
LLM-as-Judge(LLM充當法官)可以(在一定程度上)發揮作用,但并不是銀彈
LLM-as-Judge,即我們使用一個強大的 LLM 來評估其他 LLM 的輸出,有些人對此持懷疑態度。(不過,如果實施得當,LLM-as-Judge 與人類判斷之間的相關性還是不錯的,至少可以幫助建立新提示或新技術的性能預設。具體來說,在進行配對比較(如對照組與治療組)時,LLM-as-Judge 通常能正確地判斷方向,盡管輸贏的偏差可能比較大。
以下是一些建議,可以讓LLM-as-Judge 發揮最大作用:
- ?使用成對比較:與其要求 LLM 在Likert scale上對單項輸出打分,不如向它提供兩個選項,讓它選擇更好的那個。這往往會帶來更穩定的結果。
- 控制位置偏差:提交選項的順序會使 LLM 的決策出現偏差。為了減少這種偏差,可以將每個配對比較進行兩次,每次交換配對的順序。交換順序后,確保正確的選項獲勝!
- 允許并列:在某些情況下,兩個選項可能同樣好。因此,允許LLM宣布平局,這樣就不必武斷地選出勝者。
- 使用COT:在給出最終偏好之前,要求 LLM 解釋其決定,可以提高評估的可靠性。另外,這還能讓您使用較弱但較快的 LLM,并仍能獲得類似的結果。由于pipeline的這一部分經常處于批處理模式,CoT 帶來的額外延遲不成問題。
- 控制回答長度:LLM 往往偏向于較長的回答。為減少這種偏差,應確保成對的回答長度相似。
LLM-as-Judge 的一個特別強大的應用是根據回歸結果檢查新的提示策略。如果已經跟蹤了一系列生產結果,有時可以使用新的提示策略重新運行這些生產示例,并使用 LLM-as-Judge 快速評估新策略可能存在的問題。
下面是一個簡單而有效的 "LLM-as-Judge "迭代方法示例,我們只需記錄 LLM 響應、法官評價(即 CoT)和最終結果。然后與利益相關者一起對其進行審查,以確定需要改進的地方。經過三次迭代,人類與 LLM 的一致性從 68% 提高到 94%!
不過,LLM-as-Judge 并非銀彈。在語言的某些微妙方面,即使是最強大的模型也無法進行可靠的評估。此外,我們還發現傳統的分類器和獎勵模型可以達到比 LLM-as-Judge 更高的準確度,而且成本和延遲更低。在代碼生成方面,LLM-as-Judge 可能比執行評估等更直接的評估策略更弱。
"實習生測試”評估產品
在評估一代產品時,我們喜歡使用以下 "實習生測試":如果您將語言模型的準確輸入(包括上下文)作為一項任務交給相關專業的普通大學生,他們能成功嗎?需要多長時間?
如果答案是否定的,因為LLM缺乏所需的知識,那么請考慮如何豐富背景知識。
如果答案是否定的,而且我們根本無法改進語境來解決這個問題,那么我們可能遇到了對這代LLM來說太難的任務。
如果答案是肯定的,但需要一段時間,我們可以嘗試降低任務的復雜性。它可以分解嗎?任務的某些方面是否可以更加模板化?
如果答案是肯定的,他們會很快得到答案,那么就該深入研究數據了。模型做錯了什么?我們能找到失敗的模式嗎?試著讓模型在做出反應之前或之后解釋自己,以幫助你建立思維理論。
過分強調某些測試成績會影響整體成績
這方面的一個例子是 "大海撈針"(NIAH)評估。最初的評估有助于量化模型召回率隨著上下文大小的增加而增加,以及召回率如何受針的位置影響。然而,它已經被過分強調,以至于在雙子座 1.5 的報告中被列為圖 1。評估涉及在重復保羅-格雷厄姆(Paul Graham)文章的長文檔中插入一個特定短語("The special magic {city} number is: {number}"),然后提示模型回憶魔術數字(magic number)。
雖然有些模型可以達到近乎完美的記憶效果,但 NIAH 是否真正反映了實際應用中所需的推理和記憶能力,還是個問題。考慮一個更實際的場景:給定一個小時的會議紀要,LLM能否總結出關鍵決策和下一步步驟,并將每個項目正確歸屬于相關人員?這項任務更切合實際,它超越了死記硬背的范疇,還考慮了解析復雜討論、識別相關信息和綜合總結的能力。
下面是一個實用的 NIAH 評估實例。利用醫患視頻通話的記錄,LLM 被問及病人的用藥情況。其中還包括一個更具挑戰性的 NIAH,即插入一個關于披薩配料的隨機配料的短語,例如 "制作完美披薩所需的秘密配料是:浸泡過濃咖啡的紅棗、檸檬、杏仁和杏仁油:浸泡過濃咖啡的紅棗、檸檬和山羊奶酪"。藥物任務的回憶率約為 80%,披薩任務的回憶率為 30%。
另外,過分強調 NIAH 評估可能會降低提取和總結任務的性能。因為這些 LLM 非常精細地關注每個句子,它們可能會開始將無關細節和干擾項視為重要內容,從而將其納入最終輸出(而它們本不應該這樣做!)。
這也適用于其他評估和用例。例如,總結。強調事實的一致性可能會導致摘要不那么具體(因此不太可能與事實不一致),也可能不那么相關。反之,如果強調寫作風格和口才,則可能導致更多花哨的營銷型語言,從而造成事實不一致。
將標注簡化為二元任務或成對比較
用Likert scale對模型輸出提供開放式反饋或評分對認知能力要求很高。因此,收集到的數據會因人類評分者之間的差異而變得更加嘈雜,從而降低其實用性。更有效的方法是簡化任務,減輕標注者的認知負擔。二元分類和成對比較是兩種行之有效的任務。
在二元分類中,標注者需要對模型的輸出做出簡單的 "是 "或 "否 "判斷。他們可能會被問到生成的摘要是否與源文件的事實一致,或者建議的回復是否相關,或者是否含有毒性。與Likert scale相比,二元判定更為精確,評分者之間的一致性更高,吞吐量也更大。Doordash 就是這樣設置標簽隊列的,通過一棵 "是 "與 "否 "的問題樹來標記菜單項。
在成對比較中,標注者會看到一對模型響應,并詢問哪個更好。對于人類來說,說出 "A 比 B 好 "比單獨給 A 或 B 打分更容易,因此標注速度更快、更可靠(比Likert scale更可靠)。在一次 Llama2 會議上,Llama2 論文的作者托馬斯-斯基亞洛姆(Thomas Scialom)證實,成對比較比收集監督下的微調數據(如書面回復)更快、更便宜。前者的成本為每單位 3.5 美元,而后者的成本為每單位 25 美元。
(無參考文獻)評估(EVAL)和圍欄(guardrails)可以互換使用
Guardrails 有助于捕捉不恰當或有害的內容,而 evals 則有助于衡量模型輸出的質量和準確性。就無參考的 evals 而言,它們可以說是一枚硬幣的兩面。無參照評估是指不依賴于 "黃金 "參照(如人工撰寫的答案)的評估,可以僅根據輸入提示和模型的響應來評估輸出的質量。
其中的一些例子是摘要評估,我們只需考慮輸入文檔,就能對摘要的事實一致性和相關性進行評估。如果摘要在這些指標上得分較低,我們就可以選擇不向用戶顯示它,從而有效地將評估用作圍欄。同樣,無參考翻譯 evals 可以在不需要人工翻譯參考的情況下評估翻譯質量,這同樣允許我們將其用作圍欄。
LLM 在不應該返回輸出時也會返回輸出
使用 LLM 時的一個主要挑戰是,它們經常會在不應該產生輸出的情況下產生輸出。這可能導致無害但無意義的響應,或更嚴重的缺陷,如毒性或危險內容。例如,當被要求從文檔中提取特定屬性或元數據時,LLM 可能會自信地返回值,即使這些值實際上并不存在。另外,由于我們在上下文中提供了非英語文檔,因此模型可能會以英語以外的語言做出響應。
雖然我們可以嘗試提示 LLM 返回 "不適用 "或 "未知 "的響應,但這并非萬無一失。即使有對數概率,它們也不是衡量輸出質量的好指標。雖然日志概率表明了輸出中出現標記的可能性,但并不一定反映了生成文本的正確性。相反,對于經過訓練以響應查詢并生成連貫響應的指令調整模型來說,對數概率可能沒有得到很好的校準。因此,雖然高對數概率可能表明輸出是流暢和連貫的,但并不意味著它是準確或相關的。
雖然謹慎的提示工程能在一定程度上起到幫助作用,但我們還應輔之以強大的防護機制,以檢測和過濾/再生不受歡迎的輸出。例如,OpenAI 提供了一個內容節制 API,可以識別不安全的回應,如仇恨言論、自殘或性輸出。同樣,還有許多用于檢測個人身份信息(PII)的軟件包。這樣做的好處之一是,guardrails 在很大程度上與用例無關,因此可以廣泛應用于特定語言的所有輸出。此外,通過精確檢索,如果沒有相關文檔,我們的系統可以確定性地回答 "我不知道"。
由此得出的一個推論是,LLM 可能無法在預期時間內產生輸出結果。發生這種情況的原因有很多,從直接的問題(如來自 API 提供商的長尾延遲)到更復雜的問題(如輸出被內容審核過濾器阻止)。因此,必須持續記錄輸入和(可能缺乏的)輸出,以便進行調試和監控。
幻覺是一個頑固的問題。
內容安全或 PII 缺陷備受關注,因此很少發生,而事實不一致則不同,它頑固存在,檢測起來更具挑戰性。它們更常見,發生率基線為 5%-10%,而根據我們從LLM的提供者那里了解到的情況,要將其控制在 2% 以下是很有挑戰性的,即使是在摘要等簡單任務中也是如此。
為了解決這個問題,我們可以將提示工程(生成的上游)和事實不一致防護(生成的下游)結合起來。在提示工程方面,CoT 等技術可以讓 LLM 在最終返回輸出之前解釋其推理,從而幫助減少幻覺。然后,我們可以應用事實不一致圍欄(https://eugeneyan.com/writing/finetuning/)來評估摘要的事實性,并過濾或重新生成幻覺。在某些情況下,幻覺可以被確定地檢測出來。在使用來自 RAG 檢索的資源時,如果輸出是結構化的,并能識別出資源是什么,那么就應該能夠手動驗證它們來自輸入上下文。
原文:https://www.oreilly.com/radar/what-we-learned-from-a-year-of-building-with-llms-part-i/
本文轉載自?? AI工程化??,作者: ully
