Try   HackMD

Prompt Engineering

原文: https://www.kaggle.com/whitepaper-prompt-engineering

Introduction

文字提示 (text prompt) 是模型用來預測特定輸出的主要輸入方式,有時也會伴隨圖像等其他模態 (modalities)。雖然人人都能撰寫提示,但打造最有效的提示可能相當複雜。
提示的效果受到多種因素影響,包含使用的模型 (model)、模型的訓練資料 (training data)、模型配置 (model configurations)、用字遣詞 (word-choice)、風格語氣 (style and tone)、結構 (structure) 以及上下文 (context) 等。
因此提示工程 (prompt engineering) 是一個迭代的過程 (iterative process)。不恰當的提示可能導致模糊、不準確的回應,並阻礙模型提供有意義輸出的能力。

Prompt engineering

回顧 LLM 的運作方式:它是一個預測引擎 (prediction engine)。模型接收序列文字 (sequential text) 作為輸入,然後根據其訓練數據預測下一個應該出現的 token。LLM 被操作化 (operationalized) 以反覆執行此過程,將先前預測的 token 添加到序列文字的末尾,以預測下一個 token。下一個 token 的預測是基於先前 tokens 中的內容與 LLM 在訓練期間所學習到的內容之間的關係。

當您撰寫提示時,您正試圖設定 LLM 以預測正確的 tokens 序列。Prompt engineering 是設計高品質提示的過程,用以引導 LLM 產生準確的輸出。此過程涉及調整 (tinkering) 以找到最佳提示,優化提示長度 (prompt length),並評估提示的寫作風格和結構與任務的關係。在自然語言處理 (natural language processing) 和 LLM 的脈絡下,提示是提供給模型的輸入,用以生成回應或預測。

這些提示可用於實現各種類型的理解和生成任務,例如文字摘要 (text summarization)、資訊提取 (information extraction)、問答 (question and answering)、文字分類 (text classification)、語言或程式碼翻譯 (language or code translation)、程式碼生成 (code generation) 以及程式碼文件 (code documentation) 或推理 (reasoning)。

進行 prompt engineering 時,您將從選擇模型開始。提示可能需要針對您的特定模型進行優化,無論您使用的是 Vertex AI 中的 Gemini 語言模型、GPT、Claude,還是像 Gemma 或 LLaMA 這樣的開源模型 (open source model)。除了提示本身,您還需要調整 LLM 的各種配置。

LLM output configuration

本節說明在選擇模型後,需要找出模型的配置。大多數 LLM 都帶有各種配置選項,用於控制 LLM 的輸出。有效的 prompt engineering 需要針對您的任務最佳地設定這些配置。

Output length

  • 定義: 一個重要的配置設定是回應中要生成的 tokens 數量。
    • 說明: 生成更多 tokens 需要 LLM 進行更多計算,導致更高的能源消耗、可能更慢的回應時間以及更高的成本。
    • 影響: 減少 LLM 的輸出長度並不會使 LLM 在其創建的輸出中變得更具風格性或文本簡潔性,它只是導致 LLM 在達到限制後停止預測更多 tokens。如果您的需求需要較短的輸出長度,您可能還需要設計您的提示以適應這種情況。
    • 特定技術的重要性: 輸出長度限制對於某些 LLM 提示技巧,如 ReAct,尤其重要,在這些技巧中,LLM 在您想要的回應之後會持續發出無用的 tokens。

Sampling controls

  • 說明: LLM 並非正式預測單一 token。相反,LLM 預測下一個 token 可能為何的機率,LLM 詞彙表 (vocabulary) 中的每個 token 都會獲得一個機率。然後對這些 token 機率進行取樣 (sampled),以確定下一個產生的 token 將是什麼。
  • 主要配置設定: Temperaturetop-Ktop-P 是最常見的配置設定,用於決定如何處理預測的 token 機率以選擇單一輸出 token。

Temperature

  • 定義: Temperature 控制 token 選擇中的隨機程度 (degree of randomness)。
    • 低溫: 適用於期望更具確定性 (deterministic) 回應的提示。
    • 高溫: 可能導致更多樣化 (diverse) 或意想不到 (unexpected) 的結果。
    • Temperature 為 0 (greedy decoding): 具確定性,總是選擇機率最高的 token(但請注意,如果兩個 tokens 具有相同的最高預測機率,根據 tiebreaking 的實現方式,您可能不會總是得到相同的輸出)。
    • 趨近最大值的 Temperatures: 傾向於創建更隨機的輸出。隨著 temperature 越來越高,所有 tokens 變得同等可能成為下一個預測的 token。
    • 與 Softmax 的類比: Gemini 的 temperature 控制可以類似於機器學習中使用的 softmax 函數來理解。低的 temperature 設定反映了低的 softmax temperature (T),強調具有高確定性的單一首選溫度。高的 Gemini temperature 設定則像高的 softmax temperature,使得圍繞所選設定的更廣泛溫度範圍更可接受。這種增加的不確定性適用於不需要嚴格、精確溫度的情境,例如在實驗創意輸出時。

Top-K and top-P

  • 定義: Top-Ktop-P(也稱為 nucleus sampling)是 LLM 中使用的兩種取樣設定,用於限制預測的下一個 token 來自具有最高預測機率的 tokens。與 temperature 類似,這些取樣設定控制生成文本的隨機性和多樣性。
    • Top-K sampling:
      • 機制: 從模型的預測分佈中選擇 K 個最可能的 tokens。
      • 影響: 較高的 top-K 會使模型輸出更具創意和多樣性;較低的 top-K 會使模型輸出更受限和更基於事實。top-K 為 1 等同於 greedy decoding
    • Top-P sampling:
      • 機制: 選擇累積機率 (cumulative probability) 不超過特定值 (P) 的頂部 tokens。P 的值範圍從 0 (greedy decoding) 到 1 (LLM 詞彙表中的所有 tokens)。
  • 選擇: 選擇 top-Ktop-P 的最佳方法是實驗這兩種方法(或兩者結合),看看哪種方法能產生您想要的結果。

Putting it all together

  • 考量因素: 選擇 top-Ktop-Ptemperature 以及要生成的 tokens 數量,取決於具體的應用和期望的結果,且這些設定會相互影響。理解您選擇的模型如何結合不同的取樣設定也很重要。
  • 極端設定的影響:
    • temperature 為 0: top-Ktop-P 變得無關緊要,最可能的 token 成為下一個預測 token。
    • temperature 極高 (例如 >1,通常到 10 位數): temperature 變得無關緊要,任何通過 top-K 和/或 top-P 標準的 tokens 都會被隨機取樣以選擇下一個預測 token。
    • top-K 為 1: temperaturetop-P 變得無關緊要。只有一個 token 通過 top-K 標準,該 token 即為下一個預測 token。
    • top-K 極高 (例如 LLM 詞彙表的大小): 任何具有非零機率成為下一個 token 的 token 都將符合 top-K 標準,沒有 token 會被篩選掉。
    • top-P 為 0 (或非常小的值): 大多數 LLM 取樣實現將僅考慮最可能的 token 以符合 top-P 標準,使得 temperaturetop-K 無關緊要。
    • top-P 為 1: 任何具有非零機率成為下一個 token 的 token 都將符合 top-P 標準,沒有 token 會被篩選掉。
  • 一般起點:
    • temperature 為 0.2,top-P 為 0.95,top-K 為 30,可以得到相對連貫且具有一定創意的結果。
    • 追求高創意: temperature 為 0.9,top-P 為 0.99,top-K 為 40。
    • 追求低創意: temperature 為 0.1,top-P 為 0.9,top-K 為 20。
    • 單一正確答案任務 (例如數學問題): temperature 從 0 開始。
  • 注意 (NOTE): 擁有更多自由度(更高的 temperaturetop-Ktop-P 和輸出 tokens)時,LLM 可能會生成不太相關的文本。
  • 警告 (WARNING) - Repetition Loop Bug:
    • 現象: 回應以大量填充詞結束。模型陷入循環,重複生成相同的(填充)詞、短語或句子結構。
    • 原因: 常見於大型語言模型,通常因不當的 temperaturetop-K/top-P 設定而加劇。
    • 低溫下的原因: 模型變得過於確定性,嚴格遵循最高機率路徑,如果該路徑重新訪問先前生成的文本,則可能導致循環。
    • 高溫下的原因: 模型輸出變得過於隨機,增加了隨機選擇的詞或短語偶然引導回先前狀態的機率,由於可用選項過多而產生循環。
    • 結果: 模型取樣過程「卡住」,導致單調且無用的輸出,直到填滿輸出窗口。
    • 解決方案: 通常需要仔細調整 temperaturetop-K/top-P 值,以找到確定性和隨機性之間的最佳平衡。

Prompting techniques

LLM 經過調整以遵循指示,並在大量數據上進行訓練,因此它們可以理解提示並生成答案。但 LLM 並非完美無缺;您的提示文本越清晰,LLM 就越能更好地預測下一個可能的文本。此外,利用 LLM 訓練方式和運作方式的特定技巧,將有助於您從 LLM 獲得相關結果。

General prompting / zero shot

  • 定義: zero-shot 提示是最簡單的提示類型。它僅提供任務的描述和一些供 LLM 開始的文本。此輸入可以是任何東西:一個問題、一個故事的開頭或指示。名稱 zero-shot 代表「沒有範例 (no examples)」。
  • 範例: 使用 Vertex AI Studio (for Language) 測試提示。
    • An example of zero-shot prompting:
      • Prompt:
      ​​​​​​​​Classify movie reviews as POSITIVE, NEUTRAL or NEGATIVE.
      ​​​​​​​​Review: "Her" is a disturbing study revealing the direction humanity is headed if AI is allowed to keep evolving, unchecked. I wish there were more movies like this masterpiece.
      ​​​​​​​​Sentiment:
      
      • Output: POSITIVE
    • 說明: 模型 temperature 應設定為較低的值,因為不需要創意。使用 gemini-pro 預設的 top-Ktop-P 值,這實際上禁用了這兩個設定。注意生成的輸出。"disturbing" 和 "masterpiece" 這兩個詞應使預測稍微複雜一些,因為它們出現在同一個句子中。
    • 提示記錄的重要性: 表格格式是記錄提示的好方法。提示在最終進入程式碼庫之前可能會經歷多次迭代,因此以有紀律、結構化的方式追蹤您的 prompt engineering 工作非常重要。

One-shot & few-shot

  • 簡介: 當 zero-shot 無法奏效時,您可以在提示中提供示範 (demonstrations) 或範例 (examples),這就引出了 one-shotfew-shot prompting。
  • 定義:
    • One-shot prompt: 提供單一範例,因此得名 one-shot。其思想是模型有一個可以模仿以最好地完成任務的範例。
    • Few-shot prompt: 提供多個範例給模型。這種方法向模型展示了它需要遵循的模式。其思想與 one-shot 類似,但多個期望模式的範例增加了模型遵循該模式的機會。
  • 範例數量: few-shot prompting 所需的範例數量取決於幾個因素,包括任務的複雜性、範例的品質以及您使用的生成式 AI (gen AI) 模型的能力。作為一般經驗法則,您應該為 few-shot prompting 使用至少三到五個範例。但是,對於更複雜的任務,您可能需要使用更多範例,或者由於模型的輸入長度限制,您可能需要使用較少範例。
  • 範例:
    • An example of few-shot prompting:
      • Goal: Parse pizza orders to JSON
      • Prompt:
      ​​​​​​​​Parse a customer's pizza order into valid JSON:
      ​​​​​​​​​ EXAMPLE1:
      ​​​​​​​​​ I want a small pizza with cheese, tomato sauce, and pepperoni.
      ​​​​​​​​​ JSON Response:
      ​​​​​​​​​ {
      ​​​​​​​​​   "size": "small",
      ​​​​​​​​​   "type": "normal",
      ​​​​​​​​​   "ingredients": [["cheese", "tomato sauce", "peperoni"]]
      ​​​​​​​​​ }
      ​​​​​​​​​ EXAMPLE2:
      ​​​​​​​​​ Can I get a large pizza with tomato sauce, basil and mozzarella
      ​​​​​​​​​ {
      ​​​​​​​​​   "size": "large",
      ​​​​​​​​​   "type": "normal",
      ​​​​​​​​​   "ingredients": [["tomato sauce", "bazel", "mozzarella"]]
      ​​​​​​​​​ }
      ​​​​​​​​​ Now, I would like a large pizza, with the first half cheese and mozzarella. And the other tomato sauce, ham and pineapple.
      ​​​​​​​​​ JSON Response:
      
      • Output:
      ​​​​​​​​  json
      ​​​​​​​​  {
      ​​​​​​​​    "size": "large",
      ​​​​​​​​    "type": "half-half",
      ​​​​​​​​    "ingredients": [["cheese", "mozzarella"], ["tomato sauce", "ham", "pineapple"]]
      ​​​​​​​​  }
      
  • 選擇範例的注意事項:
    • 相關性: 選擇與您要執行的任務相關的範例。
    • 品質: 範例應該是多樣化的、高品質的且書寫良好的。一個小錯誤可能會混淆模型並導致不希望的輸出。
    • 邊緣案例 (Edge cases): 如果您試圖生成對各種輸入都具有穩健性 (robust) 的輸出,那麼在範例中包含邊緣案例非常重要。邊緣案例是不尋常或意外的輸入,但模型仍應能夠處理。

System, contextual and role prompting

  • 概述: System, contextualrole prompting 都是用於引導 LLM 如何生成文本的技術,但它們專注於不同的方面。
    • System prompting: 設定語言模型的整體上下文 (context) 和目的 (purpose)。它定義了模型應該做什麼的「大方向 (big picture)」,例如翻譯語言、分類評論等。
    • Contextual prompting: 提供與當前對話或任務相關的特定細節或背景資訊。它幫助模型理解所提問內容的細微差別 (nuances),並相應地調整回應。
    • Role prompting: 為語言模型分配一個特定的角色 (character) 或身份 (identity) 來扮演。這有助於模型生成與所分配角色及其相關知識和行為一致的回應。
  • 重疊性: systemcontextualrole prompting 之間可能存在相當大的重疊。例如,一個為系統分配角色的提示,也可能帶有上下文。
  • 主要目的區別:
    • System prompt: 定義模型的基本能力和總體目的。
    • Contextual prompt: 提供即時的、特定於任務的資訊以引導回應。它高度特定於當前的任務或輸入,這是動態的。
    • Role prompt: 塑造模型的輸出風格和語氣。它增加了一層特異性 (specificity) 和個性 (personality)。
  • 框架作用: 區分 systemcontextualrole prompts 提供了一個設計具有明確意圖的提示的框架,允許靈活組合,並更容易分析每種類型的提示如何影響語言模型的輸出。

1. System prompting

  • 定義: System prompts 用於生成符合特定需求的輸出。名稱「system prompt」實際上代表「向系統提供額外任務」。
  • 應用:
    • 生成與特定程式語言相容的程式碼片段。
    • 返回特定結構的輸出,例如 JSON 格式。
  • 範例 1: 基本分類與格式化
    • An example of system prompting
      • Goal: Classify movie reviews as positive, neutral or negative.
      • Prompt:
      ​​​​​​​​​ Classify movie reviews as positive, neutral or negative. Only return the label in uppercase.
      ​​​​​​​​​ Review: "Her" is a disturbing study revealing the direction humanity is headed if AI is allowed to keep evolving, unchecked. It's so disturbing I couldn't watch it.
      ​​​​​​​​​ Sentiment:
      
      • Output: NEGATIVE
  • 範例 2: JSON 格式輸出
    • An example of system prompting with JSON format:
      • Goal: Classify movie reviews as positive, neutral or negative, return JSON.
      • Prompt:
      ​​​​​​​​ Classify movie reviews as positive, neutral or negative. Return valid JSON:
      ​​​​​​​​ Review: "Her" is a disturbing study revealing the direction humanity is headed if AI is allowed to keep evolving, unchecked. It's so disturbing I couldn't watch it.
      ​​​​​​​​ Schema:
      ​​​​​​​​ MOVIE:
      ​​​​​​​​  { 
      ​​​​​​​​  "sentiment": String "POSITIVE" or "NEGATIVE" or "NEUTRAL",
      ​​​​​​​​    "name": String
      ​​​​​​​​  }
      ​​​​​​​​ MOVIE REVIEWS:
      ​​​​​​​​  {
      ​​​​​​​​    "movie_reviews": [MOVIE]
      ​​​​​​​​  }
      ​​​​​​​​ JSON Response:
      
      • Output:
      ​​​​​​​​​ {
      ​​​​​​​​​   "movie_reviews": [
      ​​​​​​​​​     {
      ​​​​​​​​​       "sentiment": "NEGATIVE",
      ​​​​​​​​​       "name": "Her"
      ​​​​​​​​​     }
      ​​​​​​​​​   ]
      ​​​​​​​​​ }
      
    • JSON 輸出的好處:
      • 在實際應用中,無需手動創建 JSON 格式。
      • 可以返回已排序的數據(處理日期時間對象時非常方便)。
      • 最重要的是,通過提示 JSON 格式,它迫使模型創建一個結構並限制幻覺 (hallucinations)。
  • 安全性與毒性 (Safety and toxicity): System prompts 對於控制輸出的安全性和毒性也非常有用。只需在提示中添加一行,例如:「You should be respectful in your answer.」。

2. Role prompting

  • 定義: Role prompting 是一種 prompt engineering 技術,涉及為 gen AI 模型分配特定角色。這有助於模型生成更相關和資訊更豐富的輸出,因為模型可以根據已分配的特定角色來製作其回應。
  • 應用:
    • 將 gen AI 模型設定為書籍編輯、幼兒園老師或勵志演說家。
    • 一旦模型被分配了角色,就可以給予特定於該角色的提示。例如,可以提示老師創建一個課程計劃供其審查。
  • 範例 1: 旅行指南
    • An example of role prompting:
      • Goal: Act as travel guide and provide 3 travel suggestions
      • Prompt:
      ​​​​​​​​​ I want you to act as a travel guide. I will write to you about my location and you will suggest 3 places to visit near me. In some cases, I will also give you the type of places I will visit.
      ​​​​​​​​​ My suggestion: "I am in Amsterdam and I want to visit only museums."
      ​​​​​​​​​ Travel Suggestions:
      
      • Output:
      ​​​​​​​​​ 1. Rijksmuseum: ...
      ​​​​​​​​​ 2. Van Gogh Museum: ...
      ​​​​​​​​​ 3. Stedelijk Museum Amsterdam: ...
      
    • 說明: 上述範例展示了扮演旅行社代理角色的範例。如果將角色更改為地理老師,您會注意到收到的回應會有所不同。
  • 優勢: 為 AI 模型定義角色視角,為其提供了您所期望的語氣、風格和專業知識的藍圖,從而提高輸出的品質、相關性和有效性。
  • 可選風格: Confrontational, Descriptive, Direct, Formal, Humorous, Influential, Informal, Inspirational, Persuasive.

3. Contextual prompting

  • 定義: 通過提供 contextual prompts,您可以幫助確保您的 AI 互動盡可能無縫和高效。模型將能夠更快地理解您的請求,並能生成更準確和相關的回應。
  • 範例:
    • An example of contextual prompting:
      • Goal: Suggest articles for a blog about retro games
      • Prompt:
      ​​​​​​​​​ Context: You are writing for a blog about retro 80's arcade video games.
      ​​​​​​​​​ Suggest 3 topics to write an article about with a few lines of description of what this article should contain.
      
      • Output:
      ​​​​​​​​  1. The Evolution of Arcade Cabinet Design: ...
      ​​​​​​​​  2. Blast From The Past: Iconic Arcade Games of The 80’s: ...
      ​​​​​​​​  3. The Rise and Retro Revival of Pixel Art: ...
      
      

Step-back prompting

  • 定義: Step-back prompting 是一種通過提示 LLM 首先考慮與手頭特定任務相關的一般性問題,然後將該一般性問題的答案提供給後續針對特定任務的提示中,從而提高性能的技術。這種退一步 (step back) 允許 LLM 在嘗試解決特定問題之前,激活相關的背景知識和推理過程。
  • 優勢:
    • 通過考慮更廣泛和潛在的原則,LLM 可以生成更準確和有洞察力的回應。
    • 鼓勵 LLM 批判性思考,並以新的和創造性的方式應用其知識。
    • 通過利用 LLM 參數中比直接提示 LLM 時會發揮作用的更多知識,來改變執行任務的最終提示。
    • 通過專注於一般原則而非特定細節,有助於減輕 LLM 回應中的偏見 (biases)。
  • 範例:
    • 傳統提示 (Traditional Prompt):
      • Goal: Write a storyline for a level of a first-person shooter video game.
      • Prompt:
      ​​​​​​​​​Write a one paragraph storyline for a new level of a first-person shooter video game that is challenging and engaging.
      
      • Output:
      ​​​​​​​​The level begins with the player’s squad being ambushed in a dense urban area by a relentless enemy faction. 
      ​​​​​​​​Players must fight their way through a maze of back alleys and dilapidated buildings, 
      ​​​​​​​​utilizing stealth and precision to eliminate enemy forces and avoid detection. ... ...
      
    • Step-back 一般性問題:
      • Prompt:
      ​​​​​​​​​Based on popular first-person shooter action games, what are 5 fictional key settings that contribute to a challenging and engaging level storyline in a first-person shooter video game?
      
      • Output:
      ​​​​​​​​1.  Abandoned Military Base: ...
      ​​​​​​​​2.  Cyberpunk City: ...
      ​​​​​​​​3.  Alien Spaceship: ...
      ​​​​​​​​4.  Zombie-Infested Town: ...
      ​​​​​​​​5.  Underwater Research Facility: ...
      
    • 結合 Step-back 結果的提示:
      • Prompt:
      ​​​​​​​​​Context: 5 engaging themes for a first person shooter video game:
      ​​​​​​​​​   1. **Abandoned Military Base**: ...
      ​​​​​​​​​   2. **Cyberpunk City**: ...
      ​​​​​​​​​   3. **Alien Spaceship**: ...
      ​​​​​​​​​   4. **Zombie-Infested Town**: ...
      ​​​​​​​​​   5. **Underwater Research Facility**: ...
      ​​​​​​​​​   Take one of the themes and write a one paragraph storyline for a new level of a first-person shooter video game that is challenging and engaging.
      
      • Output:
      ​​​​​​​​In the heart of a murky abyss, lies a dilapidated underwater research facility, standing as a testament to human ambition and its disastrous consequences. 
      ​​​​​​​​Shrouded in darkness, pulsating with the hum of malfunctioning machinery, and haunted by the echoes of drowned souls, 
      ​​​​​​​​the facility is now a breeding ground for a nightmare borne from the deep sea. ... ...
      
  • 結論: 使用 step-back prompting 技巧可以提高提示的準確性。

Chain of Thought (CoT)

  • 定義: Chain of Thought (CoT) prompting 是一種通過生成中間推理步驟 (intermediate reasoning steps) 來提高 LLM 推理能力的技術。這有助於 LLM 生成更準確的答案。您可以將其與 few-shot prompting 結合使用,以在需要響應前進行推理的更複雜任務上獲得更好的結果,因為這對於 zero-shot chain of thought 來說是一個挑戰。
  • 優勢:
    • 低工作量高效益 (Low-effort while being very effective): 易於實施且效果顯著。
    • 適用於現成 LLM (Works well with off-the-shelf LLMs): 無需微調 (finetune)。
    • 可解釋性 (Interpretability): 可以從 LLM 的回應中學習並看到所遵循的推理步驟。如果出現故障,您將能夠識別它。
    • 穩健性 (Robustness): 在不同 LLM 版本之間轉換時,CoT 似乎能提高穩健性。這意味著與不使用推理鏈的提示相比,您的提示性能在不同 LLM 之間的漂移應該較小。
  • 劣勢:
    • 更多輸出 tokens: LLM 回應包含思維鏈推理,這意味著更多的輸出 tokens,進而導致預測成本更高且耗時更長。
  • 範例:
    • 無 CoT 的數學問題 (展示缺陷):
      • Prompt:
      ​​​​​​​​​ When I was 3 years old, my partner was 3 times my age. 
      ​​​​​​​​​ Now, I am 20 years old. How old is my partner?
      
      • Output: 63 years old (錯誤答案)
      • 說明: LLM 經常在數學任務上遇到困難,即使是像乘法這樣簡單的任務也可能提供錯誤答案,因為它們是在大量文本上訓練的,而數學可能需要不同的方法。
    • 使用 CoT 的數學問題 (zero-shot CoT):
      • Prompt:
      ​​​​​​​​​ When I was 3 years old, my partner was 3 times my age. 
      ​​​​​​​​​ Now, I am 20 years old. How old is my partner? 
      ​​​​​​​​​ Let's think step by step.
      
      • Output:
      ​​​​​​​​​     1. Let’s assume my current age is “x” years.
      ​​​​​​​​​     2. When I was 3 years old, my age was 3 years.
      ​​​​​​​​​     3. My partner’s age at that time was 3 times my age, which means my partner’s age was 3 * 3 = 9 years.
      ​​​​​​​​​     4. Now, I am 20 years old, which means my age has increased by 20 - 3 = 17 years since I was 3 years old.
      ​​​​​​​​​     5. Since my partner’s age was 9 years when I was 3 years old, and my age has increased by 17 years, my partner’s age must have also increased by 17 years.
      ​​​​​​​​​     6. Therefore, my partner’s current age is 9 + 17 = 26 years.
      ​​​​​​​​​     So, my partner is 26 years old.
      
      • 說明: 因為我們明確指示 LLM 解釋每個步驟而不是僅返回答案,所以最終答案是正確的。有趣的是,模型將增加的 17 年加了上去。
    • 使用 CoT 的數學問題 (single-shot CoT):
      • Prompt:
      ​​​​​​​​​   Q: When my brother was 2 years old, I was double his age. Now I am 40 years old. How old is my brother? Let's think step by step.
      ​​​​​​​​​   A: When my brother was 2 years, I was 2 * 2 = 4 years old. That's an age difference of 2 years and I am older. Now I am 40 years old, so my brother is 40 - 2 = 38 years old. The answer is 38.
      ​​​​​​​​​   Q: When I was 3 years old, my partner was 3 times my age. Now, I am 20 years old. How old is my partner? Let's think step by step.
      ​​​​​​​​​   A:
      
      • Output:
      ​​​​​​​​​   When I was 3 years old, my partner was 3 * 3 = 9 years old. That’s an age difference of 6 years and my partner is older. 
      ​​​​​​​​​   Now I am 20 years old, so my partner is 20 + 6 = 26 years old. The answer is 26.
      
  • 適用場景:
    • 程式碼生成 (Code generation): 將請求分解為幾個步驟,並將這些步驟映射到特定的程式碼行。
    • 合成數據創建 (Creating synthetic data): 當您有一些種子(例如「產品名為 XYZ,撰寫描述並引導模型說明您基於產品標題會做的假設」)時。
    • 一般原則: 任何可以通過「逐步解釋」解決的任務都是 CoT 的良好候選者。如果您可以解釋解決問題的步驟,請嘗試 CoT。
  • 進階 CoT 實踐: 將在「Best Practices」部分討論。

Self-consistency

  • 定義: 雖然大型語言模型在各種 NLP 任務中取得了令人印象深刻的成功,但它們的推理能力通常被視為僅靠增加模型大小無法克服的限制。Self-consistency 結合了取樣 (sampling) 和多數決 (majority voting) 來生成多樣化的推理路徑並選擇最一致的答案,從而改進了僅使用簡單「greedy decoding」策略的 CoT 的有效性。它提高了 LLM 生成回應的準確性和連貫性。
  • 機制: Self-consistency 提供了一個答案正確的pseudo-probability,但成本較高。
  • 步驟:
    1. 生成多樣化的推理路徑 (Generating diverse reasoning paths): 多次向 LLM 提供相同的提示。high temperature 設定鼓勵模型生成對問題的不同推理路徑和視角。
    2. 從每個生成的回應中提取答案 (Extract the answer from each generated response)
    3. 選擇最常見的答案 (Choose the most common answer)
  • 範例: 郵件分類系統
    • 任務: 將郵件分類為 IMPORTANT 或 NOT IMPORTANT。
    • 方法: 多次向 LLM 發送 zero-shot chain of thought 提示,以查看每次提交後的回應是否不同。注意郵件中的友好語氣、用詞選擇和諷刺意味,這些都可能誤導 LLM。
    • Prompt:
    ​​​​​   EMAIL:
    ​​​​​   Hi,
    ​​​​​   I have seen you use Wordpress for your website. A great open source content management system. I have used it in the past too. It comes with lots of great user plugins. And it's pretty easy to set up.
    ​​​​​   ...
    ​​​​​   Cheers,
    ​​​​​   Harry the Hacker.
    ​​​​​   Classify the above email as **IMPORTANT or NOT IMPORTANT**. Let's think step by step and explain why.
    
    • Output Attempt 1 (可能結果):
      ​​​​​​​ Step 1: Identify the purpose of the email.
      ​​​​​​​   ...
      ​​​​​​​ Step 2: Assess the potential impact of the bug.
      ​​​​​​​   ...
      ​​​​​​​ Step 3: Consider the credibility of the sender.
      ​​​​​​​   ...
      ​​​​​​​ Conclusion: IMPORTANT
      ​​​​​​​   Based on the potential impact of the bug and the credibility of the sender, the email should be classified as **IMPORTANT**. 
      ​​​​​​​   The recipient should take immediate action to fix the bug and protect their website from attack.
      
    • Output Attempt 2 (可能結果):
      ​​​​​​​ Explanation:
      ​​​​​​​   1. Lack of urgency: ...
      ​​​​​​​   2. Non-critical bug report: ...
      ​​​​​​​   3. Lack of personal impact: ...
      ​​​​​​​   4. Absence of action request: ...
      ​​​​​​​   5. Sender’s intent: ...
      ​​​​​​​ Conclusion: NOT IMPORTANT
      
    • Output Attempt 3 (可能結果 與 Attempt 1 類似,判定為 IMPORTANT)
      ​​​​​​    Step 1: Identify the purpose of the email.
      ​​​​​​    ...
      ​​​​​​    Step 2: Assess the potential impact of the bug.
      ​​​​​​    ...
      ​​​​​​    Step 3: Consider the credibility of the sender.
      ​​​​​​    ...
      ​​​​​​    Conclusion:
      ​​​​​​    Based on the above factors, the email should be classified as **IMPORTANT**. 
      ​​​​​​    The bug in the contact form is a serious security risk, and the sender’s credibility is unknown. 
      ​​​​​​    The recipient should take immediate action to fix the bug and investigate the sender’s claims.
      
    • 結論: 通過生成多個 Chains of Thoughts,並選擇最常出現的答案(例如「IMPORTANT」),我們可以從 LLM 獲得更一致正確的答案。此範例顯示了 self-consistency prompting 如何通過考慮多個視角並選擇最一致的答案來提高 LLM 回應的準確性。

Tree of Thoughts (ToT)

  • 定義: Tree of Thoughts (ToT) 概括了 CoT prompting 的概念,它允許 LLM 同時探索多個不同的推理路徑,而不是僅僅遵循單一的線性思維鏈。
  • 機制:
    • ToT 通過維護一個思維樹來工作,其中每個思維 (thought) 代表一個連貫的語言序列,作為解決問題的中間步驟。
    • 模型可以通過從樹中的不同節點分支來探索不同的推理路徑。
    • 這種方法使得 ToT 特別適用於需要探索的複雜任務。
  • 圖解:
    image
    • 左側 (Chain of Thought): 呈現一個線性流程。
      • Input -> Thought (方框) -> (多個 Thought 方框) -> Thought (方框) -> Output
    • 右側 (Tree of Thoughts): 呈現一個樹狀分支結構。
      • Input -> 分支出多個初始 Thought (綠色和淺紅色方框)。
      • 每個 Thought 可以進一步分支成更多的 Thought
      • 某些路徑可能被剪枝 (pruned) 或評為較不重要 (淺紅色方框)。
      • 較有前景的路徑 (較深的綠色方框) 會被進一步探索。
      • 最終的 Output 是從樹中某條路徑推導出來的。
  • 參考資料: 提到了一篇名為 "Large Language Model Guided Tree-of-Thought" 的論文。

ReAct (reason & act)

  • 定義: Reason and act (ReAct) prompting 是一種使 LLM 能夠通過結合自然語言推理與外部工具 (external tools)(如搜索 (search)、程式碼解釋器 (code interpreter) 等)來解決複雜任務的範式。它允許 LLM 執行某些操作,例如與外部 API 互動以檢索資訊,這是朝向代理建模 (agent modeling) 的第一步。
  • 機制:
    • ReAct 模仿人類在現實世界中的運作方式:我們進行口頭推理,並可以採取行動來獲取資訊。
    • ReAct prompting 通過將推理 (reasoning) 和行動 (acting) 結合到一個思維-行動循環 (thought-action loop) 中來工作。
    1. LLM 首先對問題進行推理並生成一個行動計劃 (plan of action)。
    2. 然後執行計劃中的操作並觀察結果 (observes the results)。
    3. LLM 接著使用觀察結果來更新其推理並生成新的行動計劃。
    4. 此過程持續進行,直到 LLM 找到問題的解決方案。
  • 範例: Metallica 樂隊成員有多少孩子?
    執行過程 (文字描述):
    ​​​​​​  Executing ReAct Agent in the terminal:
    ​​​​​​    Entering new AgentExecutor chain...
    ​​​​​​    Metallica has 4 members.
    ​​​​​​    Action: Search
    ​​​​​​    Action Input: How many kids does James Hetfield have?
    ​​​​​​    Observation: three children
    ​​​​​​    Thought: 1/4 Metallica band members have 3 children
    ​​​​​​    Action: Search
    ​​​​​​    Action Input: How many kids does Lars Ulrich have?
    ​​​​​​    Observation: 3
    ​​​​​​    Thought: 2/4 Metallica band members have 6 children
    ​​​​​​    Action: Search
    ​​​​​​    Action Input: How many kids does Kirk Hammett have?
    ​​​​​​    Observation: Hammett has been married to his second wife Lani since 1998. They have two sons, Angel (b. September 29, 2006) and Vincenzo (b. June 28, 2008).
    ​​​​​​    Thought: 3/4 Metallica band members have 8 children
    ​​​​​​    Action: Search
    ​​​​​​    Action Input: How many kids does Robert Trujillo have?
    ​​​​​​    Observation: 2
    ​​​​​​    Thought: 4/4 Metallica band members have 10 children
    ​​​​​​    Final Answer: 10 
    

    說明: ReAct 進行了五次搜索鏈。LLM 正在抓取 Google 搜索結果以找出樂隊成員的名字。然後,它將結果列為觀察結果,並鏈接下一次搜索的思路。最終,它確定 Metallica 有四名樂隊成員,然後搜索每個成員以請求孩子的總數並加總。

  • 實踐注意事項: ReAct prompting 在實踐中需要理解您必須持續重新發送先前的提示/回應(並修剪額外生成的內容),以及使用適當的範例/指示來設定模型。

Automatic Prompt Engineering (APE)

  • 定義: Automatic Prompt Engineering (APE) 是一種自動化撰寫提示過程的方法。該方法不僅減輕了人工輸入的需求,還增強了模型在各種任務中的性能。
  • 機制:
    1. 您提示一個模型以生成更多提示。
    2. 評估這些生成的提示。
    3. 可能修改好的提示。
    4. 重複此過程。
  • 範例: 為T恤網店訓練聊天機器人
    • 目標: 找出客戶可能用來訂購樂隊T恤的各種措辭。
    • 步驟:
      1. Use an LLM to generate prompts
      • Prompt:
      ​​​​​​​​​ We have a band merchandise t-shirt webshop, and to train a chatbot we need various ways to order: "One Metallica t-shirt size S". Generate 10 variants, with the same semantics but keep the same meaning.
      
      • Output:
      ​​​​​​​​​   1.  I’d like to purchase a Metallica t-shirt in size small.
      ​​​​​​​​​   2.  Can I order a small-sized Metallica t-shirt?
      ​​​​​​​​​   3.  I’d like to buy one Metallica t-shirt in small.
      ​​​​​​​​​   4.  One Metallica shirt, size small, please.
      ​​​​​​​​​   5.  I want one Metallica t-shirt in size small.
      ​​​​​​​​​   ...
      ​​​​​​​​​   ...
      ​​​​​​​​​   ...
      
      1. 評估候選指令: 通過基於選定指標(例如 BLEU (Bilingual Evaluation Understudy)ROUGE (Recall-Oriented Understudy for Gisting Evaluation))對候選指令進行評分來評估所有指令。
      2. 選擇最佳候選指令: 選擇評估分數最高的指令候選者。此候選者將是您可以在軟體應用程式或聊天機器人中使用的最終提示。您也可以調整所選提示並再次評估。

Code prompting

Gemini 主要專注於基於文本的提示,這也包括編寫返回程式碼的提示。

Writing code

  • 說明: Gemini 也可以扮演開發者的角色,幫助您用您選擇的任何程式語言編寫程式碼。作為開發者,這可以幫助您加快編寫程式碼的過程。
  • 範例: Bash 腳本重命名文件
    • 場景: 一個資料夾中有數百個文件需要重命名。
    • Using Gemini to program code
      • Prompt:
        ​​​​​​​​​Write a code snippet in Bash, which asks for a folder name. 
        ​​​​​​​​​Then it takes the contents of the folder and renames all the files inside by prepending the name draft to the file name.
        
      • Output:
        ​​​​​​​​​​#!/bin/bash
        ​​​​​​​​​​# Ask for the folder name
        ​​​​​​​​​​echo "Enter the folder name: "
        ​​​​​​​​​​read folder_name
        
        ​​​​​​​​​​# Check if the folder exists
        ​​​​​​​​​​if [ ! -d "$folder_name" ]; then
        ​​​​​​​​​​  echo "Folder does not exist."
        ​​​​​​​​​​  exit 1
        ​​​​​​​​​​fi
        
        ​​​​​​​​​​# Get the list of files in the folder
        ​​​​​​​​​​files=( "$folder_name"/* )
        
        ​​​​​​​​​​# Rename each file by prepending "draft" to the file name
        ​​​​​​​​​​for file in "${files[@]}"; do
        ​​​​​​​​​​  new_file_name="draft_$(basename "$file")"
        ​​​​​​​​​​  mv "$file" "$new_file_name"
        ​​​​​​​​​​done
        
        ​​​​​​​​​​echo "Files renamed successfully."
        
    • 注意事項: 由於 LLM 無法推理且會重複訓練數據,因此首先閱讀並測試您的程式碼至關重要。
    • 測試步驟:
      1. 將輸出(不含bash文本包裝器)複製並粘貼到一個名為 rename_files.sh 的新文件中。
      2. 打開終端窗口並輸入:. rename_files.sh。它會要求輸入資料夾名稱,例如 test,然後按 Enter。
      3. 腳本運行良好。您將看到消息:Files renamed successfully.。查看測試資料夾,注意到所有文件都已完美重命名為 draft_filename.txt

Explaining code

  • 說明: 作為開發者,在團隊中工作時,您必須閱讀他人的程式碼。Gemini 也可以在這方面提供幫助。
  • 範例: 解釋 Bash 腳本
    • 方法: 取上程式碼輸出,刪除註釋,並要求大型語言模型解釋正在發生的事情。
    • Prompt:
      ​​​​​​​​​ Explain to me the below Bash code:
      ​​​​​​​​​ #!/bin/bash
      ​​​​​​​​​ echo "Enter the folder name: "
      ​​​​​​​​​ read folder_name
      ​​​​​​​​​ if [ ! -d "$folder_name" ]; then
      ​​​​​​​​​   echo "Folder does not exist."
      ​​​​​​​​​   exit 1
      ​​​​​​​​​ fi
      ​​​​​​​​​ files=( "$folder_name"/* )
      ​​​​​​​​​ for file in "${files[@]}"; do
      ​​​​​​​​​   new_file_name="draft_$(basename "$file")"
      ​​​​​​​​​   mv \"$file" "$new_file_name"
      ​​​​​​​​​ done
      ​​​​​​​​​ echo "Files renamed successfully."
      
    • Output:
      ​​​​​​​​​ This Bash script performs the following tasks:
      ​​​​​​​​​ 1. User Input:
      ​​​​​​​​​    - It prompts the user to enter a folder name using the `echo` and `read` commands. The entered folder name is stored in the `folder_name` variable.
      ​​​​​​​​​ 2. Folder Existence Check:
      ​​​​​​​​​    - It checks if the folder with the specified name exists using the `[ ! -d “$folder_name” ]` condition. If the folder does not exist, it displays an error message (“Folder does not exist.”) and exits the script with an exit code of 1.
      ​​​​​​​​​ 3. File Listing:
      ​​​​​​​​​    - It lists all the files inside the specified folder using the `files=( “$folder_name”/* )` command. This creates an array called `files` containing the paths to all the files in the folder.
      ​​​​​​​​​ 4. File Renaming:
      ​​​​​​​​​    - It iterates through each file in the `files` array using a `for` loop.
      ​​​​​​​​​    - For each file, it generates a new file name using the `new_file_name=”draft_$(basename “$file”)”` command. This new file name is created by prefixing the original file name with the string “draft_”.
      ​​​​​​​​​    - It then renames the file using the `mv “$file” “$new_file_name”` command, which moves the file to the new file name.
      ​​​​​​​​​ 5. Success Message:
      ​​​​​​​​​    - After renaming all the files, it displays a success message (“Files renamed successfully.”) to indicate that the renaming operation was successful
      

Translating code

  • 說明: bash 程式碼看起來運行良好。然而當這個腳本提示我輸入文件名時,它才能真正可重用,理想情況下,它應該作為一個帶有 UI 的獨立應用程式工作。作為起點,Python 比 Bash 更適合用於(Web)應用程式。LLM 可以幫助將程式碼從一種語言翻譯到另一種語言。
  • 範例: Bash 轉 Python
    • Prompt:
      ​​​​​​​​​ Translate the below Bash code to a Python snippet.
      ​​​​​​​​​ bash
      ​​​​​​​​​ #!/bin/bash
      ​​​​​​​​​ echo "Enter the folder name: "
      ​​​​​​​​​ read folder_name
      ​​​​​​​​​ if [ ! -d "$folder_name" ]; then
      ​​​​​​​​​   echo "Folder does not exist."
      ​​​​​​​​​   exit 1
      ​​​​​​​​​ fi
      ​​​​​​​​​ files=( "$folder_name"/* )
      ​​​​​​​​​ for file in "${files[@]}"; do
      ​​​​​​​​​   new_file_name="draft_$(basename "$file")"
      ​​​​​​​​​   mv "$file" "$new_file_name"
      ​​​​​​​​​ done
      ​​​​​​​​​ echo "Files renamed successfully."
      
    • Output:
      ​​​​​​​​​ import os
      ​​​​​​​​​ import shutil
      ​​​​​​​​​ # Get the folder name from the user
      ​​​​​​​​​ folder_name = input("Enter the folder name: ")
      
      ​​​​​​​​​ # Check if the folder exists
      ​​​​​​​​​ if not os.path.isdir(folder_name):
      ​​​​​​​​​   print("Folder does not exist.")
      ​​​​​​​​​   exit(1)
      
      ​​​​​​​​​ # Get a list of all files in the folder
      ​​​​​​​​​ files = os.listdir(folder_name)
      
      ​​​​​​​​​ # Iterate over the files
      ​​​​​​​​​ for file in files:
      ​​​​​​​​​   # Create a new file name with the prefix "draft_"
      ​​​​​​​​​   new_file_name = f"draft_{file}"
      
      ​​​​​​​​​   # Move the file to the new name
      ​​​​​​​​​   shutil.move(os.path.join(folder_name, file),
      ​​​​​​​​​               os.path.join(folder_name, new_file_name))
      
      ​​​​​​​​​ # Print a success message
      ​​​​​​​​​ print("Files renamed successfully.")
      
    • 測試說明: 閱讀並審查程式碼。將提示的輸出複製並粘貼到一個新文件:file_renamer.py。通過打開終端窗口並執行以下命令來測試程式碼:python file_renamer.py

Debugging and reviewing code

  • 範例: 修復並改進 Python 程式碼
    • 場景: 手動編輯上程式碼。它應該提示用戶輸入文件名前綴,並以大寫字符寫入此前綴。但程式碼現在返回 Python 錯誤。
    • 損壞的 Python 腳本:
      ​​​​​​import os
      ​​​​​​import shutil
      
      ​​​​​​folder_name = input("Enter the folder name: ")
      ​​​​​​prefix = input("Enter the string to prepend to the filename: ")
      ​​​​​​text = toUpperCase(prefix) # Error here
      
      ​​​​​​if not os.path.isdir(folder_name):
      ​​​​​​  print("Folder does not exist.")
      ​​​​​​  exit(1)
      
      ​​​​​​files = os.listdir(folder_name)
      ​​​​​​for file in files:
      ​​​​​​  new_filename = f"{text}_{file}" # Mistake: text_file instead of text_ + original filename without extension
      
      ​​​​​​# Error in shutil.move, os.path.joi should be os.path.join
      ​​​​​​shutil.move(os.path.join(folder_name, file),
      ​​​​​​            os.path.joi(folder_name, new_file_name)) # Typo: joi instead of join
      
      ​​​​​​print("Files renamed successfully.")
      
    • 錯誤訊息:
      ​​​​​​The below Python code gives an error:
      ​​​​​​Traceback (most recent call last):
      ​​​​​​  File “/Users/leeboonstra/Documents/test_folder/rename_files.py”, line 7,
      ​​​​​​in <module>
      ​​​​​​    text = toUpperCase(prefix)
      ​​​​​​NameError: name ‘toUpperCase’ is not defined
      
    • Prompt:
      ​​​​​​​​The below Python code gives an error:
      ​​​​​​​​Traceback (most recent call last):
      ​​​​​​​​    File "/Users/leeboonstra/Documents/test_folder/rename_files.py", line 7, in <module>
      ​​​​​​​​          text = toUpperCase(prefix)
      ​​​​​​​​    NameError: name 'toUpperCase' is not defined
      
      ​​​​​​​​Debug what's wrong and explain how I can improve the code.
      ​​​​​​​​```python
      ​​​​​​​​      import os
      ​​​​​​​​      import shutil
      
      ​​​​​​​​      # Get the folder name from the user
      ​​​​​​​​      folder_name = input("Enter the folder name: ")
      ​​​​​​​​      prefix = input("Enter the string to prepend to the filename: ")
      ​​​​​​​​      text = toUpperCase(prefix)
      
      ​​​​​​​​      # Check if the folder exists
      ​​​​​​​​      if not os.path.isdir(folder_name):
      ​​​​​​​​        print("Folder does not exist.")
      ​​​​​​​​        exit(1)
      
      ​​​​​​​​      # Get a list of all files in the folder
      ​​​​​​​​      files = os.listdir(folder_name)
      
      ​​​​​​​​      # Iterate over the files
      ​​​​​​​​      for file in files:
      ​​​​​​​​        # Create a new file name with the prefix "draft_" (This part of the prompt's code is from original table 18, not the broken snippet 3)
      ​​​​​​​​        new_filename = f"{text}_{file}" # This line is present in the prompt for debugging, but should reflect the broken code's intent.
      
      ​​​​​​​​      # Move the file to the new name (This part of the prompt's code is from original table 18)
      ​​​​​​​​      shutil.move(os.path.join(folder_name, file),
      ​​​​​​​​                  os.path.join(folder_name, new_file_name))
      ​​​​​​​​      # Print a success message
      ​​​​​​​​      print("Files renamed successfully.")
      ​​​​​​​​      ```
      
    • Output (摘要與改進):
      • 錯誤修復: 程式碼調用 toUpperCase 函數將 prefix 轉換為大寫,但該函數未定義。要解決此問題,可以使用字符串類的 upper() 方法。
      • 修改後的程式碼 (僅修復 toUpperCase):
      ​​​​​​​​​   import os
      ​​​​​​​​​   import shutil
      ​​​​​​​​​   # Get the folder name from the user
      ​​​​​​​​​   folder_name = input("Enter the folder name: ")
      ​​​​​​​​​   prefix = input("Enter the string to prepend to the filename: ")
      ​​​​​​​​​   text = prefix.upper() # Corrected
      ​​​​​​​​​   # ... (rest of the corrected logic from the model output)
      
    • 結論: 模型不僅告訴我如何解決問題,還指出了我的程式碼有更多錯誤以及如何解決它們。提示的最後一部分提供了改進程式碼的總體建議。

Multimodal prompting

  • 說明: 提示程式碼仍使用相同的常規大型語言模型。Multimodal prompting 是一個獨立的問題,它指的是一種使用多種輸入格式來引導大型語言模型的技術,而不是僅僅依賴文本。這可以包括文本、圖像、音頻、程式碼甚至其他格式的組合,具體取決於模型的能力和手頭的任務。

Best Practices

1. Provide examples

  • 核心思想: 最重要的最佳實踐是在提示中提供(one shot / few shot)範例。
  • 原因: 這非常有效,因為它充當了強大的教學工具。這些範例展示了期望的輸出或類似的回應,使模型能夠從中學習並相應地調整其自身的生成。這就像給模型一個參考點或目標,以提高其回應的準確性、風格和語氣,使其更好地符合您的期望。

2. Design with simplicity

  • 核心思想: 提示應該簡潔、清晰,並且易于您和模型理解。
  • 經驗法則: 如果它對您來說已經令人困惑,那麼它很可能也會讓模型感到困惑。
  • 避免: 不要使用複雜的語言,也不要提供不必要的資訊。
  • 範例:

    BEFORE: I am visiting New York right now, and I'd like to hear more about great locations. I am with two 3 year old kids. Where should we go during our vacation?

    AFTER REWRITE: Act as a travel guide for tourists. Describe great places to visit in New York Manhattan with a 3 year old.

  • 建議: 嘗試使用描述動作的動詞。以下是一些範例動詞:

    Act, Analyze, Categorize, Classify, Contrast, Compare, Create, Describe, Define, Evaluate, Extract, Find, Generate, Identify, List, Measure, Organize, Parse, Pick, Predict, Provide, Rank, Recommend, Return, Retrieve, Rewrite, Select, Show, Sort, Summarize, Translate, Write.

3. Be specific about the output

  • 核心思想: 對期望的輸出要具體。
  • 原因: 簡潔的指令可能無法充分引導 LLM,或者可能過於籠統。在提示中提供具體細節(通過 systemcontext prompting)可以幫助模型專注於相關內容,從而提高整體準確性。
  • 範例:

    DO NOT: Generate a blog post about video game consoles.

    DO: Generate a 3 paragraph blog post about the top 5 video game consoles. The blog post should be informative and engaging, and it should be written in a conversational style.

4. Use Instructions over Constraints

  • 定義:
    • Instruction: 提供關於期望格式、風格或回應內容的明確指示。它指導模型應該做什麼或產生什麼。
    • Constraint: 對回應的一組限制或邊界。它限制模型不應該做什麼或避免什麼。
  • 研究表明: 在提示中專注於正面指令比過度依賴約束更有效。這種方法與人類更喜歡正面指令而非一堆禁忌列表的方式一致。
  • 優劣:
    • Instructions: 直接傳達期望的結果,而約束可能會讓模型猜測允許的範圍。指令在定義的邊界內提供靈活性並鼓勵創造力,而約束可能會限制模型的潛力。此外,一長串約束可能會相互衝突。
    • Constraints: 在某些情況下仍然很有價值。例如防止模型生成有害或有偏見的內容,或者當需要嚴格的輸出格式或風格時。
  • 建議:
    如果可能,使用正面指令告訴模型該做什麼,而不是不該做什麼。這可以避免混淆並提高輸出的準確性。

    DO NOT: Generate a 1 paragraph blog post about the top 5 video game consoles. Do not list video game names.

    DO: Generate a 1 paragraph blog post about the top 5 video game consoles. Only discuss the console, the company who made it, the year, and total sales.

  • 最佳實踐: 從優先考慮指令開始,清楚說明您希望模型做什麼,僅在出於安全、清晰或特定要求時才使用約束。進行實驗和迭代,以測試指令和約束的不同組合,找出最適合您特定任務的方法,並記錄下來。

5. Control the max token length

  • 方法: 要控制生成的 LLM 回應的長度,您可以在配置中設定最大 token 限制,或者在提示中明確要求特定長度。
  • 範例: "Explain quantum physics in a tweet length message."

6. Use variables in prompts

  • 目的: 重複使用提示並使其更具動態性,可以在提示中使用變數,這些變數可以針對不同的輸入進行更改。
  • 優勢: 變數可以讓您避免重複自己,從而節省時間和精力。如果您需要在多個提示中使用相同的資訊片段,可以將其存儲在變數中,然後在每個提示中引用該變數。這在將提示集成到您自己的應用程式中時非常有意義。
  • 範例:
    • Using variables in prompts
      • Prompt:
      ​​​​​​​​​ VARIABLES
      ​​​​​​​​​ {city} = "Amsterdam"
      
      ​​​​​​​​​ PROMPT
      ​​​​​​​​​ You are a travel guide. Tell me a fact about the city: {city}
      
      • Output:
      ​​​​​​​​​ Amsterdam is a beautiful city full of canals, bridges, and narrow streets.
      ​​​​​​​​​ It’s a great place to visit for its rich history, culture, and nightlife.
      

7. Experiment with input formats and writing styles

  • 核心思想: 不同的模型、模型配置、提示格式、詞語選擇和提交方式都可能產生不同的結果。
  • 建議: 因此重要的是要嘗試提示的屬性,如風格、詞語選擇和提示類型(zero shot, few shot, system prompt)。
  • 範例: 一個旨在生成關於革命性視頻遊戲機 Sega Dreamcast 文本的提示,可以表述為一個問題、一個陳述或一個指令,從而產生不同的輸出:
    • Question: What was the Sega Dreamcast and why was it such a revolutionary console?
    • Statement: The Sega Dreamcast was a sixth-generation video game console released by Sega in 1999. It...
    • Instruction: Write a single paragraph that describes the Sega Dreamcast console and explains why it was so revolutionary.

8. Experiment with output formats

  • 核心思想: 除了提示輸入格式外,還要考慮嘗試輸出格式。
  • 建議: 對於非創意性任務,如提取、選擇、解析、排序、排名或分類數據,嘗試讓您的輸出以結構化格式(如 JSON 或 XML)返回。
  • JSON 輸出總結好處:
    • 總是返回相同風格的結果。
    • 專注於您想要接收的數據。
    • 減少幻覺的機會。
    • 使其具有關係感知能力。
    • 您可以獲得數據類型。
    • 您可以對其進行排序。
  • 參考: few-shot prompting展示瞭如何返回結構化輸出的範例。

9. Working with Schemas

  • 從輸出到輸入: 使用結構化 JSON 作為輸出是一個很好的解決方案,但輸入呢?雖然 JSON 非常適合構建 LLM 生成的輸出,但它對於構建您提供的輸入也非常有用。這就是 JSON Schemas 發揮作用的地方。
  • JSON Schema: 定義 JSON 輸入的預期結構和數據類型。通過提供 schema,您可以為 LLM 提供它應該期望的數據的清晰藍圖,幫助它將注意力集中在相關信息上,並減少誤解輸入的風險。
  • 額外好處: Schema 可以幫助建立不同數據片段之間的關係,甚至可以通過包含具有特定格式的日期或時間戳字段來使 LLM 具有「時間感知 (time-aware)」能力。
  • 範例: 電子商務產品描述生成
    • 目標: 使用 LLM 為電子商務目錄中的產品生成描述。
    • 方法: 不要僅僅提供產品的自由格式文本描述,而是使用 JSON schema 來定義產品的屬性。
    • Prompt:
      ​​​​​​{
      ​​​​​​  "type": "object",
      ​​​​​​  "properties": {
      ​​​​​​    "name": { "type": "string", "description": "Product name" },
      ​​​​​​    "category": { "type": "string", "description": "Product category" },
      ​​​​​​    "price": { "type": "number", "format": "float", "description": "Product price" },
      ​​​​​​    "features": {
      ​​​​​​      "type": "array",
      ​​​​​​      "items": { "type": "string" },
      ​​​​​​      "description": "Key features of the product"
      ​​​​​​    },
      ​​​​​​    "release_date": { "type": "string", "format": "date", "description": "Date the product was released"}
      ​​​​​​  }
      ​​​​​​}
      
  • 優勢: 通過預處理您的數據,並且不僅僅提供完整文檔,而是同時提供 schema 和數據,您可以讓 LLM 清楚地了解產品的屬性,包括其發布日期,從而更有可能生成準確且相關的描述。這種結構化的輸入方法,將 LLM 的注意力引導到相關字段,在處理大量數據或將 LLM 集成到複雜應用程式中時尤其有價值。

10. Document the various prompt attempts

  • 重要性: 完整詳細地記錄您的提示嘗試,以便您可以隨著時間的推移了解哪些方法有效,哪些無效。
  • 差異性: 提示輸出可能因模型、取樣設定甚至同一模型的不同版本而異。此外,即使是對同一模型的相同提示,輸出句子的格式和詞語選擇也可能出現微小差異(例如,如前所述,如果兩個 tokens 具有相同的預測機率,則可能會隨機打破平局。這可能會影響後續預測的 tokens)。
  • 建議模板:
    • 優勢: 您將擁有完整的記錄,當您不可避免地需要重新審視您的提示工作時——無論是將來重新拾起,還是在不同版本的模型上測試提示性能,以及幫助調試未來的錯誤。
    • 額外追蹤字段:
      • 提示的版本(迭代)。
      • 捕獲結果是否為 OK/NOT OK/SOMETIMES OK 的字段。
      • 捕獲反饋的字段。
    • Retrieval Augmented Generation (RAG) 系統: 還應捕獲影響插入提示內容的 RAG 系統的特定方面,包括查詢 (query)、分塊設定 (chunk settings)、分塊輸出 (chunk output) 和其他信息。
  • 流程:
    1. 一旦您覺得提示接近完美,就將其帶到您的項目程式碼庫中。
    2. 在程式碼庫中,將提示保存在與程式碼分開的文件中,以便於維護。
    3. 理想情況下,您的提示是可操作化系統的一部分,作為 prompt engineer,您應該依賴自動化測試和評估程序來了解您的提示在任務上的泛化程度。
  • 迭代過程: Prompt engineering 是一個迭代過程。制定並測試不同的提示,分析並記錄結果。根據模型的性能改進您的提示。不斷實驗,直到達到期望的輸出。當您更改模型或模型配置時,返回並繼續使用先前使用過的提示進行實驗。
  • A template for documenting prompts
    • Name: [name and version of your prompt]
    • Goal: [One sentence explanation of the goal of this attempt]
    • Model: [name and version of the used model]
    • Temperature: [value between 0 - 1]
    • Token Limit: [number]
    • Top-K: [number]
    • Top-P: [number]
    • Prompt: [Write all the full prompt]
    • Output: [Write out the output or multiple outputs]