大語言模型(LLM)的應用效果取決於提示內容的設計。開發者需要理解如何有效結合靜態內容(定義任務)和動態內容(提供上下文),才能讓 LLM 提供更精準的輸出。靜態內容確保任務的一致性,例如在書籍推薦應用中,固定的提問:「你認為我下一步應該讀什麼書?」。而動態內容則根據使用者行為提供即時資訊,例如加入使用者最近閱讀的書籍。有效結合這兩種型別的內容,才能讓 LLM 充分理解使用者需求,並提供更個人化的服務。

提示內容的藝術

想像一下,你正在開發一個新的根據大語言模型(LLM)的書籍推薦應用程式。在競爭激烈的市場中,傳統的書籍推薦應用程式通常依賴高度數學化的方法,例如協同過濾。這些方法透過比較使用者的使用模式與所有其他使用者的使用模式來提供推薦。然而,LLM 提供了新的可能性,因為它們能夠讀取有關使用者的文字資料,並利用近乎人類的常識進行推薦。

圖 5-1 的啟示

此圖示顯示了兩個例子,分別是沒有額外資訊和加入個人化資訊後的書籍推薦結果。左側的例子只包含了我最近閱讀的書籍資訊(《白鯨記》和《哈克貝利·芬歷險記》),而右側的例子則額外包含了我的個人資訊、偏好和最近的經歷等大量文字資料。結果顯示,LLM 能夠有效地整合這些資訊,提供更具針對性和吸引力的推薦。

提供多樣化的文字資訊

與傳統演算法不同,LLM 在處理多樣化的文字資訊方面表現出色。然而,如何提供這些資訊則取決於開發者的能力。本章將探討不同型別的資訊來源,以及如何系統性地思考這些來源。我們將區分靜態來源和動態來源,前者用於構建和闡明一般問題,而後者則在請求時檢索,用於傳達特定使用者及其特定問題的詳細資訊。

內容來源的多樣性

在製作提示時,任何資訊都可能有所幫助。因此,首先要找到盡可能多的潛在內容。靜態來源可能包括常見問題、產品說明書或技術檔案等,而動態來源則可能涉及使用者的即時查詢、歷史行為資料或環境資訊等。

靜態來源

靜態來源通常用於提供背景知識或結構化資訊,以幫助 LLM 理解問題的本質。例如,在開發一個客戶服務聊天機器人時,可以使用產品手冊或常見問題集作為靜態來源,以確保機器人能夠提供準確和相關的答案。

動態來源

動態來源則是在每次請求時動態檢索的,用於提供關於特定使用者及其當前需求的詳細資訊。例如,使用者的當前位置、歷史訂單記錄或即時查詢內容都可以作為動態來源,用於個人化推薦或提供即時支援。

有效利用內容來源

要有效地利用這些內容來源,需要仔細考慮如何收集、整理和整合這些資訊。這不僅需要技術上的支援,也需要對使用者需求和行為模式有深刻的理解。透過結合靜態和動態來源,可以建立出更為豐富和個人化的提示,從而提高 LLM 的表現。

提升大語言模型(LLM)應用效果:提示內容的關鍵要素

在開發應用程式時,若能有效地引導大語言模型(LLM),就能獲得更精確和相關的輸出結果。這不僅需要清晰的問題描述,還需要提供適當的上下文資訊,以確保模型理解任務的具體需求。

靜態內容與動態內容的區別

首先,瞭解靜態內容和動態內容之間的區別至關重要。靜態內容是指在每次查詢中保持不變的部分,通常用於定義任務的一般性質或提供明確的指示。例如,在一個推薦書籍的應用程式中,靜態內容可能包括:“你認為我下一步應該讀什麼書?”這樣的問題。這個問題雖然有一定程度的模糊性,但它定義了任務的基本範圍。

程式碼例項:靜態內容範例

static_content = "你認為我下一步應該讀什麼書?我想讀一本有趣的書,而不是教科書。"
print(static_content)

#### 內容解密:
這段程式碼定義了一個靜態內容字串用於向LLM提問並澄清任務需求其中第一句話提出了一般性問題而第二句話則進一步澄清了有趣的書的定義排除了教科書的可能性這樣的靜態內容有助於模型理解任務的基本要求

另一方面,動態內容則提供了與特定查詢例項相關的上下文資訊。例如,如果使用者最後讀過的書是《白鯨記》,那麼動態內容就是:“你認為我下一步應該讀什麼書?順便說一下,我上次讀的是《白鯨記》。” 這裡,第一句話仍然是靜態的,但第二句話則提供了與使用者具體情況相關的上下文。

程式碼例項:動態內容範例

def generate_dynamic_content(last_book_read):
    dynamic_content = f"你認為我下一步應該讀什麼書?順便說一下,我上次讀的是『{last_book_read}』。"
    return dynamic_content

last_book_read = "白鯨記"
print(generate_dynamic_content(last_book_read))

#### 內容解密:
這段程式碼定義了一個函式用於根據使用者最後讀過的書生成動態內容函式接受一個引數`last_book_read`,並將其嵌入到查詢字串中這樣每次查詢都可以根據使用者的不同歷史記錄提供個人化的上下文

靜態內容的最佳實踐

靜態內容的主要目的是澄清問題或任務的需求,使LLM能夠更準確地理解和回應查詢。明確的指示對於確保模型的一致性和輸出品質至關重要。

靜態內容與動態內容關係圖

在許多情況下,明確指示可以顯著提高模型的表現。例如,在提示中加入諸如“使用Markdown格式”、“不要使用超連結”等指令,可以幫助模型按照預期的方式生成輸出。

一致性的重要性

一致性是LLM應用開發中的一個關鍵屬性。它確保了所有輸入都被以相似的方式處理,並且所有的決策都是根據相似的標準。這不僅有助於最佳化應用程式,還能提升使用者經驗和信任度。

為了實作一致性,開發者需要仔細設計靜態內容,以確保模型在每次遇到相同或相似查詢時,都能夠以一致的方式回應。此外,提供足夠的上下文資訊,也能夠幫助模型更好地理解任務需求,從而給出更準確的輸出。

提示內容的設計與最佳化

在設計給大語言模型(LLM)的指令或提示時,需要考慮多種因素以確保模型能夠正確理解並生成符合預期的回應。以下是一些最佳實踐和技術,幫助提升提示的品質和模型的表現。

明確且正面的指令

  • 正面表述:使用正面的表述方式,描述應該做什麼,而不是應該避免什麼。例如,與其說「不要殺人」,不如說「珍惜生命」。
  • 提供理由:為指令提供合理的理由,可以增強模型的理解和遵循意願。例如,「不要殺人,因為這會不尊重他人的生命權」。
  • 避免絕對化:適當地使用條件或例外情況,可以使指令更為合理和易於遵循。例如,「除非在極端必要情況下,否則應避免殺人」。

少樣本提示(Few-Shot Prompting)

少樣本提示是一種透過在提示中加入幾個示例來引導模型生成正確回應的技術。這種方法特別適用於需要特定格式或風格的回應。

少樣本提示的優勢

  • 格式和風格的學習:模型可以透過示例學習到所需的回應格式和風格。
  • 隱含規則的學習:除了明確的指令外,模型還可以透過示例學習到一些隱含的規則或模式。
  • 一致性和個人風格:透過示例,模型可以模仿特定的個人風格或語氣,從而提高回應的一致性。

示例

假設我們需要模型根據書評預測評分。我們可以構建一個少樣本提示,如圖 5-3 所示,其中包含了幾個書評和對應的評分示例。模型透過這些示例,可以學習到評分的模式和規則,從而更好地預測新書評的評分。

重要注意事項

  • 模型的侷限性:即使有明確的指令和示例,不同模型的表現也可能有所不同。RLHF(根據人類反饋的強化學習)模型通常在遵循指令方面表現更好。
  • 隱含與顯式指令:有時,隱含的指令(透過示例給出)比顯式的指令更有效,因為模型可以更好地捕捉到微妙的模式和期望。

提示內容的挑戰與限制

在與大語言模型(LLM)互動時,提示(prompt)的設計至關重要。除了直接撰寫明確的指令外,使用少數樣本提示(few-shot prompting)是一種常見的策略。然而,這種方法存在著特定的挑戰和限制。

使用少數樣本提示的缺點

1. 隨著上下文增加,擴充套件性不佳

當主要問題涉及大量上下文時,提供多個範例可能會導致模型的上下文視窗(context window)不夠用。此外,即使模型的上下文視窗足夠,過多相似但冗長的資訊可能會造成混淆,使得模型難以準確處理。

// 一個簡單的使用者資訊範例
const userInfo = {
  name: "John Doe",
  age: 30,
  reviews: ["Great book!", "Not my favorite."],
  purchases: ["Book A", "Book B"],
  favoriteIceCream: "Chocolate"
};

// 簡化的書籍推薦範例
function recommendBook(user) {
  // 在實際應用中,這裡會根據使用者的資訊進行推薦
  return "Book Recommendation Based on User Info";
}

// 使用少數樣本提示進行書籍推薦
const prompt = `
For ${userInfo.name}, we know the following: ${JSON.stringify(userInfo)},
so we recommend the book ${recommendBook(userInfo)}.
`;

內容解密:

  1. 這段程式碼定義了一個簡單的使用者資訊物件 userInfo,包含姓名、年齡、評論、購買記錄和最喜歡的冰淇淋口味。
  2. recommendBook 函式根據使用者的資訊進行書籍推薦,在這個範例中直接傳回一個固定的字串。
  3. 最後構建了一個簡化的提示字串,用於向模型輸入使用者的資訊並獲得書籍推薦。

2. 可能會使模型偏向範例

少數樣本提示可能導致模型受到錨定效應(anchoring bias)的影響。錨定效應是指初始資訊(即使不完整)會對後續判斷產生不成比例的影響。模型同樣會受到這種影響,從而可能偏向所提供的範例。

此圖示說明瞭初始範例如何透過錨定效應影響模型的判斷和最終輸出結果。

內容解密:

  1. 圖表展示了初始範例對模型判斷的影響路徑。
  2. 錨定效應可能導致模型過度依賴初始範例,從而影響最終的輸出結果。

如何有效使用少數樣本提示

儘管少數樣本提示存在上述挑戰,但仍可在特定情況下發揮作用,例如用於闡明預期的輸出格式。為了避免上述問題,應當:

  • 確保範例與主要問題相關且具有代表性。
  • 控制範例的複雜度和數量,避免過度冗長或相似的資訊。
  • 嘗試提供多樣化的範例,以減少錨定效應的影響。

提示內容的最佳實踐:靜態與動態內容的平衡

在設計大語言模型(LLM)的應用時,提示(Prompt)的內容至關重要。適當的提示內容能夠顯著提高模型的輸出品質與相關性。本章將探討靜態與動態內容在提示中的作用,並提供最佳實踐建議。

靜態內容的最佳實踐

靜態內容是指在應用執行前已確定的、固定的資訊,用於澄清任務目標與要求。適當的靜態內容能夠減少模型的歧義性,提高輸出的一致性。

使用少樣本提示(Few-shot Prompting)的注意事項

少樣本提示是一種有效的技術,透過提供少量範例來引導模型理解任務要求。然而,這種方法存在一些潛在問題:

  1. 上下文長度限制:少樣本提示會增加提示的長度,可能超出模型的最大上下文限制。
  2. 結果偏差:模型可能會過度依賴所提供的範例,導致輸出結果偏向這些範例。
  3. 虛假模式的引入:範例中的某些模式可能會被模型捕捉並重複,即使這些模式並非任務所需。

避免虛假模式的策略

為了減少虛假模式的影響,可以採取以下措施:

  • 隨機化範例順序:避免範例按特定順序排列,如升序或降序,以減少模型捕捉到無關模式的可能性。
  • 包含多樣化的範例:確保範例涵蓋不同的場景和邊緣案例,使模型能夠更全面地理解任務需求。
  • 使用系統化的方法選擇範例:透過系統化的思考和評估,選擇最能代表任務需求的範例。

何時使用少樣本提示

儘管少樣本提示存在一些問題,但它仍然是一種有用的技術,特別是在以下情況下:

  • 需要澄清任務的某些特定方面。
  • 任務涉及複雜或特殊的輸出要求。
  • 有足夠的提示空間來包含範例。

動態內容的整合

動態內容是指在應用執行時根據使用者或任務需求動態生成的資訊。這類別內容對於提供個人化輸出至關重要。

動態內容的挑戰

  1. 延遲考慮:動態內容的收集需要在應用執行時進行,因此需要考慮收集資訊所需的時間,以避免增加整體延遲。
  2. 根據緊急程度進行最佳化:根據應用的緊急程度,最佳化動態內容的收集策略。例如,在高緊急程度的應用中,可能需要簡化或加快資訊收集過程。

動態內容的最佳實踐

  1. 根據應用場景設計動態內容收集策略:區分低、中、高緊急程度的應用,並相應地最佳化動態內容的收集。
  2. 平衡資訊豐富度與收集時間:在提供足夠背景資訊的同時,盡量減少收集動態內容所需的時間。
本章重點回顧:
  • 少樣本提示的有效性與潛在問題
  • 如何避免虛假模式並最佳化範例選擇
  • 動態內容在個人化輸出中的重要性
  • 根據應用緊急程度最佳化動態內容收集策略

透過遵循上述,可以更有效地設計LLM應用的提示內容,從而提升應用的整體表現。

動態內容的挑戰與策略

在開發人工智慧應用程式時,動態內容的管理至關重要。動態內容是指那些會隨著時間或使用者行為而改變的資訊。如何有效地收集、準備和比較這些動態內容,直接影響到應用程式的回應速度和使用者經驗。

緊急性和準備度的重要性

應用程式的緊急程度通常取決於其如何被啟動。不同的觸發機制會對應不同的緊急程度,如下表所示:

觸發機制範例緊急程度結論
非使用者觸發或使用者忘記動作電子郵件摘要助手使用者不在乎你收集背景資訊的速度。
按需觸發書籍推薦助手中等使用者可以容忍一定的等待時間,但不能太長。
自動回應使用者的當前動作使用者輸入時的完成助手每毫秒的浪費都可能導致使用者的下一個動作使當前請求失效。

準備度和可比較性的考量

除了緊急程度外,還需要考慮準備度和可比較性。準備度指的是是否能夠提前準備某些內容。可比較性則是指在收集的背景資訊中,如何進行比較和篩選。

準備度

對於極度依賴即時回應的應用程式,提前準備內容是至關重要的。這樣可以減少在使用者需要時才進行檢索所造成的延遲。

可比較性

在收集背景資訊時,需要考慮如何比較這些資訊。常見的問題包括:

  • 一個專案是否比另一個專案更有用?
  • 一個專案是否依賴於另一個專案?
  • 一個專案是否會使另一個專案失效?

為每個專案評分是一種簡便的方法。例如,在書籍推薦應用程式中,「使用者最後讀的書是《The Tesseract》並且喜歡它」可能獲得高分,而「五年前,他們讀了《The Catcher in the Rye》,但不知道他們是否喜歡」可能獲得中分。

尋找動態內容的方法

尋找動態內容需要創意和對應用程式需求的深刻理解。以下是一些有用的方法:

  1. 繪製心智圖:探索問題的不同導向,改變問題中的關鍵字,產生相關的問題。
  2. 從可收集的內容出發:先確定可以收集哪些內容,然後評估其相關性。

根據接近程度排序內容來源

可以根據內容來源與應用程式的接近程度進行排序,如下:

  1. 直接可用的資訊:應用程式當前狀態、系統時間等。
  2. 儲存的資訊:使用者的個人資料等。
  3. 可記錄的資訊:使用者的歷史活動等。

透過系統地檢查這些維度,可以確保不會遺漏任何重要的動態內容。

內容解密:

本段落主要闡述了在開發人工智慧應用程式時,如何有效地管理和利用動態內容。首先介紹了緊急程度的概念,並根據不同的觸發機制進行了分類別。接著討論了準備度和可比較性的重要性,並提出了評分的方法來比較不同專案的有用程度。然後,介紹了兩種尋找動態內容的方法:繪製心智圖和從可收集的內容出發。最後,根據內容來源與應用程式的接近程度進行了排序,以確保不會遺漏任何重要的動態內容。整體而言,本段落提供了多個實用的策略和方法,以幫助開發者提高應用程式的回應速度和使用者經驗。

動態內容與檢索增強生成

在開發應用程式時,瞭解如何有效地利用上下文(context)對於提升使用者經驗至關重要。上下文可以根據其取得的難易程度和穩定性進行分類別。根據取得的難易程度,上下文可以分為以下幾類別:

  1. 應用程式可以直接存取的資訊(例如,使用者的目前地點)
  2. 應用程式可以透過公開的 API 取得的資訊(例如,目前的天氣)
  3. 應用程式需要使用者許可才能存取的資訊(例如,購買記錄、電子郵件)

通常,資訊越難取得,就需要越有價值才值得去取得。

上下文的穩定性

另一種排列上下文來源的方式是根據其穩定性。以下是根據穩定性排列的上下文來源列表:

  1. 對同一使用者始終保持不變的事物(例如,個人資料資訊)
  2. 隨時間緩慢變化的事物(例如,購買記錄)
  3. 更為短暫的事物(例如,時間、使用者與應用程式互動的狀態)

通常,資訊來源越不穩定,就越難提前準備,因此延遲影響更難以緩解。

結合兩種方法

我們建議結合上述兩種方法:首先,建立一個思維導圖,列出模型可能需要知道的事物;然後,建立一個列表,列出應用程式可以查明的資訊;接著,從最明顯的來源開始實作,並隨著專案的成熟逐漸擴充套件到更為特殊的來源。

檢索增強生成(RAG)

單純的 LLM 無法存取訓練資料中沒有的內容。這意味著,如果你詢問 LLM 有關最近事件或隱私牆後面的資訊,LLM 理想情況下會拒絕回答。更糟糕的是,LLM 可能會產生看似可信但完全沒有根據的答案。這些情況都會導致不良的使用者經驗。

幸運的是,檢索增強生成(RAG)可以解決這個問題!RAG 是一種提示模式,應用程式首先檢索與問題相關的內容,然後將該內容納入提示中,以便模型瞭解訓練期間不存在的資訊。

RAG 的核心:檢索

RAG 的主要新元素是檢索。當你需要從大量資訊中篩選出相關內容以放入上下文時,就需要進行檢索。讓我們回到書籍推薦應用程式的例子。假設應用程式已經縮小了選擇範圍到幾本文,其中一本是小說《海灘》。你的應用程式已經從維基百科複製了《海灘》的摘要:

「故事發生在泰國,講述了一位年輕揹包客尋找一個傳說中的、田園詩般的、與世隔絕的海灘,以及他在那裡與一群國際揹包客社群相處的經歷。」

應用程式剛好可以存取使用者之前寫的大量帖子、訊息、評論等。顯然,大部分內容都是無關的,但如果其中有一些與摘要中提到的主題相關的內容,就可能是非常相關的上下文!如果你找到了,你可以用它來製作一個類別似於圖 5-10 的提示。

Chekhov’s gun 謬誤

如果你檢索到的片段是有意義的,它們可以成為極好的上下文,但如果你檢索到無關的片段,它們可能會擠佔其他更有用的上下文內容。事實上,它們可能會隨機地引導模型走向錯誤的方向。最糟糕的是,它們可能會被過度解釋,因為模型通常會覺得有義務使用它獲得的每一個資訊。我們稱之為 Chekhov’s gun 謬誤。劇作家安東·契訶夫曾反對使用無關的細節。正如維基百科引述他的話:「如果你在第一幕中掛了一把手槍,那麼在接下來的劇情中,它就應該被發射。否則,就不要把它掛在那裡。」人們有意識或無意識地遵循這一原則,而 LLM 在訓練資料中已經吸收了這一原則。因此,即使是無關的上下文也很容易被模型解釋,模型會認為無關的上下文一定很重要。這就是謬誤所在。

緩解 Chekhov’s gun 謬誤

只有一種方法可以緩解 Chekhov’s gun 謬誤:如果你檢索到片段,就必須檢索到與後續完成相關的正確片段。因此,瞭解檢索的一種好方法是將其視為一個搜尋問題,其中你有一個搜尋字串(例如,一個簡短描述《海灘》的句子)和要搜尋的檔案(帖子、評論和訊息),這些檔案本身可能包含許多片段。搜尋的目標是找到與搜尋字串最相關的檔案片段,理想情況下還帶有一個相關性分數。

相似性搜尋

相關性是一個難以定義的概念,因此普遍接受的方法是搜尋與來源文字或查詢字串最相似的片段。相似性也不是非常直接了當,但至少有一些既定的方法。有些方法輕量且簡單,而其他方法則更為複雜,並伴隨著更多的開銷。

@startuml
skinparam backgroundColor #FEFEFE
skinparam sequenceArrowThickness 2

title LLM 提示設計:靜態+動態內容整合 (RAG 架構)

actor "使用者" as user
participant "應用程式" as app
participant "提示組裝器" as assembler
database "向量資料庫\n(Vectorstore)" as vectordb
database "使用者資料" as userdb
participant "檢索器\n(Retriever)" as retriever
participant "LLM" as llm

== 靜態內容準備 ==
app -> assembler : 載入靜態內容
note right of assembler
  靜態內容:
  - 系統提示 (角色定義)
  - 任務說明
  - 輸出格式要求
  - Few-shot 示例
end note

== 動態內容檢索 (RAG) ==
user -> app : 輸入查詢\n"推薦下一本書"
app -> retriever : 檢索相關上下文

alt 緊急程度: 低
    retriever -> userdb : 查詢使用者歷史
    note right
      - 閱讀記錄
      - 評分
      - 偏好
    end note
    userdb --> retriever : 完整歷史資料

    retriever -> vectordb : 語義搜尋書籍
    note right
      Query: 使用者最後讀的書
      "The Tesseract"
      使用 Embedding 相似度
    end note
    vectordb --> retriever : Top-K 相關書籍
else 緊急程度: 高
    retriever -> userdb : 僅查詢最近記錄
    userdb --> retriever : 最後3本書
endif

== 提示組裝 ==
retriever --> assembler : 動態上下文
assembler -> assembler : 組合提示
note right
  最終提示結構:
  1. 系統提示 (靜態)
  2. 使用者資訊 (動態)
     - 最後讀的書: "The Tesseract"
     - 評分: 5/5
  3. 候選書籍 (動態 RAG)
     - "The Beach" 摘要
  4. 任務指令 (靜態)
  5. Few-shot 示例 (靜態)
end note

== LLM 生成 ==
assembler -> llm : 完整提示
llm -> llm : 生成推薦
note right
  生成控制:
  - Temperature: 0.7
  - Max tokens: 500
  - Stop sequences: ["###"]
end note

llm --> user : 個人化推薦結果

note bottom
  避免 Chekhov's Gun 謬誤:
  只檢索真正相關的上下文,
  無關資訊會誤導 LLM
end note

@enduml

此圖示展示了檢索增強生成的基本流程,從搜尋字串到取得最相關的檔案片段。

內容解密:

  1. 圖表展示了 RAG 流程中的檢索步驟,強調了搜尋字串與檔案資料函式庫之間的比對過程。
  2. 透過計算相似度來找出最相關的檔案片段,這些片段將被用作模型的上下文。
  3. 相關片段經過排序後,提供給模型以輔助生成更準確和相關的輸出。