RAG(六)大語言模型應(yīng)用中的分塊策略詳解
1、分塊在不同應(yīng)用場景的作用
語義搜索
在語義搜索中,索引一組文檔,每個(gè)文檔包含特定主題的有價(jià)值信息。通過應(yīng)用有效的分塊策略,可以確保搜索結(jié)果準(zhǔn)確捕捉用戶查詢的核心。分塊的大小和方式直接影響搜索結(jié)果的準(zhǔn)確性和相關(guān)性:
- 分塊過小:可能會丟失上下文信息,導(dǎo)致搜索結(jié)果無法準(zhǔn)確理解用戶查詢的意圖。
- 分塊過大:可能會引入過多無關(guān)信息,稀釋關(guān)鍵內(nèi)容的重要性,降低搜索結(jié)果的精確度。
一般來說,如果一段文本在沒有上下文的情況下對人類有意義,那么它對語言模型也是有意義的。因此,找到文檔庫中的最佳分塊大小至關(guān)重要。
對話代理
在對話代理中,使用嵌入的分塊來構(gòu)建對話代理的上下文,基于一個(gè)知識庫,使代理能夠基于可信信息進(jìn)行對話。選擇合適的分塊策略非常重要,原因有二:
- 上下文的相關(guān)性:合適的分塊策略可以確保上下文與提示真正相關(guān),從而提高對話的質(zhì)量和準(zhǔn)確性。
- token數(shù)量限制:在將檢索到的文本發(fā)送給外部模型提供商(如OpenAI)之前,需要考慮每次請求可以發(fā)送的token數(shù)量的限制。例如,使用具有32k上下文窗口的GPT-4時(shí),分塊大小可能不是問題,但當(dāng)使用較小上下文窗口的模型時(shí),過大的分塊可能會超出限制,導(dǎo)致無法有效利用檢索到的信息。 此外,使用非常大的分塊可能會會引入過多噪聲,降低檢索結(jié)果的質(zhì)量,進(jìn)而對結(jié)果的相關(guān)性產(chǎn)生不利影響。
2、分塊的嵌入行為分析
嵌入短內(nèi)容(如句子)
當(dāng)一個(gè)句子被嵌入時(shí),生成的向量主要聚焦于該句子的具體含義。這是因?yàn)榫渥蛹墑e的嵌入模型通常會將注意力集中在句子內(nèi)部的詞匯和語法結(jié)構(gòu)上,以提取其核心語義。例如,句子“蘋果是一種水果”會被嵌入成一個(gè)向量,該向量主要表示“蘋果”和“水果”之間的關(guān)系,以及“蘋果”這一具體概念的特征。
優(yōu)點(diǎn)
- 精確匹配:句子級別的嵌入能夠精確捕捉句子的具體含義,因此在與其他句子嵌入進(jìn)行比較時(shí),可以更準(zhǔn)確地識別出語義上的相似性或差異性。
- 適合細(xì)節(jié)查詢:對于較短的查詢,如單個(gè)句子或短語,句子級別的嵌入更容易找到與之匹配的內(nèi)容。例如,當(dāng)用戶查詢“蘋果的營養(yǎng)價(jià)值”時(shí),句子級別的嵌入可以快速定位到包含“蘋果”和“營養(yǎng)”相關(guān)詞匯的句子。
缺點(diǎn)
- 缺乏上下文信息:句子級別的嵌入可能會錯過段落或文檔中的更廣泛上下文信息。例如,一個(gè)句子可能在孤立狀態(tài)下意義明確,但在整個(gè)段落或文檔中,它的含義可能會受到前后文的影響。
- 難以捕捉主題:句子級別的嵌入難以捕捉到文本的更廣泛主題和整體結(jié)構(gòu)。例如,在一個(gè)關(guān)于“健康飲食”的文檔中,單獨(dú)嵌入的句子可能無法體現(xiàn)出整個(gè)文檔的核心主題。
嵌入長內(nèi)容(如段落或整個(gè)文檔)
當(dāng)嵌入整個(gè)段落或文檔時(shí),嵌入過程會考慮整體上下文以及文本中句子和短語之間的關(guān)系。這會生成一個(gè)更全面的向量表示,捕捉到文本的更廣泛含義和主題。例如,一個(gè)段落可能包含多個(gè)句子,這些句子共同表達(dá)了一個(gè)主題或觀點(diǎn),嵌入過程會將這些信息整合到一個(gè)向量中。
優(yōu)點(diǎn)
- 捕捉主題和上下文:長內(nèi)容的嵌入能夠捕捉到文本的整體主題和上下文信息。例如,在一個(gè)關(guān)于“氣候變化”的文檔中,嵌入向量可以反映出整個(gè)文檔的核心觀點(diǎn)和論據(jù)。
- 適合主題查詢:對于跨越多個(gè)句子或段落的較長查詢,段落或文檔級別的嵌入更適合匹配。這是因?yàn)殚L查詢通常需要更廣泛的上下文信息來理解其意圖。例如,當(dāng)用戶查詢“氣候變化對全球生態(tài)系統(tǒng)的影響”時(shí),段落或文檔級別的嵌入可以更好地找到與之相關(guān)的長文本內(nèi)容。
缺點(diǎn)
- 引入噪聲:較大的輸入文本大小可能會引入噪聲或稀釋單個(gè)句子或短語的重要性。例如,一個(gè)段落中可能包含一些不相關(guān)的信息,這些信息會在嵌入過程中混入,導(dǎo)致向量表示不夠精確。
- 難以精確匹配:由于長內(nèi)容的嵌入包含了更多的信息,因此在查詢索引時(shí)更難找到精確匹配。例如,一個(gè)包含多個(gè)主題的段落可能會與多個(gè)查詢相關(guān),但無法精確匹配到某個(gè)具體的查詢。
查詢長度對嵌入匹配的影響
查詢的長度也會影響嵌入之間的關(guān)系:
- 短查詢:較短的查詢,如單個(gè)句子或短語,會集中在具體細(xì)節(jié)上,更適合與句子級別的嵌入進(jìn)行匹配。這是因?yàn)槎滩樵兺ǔP枰_的語義匹配,而句子級別的嵌入能夠提供更精確的語義表示。
- 長查詢:跨越多個(gè)句子或段落的較長查詢可能更適合與段落或文檔級別的嵌入進(jìn)行匹配。這是因?yàn)殚L查詢通常需要更廣泛的上下文信息來理解其意圖,而段落或文檔級別的嵌入能夠提供更全面的語義表示。
非均勻索引的挑戰(zhàn)與優(yōu)勢
索引也可能是非均勻的,包含不同大小的分塊嵌入。這可能會在查詢結(jié)果相關(guān)性方面帶來挑戰(zhàn),但也可能產(chǎn)生一些積極的影響:
- 挑戰(zhàn):查詢結(jié)果的相關(guān)性可能會因?yàn)殚L內(nèi)容和短內(nèi)容的語義表示之間的差異而波動。例如,一個(gè)查詢可能與某個(gè)句子的嵌入高度相關(guān),但與整個(gè)段落的嵌入相關(guān)性較低,這可能導(dǎo)致查詢結(jié)果的不一致性。
- 優(yōu)勢:非均勻索引可能捕捉到更廣泛的上下文和信息,因?yàn)椴煌姆謮K大小代表了文本中不同層次的粒度,這可能更靈活地適應(yīng)不同類型的查詢。例如,對于一些需要精確匹配的查詢,句子級別的嵌入可以提供更好的結(jié)果;而對于一些需要更廣泛上下文的查詢,段落或文檔級別的嵌入可以提供更全面的信息。
3、分塊考慮因素
內(nèi)容的性質(zhì)
索引的內(nèi)容是長文檔還是短內(nèi)容,決定了哪種模型更適合目標(biāo),進(jìn)而影響分塊策略的選擇。
嵌入模型
不同的嵌入模型在不同的分塊大小上表現(xiàn)最佳。例如,句子轉(zhuǎn)換器模型適合單個(gè)句子,而像text-embedding-ada-002這樣的通用模型在包含256或512個(gè)token的分塊上表現(xiàn)更好,能夠更好地捕捉段落或文檔級別的上下文信息,適合需要更廣泛語義理解的場景。
用戶查詢的長度和復(fù)雜性
用戶查詢的長度和復(fù)雜性會影響分塊內(nèi)容的方式,以便嵌入查詢和嵌入分塊之間有更緊密的相關(guān)性。如果用戶查詢通常很短且具體(如單個(gè)句子或短語),那么句子級別的分塊可能更適合;如果用戶查詢通常較長且復(fù)雜(如跨越多個(gè)句子或段落),那么較大的分塊(如段落或文檔級別)可能更適合。
檢索結(jié)果的用途
檢索結(jié)果在特定應(yīng)用中的用途,如語義搜索、問答、摘要等,也會影響分塊策略。
語義搜索:如果檢索結(jié)果用于語義搜索,需要考慮如何平衡分塊大小以保留上下文信息和提高檢索效率。較大的分塊可以提供更全面的上下文,但可能會降低檢索效率。
問答系統(tǒng):如果檢索結(jié)果用于問答系統(tǒng),需要考慮如何確保分塊與用戶問題的語義相關(guān)性。較小的分塊可以提供更精確的匹配,但可能會丟失上下文信息。
摘要生成:如果檢索結(jié)果用于摘要生成,需要考慮如何選擇分塊大小以保留關(guān)鍵信息。較小的分塊可以提供更精確的信息,但可能需要更多的分塊來覆蓋整個(gè)文檔。
其他用途:如果檢索結(jié)果需要輸入到另一個(gè)具有token限制的LLM中(如OpenAI的GPT模型),則需要根據(jù)token限制來調(diào)整分塊大小。例如,如果模型的上下文窗口為32k tokens,分塊大小可以相對較大;但如果上下文窗口較小,則需要更小的分塊。
4、經(jīng)典分塊方法 固定大小分塊
最常見且直接的分塊方法,該方法只需要通過決定分塊中的token數(shù)量,并可選地決定分塊之間是否有重疊來實(shí)現(xiàn)。通常,分塊之間會保留一些重疊,以確保語義上下文不會在分塊之間丟失。
優(yōu)點(diǎn):這種方法計(jì)算成本低且易于使用,不需要使用任何NLP庫。
缺點(diǎn):無法根據(jù)內(nèi)容的語義結(jié)構(gòu)進(jìn)行動態(tài)調(diào)整。如果分塊過大,可能會稀釋關(guān)鍵信息;如果分塊過小,可能會丟失上下文信息。
適用于大多數(shù)常見情況,尤其是當(dāng)文本內(nèi)容較為均勻且不需要復(fù)雜語義分析的情況。
text = "..." # 你的文本
from langchain.text_splitter import CharacterTextSplitter
text_splitter = CharacterTextSplitter(
separator = "\n\n",
chunk_size = 256,
chunk_overlap = 20
)
docs = text_splitter.create_documents([text])
5、經(jīng)典分塊方法 “內(nèi)容感知”分塊
“內(nèi)容感知”分塊方法利用分塊內(nèi)容的性質(zhì),應(yīng)用更復(fù)雜的分塊策略。這些方法通常基于自然語言處理技術(shù),能夠更好地保留語義結(jié)構(gòu)。
句子分割
句子分割是將文本分割成句子級別的分塊。許多模型都針對句子級別的嵌入進(jìn)行了優(yōu)化。
適用場景于需要精確句子匹配的場景(如問答系統(tǒng)、語義搜索)和文本內(nèi)容較為均勻且以句子為單位的場景(如新聞文章、學(xué)術(shù)論文等)。
- 簡單分割:通過句號(“.”)和換行符分割句子。快速且簡單,但可能無法處理所有邊緣情況。
text = "..." # 你的文本
docs = text.split(".")
- NLTK:自然語言工具包(NLTK)提供了一個(gè)句子分詞器,可以準(zhǔn)確地識別句子邊界,避免在句子中間進(jìn)行分塊,從而確保每個(gè)分塊都包含完整的句子。,
text = "..." # 你的文本
from langchain.text_splitter import NLTKTextSplitter
# 創(chuàng)建 NLTKTextSplitter 實(shí)例
text_splitter = NLTKTextSplitter(
chunk_size=256, # 分塊大小
chunk_overlap=20 # 分塊重疊部分
)
docs = text_splitter.split_text(text)
- spaCy:spaCy 提供了多種預(yù)訓(xùn)練模型,支持多種語言,這些模型能夠準(zhǔn)確地識別句子邊界、詞性等信息,并可以通過設(shè)置分塊之間的重疊部分, 在一定程度上保留上下文信息。
text = "..." # 你的文本
from langchain.text_splitter import SpacyTextSplitter
# 創(chuàng)建 SpacyTextSplitter 實(shí)例
text_splitter = SpacyTextSplitter(
nlp=nlp, # spaCy 模型
chunk_size=256, # 分塊大小
chunk_overlap=20 # 分塊重疊部分
)
docs = text_splitter.split_text(text)
遞歸分塊
遞歸分塊使用一組分隔符以分層和迭代的方式將輸入文本分割成較小的塊。如果初始的分割嘗試沒有生成所需大小或結(jié)構(gòu)的塊,該方法會使用不同的分隔符或標(biāo)準(zhǔn)遞歸調(diào)用自身,直到達(dá)到所需的塊大小或結(jié)構(gòu)。
優(yōu)點(diǎn):可以根據(jù)不同的分隔符和標(biāo)準(zhǔn)動態(tài)調(diào)整分塊大小,能夠處理不同結(jié)構(gòu)的文本。
缺點(diǎn):遞歸調(diào)用可能導(dǎo)致較高的計(jì)算開銷。
適用于需要處理復(fù)雜文本結(jié)構(gòu)的場景(如長文檔、多級標(biāo)題的文檔)和需要動態(tài)調(diào)整分塊大小的場景(如根據(jù)內(nèi)容的語義結(jié)構(gòu)進(jìn)行分塊)。
text = "..." # 你的文本
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
# 設(shè)置一個(gè)非常小的塊大小,僅用于展示。
chunk_size = 256,
chunk_overlap = 20
)
docs = text_splitter.create_documents([text])
專用分塊
專用分塊方法針對特定格式的文本(如Markdown和LaTeX)進(jìn)行優(yōu)化,以在分塊過程中保留內(nèi)容的原始結(jié)構(gòu)。
優(yōu)點(diǎn):能夠根據(jù)特定格式的語法和結(jié)構(gòu)進(jìn)行分塊,生成更具語義連貫性的塊。
缺點(diǎn):僅適用于特定格式的文本,通用性較差。需要解析特定格式的語法和結(jié)構(gòu)。
適用于特定格式的文本處理。
- Markdown
from langchain.text_splitter import MarkdownTextSplitter
markdown_text = "..."
markdown_splitter = MarkdownTextSplitter(chunk_size=100, chunk_overlap=0)
docs = markdown_splitter.create_documents([markdown_text])
- LaTeX
from langchain.text_splitter import LatexTextSplitter
latex_text = "..."
latex_splitter = LatexTextSplitter(chunk_size=100, chunk_overlap=0)
docs = latex_splitter.create_documents([latex_text])
語義分塊
語義分塊是一種新的實(shí)驗(yàn)性分塊技術(shù),通過語義分析創(chuàng)建由談?wù)撓嗤黝}或話題的句子組成的塊。
優(yōu)點(diǎn):能夠根據(jù)語義內(nèi)容動態(tài)調(diào)整分塊,生成更有意義的文本片段。
缺點(diǎn):需要生成嵌入并進(jìn)行語義分析,實(shí)現(xiàn)復(fù)雜度較高。效果依賴于嵌入模型的質(zhì)量。
實(shí)現(xiàn)步驟:
- 將文檔分割成句子。
- 創(chuàng)建句子組:對于每個(gè)句子,創(chuàng)建一個(gè)包含該句子前后一些句子的組。
- 為每個(gè)句子組生成嵌入,并將它們與它們的“錨定”句子相關(guān)聯(lián)。
- 按順序比較每個(gè)組之間的距離:較低的語義距離表明主題相同,較高的語義距離表明主題已發(fā)生變化。
from langchain.text_splitter import SemanticTextSplitter
text = "..."
# 加載預(yù)訓(xùn)練的語言模型
model = SentenceTransformer('all-MiniLM-L6-v2')
# 創(chuàng)建 SemanticTextSplitter 實(shí)例
text_splitter = SemanticTextSplitter(
model=model, # 預(yù)訓(xùn)練的語言模型
chunk_size=256, # 分塊大小
chunk_overlap=20, # 分塊重疊部分
semantic_threshold=0.75 # 語義距離閾值
)
docs = text_splitter.split_text(text)
5經(jīng)典分塊方法確定最佳分塊大小
數(shù)據(jù)預(yù)處理:在確定最佳分塊大小之前,需要對數(shù)據(jù)進(jìn)行預(yù)處理以確保質(zhì)量,如刪除HTML標(biāo)簽或去除噪聲元素。選擇分塊大小范圍:根據(jù)內(nèi)容的性質(zhì)(如短消息或長文檔)和嵌入模型的功能(如token限制),選擇一系列潛在的分塊大小進(jìn)行測試。目標(biāo)是找到保留上下文和保持準(zhǔn)確性之間的平衡。評估每個(gè)分塊大小性能:使用多個(gè)索引或具有多個(gè)命名空間的單個(gè)索引,為測試的分塊大小創(chuàng)建嵌入并保存在索引中。然后運(yùn)行一系列查詢來評估質(zhì)量,并比較不同分塊大小的性能,通過迭代過程確定最適合內(nèi)容和預(yù)期查詢的分塊大小。
6、Agentic Chunking
Agentic Chunking是一種基于大語言模型(LLM)的先進(jìn)文本分塊方法,旨在通過模擬人類在文本分割時(shí)的理解和判斷,生成語義連貫的文本塊。這種方法的核心在于關(guān)注文本中的“Agentic”元素(如人物、組織機(jī)構(gòu)等),并將圍繞這些元素相關(guān)的句子聚合在一起,形成有意義的文本塊。
使用 agentic chunking 能夠解決遞歸字符分割和語義分割的局限性。它不依賴于固定的 token 長度或語義意義的變化,而是主動評估每一句話,并將其分配到相應(yīng)的文本塊中。正因?yàn)槿绱?,agentic chunking 能夠?qū)⑽臋n中相隔甚遠(yuǎn)的相關(guān)句子歸入同一組。
優(yōu)點(diǎn):
- 語義連貫性:能夠?qū)⑽臋n中相隔較遠(yuǎn)但主題相關(guān)的句子歸入同一組,生成語義連貫的文本塊。
- 動態(tài)調(diào)整:根據(jù)文本內(nèi)容動態(tài)調(diào)整分塊大小,適應(yīng)不同類型的文本。
- 上下文保留:通過句子獨(dú)立化和語義評估,保留上下文信息,提升檢索效率。
- 智能分塊:通過 LLM 的智能判斷,實(shí)現(xiàn)更高效的文本分塊。
缺點(diǎn):
- 成本較高:每次調(diào)用 LLM 都會消耗成本,且增加延遲。
- 處理速度較慢:由于需要進(jìn)行復(fù)雜的語義評估,處理速度相對較慢。
- 資源需求高:需要足夠的計(jì)算資源和內(nèi)存來處理大型文檔。
Agentic Chunking 特別適用于以下場景
非結(jié)構(gòu)化文本:如客服對話記錄、播客內(nèi)容等。
主題反復(fù)變化的內(nèi)容:如技術(shù)沙龍實(shí)錄、會議記錄等。
需要跨段落關(guān)聯(lián)的 QA 系統(tǒng):如智能問答系統(tǒng)、語義搜索等。
下面來看下該方法的實(shí)現(xiàn):
句子獨(dú)立化(Propositioning)
將文本中的每個(gè)句子獨(dú)立化,確保每個(gè)句子都有自己的主語。例如,將句子 “He was leading NASA’s Apollo 11 mission.” 轉(zhuǎn)換為 “Neil Armstrong was leading NASA’s Apollo 11 mission.”。這一步驟可以看作是對文檔進(jìn)行“句子級整容”,確保每個(gè)句子獨(dú)立完整。
from langchain.chains import create_extraction_chain_pydantic
from langchain_core.pydantic_v1 import BaseModel
from typing import Optional
from langchain.chat_models import ChatOpenAI
import uuid
import os
from typing import List
from langchain import hub
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from pydantic import BaseModel
# 定義pydantic模型
class Sentences(BaseModel):
sentences: List[str]
# 初始化 LLM 和提取鏈
obj = hub.pull("wfh/proposal-indexing")
llm = ChatOpenAI(model="gpt-4o")
extraction_llm = llm.with_structured_output(Sentences)
extraction_chain = obj | extraction_llm
# 調(diào)用提取鏈并處理文本
sentences = extraction_chain.invoke(
"""
On July 20, 1969, astronaut Neil Armstrong walked on the moon.
He was leading the NASA's Apollo 11 mission.
Armstrong famously said, "That's one small step for man, one giant leap for mankind" as he stepped onto the lunar surface.
"""
)
創(chuàng)建文本塊
第一次啟動時(shí),沒有任何文本塊。因此,必須創(chuàng)建一個(gè)文本塊來存儲第一個(gè) proposition。
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(temperature=0)
chunks = {}
def create_new_chunk(chunk_id, proposition):
summary_llm = llm.with_structured_output(ChunkMeta)
summary_prompt_template = ChatPromptTemplate.from_messages(
[
(
"system",
"Generate a new summary and a title based on the propositions.",
),
(
"user",
"propositions:{propositions}",
),
]
)
summary_chain = summary_prompt_template | summary_llm
chunk_meta = summary_chain.invoke(
{
"propositions": [proposition],
}
)
chunks[chunk_id] = {
"summary": chunk_meta.summary,
"title": chunk_meta.title,
"propositions": [proposition],
}
更新文本塊
每個(gè)后續(xù)的 proposition 都需要被添加到一個(gè)文本塊中。當(dāng)添加一個(gè) proposition 時(shí),文本塊的標(biāo)題和摘要可能并不完全準(zhǔn)確地反映其內(nèi)容。因此,要對它們進(jìn)行重新評估,并在必要時(shí)進(jìn)行重寫。
from langchain_core.pydantic_v1 import BaseModel, Field
class ChunkMeta(BaseModel):
title: str = Field(descriptinotallow="The title of the chunk.")
summary: str = Field(descriptinotallow="The summary of the chunk.")
def add_proposition(chunk_id, proposition):
summary_llm = llm.with_structured_output(ChunkMeta)
summary_prompt_template = ChatPromptTemplate.from_messages(
[
(
"system",
"If the current_summary and title is still valid for the propositions return them."
"If not generate a new summary and a title based on the propositions.",
),
(
"user",
"current_summary:{current_summary}\n\ncurrent_title:{current_title}\n\npropositions:{propositions}",
),
]
)
summary_chain = summary_prompt_template | summary_llm
chunk = chunks[chunk_id]
current_summary = chunk["summary"]
current_title = chunk["title"]
current_propositions = chunk["propositions"]
all_propositions = current_propositions + [proposition]
chunk_meta = summary_chain.invoke(
{
"current_summary": current_summary,
"current_title": current_title,
"propositions": all_propositions,
}
)
chunk["summary"] = chunk_meta.summary
chunk["title"] = chunk_meta.title
chunk["propositions"] = all_propositions
語義評估與合并
LLM 會根據(jù)句子的語義內(nèi)容,將其分配到現(xiàn)有的文本塊中,或者在找不到合適的文本塊時(shí)創(chuàng)建新的文本塊。如果新的句子被添加到文本塊中,LLM 可以更新文本塊的摘要和標(biāo)題,以反映新信息。
def find_chunk_and_push_proposition(proposition):
class ChunkID(BaseModel):
chunk_id: int = Field(descriptinotallow="The chunk id.")
allocation_llm = llm.with_structured_output(ChunkID)
allocation_prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You have the chunk ids and the summaries"
"Find the chunk that best matches the proposition."
"If no chunk matches, return a new chunk id."
"Return only the chunk id.",
),
(
"user",
"proposition:{proposition}" "chunks_summaries:{chunks_summaries}",
),
]
)
allocation_chain = allocation_prompt | allocation_llm
chunks_summaries = {
chunk_id: chunk["summary"] for chunk_id, chunk in chunks.items()
}
best_chunk_id = allocation_chain.invoke(
{"proposition": proposition, "chunks_summaries": chunks_summaries}
).chunk_id
if best_chunk_id not in chunks:
best_chunk_id = create_new_chunk(best_chunk_id, proposition)
return
add_proposition(best_chunk_id, proposition)
7、總結(jié)
分塊內(nèi)容在大多數(shù)情況下相對簡單,但當(dāng)偏離常規(guī)路徑時(shí)可能會帶來挑戰(zhàn)。沒有一種適用于所有情況的分塊解決方案,不同的用例需要不同的分塊策略。通過理解分塊策略的關(guān)鍵點(diǎn)和權(quán)衡,可以為特定的應(yīng)用程序找到最適合的分塊方法。