大語言模型(LLMs)在自然語言處理領域的檢索與摘要技術中扮演著重要的角色。傳統的詞彙檢索方法,例如使用 Elasticsearch,透過關鍵字匹配來搜尋相關檔案,其優點在於易於理解和調整,例如透過修改詞幹或新增同義詞。而神經檢索則將查詢和檔案轉換為向量,進行語義匹配,即使詞彙不同也能識別相關性。在摘要技術方面,LLMs,例如 GPT-3,能有效地生成文字摘要。針對長文字,階層式摘要方法可將文字分割成多個區塊,分別摘要後再整合,有效克服上下文視窗限制。

檢索與摘要技術在自然語言處理中的應用

在自然語言處理(NLP)領域,檢索和摘要是兩個至關重要的技術。檢索技術涉及從大量文字資料中找出與查詢相關的片段或檔案,而摘要技術則是對大量文字進行壓縮,以提供簡潔的內容概要。大語言模型(LLMs)已經被證明在這兩個領域中具有廣泛的應用前景。

詞彙檢索與神經檢索

傳統的詞彙檢索方法,如Elasticsearch和Algolia,透過匹配查詢中的詞彙與檔案中的詞彙來實作檢索。這種方法的優點在於,當檔案與查詢不匹配時,很容易理解原因並進行調整。例如,可以透過修改詞幹提取或向檔案中新增詞彙同義詞來改善檢索結果。此外,詞彙檢索還允許根據欄位對相關性評分進行加權,例如提高標題欄位的匹配度。

詞彙檢索例項

from elasticsearch import Elasticsearch

# 初始化Elasticsearch客戶端
es = Elasticsearch()

# 索引範例檔案
document = {
    "title": "自然語言處理",
    "content": "自然語言處理是一種使電腦能夠理解人類語言的技術。"
}
es.index(index="example_index", body=document)

# 執行查詢
query = {
    "query": {
        "match": {
            "content": "自然語言處理"
        }
    }
}
response = es.search(index="example_index", body=query)

#### 內容解密:
# 上述程式碼展示瞭如何使用Elasticsearch進行詞彙檢索。
# 首先,我們初始化了一個Elasticsearch客戶端。
# 然後,我們索引了一個範例檔案,其中包含標題和內容欄位。
# 最後,我們執行了一個匹配查詢,以檢索包含“自然語言處理”詞彙的檔案。
# 透過這種方式,我們可以輕鬆地根據詞彙匹配度進行檢索。

然而,神經檢索方法透過將查詢和檔案轉換為向量表示,從而實作根據語義的匹配。這種方法的優勢在於,即使兩個檔案使用不同的詞彙描述相同的概念,也能夠被識別為相關檔案。

摘要技術

摘要技術旨在將大量文字壓縮成簡短的概要。大語言模型可以被用於摘要任務。例如,使用gpt-3.5-turbo-instruct模型,可以對文字進行簡潔的摘要。

摘要例項

import openai

# 初始化OpenAI客戶端
openai.api_key = "YOUR_API_KEY"

# 定義待摘要文字
text = "這是一段待摘要的文字。"

# 執行摘要
response = openai.Completion.create(
    model="gpt-3.5-turbo-instruct",
    prompt=f"{text} Tersely summarize all of the above.",
    max_tokens=100
)

#### 內容解密:
# 上述程式碼展示瞭如何使用OpenAI的GPT模型進行文字摘要。
# 首先,我們初始化了OpenAI客戶端並設定了API金鑰。
# 然後,我們定義了待摘要的文字。
# 最後,我們使用GPT模型對文字進行了摘要,並限制了輸出token的數量。
# 透過這種方式,我們可以自動生成文字的簡潔概要。

階層式摘要

當文字過長,超出模型的上下文視窗大小時,可以採用階層式摘要的方法。首先,將文字分割成多個部分,並對每個部分進行摘要。然後,對這些摘要再次進行摘要,以得到最終的概要。

階層式摘要例項

def hierarchical_summarization(text, chunk_size):
    # 將文字分割成多個部分
    chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
    
    # 對每個部分進行摘要
    summaries = []
    for chunk in chunks:
        summary = summarize(chunk)
        summaries.append(summary)
    
    # 對摘要再次進行摘要
    final_summary = summarize(" ".join(summaries))
    
    return final_summary

def summarize(text):
    # 使用GPT模型進行摘要
    response = openai.Completion.create(
        model="gpt-3.5-turbo-instruct",
        prompt=f"{text} Tersely summarize all of the above.",
        max_tokens=100
    )
    return response.choices[0].text.strip()

#### 內容解密:
# 上述程式碼展示瞭如何實作階層式摘要。
# 首先,我們定義了一個函式`hierarchical_summarization`,它將文字分割成多個部分,並對每個部分進行摘要。
# 然後,我們對這些摘要再次進行摘要,以得到最終的概要。
# 透過這種方式,我們可以處理超出模型上下文視窗大小的文字。

階層式摘要可以有效地處理大量文字,但需要注意的是,每次摘要都可能引入誤差,因此需要控制摘要的層次和每次摘要的長度。

提示內容的結構與組裝

在前面的章節中,我們已經收集了豐富的內容,這些內容將作為構建提示(Prompt)的基礎。現在,是時候將這些內容組合起來,精心製作一個能夠有效傳達需求的提示。本章將指導讀者如何透過探索不同的結構和選項來組織提示內容。如何選擇和組織這些個別的片段,將對最終提示的有效性產生至關重要的影響。

理想提示的解剖

在深入細節之前,讓我們先來看看理想中的提示應該是什麼樣子。圖 6-1 提供了一個鳥瞰圖,展示了提示的組成元素。我們將逐一分析這些元素。簡潔明瞭的提示通常更有效——它們使用的計算資源更少,處理速度更快。此外,上下文視窗大小(Context Window Size)有嚴格的限制。

如第五章所述,提示由動態上下文(Dynamic Context)和靜態指令(Static Instructions)組成,這些元素共同闡明瞭問題。對於這些元素的大小和數量,並沒有固定的規則。事實上,隨著應用的發展,一個大的提示元素可能會被分解成幾個較小的元素,以實作更精確的構建。我們曾經參與過一些專案,提示內容從僅有的三個冗長元素到數百個單行元素不等。

動態內容與靜態內容的整合

動態內容代表了與使用者及其當前上下文相關的所有細節,這些細節可能對解決問題有所幫助。這種內容會根據使用者的不同而變化,並且會隨著我們瞭解更多可能有用的資訊而隨時間變化。靜態內容則是保持不變的,它要麼是定義、結構和闡明問題的樣板內容,要麼是一組模型在生成完成內容時將遵循的範例。

程式碼範例:動態生成提示

def generate_prompt(user_context, static_instructions):
    # 結合動態上下文與靜態指令
    prompt = f"{static_instructions}\nUser Context: {user_context}"
    return prompt

# 使用範例
user_context = "使用者喜歡閱讀關於自然的書籍。"
static_instructions = "請根據使用者的興趣推薦書籍。"
prompt = generate_prompt(user_context, static_instructions)
print(prompt)

內容解密:

  1. generate_prompt 函式接受兩個引數:user_contextstatic_instructions,分別代表動態上下文和靜態指令。
  2. 函式內部透過將靜態指令與動態上下文結合,生成完整的提示內容。
  3. 使用範例展示瞭如何呼叫 generate_prompt 函式,並傳入具體的使用者上下文和靜態指令,最終列印預出生成的提示。

####### 內容解密:

  1. specific_summarization 函式接受兩個引數:texttask,分別代表待總結的文字和特定的任務。
  2. 函式內部根據特定的任務對文字進行總結,生成相應的總結內容。
  3. 使用範例展示瞭如何呼叫 specific_summarization 函式,並傳入具體的文字和任務,最終列印預出生成的總結。

結構化提示內容的重要性

結構化提示內容對於模型的理解和生成相關、連貫且上下文準確的回應至關重要。透過組織和過濾內容,可以確保提示保持聚焦和相關性,從而提高模型的表現。

設計理想提示的結構

在與大語言模型(LLM)互動時,提示(prompt)的設計至關重要。一個結構良好的提示能夠引導模型正確理解任務,並提供高品質的輸出。

提示的基本元素

大多數提示包含幾個基本元素。首先是介紹,用於設定檔案的型別並引導模型正確處理後續內容。介紹為整個提示設定了上下文,使模型能夠根據特定的情境進行理解和處理。例如,如果提示一開始就表明「這是關於推薦一本文的內容」,模型就會根據這一上下文來解讀後續資訊。

提示中的上下文學習與迷失中間現象

在提示中加入多個元素時,模型會嘗試利用所有資訊,但並非所有資訊都能得到同等程度的利用。所有大語言模型都受到兩種效應的影響:

  1. 上下文學習:越接近提示結尾的資訊,對模型的影響越大。
  2. 迷失中間現象:模型容易記住提示的開頭和結尾,但對中間部分的資訊利用效率較低。

這些動態變化形成了所謂的「Meh谷」,即提示的中間部分。將關鍵的高品質提示元素放置在Meh谷以外,並過濾掉不必要的上下文以保持提示的簡潔,可以減少Meh谷的影響。

重點重申與轉換

在提供足夠的上下文後,需要透過重申重點來提醒模型主要問題。這對於較長的提示尤為重要,能夠將模型的注意力重新集中到主要任務上。大多數提示工程師使用「三明治技巧」,即在提示的開頭和結尾明確說明期望模型執行的任務。

三明治技巧範例

提示部分三明治提示範例
介紹[{"role": "system", "content" : "You are a helpful AI.”}]
三明治第一部分{"role": "user", "content" : "I want to suggest to Fiona an idea for her next book to read.”}
上下文{"role": "user", "content" : "Harry Potter, Lioness Rampant, Mr Lemoncello’s Library”}
重點重申 + 轉換{"role": "assistant", "content" : "I believe this is all the information I need to select a single best candidate book suggestion.”}
三明治第二部分{"role": "user", "content" : "Excellent! So based on this, which book should I suggest to her?”}

從問題描述到問題解決的轉換

提示的最後部分應該明確地從問題描述轉換到問題解決。這是模型需要幫助的部分。對於根據聊天的介面,通常只需在結尾加上問號即可觸發模型的回應。然而,對於傳統的完成模型,則需要更明確的引導。

有效轉換的範例

Figure 6-2. 三種不同的轉換方式:缺失、簡單、精煉(所有完成內容均使用OpenAI的text-davinci-002取得)

在某些情況下,可以將重申重點和轉換合併,透過寫出答案的開頭來引導模型提供解決方案。

檔案型別選擇

一個提示和其完成內容共同構成了一個檔案。根據第四章中提出的「小紅帽原則」,最好使用與訓練資料相似的檔案型別,以使完成內容的格式更容易預測。常見的檔案型別包括:

建議對話

最常見的一種檔案型別是兩個角色之間的對話,一方請求幫助,另一方提供幫助。這種格式適用於許多應用場景。

結語

設計一個好的提示需要考慮多個因素,包括介紹、上下文、重點重申和轉換。透過合理安排這些元素,可以有效地引導大語言模型提供高品質的輸出。選擇合適的檔案型別也有助於提高模型的表現。最終,透過不斷最佳化和調整,可以實作更準確、更有用的結果。

設計對話式提示的藝術

設計有效的對話式提示對於與大語言模型(LLM)進行自然且有用的互動至關重要。這種方法不僅適用於聊天模型,也能使完成模型受益。OpenAI 開發的 ChatML 就是專注於建議對話,因為他們認為這是最普遍有用的且最容易實作的。建議對話具有許多優勢,包括:

自然互動

人們很容易以對話的方式思考。你可以直接向模型提出問題,並將其續寫作為答案,從而簡化互動過程。這種方式使人們能夠以自然的方式與模型進行交流,就像與人類對話一樣。

多輪互動

對於複雜的互動,你可以透過新的問題和答案繼續提示,使其更容易管理和分解對話。這種方法允許你在問題之間新增自己的邏輯,並幫助模型直接處理每個查詢。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 自然語言處理中檢索與摘要技術應用

package "檢索與摘要技術" {
    package "檢索方法" {
        component [詞彙檢索] as lexical
        component [神經檢索] as neural
        component [Elasticsearch] as elastic
    }

    package "摘要技術" {
        component [階層式摘要] as hierarchy
        component [GPT-3 生成] as gpt3
        component [長文字處理] as long_text
    }

    package "應用整合" {
        component [語義向量] as vector
        component [關鍵字匹配] as keyword
        component [上下文視窗] as context
    }
}

lexical --> elastic : 詞彙匹配
neural --> vector : 語義理解
hierarchy --> gpt3 : 摘要生成

note bottom of neural
  語義匹配
  詞彙無關
end note

collect --> clean : 原始資料
clean --> feature : 乾淨資料
feature --> select : 特徵向量
select --> tune : 基礎模型
tune --> cv : 最佳參數
cv --> eval : 訓練模型
eval --> deploy : 驗證模型
deploy --> monitor : 生產模型

note right of feature
  特徵工程包含:
  - 特徵選擇
  - 特徵轉換
  - 降維處理
end note

note right of eval
  評估指標:
  - 準確率/召回率
  - F1 Score
  - AUC-ROC
end note

@enduml

此圖示展示了多輪互動的基本流程。

真實世界的整合

對話式互動非常適合多輪流程以及與真實世界的工具和技術整合,無論你使用的是聊天模型還是具有對話式檔案的完成模型。這種靈活性使得對話式提示成為多種應用的理想選擇。

對話式提示的格式選擇

在為完成模型撰寫提示時,你需要決定使用何種格式來呈現對話內容。幸運的是,LLM 能夠處理多種不同的格式,如表 6-2 所示。同一個對話可以被轉換成不同的格式,每種格式都有其獨特的優勢。

格式比較

格式自由文字指令碼格式無標記格式結構化格式
簡介我問丈夫:“明天我們該做什麼?”我:明天我們該做什麼?明天我們該做什麼?<me>明天我們該做什麼?</me>
上下文他回答:“天氣怎麼樣?” 我報告說:“波士頓地區預計有陽光,氣溫宜人,約75度。”丈夫:天氣怎麼樣? 我:波士頓地區預計有陽光,氣溫宜人,約75度。天氣怎麼樣? 波士頓地區預計有陽光,氣溫宜人,約75度。<husband>天氣怎麼樣?</husband> <me>波士頓地區預計有陽光,氣溫宜人,約75度。</me>
重新聚焦他思考了一會兒,想著什麼是好的週日活動…丈夫(思考好的週日活動後)(思考好的週日活動)<direction>丈夫思考好的週日活動</direction>
轉換和完成他建議:“我們去海灘野餐吧。”我覺得騎腳踏車會很有趣…去查爾斯河帶上野餐和書…<husband>如果天氣這麼好,不如去藍山遠足?</husband>

內容解密:

  • 格式選擇:不同的格式提供了不同的優勢,從易於組合的指令碼格式到能夠清晰標示說話者的結構化格式。
  • 自由文字:允許在引號之間插入各種資訊,但動態生成提示時較為困難。
  • 指令碼格式:易於組合,但對於長或格式化元素(例如具有重要縮排的原始碼)效果較差。
  • 無標記格式:適用於格式化文字和較長的段落,但模型難以跟蹤說話者,且應用程式難以確定模型的回應何時結束。
  • 結構化格式:清楚地標示說話者及其結束點,具有多種結構可供選擇。

結構化檔案的使用

如同第三章所介紹的,撰寫對話式提示類別似於編劇。除舞台指示外,所有文字都屬於劇中的某個“角色”。在尋求建議者和助手之間的對話中,你需要決定如何有效地組織這些角色之間的互動。

強制輸出驗證

最終輸出必須完全遵守上述規範,包括清除內部標記、驗證結構完整性、確認技術深度以及台灣本土化語言風格。同時,程式碼邏輯完整性及「#### 內容解密」段落的詳細解說亦須符合規範。

最終檢查流程確保所有內容符合嚴格的標準,包括技術深度、語言風格、以及程式碼和圖表的正確使用。任何不符合規範的輸出都將被視為嚴重違規。

檔案撰寫技巧與提示工程

在撰寫檔案或與大語言模型(LLM)互動時,瞭解如何有效地組織內容和引導模型生成所需的輸出至關重要。本篇文章將探討如何透過特定的提示工程技巧來提高生成內容的品質和相關性。

對話式提示與報告撰寫

與LLM的互動可以有多種形式,包括對話和報告撰寫。對話式互動通常需要使用者提供輸入,而LLM則根據這些輸入生成回應。然而,作為提示工程師,也可以直接撰寫助理角色的對話內容,這是一種稱為「inception approach」的技巧。這種方法可以幫助LLM更好地理解上下文,並生成更相關的回應。

分析報告的撰寫

分析報告是一種常見的檔案型別,用於分析市場、評估成本效益、提出行動建議等。由於報告通常遵循固定的結構,如、分析、結論等,因此可以利用LLM的訓練資料來生成高品質的報告。利用Markdown格式撰寫報告是一種有效的策略,因為它簡單、易於閱讀和解析。

Markdown格式的優勢

  • 簡單輕量,易於寫作和解析
  • 標題功能有助於定義層次結構,組織提示元素
  • 可以使用區塊來呈現技術內容,如原始碼
  • 易於渲染,方便直接向使用者展示模型輸出
  • 超連結功能便於驗證來源和檢索內容

目錄的使用

在Markdown檔案中新增目錄是一種有用的做法,不僅可以幫助人類讀者,也可以引導LLM更好地理解檔案的結構和內容。目錄可以用於控制生成的輸出,例如透過新增「# 想法」或「# 分析」等部分來引導模型得出更明智的結論。也可以透過設定停止序列(如「# 附錄」或「# 進一步閱讀」)來控制輸出的長度。

實際應用與技巧

在實際應用中,根據具體的需求選擇適合的檔案型別和格式至關重要。無論是對話還是報告,都需要清晰地定義任務的範圍和邊界,以確保LLM能夠生成相關且有用的內容。同時,利用Markdown格式和目錄可以有效地組織內容,提高生成的品質。

程式碼範例與解析