iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0

每天的專案會同步到 GitLab 上,可以前往 GitLab
查看,有興趣的朋友歡迎留言 or 來信討論,我的信箱是 nickchen1998@gmail.com

Day 10 的時候,我們介紹了如何使用 LangChain 的 PyMuPDFLoader 讀取
PDF 文件,並將其轉換成向量寫入 Pinecone 的資料庫當中,不過那時我們使用的方式,是直接將 PDFLoader 按照頁數讀取後的內文直接做計算然後儲存,
而這次我們要來介紹如何使用 Chunking Strategy 來提升檢索段落的成效,會實際來看要怎麼要切割段落。

什麼是 Chunking Strategy?

Chunking Strategy 是一種將文件內容切割成多個段落的策略,這樣做的好處是可以提升檢索的效率,因為當我們將文件內容切割成多個段落後,可以更精準地找到與查詢問題相關的段落,進而提升回答的準確度。

而 Chunking Strategy 可以分成兩大方向來討論,分別是「文章切割」以及「段落大小」來做討論,今天我們會針對文章切割的部分來做討論。

為什麼要使用 Chunking Strategy?

為什麼要使用 Chunking Strategy 呢?因為當文件內容過於龐大時,直接將整份文件作為檢索對象,會增加檢索的複雜度,並且可能導致檢索結果不夠精準。透過
Chunking Strategy,我們可以將文件內容切割成多個段落,讓檢索更加精準,提升回答的準確度。

以 OpenAI 提供的 GPT-4o 模型為例,他最大能接受 128,000 個 token 的輸入,如果參考的段落過長,可能會超過這個限制,而造成 API
請求失敗,即便可以把所有的段落都傳遞給模型,但是模型可能無法正確的理解太長的段落,越多的段落反而會越容易混淆模型,因此好的
Chunking Strategy 會大幅提升我們的檢索品質進而影響到回答的品質。

下面附上一些常見模型的最大 token 限制給大家參考:

模型名稱 最大 token 數
GPT-3.5 turbo 16,385
GPT-4o mini 128,000
GPT-4o 128,000
sonnet 200,000

Character Splitting

首先我們來介紹 Character Splitting,這是最簡單的方法,將文本以固定字元數分割,並且在相鄰的片段之間進行重疊。缺點是會忽略語句結構和語義。這種方法較少使用,因為容易導致上下文丟失。

讓我們快速看一下下面這段程式碼:

from env_settings import BASE_DIR
from langchain_community.document_loaders import PyMuPDFLoader
from langchain.text_splitter import CharacterTextSplitter

loader = PyMuPDFLoader(file_path=BASE_DIR / "勞動基準法.pdf")
first_page_content = loader.load()[0].page_content

spliter = CharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=5
)
documents = spliter.create_documents([first_page_content])
print(documents[0].page_content)

可以看到擷取出的片段結果,基本快要等同於原本直接將資料讀取近來第一頁的原始內文,而造成這樣的結果,是因為 Character Splitting 會忽略語句結構和語義,導致切割的結果並不是我們想要的,這樣的方式並不會提升檢索的效率,因此我們需要更進階的方法來切割段落。

Character Splitting

Recursive Splitting

這是比較理想的初學者方法,強調保持語句結構的完整性。會依照段落、換行符號和空格等層次來進行分割,確保相關資訊盡可能地保持在同一片段中。

讓我們快速看一下下面這段程式碼:

from env_settings import BASE_DIR
from langchain_community.document_loaders import PyMuPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

loader = PyMuPDFLoader(file_path=BASE_DIR / "勞動基準法.pdf")
first_page_content = loader.load()[0].page_content

spliter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=5
)
documents = spliter.create_documents([first_page_content])
print(documents[0].page_content)

讓我們看一下下面切割後的結果:

Recursive Splitting

可以看到 Recursive Splitting 的結果,已經比 Character Splitting 來得好很多,開始可以按照文本內容的區塊來進行切割,並且切割的同時保持著段落的完整性。

內容預告

實務上來說,最常用的方法是第二種 Recursive Splitting,因為這種方法可以保持語句結構的完整性,並且可以確保相關資訊盡可能地保持在同一片段中,這樣的方式可以提升檢索的效率,進而提升回答的準確度。明天我們會來看一篇論文,是有關讓語言模型替我們進行段落切割。


上一篇
Day 13 - DeepEval 評估測試套件介紹 - 文本召回率 & 文本關聯性
下一篇
Day 15 - Chunking Strategy - 使用 LLM 重構段落
系列文
初探 Langchain 與 LLM:打造簡易問診機器人30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言