LangChain 提供了便捷的 Few-Shot Prompt Templates 工具,讓開發者能以少量範例引導大語言模型 (LLM) 生成更精確的文字。透過 FewShotChatMessagePromptTemplate 和 FewShotPromptTemplate,我們可以輕鬆建構包含固定數量範例的提示範本。同時,LengthBasedExampleSelector 能根據輸入長度動態調整範例,提升模型的靈活性。

理解文字分割對於處理長篇內容至關重要。LangChain 提供了 CharacterTextSplitter、TokenTextSplitter 和 RecursiveCharacterTextSplitter 等工具,讓開發者能根據字元或詞彙數量,將長文字分割成適合 LLM 處理的區塊。此外,妥善處理特殊字元和格式,能確保分割結果的準確性,避免模型誤判。LangChain 的核心元件,包含檔案載入器、轉換器、嵌入模型、向量資料函式庫和檢索器,則提供更全面的資料處理流程,讓開發者能有效地載入、修改、儲存和檢索資料,進一步提升文字生成的效率和品質。任務分解的策略,能將複雜的文字生成任務拆解成更小的子任務,例如生成大綱、撰寫段落等,讓模型更容易處理,並產出更結構化的結果。

使用Few-Shot Prompt Templates進行文字生成

在使用大語言模型(LLM)進行文字生成時,Few-Shot Prompt Templates是一種強大的工具,可以幫助您最佳化模型的行為,從而產生更好的輸出。這種方法涉及在提示中提供幾個例子,以展示所需的任務效能。

固定長度的Few-Shot例子

首先,讓我們看看如何使用固定數量的例子建立Few-Shot Prompt Templates。這種方法的基礎是建立一個強大的Few-Shot例子集:

from langchain_openai.chat_models import ChatOpenAI
from langchain_core.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate

examples = [
    {"question": "法國的首都是什麼?", "answer": "巴黎"},
    {"question": "西班牙的首都是什麼?", "answer": "馬德里"},
    #...更多例子...
]

example_prompt = ChatPromptTemplate.from_messages(
    [
        ("human", "{question}"),
        ("ai", "{answer}"),
    ]
)

few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

print(few_shot_prompt.format())

這將輸出:

Human: 法國的首都是什麼?
AI: 巴黎
Human: 西班牙的首都是什麼?
AI: 馬德里
...更多例子...

使用LengthBasedExampleSelector選擇Few-Shot例子

現在,讓我們探索如何使用LengthBasedExampleSelector選擇Few-Shot例子。這種方法可以根據使用者輸入的長度來適應提示:

from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector
from langchain_openai.chat_models import ChatOpenAI
from langchain_core.messages import SystemMessage

import tiktoken

examples = [
    {"input": "戈勒姆", "output": "<戈勒姆的故事>"},
    {"input": "甘道夫", "output": "<甘道夫的故事>"},
    {"input": "比爾博", "output": "<比爾博的故事>"},
]

story_prompt = PromptTemplate(
    input_variables=["input", "output"],
    template="角色:{input}\n故事:{output}",
)

這些例子展示瞭如何使用Few-Shot Prompt Templates進行文字生成。透過提供固定數量的例子或使用LengthBasedExampleSelector選擇例子,您可以最佳化模型的行為,從而產生更好的輸出。

內容解密:

在上面的例子中,我們使用了FewShotChatMessagePromptTemplateFewShotPromptTemplate來建立Few-Shot Prompt Templates。這些類別提供了一種方便的方式來建立具有固定數量的例子的提示。同時,我們還使用了LengthBasedExampleSelector來選擇Few-Shot例子,根據使用者輸入的長度來適應提示。

圖表翻譯:

  flowchart TD
    A[使用者輸入] --> B[LengthBasedExampleSelector]
    B --> C[選擇Few-Shot例子]
    C --> D[建立Few-Shot Prompt Template]
    D --> E[輸出文字]

這個圖表展示瞭如何使用LengthBasedExampleSelector選擇Few-Shot例子,然後建立Few-Shot Prompt Template,最終輸出文字。

自動化文字生成的基礎:Few-Shot Prompt Templates

在自然語言處理(NLP)中,Few-Shot Prompt Templates是一種強大的工具,能夠幫助我們根據給定的示例生成高品質的文字。這種方法透過提供少量的示例來引導模型生成新的文字,從而實作了更好的控制和定製。

Few-Shot Prompt Templates的工作原理

Few-Shot Prompt Templates的核心思想是定義一個範本,該範本包含了一個或多個變數,然後使用這些變數來生成新的文字。例如,我們可以定義一個範本,該範本包含一個character變數,然後使用這個變數來生成一個故事。

dynamic_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=story_prompt,
    prefix='''Generate a story for {character} using the
    current Character/Story pairs from all of the characters
    as context.''',
    suffix="Character: {character}\nStory:",
    input_variables=["character"],
)

在這個例子中,dynamic_prompt是一個Few-Shot Prompt Template的例項,該例項包含了一個prefix、一個suffix和一個input_variables列表。prefixsuffix分別定義了生成文字的開頭和結尾,而input_variables列表包含了需要被替換的變數。

自動化文字生成的應用

Few-Shot Prompt Templates可以被用於各種自動化文字生成的任務,例如:

  • 根據給定的示例生成新的故事
  • 根據給定的產品描述生成新的產品介紹
  • 根據給定的使用者評價生成新的評價

實作Few-Shot Prompt Templates

要實作Few-Shot Prompt Templates,我們需要定義一個範本,然後使用這個範本來生成新的文字。以下是實作Few-Shot Prompt Templates的一個簡單示例:

def num_tokens_from_string(string: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.get_encoding("cl100k_base")
    num_tokens = len(encoding.encode(string))
    return num_tokens

example_selector = LengthBasedExampleSelector(
    examples=examples,
    example_prompt=story_prompt,
    max_length=1000, 
    get_text_length=num_tokens_from_string,
)

dynamic_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=story_prompt,
    prefix='''Generate a story for {character} using the
    current Character/Story pairs from all of the characters
    as context.''',
    suffix="Character: {character}\nStory:",
    input_variables=["character"],
)

formatted_prompt = dynamic_prompt.format(character="Frodo")

chat = ChatOpenAI()
response = chat.invoke([SystemMessage(content=formatted_prompt)])

在這個示例中,我們定義了一個FewShotPromptTemplate的例項,然後使用這個例項來生成一個新的故事。formatted_prompt是生成的提示,該提示包含了需要被替換的變數。最後,我們使用這個提示來生成新的文字。

文字生成的高階技巧

文字生成是自然語言處理的一個重要領域,LangChain是一個強大的工具,能夠幫助開發者建立高品質的文字生成模型。在本章中,我們將探討如何使用LangChain建立高階文字生成模型。

幾何學習的限制

幾何學習是一種強大的技術,但它也有一些限制。首先,預訓練模型可能會過度適應幾何學習的例子,這可能會導致模型過度優先考慮例子而不是實際的提示。其次,LLM有令牌限制,這意味著在提供的例子數量和回應長度之間存在權衡。

儲存和載入LLM提示

LangChain支援將提示儲存為JSON和YAML檔案。這使得提示的分享、儲存和版本控制更加容易。使用PromptTemplateload_prompt函式,可以輕鬆地儲存和載入提示。

資料連線

LangChain提供了一種連線資料的方法,可以利用LLM應用程式和資料來提高效率和最佳化決策過程。資料可以以多種形式存在,包括非結構化資料和結構化資料。非結構化資料需要進行載入、轉換、嵌入和儲存,而結構化資料可以使用LangChain代理進行中間查詢。

LangChain的元件

LangChain提供了多種元件,包括檔案載入器、檔案轉換器、文字嵌入模型、向量資料函式庫和檢索器。這些元件可以幫助開發者載入、修改、儲存和檢索資料。

圖表翻譯:

此圖表展示瞭如何使用LangChain建立高階文字生成模型的流程。首先,文字生成是自然語言處理的一個重要領域。然後,幾何學習是一種強大的技術,但它也有一些限制。接下來,儲存和載入LLM提示是非常重要的,因為它可以幫助開發者分享、儲存和版本控制提示。然後,資料連線是另一種重要的技術,可以利用LLM應用程式和資料來提高效率和最佳化決策過程。最後,LangChain的元件可以幫助開發者載入、修改、儲存和檢索資料。透過使用LangChain,開發者可以建立高品質的文字生成模型。

資料載入器

讓我們想象一下,你被委託負責建立一個大語言模型(LLM)資料收集管道,為 NutriFusion Foods 這間公司服務。所需的資料包含在以下幾個檔案中:

  • 一份名為「行銷原理」(Principles of Marketing)的 PDF 書籍
  • 兩份以.docx 格式儲存的行銷報告,存放在公共的 Google Cloud Storage 儲存桶中
  • 三份.csv 檔案,展示 2021 年、2022 年和 2023 年的行銷績效資料

首先,建立一個新的 Jupyter Notebook 或 Python 檔案,存放在分享儲存函式庫中的 content/chapter_4 目錄下。接著,執行 pip install pdf2image docx2txt pypdf 指令,以安裝必要的套件。

除了.docx 檔案外,所有其他資料都可以在 content/chapter_4/data 目錄中找到。現在,讓我們開始使用 Python 來載入這些資料。

from langchain_community.document_loaders import Docx2txtLoader
from langchain_community.document_loaders import PyPDFLoader
from langchain_community.document_loaders.csv_loader import CSVLoader
import glob
from langchain.text_splitter import CharacterTextSplitter

# 宣告一個列表來儲存所有載入的檔案
all_documents = []

# 載入 PDF 檔案
loader = PyPDFLoader("data/principles_of_marketing_book.pdf")
pages = loader.load_and_split()
print(pages[0])

# 為每個頁面新增額外的中繼資料
for page in pages:
    page.metadata["description"] = "行銷原理書籍"

# 驗證中繼資料是否已新增
for page in pages[0:2]:
    print(page.metadata)

# 將行銷書籍頁面新增到 all_documents 列表中
all_documents.extend(pages)

# 找到所有.csv 檔案
csv_files = glob.glob("data/*.csv")

# 篩選只包含 "Marketing" 字串的檔案名稱
csv_files = [f for f in csv_files if "Marketing" in f]

# 載入每個.csv 檔案
for csv_file in csv_files:
    #... (待續)

內容解密:

上述程式碼片段示範瞭如何使用 PyPDFLoader 來載入 PDF 檔案,並將其分割成個別頁面。同時,也展示瞭如何為每個頁面新增中繼資料,例如描述。接著,程式碼會將載入的頁面新增到 all_documents 列表中,以便後續處理。最後,程式碼會找到所有.csv 檔案,並篩選出包含 “Marketing” 字串的檔案名稱,以便進行後續的資料載入和處理。

圖表翻譯:

  flowchart TD
    A[載入 PDF] --> B[分割成頁面]
    B --> C[新增中繼資料]
    C --> D[儲存頁面]
    D --> E[找到.csv 檔案]
    E --> F[篩選檔案]
    F --> G[載入.csv 檔案]

此圖表展示了程式碼的執行流程,從載入 PDF 檔案開始,到找到和篩選.csv 檔案為止。每個步驟都對應到程式碼中的特定部分,清楚地展示了資料載入和處理的過程。

檔案載入和分割技術

檔案載入和分割是自然語言處理中的一個重要步驟,尤其是在使用大語言模型(LLM)時。LangChain是一個強大的工具,提供了多種檔案載入和分割方法,以適應不同的需求。

檔案載入

LangChain提供了多種檔案載入方法,包括:

  • CSVLoader:用於載入CSV檔案。
  • Docx2txtLoader:用於載入DOCX檔案。
  • PyPDFLoader:用於載入PDF檔案。

這些載入器可以用於載入不同格式的檔案,並將其轉換為LangChain檔案物件。

檔案分割

檔案分割是指將大型檔案分割為小塊,以適應LLM的上下文視窗。LangChain提供了多種檔案分割方法,包括:

  • CharacterTextSplitter:根據字元數量分割檔案。
  • TokenTextSplitter:根據令牌數量分割檔案。
  • RecursiveCharacterTextSplitter:遞迴地根據字元數量分割檔案。

這些分割器可以用於分割不同格式的檔案,並將其轉換為LangChain檔案物件。

檔案分割的挑戰

檔案分割可能會遇到一些挑戰,例如:

  • 特殊字元:特殊字元,如#、@符號或連結,可能會影響檔案分割的結果。
  • 格式:檔案中的格式,如表格、列表或多級標題,可能會影響檔案分割的結果。

解決方案

為瞭解決這些挑戰,LangChain提供了多種工具和方法,包括:

  • tiktoken:一個用於計算令牌數量的工具。
  • langchain-text-splitters:一個提供多種檔案分割方法的函式庫。

範例

以下是一個使用CharacterTextSplitter分割檔案的範例:

from langchain_text_splitters import CharacterTextSplitter

# 建立一個CharacterTextSplitter
splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=50, chunk_overlap=0)

# 載入一個檔案
text = "這是一個示範檔案。"

# 分割檔案
chunks = splitter.split_text(text)

# 列印分割結果
print(chunks)

這個範例展示瞭如何使用CharacterTextSplitter分割一個檔案,並列印出分割結果。

文字分割技術

文字分割是一種將大塊文字分解成小塊、可管理的文字片段的技術。這種技術在自然語言處理和文字分析中非常重要,因為它可以幫助我們更好地理解和處理大塊文字。

文字分割的方法

有多種文字分割的方法,包括:

  • 根據字元的分割:這種方法是根據字元(如空格、換行符等)來分割文字。
  • 根據詞彙的分割:這種方法是根據詞彙(如單詞、短語等)來分割文字。
  • 根據句子的分割:這種方法是根據句子來分割文字。

RecursiveCharacterTextSplitter

RecursiveCharacterTextSplitter是一種根據字元的分割方法,它可以根據一組字元來分割文字。這種方法可以保留文字的語義內容,並且可以根據需要調整分割的粒度。

使用RecursiveCharacterTextSplitter

使用RecursiveCharacterTextSplitter需要先初始化一個分割器物件,然後設定分割的引數,例如分割的大小(chunk_size)和重疊的大小(chunk_overlap)。最後,可以使用.split_text()方法來分割文字。

from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20,
    length_function=len,
)

texts = text_splitter.split_text(text)

TokenTextSplitter

TokenTextSplitter是一種根據詞彙的分割方法,它可以根據詞彙來分割文字。這種方法可以保留文字的語義內容,並且可以根據需要調整分割的粒度。

使用TokenTextSplitter

使用TokenTextSplitter需要先初始化一個分割器物件,然後設定分割的引數,例如分割的大小(chunk_size)和重疊的大小(chunk_overlap)。最後,可以使用.split_text()方法來分割文字。

from langchain.text_splitter import TokenTextSplitter

text_splitter = TokenTextSplitter(chunk_size=500, chunk_overlap=50)
loader = PyPDFLoader("data/principles_of_marketing_book.pdf")
pages = loader.load_and_split(text_splitter=text_splitter)

CharacterTextSplitter

CharacterTextSplitter是一種根據字元的分割方法,它可以根據字元來分割文字。這種方法可以保留文字的語義內容,並且可以根據需要調整分割的粒度。

使用CharacterTextSplitter

使用CharacterTextSplitter需要先初始化一個分割器物件,然後設定分割的引數,例如分割的大小(chunk_size)和重疊的大小(chunk_overlap)。最後,可以使用.split_text()方法來分割文字。

text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=50, chunk_overlap=0, separator="\n",
)

texts = text_splitter.split_text(text)

圖表翻譯:

  flowchart TD
    A[文字] --> B[分割器]
    B --> C[分割引數]
    C --> D[分割結果]
    D --> E[輸出]

內容解密:

以上程式碼展示瞭如何使用不同的文字分割方法來分割文字。每種方法都有其優缺點,需要根據具體需求選擇合適的方法。

文字分割和任務分解的應用

在自然語言處理中,文字分割是一種重要的技術,能夠將長文字分割成更小的、可管理的塊,以便於後續的處理和分析。同時,任務分解是一種戰略性的過程,能夠將複雜的問題分解成一系列可管理的子問題,以便於解決。

文字分割的實作

文字分割可以透過多種方法實作,例如根據字元的分割、根據詞彙的分割等。在 LangChain 中,提供了多種文字分割器,例如 RecursiveCharacterTextSplitter,可以根據字元數量將文字分割成更小的塊。

text_splitter = RecursiveCharacterTextSplitter(chunk_size=300)
texts = text_splitter.split_text(text)

任務分解的應用

任務分解是一種重要的技術,能夠將複雜的問題分解成一系列可管理的子問題,以便於解決。在自然語言處理中,任務分解可以應用於多種場景,例如:

  • 複雜問題解決:將複雜的問題分解成一系列可管理的子問題,以便於解決。
  • 內容生成:將內容生成任務分解成多個子任務,例如生成大綱、撰寫個別章節等。
  • 檔案摘要:將檔案摘要任務分解成多個子任務,例如理解個別章節、生成摘要等。
  flowchart TD
    A[任務分解] --> B[複雜問題解決]
    A --> C[內容生成]
    A --> D[檔案摘要]
    B --> E[子問題1]
    B --> F[子問題2]
    C --> G[生成大綱]
    C --> H[撰寫個別章節]
    D --> I[理解個別章節]
    D --> J[生成摘要]

圖表翻譯:

上述流程圖展示了任務分解的過程。首先,將任務分解成多個子任務,然後對每個子任務進行處理。例如,在複雜問題解決中,將問題分解成多個子問題,以便於解決。在內容生成中,將內容生成任務分解成生成大綱、撰寫個別章節等子任務。在檔案摘要中,將檔案摘要任務分解成理解個別章節、生成摘要等子任務。

從技術架構視角來看,Few-Shot Prompt Templates 作為一種最佳化大語言模型(LLM)文字生成能力的技術,其核心價值在於引導模型理解任務需求並產生更符合預期的輸出。透過提供少量示例,Few-Shot Learning 能夠有效降低 LLM 生成 irrelevant 或 nonsensical 內容的風險,並提升生成文字的準確性和相關性。分析段落中提供的程式碼示例,清晰地展示瞭如何利用 LangChain 構建 Few-Shot Prompt Templates,並結合 LengthBasedExampleSelector 根據輸入長度動態調整提示內容,從而提升模型的適應性。然而,Few-Shot Learning 的有效性高度依賴於示例的品質和數量,選擇不當的示例反而可能誤導模型。此外,LLM 的 token 限制也制約了示例的數量和生成的文字長度。展望未來,隨著 LLM 技術的持續發展,預計 Few-Shot Learning 的效率將進一步提升,並與其他技術如 meta-learning 和 transfer learning 融合,以更有效地利用少量資料提升 LLM 的泛化能力。對於開發者而言,深入理解 Few-Shot Learning 的原理和侷限性,並結合 LangChain 等工具,將是構建高效能文字生成應用的關鍵。玄貓認為,Few-Shot Prompt Templates 已成為 LLM 應用的重要組成部分,值得技術團隊深入研究並應用於實際專案中。