精品欧美一区二区三区在线观看 _久久久久国色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修改
收藏
回復
舉報
回復
相關推薦
91免费看国产| 日韩色视频在线观看| 国产在线视频91| av资源在线免费观看| 成人黄色免费观看| 久久―日本道色综合久久| 国产精品jizz在线观看麻豆| 特级西西www444人体聚色| 美女久久久久久| 亚洲视频资源在线| 国产美女精品久久久| 你懂的国产视频| 精品国产一区二区三区噜噜噜| 欧美性生活大片视频| 亚洲一卡二卡| 亚洲精品字幕在线| 免费在线欧美黄色| 色妞欧美日韩在线| 国产一精品一aⅴ一免费| 色是在线视频| 亚洲天天做日日做天天谢日日欢 | 99re视频在线播放| av大片免费观看| 色777狠狠狠综合伊人| 欧美v国产在线一区二区三区| 精品中文字幕av| 黄色在线观看网站| 懂色av中文一区二区三区| 欧美尤物巨大精品爽| 国产精品无码无卡无需播放器| 欧美日本三级| 在线观看国产精品网站| 国产片侵犯亲女视频播放| 美国一级片在线免费观看视频| 国产综合久久久久影院| 欧美一级电影久久| 极品久久久久久| 国产精品密蕾丝视频下载| 欧美一区二区三区视频免费播放| 男人揉女人奶房视频60分| av在线麻豆| 国产亚洲福利社区一区| 国产精品对白刺激久久久| 综合久久中文字幕| 亚洲尤物影院| 欧美—级a级欧美特级ar全黄| 国产精品www爽爽爽| 精品视频在线播放一区二区三区| 日韩欧美福利视频| 亚洲区成人777777精品| 亚洲av片在线观看| 国产九九视频一区二区三区| 国产精品日韩在线观看| 欧产日产国产69| 18成人免费观看视频| 另类色图亚洲色图| 亚洲欧美卡通动漫| 精品久久电影| 一本色道久久综合狠狠躁篇的优点| 视频免费在线观看| 57pao国产一区二区| 欧美日韩一区二区在线视频| 成人在线观看a| 国产网站在线| 亚洲国产日韩av| 日韩亚洲欧美一区二区| 欧美三级黄网| 国产精品毛片a∨一区二区三区| 蜜桃视频在线观看91| 欧美在线 | 亚洲| 国产盗摄一区二区三区| 亚洲v日韩v综合v精品v| 999久久久久| 久久国产精品一区二区| 国产一区视频在线播放| 在线观看国产小视频| 青青草精品视频| 国产精品久久久久91| 免费看日批视频| 久久久久久久欧美精品| 日产精品久久久一区二区福利| 免费视频久久久| 久久免费国产| 国产精品久久999| 亚洲午夜在线播放| 精彩视频一区二区三区| 91欧美精品成人综合在线观看| 亚洲自拍第二页| 国产在线精品免费| 国产精品成人免费视频| 一本一道精品欧美中文字幕| 国产中文字幕精品| 国产九色91| 你懂的视频在线| 久久久久久97三级| 日韩欧美一区二区三区四区| 国产三级视频在线播放线观看| 2020国产精品自拍| 欧美亚洲精品日韩| 日本最新在线视频| 亚洲你懂的在线视频| 成人免费a级片| 日韩影院在线| 欧美日韩一区高清| 欧美激情 亚洲| 美女久久久久| 久久精品美女视频网站| 国产一级在线播放| 性色一区二区三区| 成人免费福利在线| 男人天堂一区二区| 国产日韩一级二级三级| 色乱码一区二区三区熟女| 欧美高清另类hdvideosexjaⅴ| 精品久久久一区二区| 九九热精品在线播放| av不卡一区二区| 国产亚洲a∨片在线观看| 欧美亚洲日本在线| 老司机午夜免费精品视频 | 伊人色综合影院| 丝袜综合欧美| 色伊人久久综合中文字幕| 一级黄色在线播放| 你微笑时很美电视剧整集高清不卡 | 青青在线视频免费观看| 国产韩日精品| 亚洲福利在线视频| 亚洲一二三在线观看| 免费视频久久| 国产99在线免费| 日本黄色片在线观看| 午夜视频在线观看一区二区三区| wwww.国产| 卡通动漫精品一区二区三区| 日韩在线视频中文字幕| 中文字幕在线观看视频网站| 国产一区二区调教| 五月天色一区| 在线手机中文字幕| 精品国一区二区三区| 精品人体无码一区二区三区| 国产精品一页| 国产福利久久精品| 黄色免费在线观看| 欧美日韩在线播放一区| 美女脱光内衣内裤| 在线看片一区| 91精品免费| 99福利在线| 欧美日韩一区二区在线观看 | 久久亚洲一区二区三区四区| 久久av综合网| av成人综合| 欧美另类在线播放| 国产精品九九九九| 欧美激情在线免费观看| 欧美性久久久久| 日本国产精品| 77777亚洲午夜久久多人| www.国产视频| 亚洲精品国产a| 成人性生交视频免费观看| 日韩av在线中文字幕| 国产精品wwwwww| av播放在线| 欧美日韩一卡二卡| 69xxx免费| 奇米影视7777精品一区二区| 欧美日韩国产综合在线| 厕沟全景美女厕沟精品| 亚洲香蕉在线观看| 日韩中文字幕高清| 欧美激情中文不卡| 亚洲性图一区二区| 欧美独立站高清久久| 国产欧洲精品视频| 久操视频在线免费播放| 91福利小视频| gv天堂gv无码男同在线观看| 日韩成人一区二区| 新呦u视频一区二区| 国产成人精选| 欧美成人免费va影院高清| 99产精品成人啪免费网站| 洋洋成人永久网站入口| 欧美性生交xxxxx| 国产人成精品一区二区三| 免费久久99精品国产自| 播放一区二区| 久久亚洲精品视频| 国产小视频免费观看| 午夜精品免费在线| 久久久久亚洲av无码a片| 黄页视频在线91| 久久综合久久久久| 免费看av成人| 国产日韩欧美日韩| 免费在线国产视频| 日韩精品中文在线观看| 亚洲精品国产精品乱码视色| 1000部国产精品成人观看| 三上悠亚 电影| 亚洲综合好骚| 伊人情人网综合| 成人av地址| 久久久久亚洲精品成人网小说| 亚洲av成人精品一区二区三区在线播放| 一本大道综合伊人精品热热| 五月天免费网站| 久久99精品久久久久久| 国产又大又长又粗又黄| 久久精品亚洲成在人线av网址| 国产999视频| 在线观看电影av| 亚洲精品小视频| 国产精品美女一区| 欧美午夜久久久| 加勒比婷婷色综合久久| 久久久影院官网| 欧美老女人bb| 蜜桃视频一区二区| 成人午夜精品久久久久久久蜜臀| 成人嫩草影院| 国产精品一区二区三区免费| 狠狠久久综合| 51精品国产黑色丝袜高跟鞋| 蜜桃视频在线观看www社区| 日韩精品欧美国产精品忘忧草 | 石原莉奈在线亚洲二区| 欧美极品少妇无套实战| 日韩激情在线| 免费看污久久久| 亚洲综合网站| 成人精品福利视频| 这里有精品可以观看| 欧美激情喷水视频| 国产理论在线观看| 在线观看欧美www| 亚洲日本香蕉视频| 日韩欧美国产综合在线一区二区三区| 黄色小说在线观看视频| 日韩美女视频一区| 少妇精品无码一区二区免费视频| 99精品在线观看视频| 天天爽夜夜爽视频| 久久国产综合精品| 免费日韩视频在线观看| 伊人久久久大香线蕉综合直播| 资源网第一页久久久| 欧美视频网址| 精品中文字幕人| 超碰一区二区三区| 99热在线国产| 欧美大片91| 国产免费一区二区三区香蕉精| 性爽视频在线| 91精品国产高清久久久久久91| 色老头在线观看| 欧美美女操人视频| 国产精品久久久久久福利| 中文字幕日韩欧美在线| 国产福利第一视频在线播放| 亚洲欧美中文字幕| 欧美精品a∨在线观看不卡| 亚洲精品久久久一区二区三区| 丰满人妻一区二区| 亚洲成人av资源网| 熟妇高潮一区二区三区| 亚洲激情自拍图| 天堂av资源网| 日韩精品在线免费观看| 欧美另类自拍| 国产一区二区黄| www.亚洲.com| 日韩有码视频在线| 黄色网在线免费观看| 久久天天躁狠狠躁夜夜爽蜜月| 国内精品久久久久国产| 欧美成人亚洲成人日韩成人| 2020国产在线视频| 久久全球大尺度高清视频| 51av在线| 国产极品精品在线观看| 成人黄色视屏网站| 成人有码在线视频| 99久久婷婷国产综合精品青牛牛| 岛国一区二区三区高清视频| 狼人精品一区二区三区在线| 蜜桃导航-精品导航| 日韩国产一区二区| 蜜桃视频一区二区在线观看| 一本色道久久综合| 少妇高潮毛片色欲ava片| 日精品一区二区| 五月天激情播播| 国产福利视频一区二区三区| 国产精品无码一区二区三| 国产亚洲婷婷免费| 韩国一级黄色录像| 亚洲国产成人91porn| 国产一级片免费在线观看| 欧美剧情片在线观看| 熟妇高潮一区二区三区| 最新国产成人av网站网址麻豆| 在线中文字幕视频观看| 91av视频导航| www.成人在线.com| 精品国产免费久久久久久尖叫| 欧洲杯半决赛直播| 欧美亚洲色图视频| 视频一区二区三区中文字幕| 少妇高潮一69aⅹ| 久久久久国产精品厨房| www.毛片com| 日本道色综合久久| 精品国产乱码一区二区三| 国产手机视频精品| a级片国产精品自在拍在线播放| 97avcom| 国产精品视频一区二区三区综合| 老牛影视免费一区二区| 2023国产精品久久久精品双| 国产 福利 在线| 国产一区二区看久久| 精品人伦一区二区三电影| 亚洲夂夂婷婷色拍ww47| 自拍偷拍福利视频| 日韩极品精品视频免费观看| 国精产品一区| 日本久久亚洲电影| 2021年精品国产福利在线| 亚洲午夜在线观看| 久久一区亚洲| 国产精品无码一区二区三| 亚洲黄色在线视频| 青青艹在线观看| 日韩成人激情在线| 欧美黑人猛交| 91精品视频大全| 欧洲grand老妇人| 成年人观看网站| 成人禁用看黄a在线| tube国产麻豆| 欧美日韩国产精品自在自线| 日本一区二区三区在线观看视频| 欧美高清自拍一区| 欧美性xxx| 免费观看成人高| 国产精品日本| 捆绑凌虐一区二区三区| 亚洲国产一区在线观看| 精品人妻一区二区三区浪潮在线| 色综合影院在线| 成人不卡视频| 亚洲精品久久区二区三区蜜桃臀| 亚洲尤物影院| 蜜桃av免费看| 欧美日韩在线免费观看| 人人妻人人澡人人爽人人欧美一区| 在线国产精品视频| 久久91导航| 清纯唯美一区二区三区| 亚洲一区二区成人| 久久精品一区二区免费播放| 精品国产91久久久| 日韩在线观看视频网站| 午夜精品久久久久久久久久久久久| 狂野欧美xxxx韩国少妇| 亚洲一区三区| 国产精品1区2区3区在线观看| 天天干中文字幕| 日韩欧美精品在线| 女囚岛在线观看| 国产精品免费在线| 亚洲精选91| 国产又粗又猛又爽视频| 欧美亚洲禁片免费| 91精品大全| 91亚洲精品在线观看| 欧美激情综合| 稀缺呦国内精品呦| 亚洲综合在线第一页| 日本激情一区二区| 欧美与黑人午夜性猛交久久久| 欧美热在线视频精品999| 中文字幕第38页| 亚洲精品写真福利| 懂色av成人一区二区三区| 77777亚洲午夜久久多人| 欧美亚洲国产激情| 亚洲精品国产久| 五月天一区二区三区| 搞黄视频免费在线观看| 成人黄色片网站| 亚洲全部视频| 色婷婷国产精品免| 精品国产一区二区亚洲人成毛片| 亚洲十八**毛片| 亚洲精品日韩在线观看|