精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析! 原創 精華

發布于 2025-8-25 08:50
瀏覽
0收藏

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

在深入每一種切塊策略之前,需要先把基礎工具和模擬數據準備好。

import re
import nltk
from nltk.tokenize import sent_tokenize, word_tokenize
from transformers import AutoTokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# 確保已經下載了nltk的punkt分詞器
try:
    nltk.data.find('tokenizers/punkt')
except nltk.downloader.DownloadError:
    nltk.download('punkt')

# 模擬一些文本數據
sample_text_long = """
RAG(Retrieval-Augmented Generation)是一種結合了檢索和生成能力的AI技術。它的核心思想是,當大語言模型(LLM)需要回答問題時,它不再是憑空生成答案,而是首先從一個龐大的知識庫中檢索出最相關的上下文信息。

這些檢索到的信息隨后會被作為輸入的一部分,提供給LLM,LLM再基于這些“額外”的知識來生成最終的回答。這種方式能夠顯著減少模型“胡說八道”(幻覺)的現象,并使得模型能夠回答特定領域的問題,因為它的知識不再僅僅局限于訓練時的數據。

在實際應用中,RAG系統涉及到多個關鍵組件。首先是**數據攝取和預處理**,這通常包括將原始文檔(如PDF、網頁、數據庫記錄等)清洗、解析,并轉換為適合存儲和檢索的格式。接著是**切塊(Chunking)**,這是RAG流程中至關重要的一步。切塊的目的是將長文本分割成較小的、易于管理和檢索的片段。

切塊策略的選擇直接影響檢索的質量。如果切塊過大,可能包含太多無關信息,增加LLM處理的負擔;如果切塊過小,則可能丟失上下文,導致LLM無法理解完整語義。

然后是**嵌入(Embedding)**,將文本切塊轉換為高維向量,這些向量能夠捕捉文本的語義信息。接著是**向量數據庫(Vector Database)**,用于高效存儲和檢索這些嵌入向量。當用戶提出問題時,**檢索器(Retriever)**會根據用戶問題的嵌入向量,在向量數據庫中查找最相似的文本切塊。

最后,**生成器(Generator)**,也就是LLM,會結合用戶的原始問題和檢索到的相關上下文信息,生成最終的答案。整個RAG流程的優化是一個迭代的過程,需要不斷地調整各個環節,才能達到最佳效果。
"""

sample_text_structured = """
# 第一章 引言
## 1.1 RAG的魅力
RAG技術有效解決了大模型幻覺問題。

## 1.2 本文目的
本文將深入探討RAG中的切塊策略。

# 第二章 切塊基礎
## 2.1 樸素切塊
這是一種簡單的切塊方法。

## 2.2 固定大小切塊
我們將會看到固定大小切塊的實現。

---
**Note:** 本文檔旨在提供RAG切塊的全面指南。
"""

sample_text_with_tables = """
這是一段關于公司業績的文本。

| Month | Sales | Profit |
|---|---|---|
| Jan | 100 | 20 |
| Feb | 120 | 25 |
| Mar | 110 | 22 |

以上是第一季度的財務數據。

下面是團隊成員信息:

| Name | Role |
|---|---|
| Alice | Engineer |
| Bob | Designer |
"""

sample_text_mixed_format = """
這是一個段落。它包含一些重要的信息,需要被完整保留。

1.  這是一個列表項。
2.  這是另一個列表項。
    * 子項1
    * 子項2

## 重要提示
請注意以下表格數據:

| Item | Quantity | Price |
|---|---|---|
| Apple | 10 | 1.0 |
| Banana | 5 | 0.5 |
"""


一、基礎篇:簡單粗暴,但有時特好用!

這些方法操作起來賊簡單,對付特定數據效果還真不賴。

1. 樸素切塊(Naive Chunking):

  • 場景使用:當你的文本天然就以行為單位組織,并且每一行都承載一個相對完整、獨立的想法時,這種方法特別高效。比如,會議紀要、聊天記錄、產品FAQ列表、項目待辦事項、帶有明確換行符的筆記等等。
  • 優點:

     a.實現簡單: 幾乎是所有切塊方法中最容易實現的,一行代碼搞定。

     b.速度快: 處理大量文本時效率極高,不會引入復雜計算。

     c.語義清晰(特定場景下): 如果文本就是按行劃分語義,那么切出來的塊語義很純粹。

  • 缺點:

     a.上下文丟失風險: 如果一句話或一個完整想法跨越多行,這種方法會直接將其“腰斬”,導致重要的上下文信息丟失。

     b.塊大小不均: 每行長度不一,導致切出來的塊大小差異大,可能超出LLM的token限制或過短導致信息不足。

     c.不適用于連續文本: 對于小說、論文、博客等段落式的連續文本,效果通常很差。

def naive_chunking(text):
    """
    按行分割文本。
    """
    return text.split('\n')

print("--- 1. 樸素切塊 ---")
chunks_naive = naive_chunking(sample_text_long)
for i, chunk in enumerate(chunks_naive[:5]): # 只打印前5個示例
    print(f"Chunk {i+1}: '{chunk.strip()}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

2. 固定大小切塊(Fixed-size/Fixed Window Chunking):

  • 場景使用:面對“一鍋粥”式的原始、混亂文本數據時,比如從PDF中OCR(光學字符識別)出來的、沒有標點符號或格式的文本,或者大型的日志文件、數據流。當你對文本結構一無所知,又需要快速將數據拆分成固定大小的片段以適應模型輸入時,這是最直接的選擇。
  • 優點:

     a.簡單且快速: 實現起來也很簡單,切割效率高。

     b.易于管理: 每個塊的大小固定,便于批量處理和模型輸入管理,尤其是在LLM有嚴格token限制時。

     c.兜底策略: 在其他結構化切塊方法都失效時,可以作為一種普適的兜底方案。

  • 缺點:

     a.上下文被截斷: 最大的缺點是它會毫不留情地在任何位置切開文本,常常會把句子、段落甚至完整的想法截斷,導致語義不完整或上下文信息流失嚴重。

     b.信息冗余: 在處理結構化文本時,一個塊可能包含多余的信息,或與下一個塊的內容高度重疊。

def fixed_size_chunking(text, chunk_size, overlap=0):
    """
    按固定大小切塊,可選擇重疊。
    chunk_size: 每個切塊的字符數
    overlap: 重疊的字符數
    """
    chunks = []
    text_len = len(text)
    # 注意:這里 i 的步長是 chunk_size - overlap,確保重疊
    for i in range(0, text_len, chunk_size - overlap):
        chunk = text[i:i + chunk_size]
        chunks.append(chunk)
        if i + chunk_size >= text_len: # 防止最后一個切塊不完整,但又跳過重疊部分
            break
    return chunks

print("\n--- 2. 固定大小切塊 ---")
chunks_fixed = fixed_size_chunking(sample_text_long, chunk_size=200, overlap=0)
for i, chunk in enumerate(chunks_fixed[:3]):
    print(f"Chunk {i+1}: '{chunk.strip()}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

3. 滑動窗口切塊(Sliding Window Chunking):

  • 場景使用:當你的文本內容上下文關聯緊密、信息連續性強時,比如小說、敘事性報告、詳細的技術文檔、自由流動的隨筆等。它能有效緩解固定大小切塊中上下文被截斷的問題,尤其適用于LLM需要更廣闊語境才能準確理解和生成回答的場景。
  • 優點:

     a.保持上下文: 通過塊之間的重疊,能有效保留跨塊的上下文信息,降低LLM理解時出現“斷層”的風險。

     b.提高檢索精度: 檢索時,即使查詢命中一個重疊部分,也能帶回包含更完整上下文的塊。

     c.適用于無結構文本: 對沒有明確標題、段落分隔的文本也能較好地處理。

  • 缺點:

     a.冗余度增加: 重疊部分會增加存儲和處理的冗余,導致向量數據庫更大,嵌入和檢索成本增加。

     b.計算開銷: 更多的塊意味著更多的嵌入計算和檢索操作。

     c.參數調優:??chunk_size??? 和 ??overlap?? 的比例需要根據實際數據和LLM的特性進行仔細調優,否則可能效果不佳。

def sliding_window_chunking(text, chunk_size, overlap):
    """
    滑動窗口切塊,每個切塊與前一個重疊。
    chunk_size: 每個切塊的字符數
    overlap: 重疊的字符數
    """
    chunks = []
    text_len = len(text)
    start = 0
    while start < text_len:
        end = min(start + chunk_size, text_len)
        chunk = text[start:end]
        chunks.append(chunk)
        if end == text_len:
            break
        start += (chunk_size - overlap)
    return chunks

print("\n--- 3. 滑動窗口切塊 ---")
chunks_sliding = sliding_window_chunking(sample_text_long, chunk_size=200, overlap=50)
for i, chunk in enumerate(chunks_sliding[:3]):
    print(f"Chunk {i+1}: '{chunk.strip()}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

4. 基于句子切塊(Sentence-based Chunking):

  • 場景使用:最適合語法結構完整、句子獨立承載完整語義的文本,如新聞報道、博客文章、產品說明書、法律條文、論文摘要、結構化的文檔或純文本數據。它可以作為更復雜切塊策略的“第一步”,得到粒度最小的語義單元。
  • 優點:

     a.語義完整性高: 每個切塊都是一個完整的句子,通常能保證最小的語義單元不被破壞。

     b.粒度精細: 提供了最細粒度的信息,便于后續的重排、過濾或更復雜的組合操作。

     c.易于理解: LLM處理完整句子時,理解成本更低。

  • 缺點:

     a.上下文不足: 單個句子可能缺乏足夠的上下文來完全理解其含義,尤其是在上下文分散于多個句子的復雜概念中。

     b.數量龐大: 對于長文檔,句子切塊會生成大量小塊,增加存儲和檢索的負擔。

     c.標點依賴: 嚴重依賴文本中的標點符號來識別句子邊界,如果文本質量差(如OCR錯誤、缺乏標點),效果會大打折扣。

def sentence_based_chunking(text):
    """
    使用nltk進行句子級別的切塊。
    """
    return sent_tokenize(text)

print("\n--- 4. 基于句子切塊 ---")
chunks_sentence = sentence_based_chunking(sample_text_long)
for i, chunk in enumerate(chunks_sentence[:5]):
    print(f"Chunk {i+1}: '{chunk.strip()}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

5. 基于段落切塊(Paragraph-based Chunking):

  • 場景使用:適用于傳統意義上以段落為單位組織內容的文檔,如博客文章、報告、論文、書籍章節等。當你想在保持一定上下文量的同時,又能根據文章的自然邏輯進行分割時,這是非常好的選擇。
  • 優點:

     a.上下文適中: 比句子切塊能提供更多的上下文,通常一個段落能表達一個完整的想法或論點。

     b.結構清晰: 尊重文檔原有的段落結構,切塊結果更符合人類閱讀習慣。

     c.實現簡單: 通常通過雙換行符(??\n\n??)或簡單的文本解析就能實現。

  • 缺點:

     a.段落長度不一: 不同段落的長度差異可能很大,有些段落可能過長超出LLM的token限制,有些可能過短信息量不足。

     b.上下文跨段落: 如果一個邏輯概念跨越多個段落,可能會被切斷。

     c.格式依賴: 依賴于文本中正確的段落分隔符,如果原始文本格式混亂,效果會受影響。

def paragraph_based_chunking(text):
    """
    按雙換行符分割文本(通常表示段落)。
    """
    # 使用正則表達式匹配一個或多個換行符,并移除空字符串
    paragraphs = [p.strip() for p in re.split(r'\n{2,}', text) if p.strip()]
    return paragraphs

print("\n--- 5. 基于段落切塊 ---")
chunks_paragraph = paragraph_based_chunking(sample_text_long)
for i, chunk in enumerate(chunks_paragraph[:3]):
    print(f"Chunk {i+1}: '{chunk.strip()}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

6. 基于頁面切塊(Page-based Chunking):

  • 場景使用:主要針對具有明確分頁結構的文檔,如PDF文檔、掃描的紙質文檔、幻燈片(PPT)、書籍等。當你的檢索結果需要引用到頁碼,或者文檔的布局(如圖片、表格分布)與頁面的邏輯高度相關時,這種方法就顯得尤為重要。
  • 優點:

     a.保留原始布局信息: 每個切塊對應一個物理頁面,能完整保留該頁面的所有信息和布局,方便在原始文檔中定位。

     b.易于引用: 直接關聯頁碼,便于用戶或LLM引用原始出處。

     c.簡化處理: 對于已分頁的文檔,省去了復雜的語義分析。

  • 缺點:

     a.上下文被截斷: 如果一個概念、句子或表格跨越頁面,則會被無情截斷,導致語義不完整。

     b.塊大小差異大: 不同頁面的內容量差異可能很大,導致切塊大小不均,影響LLM處理效率。

     c.依賴于文檔格式: 必須是已經分頁的文檔才能使用,對于純文本或無分頁概念的文檔不適用。

def page_based_chunking(text, page_delimiter="---PAGE_BREAK---"):
    """
    模擬頁面切塊,假設文本中存在頁面分隔符。
    實際應用中需要從PDF等文件讀取。
    """
    # 模擬一個多頁文本
    multi_page_text = (
        "這是第一頁的內容。\n一些重要的信息在這里。\n" +
        page_delimiter + "\n" +
        "這是第二頁的內容。\n繼續重要的討論。\n" +
        page_delimiter + "\n" +
        "第三頁是總結。\n全文到此結束。"
    )
    return [p.strip() for p in multi_page_text.split(page_delimiter) if p.strip()]

print("\n--- 6. 基于頁面切塊 ---")
chunks_page = page_based_chunking(sample_text_long) # 使用模擬文本
for i, chunk in enumerate(chunks_page):
    print(f"Page {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

7. 結構化切塊(Structured Chunking):

  • 場景使用:當你處理的是具有明確內部結構的數據時,如日志文件(按日志條目)、JSON數據(按字段)、XML/HTML文檔(按標簽)、Markdown文檔(按標題或特定元素)、CSV文件(按行或特定列)。這種方法能確保切塊結果嚴格遵循數據本身的邏輯和層級。
  • 優點:

     a.語義完整性強: 每個切塊都對應數據中的一個邏輯單元,語義上高度完整和聚焦。

     b.準確性高: 不依賴模糊的文本特征,而是基于確定的結構規則,切塊準確率高。

     c.便于信息抽取: 切塊后可以直接提取結構化信息,方便后續的知識圖譜構建或特定字段檢索。

  • 缺點:

     a.依賴于結構: 如果數據結構不一致或有錯誤,切塊會失敗。

     b.解析復雜性: 需要針對不同結構編寫特定的解析邏輯,增加了實現的復雜性。

     c.通用性差: 每種結構需要一套獨立的切塊規則,無法通用。

def structured_chunking(text):
    """
    根據Markdown標題結構進行切塊。
    """
    chunks = []
    # 匹配Markdown標題,同時捕獲標題和其后的內容
    # 注意:這里會把每個標題下的內容切成一個塊
    sections = re.split(r'^(#+ .*)$', text, flags=re.MULTILINE)
    
    current_heading = ""
    current_content = []
    
    # 第一個元素通常是空字符串或標題之前的內容
    if sections[0].strip():
        chunks.append(sections[0].strip())

    for i in range(1, len(sections)):
        part = sections[i].strip()
        if part.startswith('#'): # 這是一個標題
            if current_content: # 如果有之前收集的內容,先作為一個塊
                chunks.append("\n".join(current_content).strip())
                current_content = [] # 重置
            current_heading = part
            current_content.append(current_heading) # 將標題也包含在塊內
        else: # 這是一個標題下的內容
            current_content.append(part)
    
    if current_content: # 添加最后一個塊
        chunks.append("\n".join(current_content).strip())

    return [chunk for chunk in chunks if chunk] # 過濾空塊

print("\n--- 7. 結構化切塊 ---")
chunks_structured = structured_chunking(sample_text_structured)
for i, chunk in enumerate(chunks_structured):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

8. 基于文檔結構切塊(Document-Based Chunking):

  • 場景使用:適用于具有清晰的章節、小節和標題層級的文檔,例如技術手冊、教科書、研究論文、長篇報告、企業知識庫文檔。當你希望用戶能夠根據文檔的自然邏輯結構進行檢索,或者LLM需要理解某個特定章節的完整語境時,這種方法是首選。它也是實現分層切塊(Hierarchical Chunking)的基礎。
  • 優點:

     a.高度貼合文檔原意: 切塊結果與文檔的邏輯結構保持一致,非常自然。

     b.上下文豐富: 每個塊通常包含一個完整的章節或小節內容,提供足夠的上下文。

     c.便于導航和理解: 用戶和LLM都能清晰地知道信息所屬的章節位置。

  • 缺點:

     a.依賴文檔格式: 需要文檔有明確的標題或章節標記,對于非結構化文本無效。

     b.解析復雜: 需要更智能的解析器來識別不同級別的標題和其對應的內容。

     c.塊大小不均: 不同章節的長度可能差異巨大,導致一些塊過大。

def document_based_chunking(text):
    """
    基于文檔的自然結構(如Markdown的章節和子章節)進行切塊。
    這里我們將捕獲頂級標題下的所有內容作為一個塊,直到下一個同級或更高級的標題。
    """
    chunks = []
    lines = text.split('\n')
    current_chunk_lines = []
    
    for line in lines:
        if line.startswith('#'): # 匹配任何級別的標題
            if current_chunk_lines: # 如果當前塊有內容,就結束并添加
                chunks.append("\n".join(current_chunk_lines).strip())
                current_chunk_lines = []
            current_chunk_lines.append(line) # 將標題作為新塊的開始
        else:
            current_chunk_lines.append(line)
            
    if current_chunk_lines: # 添加最后一個塊
        chunks.append("\n".join(current_chunk_lines).strip())
        
    return [chunk for chunk in chunks if chunk]

print("\n--- 8. 基于文檔結構切塊 ---")
chunks_doc_struct = document_based_chunking(sample_text_structured)
for i, chunk in enumerate(chunks_doc_struct):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

二、進階篇:聰明切分,解決復雜問題!

這些方法需要更多的策略和算法支持,能應對更復雜的場景。

9. 基于關鍵詞切塊(Keyword-based Chunking):

  • 場景使用:當文檔沒有明確的標題結構,但特定的關鍵詞或短語總是標志著新主題或重要信息的開始時,這種方法非常有效。比如,法律合同中的“WHEREAS”、“THEREFORE”,醫療記錄中的“Diagnosis:”、“Treatment:”,或者產品說明書中的“Warning:”、“Troubleshooting:”。
  • 優點:

     a.聚焦特定信息: 能有效地將包含特定關鍵詞的重要信息切分出來。

     b.規則靈活: 可以根據業務需求自定義關鍵詞列表。

     c.適用于半結構化文本: 對缺乏嚴格結構,但有固定標記的文本很有用。

  • 缺點:

      a.關鍵詞依賴: 嚴重依賴預定義的關鍵詞,如果關鍵詞選擇不當或缺失,切塊效果會很差。

      b.上下文丟失: 關鍵詞可能出現在句子中間,切塊時可能導致句子被截斷。

      c.人工成本: 確定有效的關鍵詞列表可能需要人工分析和迭代。

def keyword_based_chunking(text, keywords):
    """
    在指定關鍵詞處進行切塊。
    """
    chunks = []
    # 構建正則表達式,匹配所有關鍵詞并保留關鍵詞本身
    # 使用非捕獲組 (?:...) 結合 | 運算符
    pattern = '|'.join(re.escape(k) for k in keywords)
    parts = re.split(f'({pattern})', text) # 使用捕獲組保留分隔符

    current_chunk = ""
    for part in parts:
        if part.strip() in keywords: # 如果當前部分是關鍵詞
            if current_chunk.strip(): # 將之前的累積作為新塊
                chunks.append(current_chunk.strip())
            current_chunk = part # 關鍵詞作為新塊的開始
        else:
            current_chunk += part
    
    if current_chunk.strip(): # 添加最后一個塊
        chunks.append(current_chunk.strip())
        
    return [chunk for chunk in chunks if chunk] # 過濾空塊

print("\n--- 9. 基于關鍵詞切塊 ---")
keywords_for_chunking = ["Note:", "首先是", "接著是"]
chunks_keyword = keyword_based_chunking(sample_text_long + sample_text_structured, keywords_for_chunking)
for i, chunk in enumerate(chunks_keyword):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

10. 基于實體切塊(Entity-based Chunking):

  • 場景使用:適用于文檔中特定實體(人名、地名、公司、產品等)是核心信息的場景,如新聞文章(圍繞特定人物或事件)、法律合同(圍繞當事人)、醫學報告(圍繞患者、疾病)、電影劇本(圍繞角色)。當你希望檢索結果能聚焦于某個實體及其相關描述時,這種方法能提供高度相關的上下文。
  • 優點:

      a.高度聚焦: 每個切塊都圍繞一個或一組實體,保證了信息的強相關性。

      b.提升檢索精度: 用戶查詢某個實體時,能精準召回所有與該實體相關的描述。

      c.知識圖譜構建: 為后續構建知識圖譜提供了結構化的基礎。

  • 缺點:

       a.依賴NER模型: 需要高質量的命名實體識別(NER)模型,模型性能直接影響切塊效果。

       b.計算開銷大: NER處理本身有計算成本,且切塊邏輯可能更復雜。

       c.通用性受限: 對于沒有明顯實體的文本,效果不佳。

# pip install spacy
# python -m spacy download en_core_web_sm
import spacy

try:
    nlp = spacy.load("en_core_web_sm")
except OSError:
    print("Downloading spacy model 'en_core_web_sm'...")
    spacy.cli.download("en_core_web_sm")
    nlp = spacy.load("en_core_web_sm")

def entity_based_chunking(text):
    """
    使用NER模型識別實體,并圍繞實體聚合文本。
    這里為了簡化,我們找到實體所在句子,并以句子為單位聚合。
    """
    doc = nlp(text)
    entities = {} # {entity_text: [sentences containing this entity]}

    for sent in doc.sents:
        found_entities_in_sent = False
        for ent in sent.ents:
            if ent.label_ in ["PERSON", "ORG", "GPE", "PRODUCT"]: # 關注人、組織、地理、產品等實體
                if ent.text notin entities:
                    entities[ent.text] = []
                entities[ent.text].append(sent.text.strip())
                found_entities_in_sent = True
        ifnot found_entities_in_sent: # 如果句子沒有實體,作為獨立塊或添加到“無實體”塊
            if"NO_ENTITY"notin entities:
                entities["NO_ENTITY"] = []
            entities["NO_ENTITY"].append(sent.text.strip())
            
    # 將字典轉換為列表,每個實體或無實體組一個塊
    chunks = []
    for entity, sents in entities.items():
        chunk_content = f"Related to {entity}:\n" + "\n".join(list(set(sents))) # 使用set去重
        chunks.append(chunk_content)
    
    return chunks

print("\n--- 10. 基于實體切塊 ---")
sample_ner_text = "Apple公司發布了新的iPhone 15。Tim Cook在發布會上強調了其強大的A17芯片。用戶可以在紐約的Apple Store購買。"
chunks_entity = entity_based_chunking(sample_ner_text)
for i, chunk in enumerate(chunks_entity):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

11. 基于Token切塊(Token-based Chunking):

  • 場景使用:主要用于需要精確控制LLM輸入token數量的場景,比如LLM有嚴格的上下文窗口限制(token limit),或者你希望最大化單個token的使用效率。它通常作為其他切塊方法(如句子切塊)的補充或后處理步驟,以確保最終的塊大小符合LLM要求,同時避免語義被完全破壞。
  • 優點:

     a.精確控制塊大小: 能夠嚴格控制每個塊的token數量,避免超出LLM的輸入限制。

     b.適用于非結構化文本: 對于沒有明確語義結構(如標題、段落)的文本,可以作為一種有效的切塊方式。

     c.與LLM兼容性好: 直接以LLM理解的token為單位進行切塊,減少了LLM處理時的額外計算。

  • 缺點:

     a.語義完整性風險: 和固定大小切塊類似,可能在token級別直接截斷句子或單詞,導致語義不完整。

     b.需要與語義策略結合: 單獨使用時容易丟失上下文,通常需要與句子切塊等語義方法結合,先按語義切小段,再對過長的段落進行token切分。

     c.依賴分詞器: 切塊結果依賴于所選分詞器的行為,不同分詞器結果可能不同。

# pip install transformers
def token_based_chunking(text, tokenizer_name="bert-base-uncased", max_tokens=128):
    """
    使用分詞器按token數量進行切塊。
    """
    tokenizer = AutoTokenizer.from_pretrained(tokenizer_name)
    tokens = tokenizer.encode(text, add_special_tokens=False) # 不添加特殊token
    
    chunks = []
    for i in range(0, len(tokens), max_tokens):
        chunk_tokens = tokens[i:i + max_tokens]
        chunk_text = tokenizer.decode(chunk_tokens)
        chunks.append(chunk_text)
    return chunks

print("\n--- 11. 基于Token切塊 ---")
chunks_token = token_based_chunking(sample_text_long, max_tokens=60)
for i, chunk in enumerate(chunks_token[:3]):
    print(f"Chunk {i+1}:\n'{chunk}'")
print("...")

12. 基于主題切塊(Topic-based Chunking):

  • 場景使用:當你的文檔涵蓋多個主題,且主題之間有清晰的界限(但可能沒有明確的標題或關鍵詞標記),或者你希望每個切塊都能高度聚焦于一個單一主題時。比如,一個關于科技趨勢的報告可能同時討論AI、區塊鏈和元宇宙,用主題切塊可以確保每個塊只包含一個主題的內容。
  • 優點:

     a.高語義相關性: 每個切塊都包含一個或少數幾個緊密相關的主題,檢索命中后能提供高度聚焦的信息。

     b.應對復雜文檔: 能夠處理主題交織、沒有明確結構的長文檔。

     c.提升檢索質量: 減少了切塊中的無關信息,提高了召回的精確性。

  • 缺點:

     a.實現復雜: 需要主題模型(如LDA、NMF)或高級聚類算法,計算成本較高。

     b.主題邊界模糊: 在主題過渡平滑的文檔中,確定清晰的主題邊界可能很困難。

     c.參數調優: 聚類算法的參數(如主題數量、相似度閾值)需要仔細調優。

# pip install scikit-learn
def topic_based_chunking(text, min_sentences_per_topic=3):
    """
    通過句子相似度模擬主題切塊。
    將相似的句子聚類成一個主題塊。
    """
    sentences = sent_tokenize(text)
    if len(sentences) < min_sentences_per_topic:
        return [text] # 句子太少,無法有效分主題

    # 使用TF-IDF向量化句子
    vectorizer = TfidfVectorizer().fit(sentences)
    sentence_vectors = vectorizer.transform(sentences)

    chunks = []
    current_topic_sentences = [sentences[0]]
    
    for i in range(1, len(sentences)):
        # 計算當前句子與當前主題塊中所有句子的平均相似度
        current_sentence_vector = sentence_vectors[i]
        
        # 將當前主題塊的句子向量合并
        current_topic_vectors = vectorizer.transform(current_topic_sentences)
        avg_similarity = np.mean(cosine_similarity(current_sentence_vector, current_topic_vectors))

        # 如果相似度低于某個閾值,或者當前主題塊句子太多,就認為主題切換
        # 這里閾值和數量都是啟發式的,實際應用中需調優
        if avg_similarity < 0.3or len(current_topic_sentences) >= 5: # 假設相似度低于0.3或句子多于5句視為新主題
            chunks.append(" ".join(current_topic_sentences))
            current_topic_sentences = [sentences[i]]
        else:
            current_topic_sentences.append(sentences[i])
            
    if current_topic_sentences:
        chunks.append(" ".join(current_topic_sentences))
        
    return chunks

print("\n--- 12. 基于主題切塊 ---")
chunks_topic = topic_based_chunking(sample_text_long)
for i, chunk in enumerate(chunks_topic):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

13. 表格感知切塊(Table-aware Chunking):

  • 場景使用:當你的文檔中包含重要的表格數據,并且你希望這些表格能夠作為一個完整的語義單元被處理和檢索時。這在財務報表、產品規格、統計數據、研究數據等文檔中尤為常見。通過將表格獨立切塊,LLM能更好地理解表格的結構和內容。
  • 優點:

     a.保留表格結構和完整性: 確保表格作為一個整體,不會被中間切斷,方便LLM理解其數據關系。

     b.提升表格數據檢索: 用戶查詢表格內容時,能精確召回整個表格。

     c.有利于LLM處理: LLM對結構化表格數據(如Markdown或JSON格式)的處理能力通常優于純文本。

  • 缺點:

      a.解析復雜: 需要強大的表格解析能力,尤其對于非標準格式的表格或圖像中的表格(需要OCR+表格檢測)。

      b.上下文丟失: 表格周圍的文本上下文可能與表格內容緊密相關,但如果表格被單獨切塊,這種關聯可能會被削弱。

      c.依賴于格式: 僅適用于能夠識別出表格結構的文檔。

def table_aware_chunking(text):
    """
    識別并單獨切塊表格。將表格內容轉換為Markdown格式。
    """
    chunks = []
    # 匹配Markdown表格的正則表達式
    # 捕獲表格內容,包括表頭、分隔線和行
    table_pattern = re.compile(r'(\|.*\|\n\|[-: ]+\|\n(?:\|.*\|\n?)+)', re.MULTILINE)
    
    last_end = 0
    for match in table_pattern.finditer(text):
        # 添加表格前的內容
        pre_table_text = text[last_end:match.start()].strip()
        if pre_table_text:
            chunks.append(pre_table_text)
        
        # 添加表格本身
        chunks.append(match.group(0).strip())
        last_end = match.end()
        
    # 添加最后一個表格后的內容
    post_table_text = text[last_end:].strip()
    if post_table_text:
        chunks.append(post_table_text)
        
    return [chunk for chunk in chunks if chunk]

print("\n--- 13. 表格感知切塊 ---")
chunks_table_aware = table_aware_chunking(sample_text_with_tables)
for i, chunk in enumerate(chunks_table_aware):
    print(f"Chunk {i+1}:\n'{chunk}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

14. 內容感知切塊(Content-aware Chunking):

  • 場景使用:適用于包含多種內容類型和結構的復雜文檔,如網頁文章(包含段落、列表、圖片、嵌入視頻)、學術論文(包含正文、圖表、公式、參考文獻)、商業報告(包含文字、表格、圖示)。它是一種“智能”的切塊方法,能根據不同內容的特點采用最合適的分割策略。
  • 優點:

     a.語義完整性強: 能夠根據內容類型靈活調整,最大程度地保持語義完整性,例如段落不被切斷,表格保持完整。

     b.通用性廣: 能夠處理混合格式的復雜文檔,適應性強。

     c.提升檢索質量: 每個切塊的內容更加聚焦和完整,提高了檢索的準確性和LLM的理解能力。

  • 缺點:

     a.實現復雜: 需要一套復雜的規則引擎來識別和區分不同類型的內容,并應用相應的切塊邏輯。

     b.性能開銷: 解析和識別內容類型可能增加處理時間。

     c.規則維護: 隨著文檔格式的變化,可能需要不斷更新和維護切塊規則。

def content_aware_chunking(text):
    """
    根據內容類型(段落、列表、表格、標題等)應用不同的切塊規則。
    這是一個結合了多種策略的示例。
    """
    chunks = []
    lines = text.split('\n')
    current_chunk_lines = []
    in_table = False
    
    for line in lines:
        stripped_line = line.strip()

        # 檢查是否是表格行(簡單的啟發式判斷)
        if stripped_line.startswith('|') and'|'in stripped_line[1:]:
            ifnot in_table: # 如果剛進入表格,先結束前一個非表格塊
                if current_chunk_lines:
                    chunks.append("\n".join(current_chunk_lines).strip())
                    current_chunk_lines = []
                in_table = True
            current_chunk_lines.append(line)
        elif in_table: # 如果在表格中,但當前行不是表格行,則表格結束
            if current_chunk_lines: # 添加完整的表格塊
                chunks.append("\n".join(current_chunk_lines).strip())
                current_chunk_lines = []
            in_table = False
            current_chunk_lines.append(line) # 當前行作為新塊的開始
        elif stripped_line.startswith('#'): # 匹配標題
            if current_chunk_lines: # 如果有內容,結束前一個塊
                chunks.append("\n".join(current_chunk_lines).strip())
                current_chunk_lines = []
            current_chunk_lines.append(line) # 標題作為新塊的開始
        elifnot stripped_line and current_chunk_lines: # 空行作為段落分隔符
            if current_chunk_lines[-1].strip() != "": # 避免連續空行導致空塊
                chunks.append("\n".join(current_chunk_lines).strip())
                current_chunk_lines = []
        else: # 普通文本行
            current_chunk_lines.append(line)
            
    if current_chunk_lines: # 添加最后一個塊
        chunks.append("\n".join(current_chunk_lines).strip())
        
    return [chunk for chunk in chunks if chunk['content']]

print("\n--- 14. 內容感知切塊 ---")
chunks_content_aware = content_aware_chunking(sample_text_mixed_format)
for i, chunk in enumerate(chunks_content_aware):
    print(f"Chunk {i+1}:\n'{chunk}'")

15. 上下文切塊(Contextual Chunking):

  • 場景使用:當你的知識庫內容復雜、主題關聯性強,且LLM的上下文窗口足夠大,能夠容納額外注入的上下文信息時。這對于金融報告、法律合同、技術規范等需要深入理解文本背后邏輯和關聯性的場景非常有用。LLM可以生成關于某個切塊的摘要、主題標簽或與相關切塊的鏈接,從而豐富每個塊的信息。
  • 優點:

     a.提升理解深度: 通過LLM添加額外上下文,增強了每個切塊的語義豐富性,幫助下游LLM更好地理解和推理。

     b.降低幻覺: LLM對檢索到的信息理解更全面,減少了生成錯誤答案的風險。

     c.靈活適應: LLM可以根據具體需求生成不同類型的上下文信息。

  • 缺點:

     a.成本高昂: 需要調用LLM進行額外處理,會增加API調用成本和計算延遲。

     b.token消耗: 添加額外上下文會增加每個切塊的token數量,可能更快達到LLM的上下文限制。

     c.LLM依賴: 效果嚴重依賴LLM的生成能力和對知識庫的理解程度。

def mock_llm_add_context(chunk_text, knowledge_base_overview):
    """
    模擬LLM為每個切塊添加相關上下文。
    在實際中,這需要調用一個真正的LLM。
    """
    if"RAG"in chunk_text and"檢索"in chunk_text:
        returnf"Context: This chunk details the core retrieval mechanism of RAG and its purpose related to knowledge bases. ---\n{chunk_text}"
    elif"切塊"in chunk_text and"影響"in chunk_text:
        returnf"Context: This chunk elaborates on the criticality of chunking strategies and their impact on LLM performance and context. ---\n{chunk_text}"
    else:
        # 模擬一個通用上下文
        returnf"Context: This text fragment discusses general AI concepts or system components. ---\n{chunk_text}"

def contextual_chunking(text, base_chunking_strategy=paragraph_based_chunking, knowledge_base_overview="Overview of AI and RAG systems."):
    """
    先進行基礎切塊,然后用LLM為每個切塊添加上下文。
    """
    base_chunks = base_chunking_strategy(text, **{}) # 確保可以傳入空字典
    contextualized_chunks = [mock_llm_add_context(chunk, knowledge_base_overview) for chunk in base_chunks]
    return contextualized_chunks

print("\n--- 15. 上下文切塊 ---")
chunks_contextual = contextual_chunking(sample_text_long)
for i, chunk in enumerate(chunks_contextual[:3]):
    print(f"Chunk {i+1}:\n'{chunk}'")
print("...")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

16. 語義切塊(Semantic Chunking):

  • 場景使用:當你的文檔主題連貫但缺乏明確結構,或者不同主題的句子交織在一起時,如訪談記錄、會議紀要的自由轉錄、長篇小說中人物情感的起伏、對某個復雜概念的多角度闡述。這種方法通過識別句子或段落的語義相似性,將真正“談論同一件事”的內容聚合在一起。
  • 優點:

     a.高語義純度: 確保每個切塊中的內容在語義上高度相關,減少無關信息的干擾。

     b.應對無結構文本: 在沒有明確結構的情況下,也能找到自然的語義邊界。

     c.提升檢索質量: 用戶查詢某個概念時,能召回所有語義上相關的片段,即使它們在原文中不相鄰。

  • 缺點:

     a.實現復雜: 需要使用句子嵌入模型(如Sentence Transformers),并進行向量計算和聚類分析。

     b.計算開銷: 嵌入生成和相似度計算會增加處理時間。

     c.閾值敏感: 相似度閾值的設置非常關鍵,過高可能導致塊過小,過低可能導致塊過大并包含多個主題。

     d.模型依賴: 效果取決于所選嵌入模型的語義理解能力。

# pip install sentence-transformers # 實際應用會用這個
from sentence_transformers import SentenceTransformer

# 加載一個預訓練的句子嵌入模型 (首次運行可能需要下載)
try:
    embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
except Exception:
    print("Failed to load sentence-transformers model. Please ensure you have internet or download it manually.")
    # 提供一個備用/跳過策略
    embedding_model = None

def semantic_chunking(text, model=embedding_model, similarity_threshold=0.7):
    """
    先嵌入所有句子,然后根據相似度聚合。
    """
    if model isNone:
        print("Embedding model not loaded, skipping embedding chunking demo.")
        return [text] # 返回原始文本或進行其他默認切塊

    sentences = sent_tokenize(text)
    if len(sentences) <= 1:
        return sentences

    sentence_embeddings = model.encode(sentences)
    
    chunks = []
    current_chunk_sentences = [sentences[0]]

    for i in range(1, len(sentences)):
        # 計算當前句子與前一個句子嵌入的余弦相似度
        similarity = cosine_similarity([sentence_embeddings[i]], [sentence_embeddings[i-1]])[0][0]
        
        if similarity < similarity_threshold:
            # 如果相似度低,則認為語義不連續,結束當前塊
            chunks.append(" ".join(current_chunk_sentences))
            current_chunk_sentences = [sentences[i]]
        else:
            current_chunk_sentences.append(sentences[i])
            
    if current_chunk_sentences: # 添加最后一個塊
        chunks.append(" ".join(current_chunk_sentences))
        
    return chunks

print("\n--- 16. 語義切塊 ---")
if embedding_model:
    chunks_semantic = semantic_chunking(sample_text_long, similarity_threshold=0.5) # 調整閾值以觀察不同效果
    for i, chunk in enumerate(chunks_semantic[:3]):
        print(f"Chunk {i+1}:\n'{chunk}'")
    print("...")
else:
    print("跳過嵌入切塊演示,因為SentenceTransformer模型未加載。")

17. 遞歸切塊(Recursive Chunking):

  • 場景使用:對于長度不確定、結構不規則的文本,如采訪記錄、自由形式的寫作、用戶評論、非結構化文檔等。當你想確保每個切塊都滿足LLM的最大token限制,同時盡可能保持語義完整性時,遞歸切塊是一個非常強大的通用解決方案。它會優先使用大的語義分隔符,如果仍超出限制,則嘗試更小的分隔符,直至滿足要求。
  • 優點:

    a.靈活性高: 能夠處理各種長度和結構的文本,適應性強。

    b.平衡完整性與粒度: 優先保留較大的語義單元(如段落),在必要時才進一步細分到句子或單詞,盡量減少上下文破壞。

    c.通用性強: 適合作為大多數RAG系統的通用切塊策略。

  • 缺點:

    a.實現略復雜: 相較于簡單切塊,邏輯更復雜,需要定義分隔符優先級。

    b.分隔符依賴: 分隔符的選擇和順序會影響切塊質量,需要一定的經驗和實驗。

    c.可能仍然截斷: 在極端情況下,如果所有分隔符都用完仍無法滿足長度要求,最終可能還是會強制截斷文本。

def recursive_chunking(text, separators, max_chunk_size_char=500):
    """
    遞歸切塊,嘗試不同的分隔符,直到塊大小符合要求。
    separators: 分隔符列表,從大到小排列 (如 ['\n\n', '\n', '. ', ' '])
    max_chunk_size_char: 最大切塊字符數
    """
    chunks = []
    ifnot text:
        return []

    # 如果文本已經小于最大塊大小,直接返回
    if len(text) <= max_chunk_size_char:
        return [text]

    # 嘗試當前最大的分隔符
    if separators:
        current_separator = separators[0]
        remaining_separators = separators[1:]
        
        parts = text.split(current_separator)
        
        for part in parts:
            part_stripped = part.strip()
            if part_stripped: # 確保不是空字符串
                if len(part_stripped) > max_chunk_size_char:
                    # 如果部分仍然太大,遞歸調用更小的分隔符
                    chunks.extend(recursive_chunking(part_stripped, remaining_separators, max_chunk_size_char))
                else:
                    chunks.append(part_stripped)
    else: # 沒有更多分隔符可用,直接按字符切分(作為兜底)
        for i in range(0, len(text), max_chunk_size_char):
            chunks.append(text[i:i + max_chunk_size_char])
            
    return [chunk for chunk in chunks if chunk] # 過濾空塊

print("\n--- 17. 遞歸切塊 ---")
# 模擬一個非常長的段落,需要遞歸切分
long_paragraph = "這是一個非常非常長的段落,它包含了多句話,并且可能在語義上可以被分割。我們希望這個段落能夠被智能地切分成更小的部分,以便于RAG系統處理。如果直接固定大小切塊,可能會切斷句子的上下文,導致信息丟失。所以,我們需要一個更靈活的策略來處理這種長文本。RAG的成功很大程度上取決于切塊的質量。我們在這里模擬一個非常長的輸入,以測試遞歸切塊的能力。請注意,這個段落的長度遠遠超過了我們設定的最大塊大小,所以它將被進一步切分。切塊的藝術在于平衡信息的完整性和粒度。適當的切塊能夠幫助大模型更好地理解檢索到的信息,從而生成更準確、更相關的回答。這是一項技術挑戰,也是RAG優化的關鍵一步。通過不同的分隔符進行遞歸切分,我們可以確保每個塊都不會過大,同時盡量保持語義的完整性。當遇到一個超長的段落時,首先嘗試用段落符切分,如果還超長,就用句號切分,再超長就用逗號,直到達到預設的最大長度。"

separators = ['\n\n', '. ', ',', ' '] # 嘗試從大到小的分隔符
chunks_recursive = recursive_chunking(long_paragraph, separators, max_chunk_size_char=100)
for i, chunk in enumerate(chunks_recursive):
    print(f"Chunk {i+1} (len={len(chunk)}):\n'{chunk}'")

18. 嵌入切塊(Embedding Chunking):

  • 場景使用:當你的文檔完全非結構化,缺乏任何標點、標題或清晰的段落分隔,或者簡單的啟發式切塊效果不佳時。這種方法特別適合處理口語化的轉錄文本、網絡爬取的混亂數據流等。它基于語義相似度來決定切塊邊界,從而在缺乏顯式結構的情況下創建有意義的塊。
  • 優點:

     a.應對無結構文本: 對沒有明確結構的信息非常有效,能自動識別語義邊界。

     b.語義準確性高: 直接利用句子嵌入的語義信息,確保切塊內容的相關性。

     c.自動化程度高: 無需手動定義規則或關鍵詞,自動化程度高。

  • 缺點:

     a.計算成本高: 需要為所有句子生成嵌入,這比簡單的文本分割計算量更大。

     b.模型依賴: 效果嚴重依賴所使用的嵌入模型的質量和適用性。

     c.閾值敏感: 相似度閾值的設置對最終切塊結果有很大影響,需要仔細調優。

# pip install sentence-transformers
from sentence_transformers import SentenceTransformer

# 加載一個預訓練的句子嵌入模型 (首次運行可能需要下載)
try:
    embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
except Exception:
    print("Failed to load sentence-transformers model. Please ensure you have internet or download it manually.")
    # 提供一個備用/跳過策略
    embedding_model = None

def embedding_chunking(text, model=embedding_model, similarity_threshold=0.7):
    """
    先嵌入所有句子,然后根據相似度聚合。
    """
    if model isNone:
        print("Embedding model not loaded, skipping embedding chunking demo.")
        return [text] # 返回原始文本或進行其他默認切塊

    sentences = sent_tokenize(text)
    if len(sentences) <= 1:
        return sentences

    sentence_embeddings = model.encode(sentences)
    
    chunks = []
    current_chunk_sentences = [sentences[0]]

    for i in range(1, len(sentences)):
        # 計算當前句子與前一個句子嵌入的余弦相似度
        similarity = cosine_similarity([sentence_embeddings[i]], [sentence_embeddings[i-1]])[0][0]
        
        if similarity < similarity_threshold:
            # 如果相似度低,則認為語義不連續,結束當前塊
            chunks.append(" ".join(current_chunk_sentences))
            current_chunk_sentences = [sentences[i]]
        else:
            current_chunk_sentences.append(sentences[i])
            
    if current_chunk_sentences: # 添加最后一個塊
        chunks.append(" ".join(current_chunk_sentences))
        
    return chunks

print("\n--- 18. 嵌入切塊 ---")
if embedding_model:
    chunks_embedding = embedding_chunking(sample_text_long, similarity_threshold=0.5) # 調整閾值以觀察不同效果
    for i, chunk in enumerate(chunks_embedding[:3]):
        print(f"Chunk {i+1}:\n'{chunk}'")
    print("...")
else:
    print("跳過嵌入切塊演示,因為SentenceTransformer模型未加載。")

19. Agentic / 基于LLM切塊(Agentic / LLM-based Chunking):

  • 場景使用:適用于極其復雜、高度非結構化且難以用規則或啟發式方法有效切塊的文本。例如,包含大量口語、多主題交織、推理鏈條復雜的會議討論、自由形式的用戶反饋、專業領域的專家報告等。當人類判斷是最佳的切塊方式,但又需要自動化時,可以考慮讓LLM來“智能”地完成這個任務。
  • 優點:

     a.高度智能: LLM能夠理解文本的深層含義、邏輯關系和上下文,從而做出更符合語義的切塊決策。

     b.靈活性和適應性強: 可以應對各種復雜和未知的文本結構。

     c.減少人工干預: 在一些傳統方法難以處理的場景下,可以自動化切塊過程。

  • 缺點:

     a.成本高昂: 調用大型LLM進行切塊會產生顯著的API費用和計算延遲。

     b.速度較慢: LLM推理速度通常比基于規則或嵌入的切塊慢得多。

     c.不可控性: LLM的切塊決策可能不夠穩定或可解釋,有時會出現“意料之外”的分割。

     d.token限制: 需要將文本分成LLM可以處理的較小段落進行處理。

def mock_llm_chunking_decision(text_segment):
    """
    模擬LLM決定如何切塊。
    在實際中,需要給LLM提供文本段落和切塊規則,讓它返回分割點或直接返回切好的塊。
    例如,可以給LLM一個Prompt:
    "給定以下文本,請將其分割成語義連貫的、不超過200字的獨立片段,并以'---CHUNK---'作為分隔符返回:"
    """
    # 模擬LLM智能地將文本分割成幾個邏輯塊
    if"RAG"in text_segment and"幻覺"in text_segment:
        return ["RAG技術有效解決了大模型幻覺問題。", "其核心在于結合檢索和生成能力。"]
    elif"切塊"in text_segment and"影響"in text_segment:
        return ["切塊策略直接影響檢索的質量。", "如果切塊過大,會增加LLM處理負擔;如果過小,則可能丟失上下文。"]
    else:
        # 如果LLM無法智能切分,就回退到句子切塊
        return sent_tokenize(text_segment)

def agentic_llm_based_chunking(text, max_segment_for_llm=500):
    """
    使用LLM來決定切塊邊界。
    由于LLM調用成本,通常我們會先將大文本切分成適合LLM處理的段落,
    然后讓LLM對這些段落進行細粒度切塊。
    """
    # 先進行一個粗粒度的切塊(例如,按段落或固定大小),確保每個段落大小適合LLM處理
    coarse_chunks = fixed_size_chunking(text, max_segment_for_llm, overlap=0)
    
    final_chunks = []
    for chunk in coarse_chunks:
        # 模擬LLM對每個粗粒度塊進行智能切分
        llm_decided_sub_chunks = mock_llm_chunking_decision(chunk)
        final_chunks.extend(llm_decided_sub_chunks)
        
    return [c.strip() for c in final_chunks if c.strip()]

print("\n--- 19. Agentic / 基于LLM切塊 ---")
chunks_llm_based = agentic_llm_based_chunking(sample_text_long, max_segment_for_llm=300)
for i, chunk in enumerate(chunks_llm_based[:5]):
    print(f"Chunk {i+1}:\n'{chunk}'")
print("...")

20. 分層切塊(Hierarchical Chunking):

  • 場景使用:對于結構清晰、具有多級標題的復雜文檔,如書籍、學術論文、法律法規、復雜的公司規章制度、帶有嚴格目錄的技術文檔。當你需要支持用戶在不同粒度(從章節概覽到具體段落)進行檢索,并且LLM在生成回答時需要理解信息的層級關系時,這種方法是理想選擇。
  • 優點:

     a.全面性與粒度兼顧: 提供了多粒度的檢索能力,用戶可以先獲取高層級概覽,再深入細節。

     b.保留結構上下文: 每個塊都帶有其所屬的層級信息(如章節標題),LLM在處理時能更好地理解其在文檔中的位置和作用。

     c.提升檢索效率: 可以根據查詢的廣度在不同層級進行檢索,提高效率。

  • 缺點:

      a.實現最復雜: 需要復雜的解析器來識別和構建文檔的層級結構,并處理各種邊緣情況。

      b.存儲冗余: 某些內容可能在不同層級的塊中重復出現(如一個段落既是其小節塊的一部分,也是其章節塊的一部分),增加存儲負擔。

      c.依賴文檔結構: 對于非結構化文檔或結構混亂的文檔,無法應用。

class HierarchicalChunk:
    def __init__(self, content, level, title=None, children=None):
        self.content = content
        self.level = level
        self.title = title
        self.children = children if children isnotNoneelse []

    def __repr__(self):
        returnf"Level {self.level} '{self.title or self.content[:30]}...'"

def parse_markdown_hierarchy(text):
    """
    解析Markdown文本,構建分層結構。
    返回一個包含頂級HierarchicalChunk對象的列表。
    """
    lines = text.split('\n')
    
    # 存儲當前的層級路徑,方便構建嵌套結構
    # Stack stores (level, parent_chunk)
    root_chunks = []
    current_path = [(0, None)] # (level, parent_chunk)

    for line in lines:
        stripped_line = line.strip()
        ifnot stripped_line:
            continue

        match = re.match(r'^(#+)\s*(.*)$', stripped_line)
        if match:
            level = len(match.group(1)) # 標題級別
            title = match.group(2).strip()
            
            new_chunk = HierarchicalChunk(cnotallow="", level=level, title=title)
            
            # 回溯到正確的父級
            while current_path and current_path[-1][0] >= level:
                current_path.pop()

            if current_path and current_path[-1][1]: # 有父級
                current_path[-1][1].children.append(new_chunk)
            else: # 頂級標題
                root_chunks.append(new_chunk)
            
            current_path.append((level, new_chunk))
        else: # 普通內容,添加到當前最低層級塊的內容
            if current_path and current_path[-1][1]:
                # 如果是第一個內容行,直接賦值,否則追加
                if current_path[-1][1].content:
                    current_path[-1][1].content += "\n" + line
                else:
                    current_path[-1][1].content = line
            else: # 沒有標題的開頭內容,作為頂級塊
                ifnot root_chunks or root_chunks[-1].level != 0or root_chunks[-1].title: # 如果沒有頂級塊或者上一個是標題,就創建一個新的
                     root_chunks.append(HierarchicalChunk(cnotallow=line, level=0))
                else: # 追加到第一個無標題頂級塊
                     root_chunks[-1].content += "\n" + line

    # 遞歸清理并整合內容
    def consolidate_chunks(chunk_list):
        final_chunks = []
        for chunk in chunk_list:
            # 將標題本身和內容整合到content中
            full_content = ""
            if chunk.title:
                full_content += "#" * chunk.level + " " + chunk.title + "\n"
            full_content += chunk.content.strip()
            
            if full_content: # 確保內容不為空
                 final_chunks.append(HierarchicalChunk(full_content, chunk.level, chunk.title))
            
            if chunk.children:
                final_chunks.extend(consolidate_chunks(chunk.children))
        return final_chunks

    return consolidate_chunks(root_chunks)


print("\n--- 20. 分層切塊 ---")
# 使用一個更適合分層切塊的結構化文本
hierarchical_text = """
# 第一章 RAG概述
RAG是一種強大的AI技術。

## 1.1 RAG的原理
結合檢索和生成。
### 1.1.1 檢索部分
從知識庫中獲取信息。

## 1.2 RAG的優勢
減少幻覺,提升準確性。

# 第二章 切塊策略
切塊是RAG的關鍵一步。
"""
hierarchical_chunks = parse_markdown_hierarchy(hierarchical_text)
for i, chunk_obj in enumerate(hierarchical_chunks):
    print(f"Chunk {i+1} (Level {chunk_obj.level}, Title: '{chunk_obj.title}'):\n'{chunk_obj.content}'")

RAG調優進階:21種切塊策略,不光有代碼,更有超詳細場景、優缺點分析!-AI.x社區

21. 模態感知切塊(Modality-Aware Chunking):

  • 場景使用:適用于包含不同類型數據(文本、圖像、表格、圖表、代碼等)的多模態文檔,如多媒體報告、帶有圖表的PDF文檔、網頁內容。當每種模態的信息都需要以其最適合的方式處理(例如,文本切塊,圖像生成描述,表格轉換為結構化數據)時,這種方法至關重要。
  • 優點:

     a.優化信息處理: 針對不同模態采用最佳處理方式,確保每種信息的完整性和可讀性。

     b,提升多模態檢索: 能夠支持跨模態的查詢,例如查詢“關于產品銷量的圖表”。

     c.豐富LLM上下文: 為LLM提供更全面的信息視圖,包括文本描述和結構化數據。

  • 缺點:

      a.實現最復雜: 需要圖像識別、表格檢測、文本內容分析等多種技術結合,甚至需要多模態LLM支持。

      b.工具依賴: 需要集成多個不同的解析庫和AI模型。

      c.成本高昂: 多模態處理通常涉及更復雜的模型和更高的計算資源。

def modality_aware_chunking(text):
    """
    分離不同模態的內容(文本、表格)。
    這里只處理文本和Markdown表格。
    """
    chunks = []
    lines = text.split('\n')
    current_chunk_lines = []
    
    in_table_block = False

    for line in lines:
        stripped_line = line.strip()

        # 檢查是否是Markdown表格行
        is_table_line = stripped_line.startswith('|') and'|'in stripped_line[1:]

        if is_table_line:
            ifnot in_table_block:
                # 結束之前的文本塊
                if current_chunk_lines:
                    chunks.append({"type": "text", "content": "\n".join(current_chunk_lines).strip()})
                    current_chunk_lines = []
                in_table_block = True
            current_chunk_lines.append(line)
        else:
            if in_table_block:
                # 結束表格塊
                if current_chunk_lines:
                    chunks.append({"type": "table", "content": "\n".join(current_chunk_lines).strip()})
                    current_chunk_lines = []
                in_table_block = False
            current_chunk_lines.append(line)

    # 處理最后一個塊
    if current_chunk_lines:
        chunk_type = "table"if in_table_block else"text"
        chunks.append({"type": chunk_type, "content": "\n".join(current_chunk_lines).strip()})
        
    return [chunk for chunk in chunks if chunk['content']]

print("\n--- 21. 模態感知切塊 ---")
chunks_modality = modality_aware_chunking(sample_text_mixed_format)
for i, chunk in enumerate(chunks_modality):
    print(f"Chunk {i+1} (Type: {chunk['type']}):\n'{chunk['content']}'")


BONUS:混合切塊(Hybrid Chunking):集大成者,無往不利!

  • 場景使用:當你的數據非常復雜,單一的切塊策略無法完美解決問題時。這是一種實踐中非常常見的方案,你可以根據具體的數據特點和業務需求,靈活地組合上述一種或多種策略。比如,先用段落切塊,再對過長的段落進行遞歸切塊;或者先識別表格并單獨處理,然后對剩余文本進行語義切塊。
  • 優點:

     a.高度定制化: 可以根據特定文檔類型和應用場景,設計出最匹配的切塊流程。

     b.兼顧多種需求: 結合不同策略的優勢,在語義完整性、塊大小、處理效率等方面找到最佳平衡。

     c.解決復雜問題: 能有效應對單一策略無法處理的復雜文檔結構和內容。

  • 缺點:

     a.實現和調試復雜: 組合多種策略會顯著增加代碼的復雜性和調試難度。

     b.參數調優: 多個策略的參數需要協同調優,工作量大。

     c.無通用模板: 混合切塊是高度定制的,沒有一個放之四海而皆準的方案。

def hybrid_chunking(text, primary_strategy, secondary_strategy, primary_args={}, secondary_args={}):
    """
    混合切塊策略示例:先用一種策略粗切,再用另一種策略細切。
    primary_strategy: 第一階段切塊函數 (如 paragraph_based_chunking)
    secondary_strategy: 第二階段切塊函數 (如 recursive_chunking)
    """
    # 步驟1:用主要策略進行粗粒度切塊
    coarse_chunks = primary_strategy(text, **primary_args)
    
    final_chunks = []
    # 步驟2:對每個粗粒度塊,再用次要策略進行細粒度切塊
    for chunk in coarse_chunks:
        # 如果粗粒度塊仍然太大或需要進一步細分
        if len(chunk) > 500: # 假設一個啟發式條件,可以根據token數或語義復雜度來定
            # 注意:這里需要確保secondary_strategy能夠處理傳入的參數
            fine_grained_chunks = secondary_strategy(chunk, **secondary_args)
            final_chunks.extend(fine_grained_chunks)
        else:
            final_chunks.append(chunk)
            
    return [chunk for chunk in final_chunks if chunk.strip()]

print("\n--- BONUS: 混合切塊 ---")
# 示例:先按段落切塊,然后對超過一定長度的段落進行遞歸切塊
chunks_hybrid = hybrid_chunking(
    sample_text_long + sample_text_structured,
    primary_strategy=paragraph_based_chunking,
    primary_args={}, # 段落切塊不需要額外參數
    secondary_strategy=recursive_chunking,
    secondary_args={'separators': ['. ', ','], 'max_chunk_size_char': 200}
)

for i, chunk in enumerate(chunks_hybrid[:5]):
    print(f"Chunk {i+1} (len={len(chunk)}):\n'{chunk}'")
print("...")

深入理解每種切塊策略的應用場景、優缺點,再結合代碼實現,你就能在RAG的實踐中更加游刃有余。記住,切塊是RAG成功的基石之一,選擇合適的策略,往往能讓你的RAG系統事半功倍!

本文轉載自??Halo咯咯??    作者:基咯咯

?著作權歸作者所有,如需轉載,請注明出處,否則將追究法律責任
已于2025-8-25 08:50:38修改
收藏
回復
舉報
回復
相關推薦
av资源一区| 热久久免费视频精品| 国产一区香蕉久久| 催眠调教后宫乱淫校园| 最新中文字幕免费| 国产 日韩 欧美 综合 一区| 免费观看日韩电影| 精品丝袜一区二区三区| 国产在线视频综合| 国产精品玖玖玖| 欧美综合在线视频观看| 欧美日韩国产综合新一区| av一区二区在线看| 亚洲天堂网av在线| 激情久久一区二区| 国产免费观看久久| 日韩暖暖在线视频| 中文字幕一区二区人妻电影丶| 黄色av网站在线播放| 蜜桃久久av一区| 久久人人看视频| 国产男女无遮挡猛进猛出| 尤物网在线观看| 麻豆91小视频| 北条麻妃在线一区二区| 亚洲xxx在线观看| 毛片在线不卡| 狠狠狠色丁香婷婷综合久久五月| 亚洲香蕉成视频在线观看| 国产精品-区区久久久狼| 青青操视频在线| 性欧美videos另类喷潮| 亚洲男人第一av网站| 激情婷婷综合网| 东热在线免费视频| 极品少妇xxxx偷拍精品少妇| 欧美中文在线观看国产| 久久久久久久久久久久久久免费看 | 国产污视频在线看| 99香蕉久久| 黄网站色欧美视频| 精品蜜桃一区二区三区| 精品成人av一区二区在线播放| 亚洲图片久久| 欧美色图在线观看| 日本xxxxx18| 人妻无码中文字幕| 久久精品三级| 综合久久五月天| 中文字幕在线播放一区二区| 香蕉成人在线| 一区二区三区精品| 精品视频一区在线| 天天操天天插天天射| 日韩精品视频网| 欧美床上激情在线观看| 奇米777第四色| 一区二区三区自拍视频| 色香蕉久久蜜桃| 亚洲人成人77777线观看| 国产白浆在线观看| 国产九九精品| 精品国产一区av| 黑人狂躁日本娇小| 真实国产乱子伦精品一区二区三区| 精品捆绑美女sm三区| 国产一区视频免费观看| 我爱我色成人网| 国产精品久久久久影视| 国产一区二区免费电影| 在线免费a视频| 亚洲人成高清| 精品国模在线视频| 亚洲天堂成人av| www一区二区三区| 色综合久久中文字幕| 色综合av综合无码综合网站| 日本另类视频| 亚洲成人综合网站| 欧美性视频在线播放| 欧美在线观看在线观看| 国产欧美一区二区精品秋霞影院 | 亚洲综合一区在线| 精品国产一区三区| 免费在线看a| 亚洲精品欧美在线| 日韩欧美一区二区视频在线播放| 肥臀熟女一区二区三区| 麻豆精品国产91久久久久久| 91久久久精品| 国产精品51麻豆cm传媒| 精品一区二区在线看| 日本最新高清不卡中文字幕| 影音先锋国产资源| 懂色av一区二区三区免费看| 45www国产精品网站| 麻豆亚洲av熟女国产一区二| 日韩精品影视| 亚洲午夜色婷婷在线| 日本裸体美女视频| 成人在线免费小视频| 亚洲色图av在线| 老鸭窝一区二区| 久久久精品国产**网站| 精品伦理精品一区| 日本精品在线观看视频| 日韩成人动漫在线观看| 精品99一区二区| 国产xxx在线观看| 日本成人精品| 日韩欧美综合在线| 日本女人黄色片| 欧一区二区三区| 在线播放日韩欧美| 欧美人与性囗牲恔配| 牛夜精品久久久久久久99黑人| 久久九九亚洲综合| 国产免费一级视频| 久久久久在线| 粉嫩av四季av绯色av第一区| www.色播.com| 岛国一区二区三区| 一区二区三区欧美成人| 午夜影院一区| 91福利区一区二区三区| 国产精品涩涩涩视频网站| 欧美最新精品| 欧美三区在线视频| 一本色道久久综合亚洲精品图片 | 国产av熟女一区二区三区| 成人国产一区二区三区精品麻豆| 日本丰满少妇一区二区三区| 制服丝袜在线第一页| 国产精品伦理久久久久久| 久久精品小视频| 国产污视频网站| 91亚洲精品乱码久久久久久蜜桃| 久久青青草综合| 成人综合影院| 亚洲视频一二区| 免费看欧美黑人毛片| 日韩伦理精品| 精品视频免费在线| 免费一级特黄3大片视频| 亚洲国产精品久久久天堂| 国模精品视频一区二区| 国产精品自产拍| 国产精品久久久久9999吃药| 国产精品啪啪啪视频| 国产高清中文字幕在线| 色婷婷av一区二区三区软件| 午夜一区二区三区免费| 中文一区在线| 久久久com| 欧美xxx网站| 亚洲欧美资源在线| 久久精品99北条麻妃| 国产视频亚洲色图| av在线免费观看国产| 国产精品亚洲综合在线观看| 亚洲精品久久视频| 欧美巨胸大乳hitomi| 极品av少妇一区二区| 国产精品久久久久一区二区| 国产高潮流白浆喷水视频| 亚洲男同性视频| 国产成人av免费观看| 精品电影一区| 蜜桃导航-精品导航| 在线看免费av| 亚洲二区在线视频| 色噜噜在线观看| 日韩不卡一区二区三区| 亚洲一卡二卡| 色播一区二区| 26uuu另类亚洲欧美日本一| 国产69久久| 日韩一区二区免费视频| 国产精品99精品| 久久亚洲精精品中文字幕早川悠里 | 欧美视频一二区| 欧美视频中文字幕在线| 亚洲综合123| 国产精品一区二区三区av麻 | 成人超碰在线| 欧美日本一道本| 91久久免费视频| 亚洲成色精品| 日本一区免费在线观看| 超碰在线网站| 一区二区三区 在线观看视| 97国产精品久久久| 国产日韩精品久久久| 成人av毛片在线观看| 国产伦一区二区三区| 成人动漫网站在线观看| 成人免费黄色网页| 日韩欧美中文一区| aaa在线视频| 一区二区三区久久久| 熟女俱乐部一区二区| 国内精品国产成人| www.四虎成人| 艳女tv在线观看国产一区| 蜜桃麻豆www久久国产精品| 99精品视频在线免费播放| 2019亚洲日韩新视频| 老司机在线看片网av| 亚洲精品一区二区网址| av一级黄色片| 欧美日韩一区二区三区高清| 日韩黄色精品视频| 国产黄色精品视频| 欧美一级黄色录像片| 自拍偷拍精品| av免费精品一区二区三区| 成人1区2区| 91高清视频免费观看| 深夜福利免费在线观看| 91精品国模一区二区三区| 极品色av影院| 国产调教视频一区| 黄色录像a级片| 亚洲一卡久久| 黄色三级中文字幕| 午夜精品视频一区二区三区在线看| 久久久久久久久久久一区| 视频国产精品| 69堂成人精品视频免费| 美女尤物在线视频| 日韩大陆毛片av| 精品人妻久久久久一区二区三区| 欧美日韩精品福利| 中文字幕av片| 亚洲激情男女视频| 亚洲最大视频网| 另类成人小视频在线| 欧美伦理视频在线观看| 性一交一乱一区二区洋洋av| 青青青青在线视频| 欧美搞黄网站| 欧洲金发美女大战黑人| 天天做天天爱天天爽综合网| 天天爽天天狠久久久| 91丨精品丨国产| 国产久一一精品| 另类视频在线| 九九视频直播综合网| 日本一本草久在线中文| 亚洲黄色www| www.欧美色| 色婷婷精品久久二区二区蜜臀av| 日韩欧美亚洲视频| 国产精品久久久爽爽爽麻豆色哟哟 | 中文字幕少妇一区二区三区| 精品av中文字幕在线毛片 | 性生活免费在线观看| 欧美大片一区| 欧美一区二区激情| 99成人在线| 日本xxx免费| 欧美淫片网站| 国产妇女馒头高清泬20p多| 波多野结衣一区| 日韩精品一线二线三线| 第一sis亚洲原创| 日日噜噜噜夜夜爽爽| 欧美三级不卡| 日韩欧美三级一区二区| 成人羞羞在线观看网站| 一区二区三区免费看| 欧美~级网站不卡| av高清在线免费观看| 性xx色xx综合久久久xx| 99视频精品免费| 韩国女主播成人在线| 久久久久亚洲无码| 国产喂奶挤奶一区二区三区| 正在播放国产对白害羞| 亚洲精品成人悠悠色影视| 国产在线观看免费视频今夜| 一本色道a无线码一区v| 亚洲天堂网视频| 精品欧美黑人一区二区三区| 日本在线丨区| 久久久国产一区| 国产免费拔擦拔擦8x在线播放 | 最新亚洲国产精品| 五月婷婷在线播放| 日韩亚洲欧美一区二区三区| 黄色av中文字幕| 亚洲一区二区国产| 天堂av资源在线观看| 精品国产欧美成人夜夜嗨| 牛牛精品在线| 国产精品无av码在线观看| 亚洲三区欧美一区国产二区| 欧美日韩日本网| 综合国产视频| 成人高清dvd| 天使萌一区二区三区免费观看| 男人添女人下部高潮视频在观看| 日韩和欧美一区二区| 女同性αv亚洲女同志| 国产日韩欧美综合在线| 国产一级aa大片毛片| 欧美系列亚洲系列| 中文字幕av在线免费观看| 精品成人私密视频| 免费观看在线午夜影视| 欧美做爰性生交视频| 亚洲午夜精品| 一区二区三区国| 天堂成人国产精品一区| 女性生殖扒开酷刑vk| 99久久精品费精品国产一区二区| 五月婷婷综合激情网| 色综合久久综合| 天天干天天干天天干| 欧美成人久久久| 久久青草免费| 性刺激综合网| 久久久久久久欧美精品| 黄色免费视频网站| 亚洲精品乱码久久久久久日本蜜臀| 最好看的日本字幕mv视频大全| 日韩电视剧免费观看网站| 黄色影院在线看| 成人在线视频电影| 亚洲欧洲中文字幕| 在线看免费毛片| 中文字幕+乱码+中文字幕一区| 亚洲区一区二区三| 欧美伊人精品成人久久综合97 | 男操女视频网站| 欧美日韩1区2区| 色影视在线观看| 国产免费一区二区三区在线能观看| 免费短视频成人日韩| 一区二区不卡在线观看| 蜜桃精品在线观看| 欧美日韩国产黄色| 在线观看中文字幕不卡| 一级全黄少妇性色生活片| 中文日韩电影网站| 亚洲电影有码| 婷婷久久伊人| 久久精品国内一区二区三区| 亚洲黄色网址大全| 欧美日韩国产一级二级| 欧美成人hd| 亚洲aaaaaa| 久久93精品国产91久久综合| 国产视频九色蝌蚪| 黄色日韩网站视频| www.xxxx日本| 色哟哟一区二区| www 日韩| 成人久久久久久| 综合视频在线| 国产大学生视频| 色成人在线视频| 一级日本在线| 成人网欧美在线视频| 午夜精品国产| 无码人妻aⅴ一区二区三区| 日本韩国精品在线| 四虎久久免费| 波多野结衣精品久久| 亚洲人成在线影院| 欧美做受高潮6| 午夜久久福利影院| av观看在线免费| 国外成人免费在线播放| 夜夜春成人影院| 久久撸在线视频| 亚洲综合色自拍一区| 欧美孕妇孕交xxⅹ孕妇交| 国产日韩在线看片| 黄色在线成人| 三级网站免费看| 欧美日韩裸体免费视频| av在线免费观看网| 91视频网页| 日韩精品免费视频人成| 国产性生活大片| 日韩激情视频在线播放| 国产精品高潮久久| 免费看欧美一级片| 国产女人18水真多18精品一级做| 精品国产av 无码一区二区三区 | 亚洲欧洲日韩国产| 成人豆花视频| 一女被多男玩喷潮视频| 中文字幕在线观看一区| 婷婷伊人综合中文字幕| 成人午夜激情免费视频| 免费在线亚洲| 九九视频在线观看| 色偷偷噜噜噜亚洲男人|