LangChain 文本分割器深度解析:從原理到落地應用(上)

食用指南

LangChain 作為大語言模型應用開發框架,文本分割器是其核心組件之一,本文以此作為切入點,詳細介紹文本分割的作用、策略、以及常見的文本切割器應用。考慮到篇幅過長,故拆分為上、中、下三篇,后續會在中篇介紹代碼拆分與HTML拆分,下篇介紹基于語義拆分與TOKEN拆分。若存在任何內容上的遺漏或錯誤,懇請不吝賜教。

一、概述

文檔分割通常是許多應用中至關重要的預處理步驟。它涉及將大型文本分解為更小、更易于管理的塊。此過程具有多項優勢,例如確保對不同文檔長度進行一致處理、克服模型的輸入大小限制以及提高檢索系統中使用的文本表示的質量。有幾種分割文檔的策略,每種策略都有其自身的優勢。

在這里插入圖片描述

二、為什么要分割文檔?

  • 處理非均勻文檔長度:真實世界的文檔集合通常包含大小不一的文本。分割確保所有文檔的處理一致。
  • 克服模型限制:許多嵌入模型和語言模型都有最大輸入大小約束。分割使我們能夠處理原本會超出這些限制的文檔。
  • 提高表示質量:對于較長的文檔,當它們試圖捕獲太多信息時,嵌入或其他表示的質量可能會下降。分割可以使每個部分的表示更集中和準確。
  • 提高檢索精度:在信息檢索系統中,分割可以提高搜索結果的粒度,從而更精確地將查詢與相關文檔部分匹配。
  • 優化計算資源:處理較小的文本塊可以更節省內存,并允許更好地并行處理任務。

三、分割文檔的策略

1、基于長度

最直觀的策略是根據文檔的長度進行分割。這種簡單而有效的方法確保每個塊不超過指定的尺寸限制。

基于長度分割的關鍵優勢:

  • 實施簡單直接
  • 塊大小一致
  • 易于適應不同的模型要求

基于長度的分割類型:

  • 基于 Token:基于 token 數量分割文本,這在使用語言模型時非常有用。
  • 基于字符:基于字符數分割文本,這在不同類型的文本中可能更一致。

使用 LangChainCharacterTextSplitter 進行基于 token 分割的示例實現:

from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(encoding_name="cl100k_base", chunk_size=100, chunk_overlap=0
)
texts = text_splitter.split_text(document)

2、基于文本結構

文本自然地組織成層次結構單元,例如段落、句子和單詞。我們可以利用這種固有的結構來指導我們的分割策略,創建保持自然語言流暢性、在分割中保持語義連貫性并適應不同文本粒度級別的分割。

LangChainRecursiveCharacterTextSplitter 實現了這個概念:

  • RecursiveCharacterTextSplitter 嘗試保持較大的單元(例如,段落)完整。
  • 如果一個單元超過塊大小,它將移動到下一個級別(例如,句子)。
  • 如有必要,此過程將繼續向下到單詞級別。

這是一個示例用法:

from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
texts = text_splitter.split_text(document)

3、基于文檔結構

某些文檔具有固有的結構,例如 HTMLMarkdownJSON 文件。在這些情況下,根據文檔的結構進行分割是有益的,因為它通常自然地將語義相關的文本分組。

基于結構分割的關鍵優勢:

  • 保留文檔的邏輯組織
  • 在每個塊中維護上下文
  • 對于檢索或摘要等下游任務可能更有效

基于結構的分割示例:

  • Markdown:基于標題(例如,#、##、###)分割
  • HTML:使用標簽分割
  • JSON:按對象或數組元素分割
  • 代碼:按函數、類或邏輯塊分割

4、基于語義含義

與以前的方法不同,基于語義的分割實際上考慮了文本的內容。雖然其他方法使用文檔或文本結構作為語義含義的代理,但此方法直接分析文本的語義。有幾種方法可以實現這一點,但從概念上講,該方法是在文本含義發生重大變化時分割文本。

例如,我們可以使用滑動窗口方法生成嵌入,并比較嵌入以找到顯著差異:

  • 從前幾個句子開始并生成嵌入。
  • 移動到下一組句子并生成另一個嵌入(例如,使用滑動窗口方法)。
  • 比較嵌入以找到顯著差異,這表明語義部分之間可能存在“斷點”。

這項技術有助于創建語義上更連貫的塊,從而可能提高檢索或摘要等下游任務的質量。

四、RecursiveCharacterTextSplitter

RecursiveCharacterTextSplitter 這個 文本拆分器 是通用文本的推薦選擇。它通過字符列表進行參數化。它嘗試按順序拆分它們,直到塊足夠小。默認列表是 ["\n\n", "\n", " ", ""]。這具有盡可能將所有段落(然后是句子,然后是單詞)保持在一起的效果,因為這些通常看起來是語義上最相關的文本片段。

1、通過字符遞歸拆分文本

明確以下兩點:

  1. 文本如何拆分:通過字符列表。
  2. 塊大小如何測量:通過字符數。

下面是一個使用例子:

pip install -qU langchain-text-splitters
from langchain_text_splitters import RecursiveCharacterTextSplitter# Load example document
with open("SpongeBobAndPatrick.txt") as f:sponge_bob_and_patrick = f.read()text_splitter = RecursiveCharacterTextSplitter(# Set a really small chunk size, just to show.chunk_size=100,chunk_overlap=20,length_function=len,is_separator_regex=False,
)# 創建 LangChain Document 對象(例如,用于下游任務)
texts = text_splitter.create_documents([sponge_bob_and_patrick])
print(texts[0])
print(texts[1])
page_content='SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series'
page_content='animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge'

要直接獲取字符串內容,請使用 .split_text

text_splitter.split_text(sponge_bob_and_patrick)[:2]
['SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series','animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge']

讓我們回顧一下上面為 RecursiveCharacterTextSplitter 設置的參數:

  • chunk_size:塊的最大大小,其中大小由 length_function 確定。
  • chunk_overlap:塊之間的目標重疊。重疊塊有助于減輕上下文在塊之間劃分時信息丟失。
  • length_function:確定塊大小的函數。
  • is_separator_regex:分隔符列表(默認為 ["\n\n", "\n", " ", ""])是否應解釋為正則表達式。

2、從沒有詞界符的語言拆分文本

一些書寫系統沒有 詞界符,例如中文、日語和泰語。使用默認分隔符列表 ["\n\n", "\n", " ", ""] 拆分文本可能會導致單詞在塊之間被拆分。為了保持單詞完整,我們需要覆蓋分隔符列表以包含其他標點符號:

  • 添加 ASCII 句點".“,Unicode 全角 句點”."(用于中文文本)和 表意文字句點 “。”(用于日語和中文)
  • 添加泰語、緬甸語、高棉語和日語中使用的 零寬度空格
  • 添加 ASCII 逗號",“,Unicode 全角逗號”,“和 Unicode 表意文字逗號”、"
text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n","\n"," ",".",",","\u200b",  # Zero-width space"\uff0c",  # Fullwidth comma"\u3001",  # Ideographic comma"\uff0e",  # Fullwidth full stop"\u3002",  # Ideographic full stop"",],# Existing args# Set a really small chunk size, just to show.chunk_size=100,chunk_overlap=20,length_function=len,is_separator_regex=False,
)# Load example document
with open("海綿寶寶故事.txt") as f:sponge_bob_and_patrick = f.read()texts = text_splitter.create_documents([sponge_bob_and_patrick])
text_splitter.split_text(sponge_bob_and_patrick)[:2]
['有一次海綿寶寶和派大星決定玩"交換身份"游戲。派大星穿上海綿寶寶的方形褲子和領帶,而海綿寶寶則把自己揉成星星形狀。他們互相模仿對方說話方式來到蟹堡王上班,結果:','派大星版的"海綿寶寶"把所有的蟹堡都做成了星星形狀,還理直氣壯地說"這樣更好吃";\n當章魚哥質疑時,他直接躺在地上裝死;']

五、CharacterTextSplitter

這是最簡單的方法。這個 分割器 基于給定的字符序列進行分割,默認為 "\n\n"。塊長度按字符數衡量。

明確以下兩點:

  1. 文本分割方式:按單個字符分隔符。
  2. 塊大小的衡量方式:按字符數。

下面是一個使用例子:

pip install -qU langchain-text-splitters
from langchain_text_splitters import CharacterTextSplitter# Load an example document
with open("SpongeBobAndPatrick.txt") as f:sponge_bob_and_patrick = f.read()text_splitter = CharacterTextSplitter(separator="\n\n",chunk_size=1000,chunk_overlap=200,length_function=len,is_separator_regex=False,
)# 創建 LangChain Document 對象(例如,用于下游任務)
texts = text_splitter.create_documents([sponge_bob_and_patrick])
print(texts[0])
page_content='SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge who lives in a pineapple under the sea in the underwater city of Bikini Bottom. He works as a fry cook at the Krusty Krab and absolutely loves his job. His childlike enthusiasm and naivety often lead him into hilarious misadventures.'

使用 .create_documents 將與每個文檔關聯的元數據傳播到輸出塊:

metadatas = [{"document": 1}, {"document": 2}]
documents = text_splitter.create_documents([sponge_bob_and_patrick, sponge_bob_and_patrick], metadatas=metadatas
)
print(documents[0]) # metadata={'document': 1}
print(documents[1]) # metadata={'document': 1}
print(documents[2]) # metadata={'document': 2}
print(documents[3]) # metadata={'document': 2}
page_content='SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge who lives in a pineapple under the sea in the underwater city of Bikini Bottom. He works as a fry cook at the Krusty Krab and absolutely loves his job. His childlike enthusiasm and naivety often lead him into hilarious misadventures.' metadata={'document': 1}
page_content='Patrick is SpongeBob's dim-witted but lovable best friend - a pink starfish who lives under a rock. Despite his lack of common sense, Patrick always supports SpongeBob through thick and thin. Their friendship is the heart of the show, showcasing unconditional loyalty and the joy of simple pleasures. Whether they're jellyfishing, blowing bubbles, or getting into trouble with Squidward, their antics never fail to entertain. Together, this dynamic duo represents the perfect balance of SpongeBob's energetic optimism and Patrick's laid-back simplicity, making them one of the most memorable cartoon pairs in television history.' metadata={'document': 1}
page_content='SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge who lives in a pineapple under the sea in the underwater city of Bikini Bottom. He works as a fry cook at the Krusty Krab and absolutely loves his job. His childlike enthusiasm and naivety often lead him into hilarious misadventures.' metadata={'document': 2}
page_content='Patrick is SpongeBob's dim-witted but lovable best friend - a pink starfish who lives under a rock. Despite his lack of common sense, Patrick always supports SpongeBob through thick and thin. Their friendship is the heart of the show, showcasing unconditional loyalty and the joy of simple pleasures. Whether they're jellyfishing, blowing bubbles, or getting into trouble with Squidward, their antics never fail to entertain. Together, this dynamic duo represents the perfect balance of SpongeBob's energetic optimism and Patrick's laid-back simplicity, making them one of the most memorable cartoon pairs in television history.' metadata={'document': 2}

使用 .split_text 直接獲取字符串內容:

text_splitter.split_text(sponge_bob_and_patrick)[0]
'SpongeBob SquarePants and Patrick Star are the iconic best friends from the beloved animated series "SpongeBob SquarePants." SpongeBob is an energetic, optimistic yellow sea sponge who lives in a pineapple under the sea in the underwater city of Bikini Bottom. He works as a fry cook at the Krusty Krab and absolutely loves his job. His childlike enthusiasm and naivety often lead him into hilarious misadventures.'

六、MarkdownHeaderTextSplitter

下面是一個按標題拆分 Markdown 的示例。

1、動機

許多聊天或問答應用涉及在嵌入和向量存儲之前對輸入文檔進行分塊,而這些分塊通常旨在將具有共同上下文的文本放在一起。考慮到這一點,我們可能希望特別尊重文檔本身的結構。例如,markdown 文件按標題組織,在特定標題組中創建塊是一個直觀的想法。為了解決這個挑戰,我們可以使用 MarkdownHeaderTextSplitter,這將按指定的標題集拆分 markdown 文件。

例如,如果我們想拆分此 markdown

md = """
# 派大星角色特點詳解## 基本特征
- **外形**:粉紅色五角海星,藍色短褲,無上衣
- **居住地**:比奇堡的石頭屋
- **職業**:無固定工作## 性格特質
1. **天真單純**  - 思維極其簡單直接- 經常說出富有哲理的無心之言- 對復雜事物理解困難2. **樂觀豁達**  - 永遠保持快樂心態- 經典臺詞:"我準備好了!"- 把失敗當作新游戲的開始 
"""

我們可以指定要拆分的標題:

[("#", "Header 1"),("##", "Header 2")]

內容按公共標題分組或拆分:

{'content': '- **外形**:粉紅色五角海星,藍色短褲,無上衣\n- **居住地**:比奇堡的石頭屋\n- **職業**:無固定工作', 'metadata': {'Header 1': '派大星角色特點詳解', 'Header 2': '基本特征'}}
{'content': '1. **天真單純**\n- 思維極其簡單直接\n- 經常說出富有哲理的無心之言\n- 對復雜事物理解困難  \n2. **樂觀豁達**\n- 永遠保持快樂心態\n- 經典臺詞:"我準備好了!"\n- 把失敗當作新游戲的開始'' , 'metadata': {'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}}

讓我們看看下面的一些示例。

2、基本用法

pip install -qU langchain-text-splitters
from langchain_text_splitters import MarkdownHeaderTextSplittermarkdown_document = """
# 派大星角色特點詳解## 基本特征
- **外形**:粉紅色五角海星,藍色短褲,無上衣
- **居住地**:比奇堡的石頭屋
- **職業**:無固定工作## 性格特質
1. **天真單純**  - 思維極其簡單直接- 經常說出富有哲理的無心之言- 對復雜事物理解困難2. **樂觀豁達**  - 永遠保持快樂心態- 經典臺詞:"我準備好了!"- 把失敗當作新游戲的開始 
"""headers_to_split_on = [("#", "Header 1"),("##", "Header 2"),
]markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on)
md_header_splits = markdown_splitter.split_text(markdown_document)
md_header_splits
[Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '基本特征'}, page_content='- **外形**:粉紅色五角海星,藍色短褲,無上衣\n- **居住地**:比奇堡的石頭屋\n- **職業**:無固定工作'),Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}, page_content='1. **天真單純**\n- 思維極其簡單直接\n- 經常說出富有哲理的無心之言\n- 對復雜事物理解困難  \n2. **樂觀豁達**\n- 永遠保持快樂心態\n- 經典臺詞:"我準備好了!"\n- 把失敗當作新游戲的開始')]
type(md_header_splits[0])
langchain_core.documents.base.Document

默認情況下,MarkdownHeaderTextSplitter 會從輸出塊的內容中剝離正在拆分的標題。可以通過設置 strip_headers = False 來禁用此功能。

markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on, strip_headers=False)
md_header_splits = markdown_splitter.split_text(markdown_document)
md_header_splits
[Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '基本特征'}, page_content='# 派大星角色特點詳解  \n## 基本特征\n- **外形**:粉紅色五角海星,藍色短褲,無上衣\n- **居住地**:比奇堡的石頭屋\n- **職業**:無固定工作'),Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}, page_content='## 性格特質\n1. **天真單純**\n- 思維極其簡單直接\n- 經常說出富有哲理的無心之言\n- 對復雜事物理解困難  \n2. **樂觀豁達**\n- 永遠保持快樂心態\n- 經典臺詞:"我準備好了!"\n- 把失敗當作新游戲的開始')]

注意:默認的 MarkdownHeaderTextSplitter 會剝離空格和換行符。要保留 Markdown 文檔的原始格式,請查看 ExperimentalMarkdownSyntaxTextSplitter

3、將 Markdown 行作為單獨的文檔返回

默認情況下,MarkdownHeaderTextSplitter 根據 headers_to_split_on 中指定的標題聚合行。我們可以通過指定 return_each_line 來禁用此功能。

markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on,return_each_line=True,
)
md_header_splits = markdown_splitter.split_text(markdown_document)
md_header_splits
[Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '基本特征'}, page_content='- **外形**:粉紅色五角海星,藍色短褲,無上衣\n- **居住地**:比奇堡的石頭屋\n- **職業**:無固定工作'),Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}, page_content='1. **天真單純**\n- 思維極其簡單直接\n- 經常說出富有哲理的無心之言\n- 對復雜事物理解困難'),Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}, page_content='2. **樂觀豁達**\n- 永遠保持快樂心態\n- 經典臺詞:"我準備好了!"\n- 把失敗當作新游戲的開始')]

請注意,這里的標題信息保留在每個文檔的元數據中。

4、約束塊大小

在每個 markdown 組中,我們可以應用我們想要的任何文本拆分器,例如 RecursiveCharacterTextSplitter,它允許進一步控制塊大小。

markdown_document =  """
# 派大星角色特點詳解## 基本特征
- **外形**:粉紅色五角海星,藍色短褲,無上衣
- **居住地**:比奇堡的石頭屋
- **職業**:無固定工作## 性格特質
1. **天真單純**  - 思維極其簡單直接- 經常說出富有哲理的無心之言- 對復雜事物理解困難2. **樂觀豁達**  - 永遠保持快樂心態- 經典臺詞:"我準備好了!"- 把失敗當作新游戲的開始 
"""headers_to_split_on = [("#", "Header 1"),("##", "Header 2"),
]# Step1、MD splits
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on, strip_headers=False
)
md_header_splits = markdown_splitter.split_text(markdown_document)# Step2、Char-level splits
from langchain_text_splitters import RecursiveCharacterTextSplitterchunk_size = 250
chunk_overlap = 30
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap
)# Split
splits = text_splitter.split_documents(md_header_splits)
splits
[Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '基本特征'}, page_content='# 派大星角色特點詳解  \n## 基本特征\n- **外形**:粉紅色五角海星,藍色短褲,無上衣\n- **居住地**:比奇堡的石頭屋\n- **職業**:無固定工作'),Document(metadata={'Header 1': '派大星角色特點詳解', 'Header 2': '性格特質'}, page_content='## 性格特質\n1. **天真單純**\n- 思維極其簡單直接\n- 經常說出富有哲理的無心之言\n- 對復雜事物理解困難  \n2. **樂觀豁達**\n- 永遠保持快樂心態\n- 經典臺詞:"我準備好了!"\n- 把失敗當作新游戲的開始')]

七、RecursiveJsonSplitter

json 分割器拆分 json 數據,同時允許控制 chunk 大小。它深度優先遍歷 json 數據并構建更小的 json chunk。它嘗試保持嵌套 json 對象完整,但如果需要將 chunk 保持在 min_chunk_sizemax_chunk_size 之間,則會分割它們。

如果值不是嵌套 json,而是一個非常大的字符串,則該字符串不會被分割。如果需要對 chunk 大小進行硬性限制,請考慮將此分割器與這些 chunk 上的 Recursive Text 分割器組合使用。有一個可選的預處理步驟來分割列表,首先將列表轉換為 json(dict),然后像這樣分割它們。

明確以下兩點:

  1. 文本分割方式:json 值。
  2. chunk 大小的度量方式:字符數。
pip install -qU langchain-text-splitters

首先我們加載一些 json 數據:

import jsonimport requests# This is a large nested json object and will be loaded as a python dict
json_data = requests.get("https://api.smith.langchain.com/openapi.json").json()

1、基本用法

指定 max_chunk_size 以約束 chunk 大小:

from langchain_text_splitters import RecursiveJsonSplittersplitter = RecursiveJsonSplitter(max_chunk_size=300)

要獲取 json chunk,請使用 .split_json 方法:

# Recursively split json data - If you need to access/manipulate the smaller json chunks
json_chunks = splitter.split_json(json_data=json_data)for chunk in json_chunks[:3]:print(chunk)
{'openapi': '3.1.0', 'info': {'title': 'LangSmith', 'version': '0.1.0'}, 'paths': {'/api/v1/sessions/{session_id}/dashboard': {'post': {'tags': ['tracer-sessions'], 'summary': 'Get Tracing Project Prebuilt Dashboard', 'description': 'Get a prebuilt dashboard for a tracing project.'}}}}
{'paths': {'/api/v1/sessions/{session_id}/dashboard': {'post': {'operationId': 'get_tracing_project_prebuilt_dashboard_api_v1_sessions__session_id__dashboard_post', 'security': [{'API Key': []}, {'Tenant ID': []}, {'Bearer Auth': []}]}}}}
{'paths': {'/api/v1/sessions/{session_id}/dashboard': {'post': {'parameters': [{'name': 'session_id', 'in': 'path', 'required': True, 'schema': {'type': 'string', 'format': 'uuid', 'title': 'Session Id'}}, {'name': 'accept', 'in': 'header', 'required': False, 'schema': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'title': 'Accept'}}]}}}}

要獲取 LangChain Document 對象(例如,用于下游任務),請使用 .create_documents 方法:

# The splitter can also output documents
docs = splitter.create_documents(texts=[json_data])for doc in docs[:3]:print(doc)
page_content='{"openapi": "3.1.0", "info": {"title": "LangSmith", "version": "0.1.0"}, "paths": {"/api/v1/sessions/{session_id}/dashboard": {"post": {"tags": ["tracer-sessions"], "summary": "Get Tracing Project Prebuilt Dashboard", "description": "Get a prebuilt dashboard for a tracing project."}}}}'
page_content='{"paths": {"/api/v1/sessions/{session_id}/dashboard": {"post": {"operationId": "get_tracing_project_prebuilt_dashboard_api_v1_sessions__session_id__dashboard_post", "security": [{"API Key": []}, {"Tenant ID": []}, {"Bearer Auth": []}]}}}}'
page_content='{"paths": {"/api/v1/sessions/{session_id}/dashboard": {"post": {"parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Session Id"}}, {"name": "accept", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accept"}}]}}}}'

或使用 .split_text 直接獲取字符串內容:

texts = splitter.split_text(json_data=json_data)print(texts[0])
print(texts[1])
{"openapi": "3.1.0", "info": {"title": "LangSmith", "version": "0.1.0"}, "paths": {"/api/v1/sessions/{session_id}/dashboard": {"post": {"tags": ["tracer-sessions"], "summary": "Get Tracing Project Prebuilt Dashboard", "description": "Get a prebuilt dashboard for a tracing project."}}}}
{"paths": {"/api/v1/sessions/{session_id}/dashboard": {"post": {"operationId": "get_tracing_project_prebuilt_dashboard_api_v1_sessions__session_id__dashboard_post", "security": [{"API Key": []}, {"Tenant ID": []}, {"Bearer Auth": []}]}}}}

2、約束列表內容的 chunk 大小

注意,此示例中的一個 chunk 大于指定的 max_chunk_size 300。查看其中一個較大的 chunk(第八個為 469),我們看到那里有一個列表對象:

print([len(text) for text in texts][:10])
print()
print(texts[8]) # chunk 469
[286, 238, 344, 207, 227, 224, 231, 126, 469, 210]{"paths": {"/api/v1/sessions/{session_id}": {"get": {"parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Session Id"}}, {"name": "include_stats", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Include Stats"}}, {"name": "accept", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Accept"}}]}}}}

這是因為默認情況下,json 分割器不分割列表。

我們可以指定 convert_lists=True 預處理 json,將列表內容轉換為以 index:item 作為 key:val 鍵值對的字典。

texts = splitter.split_text(json_data=json_data, convert_lists=True)

讓我們看一下 chunk 的大小,現在它們都在最大值以下:

print([len(text) for text in texts][:10])
[291, 253, 214, 232, 207, 227, 224, 236, 141, 203]

列表已轉換為字典,但即使分成多個 chunk,也保留了所有需要的上下文信息:

print(texts[8])
print(texts[9])
print(texts[10])
{"paths": {"/api/v1/sessions/{session_id}": {"get": {"security": {"0": {"API Key": {}}, "1": {"Tenant ID": {}}, "2": {"Bearer Auth": {}}}}}}}
{"paths": {"/api/v1/sessions/{session_id}": {"get": {"parameters": {"0": {"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid", "title": "Session Id"}}}}}}}
{"paths": {"/api/v1/sessions/{session_id}": {"get": {"parameters": {"1": {"name": "include_stats", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Include Stats"}}}}}}}

補充:中文字符顯示問題

默認情況下,RecursiveJsonSplitter 類中的 create_documents 方法和 split_text 方法參數 ensure_ascii 都設置為 True,這意味著在輸出中所有 非ASCII字符 都會被轉義成\uXXXX 格式的序列。這種行為確保了輸出的 JSON 字符串只包含 ASCII字符,從而可以被任何 JSON 解析器正確解析。

在這里插入圖片描述

當我們希望在 JSON 字符串中保留 非ASCII字符(如中文)時,將 ensure_ascii 設置為False 就可以直接輸出原始的 非ASCII文本 而不是轉義序列。

在這里插入圖片描述

在這里插入圖片描述

參考文檔

  • https://python.langchain.ac.cn/docs/concepts/text_splitters/
  • https://python.langchain.ac.cn/docs/how_to/recursive_text_splitter/
  • https://python.langchain.ac.cn/docs/how_to/character_text_splitter/
  • https://python.langchain.ac.cn/docs/how_to/markdown_header_metadata_splitter/
  • https://python.langchain.ac.cn/docs/how_to/recursive_json_splitter/
  • https://python.langchain.com/api_reference/text_splitters/json/langchain_text_splitters.json.RecursiveJsonSplitter.html#langchain_text_splitters.json.RecursiveJsonSplitter.create_documents

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86120.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86120.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86120.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Java高頻面試問題】高并發篇

【Java高頻面試問題】高并發篇 Kafka原理核心組件高吞吐核心機制高可用設計 Kafka 如何保證消息不丟失如何解決Kafka重復消費一、生產者端:根源防重二、消費者端:精準控制三、業務層:冪等性設計(核心方案) 如何解決Kaf…

關于結構體,排序,遞推的詳細講解(從屬于GESP四級)

本章內容 排序算法基礎 結構體 遞推 簡單雙指針 一、排序算法基礎三劍客 冒泡 Bubble、選擇 Selection、插入 Insertion 1. 預備知識 1.1 排序算法評價指標 指標 含義 影響答題的典型問法 時間復雜度 算法在最壞、平均或最好情況下所需比較 / 交換次數 “寫出此算法…

離線部署docker中的containerd服務

containerd 是一個行業標準的容器運行時,專注于簡單、健壯的容器執行。它是從 Docker 中分離出來的項目,旨在作為一個底層的運行時接口,供更高層次的容器管理層使用。 containerd 負責鏡像傳輸、存儲、容器執行、網絡配置等工作。它向上為 Do…

web布局15

CSS 網格布局除了提供定義網格和放置網格項目的相關屬性之外,也提供了一些控制對齊方式的屬性。這些控制對齊方式的屬性,和 Flexbox 布局中的對齊屬性 justify-* 、align-* 、*-items 、*-content 、 *-self 等是相似的: 在網格布局中可以用它…

leetcode 291. Word Pattern II和290. Word Pattern

目錄 291. Word Pattern II 290. Word Pattern 291. Word Pattern II 回溯法哈希表 class Solution {unordered_map<char,string> hashmap;unordered_set<string> wordset; public:bool wordPatternMatch(string pattern, string s) {return backtrack(pattern,…

大模型的開發應用(十三):基于RAG的法律助手項目(上):總體流程簡易實現

RAG法律助手項目&#xff08;上&#xff09;&#xff1a;總體流程簡易實現 1 項目介紹1.1 方案選型1.2 知識文檔 2 文檔解析3 知識庫構建3.1 構建知識節點3.2 嵌入向量初始化3.2 向量存儲 4 查詢4.1 初始化大模型4.2 模型響應4.2 本文程序存在的問題 完整代碼 1 項目介紹 本項…

覆蓋遷移工具選型、增量同步策略與數據一致性校驗

1 引言 在當今數據驅動的時代&#xff0c;數據遷移已成為系統迭代、數據庫升級、云遷移和架構演進中的關鍵環節。根據Gartner的調研&#xff0c;超過70%的企業級數據遷移項目因工具選擇不當或同步策略缺陷而延期或失敗。數據遷移不僅僅是簡單的數據搬運&#xff0c;而是涉及數…

`docker run -it --rm` 筆記250624

docker run -it --rm 筆記250624 docker run -it --rm 是一個強大且常用的 Docker 命令組合&#xff0c;特別適合交互式開發和調試場景。以下是詳細解析和使用指南&#xff1a; 參數解析 參數作用典型場景-i保持 STDIN 打開&#xff08;交互模式&#xff09;需要輸入命令的交…

解鎖阿里云AnalyticDB:數據倉庫的革新利器

AnalyticDB&#xff1a;云數據倉庫新勢力 在數字化浪潮中&#xff0c;數據已成為企業的核心資產&#xff0c;而云數據倉庫作為數據管理與分析的關鍵基礎設施&#xff0c;正扮演著愈發重要的角色。阿里云 AnalyticDB 作為云數據倉庫領域的佼佼者&#xff0c;以其卓越的性能、創…

【PX30 Qt 5.15 交叉編譯環境搭建完整指南】

PX30 Qt 5.15 交叉編譯環境搭建完整指南 (Ubuntu 20.04 → PX30 aarch64) &#x1f3af; 項目概覽 本指南詳細記錄了在Ubuntu 20.04上搭建針對Rockchip PX30的Qt 5.15.2交叉編譯環境的完整過程&#xff0c;包括實際操作步驟、遇到的問題及解決方案。 目標平臺: Rockchip PX3…

深入理解讀寫鎖 ReadWriteLock

在高性能并發編程中&#xff0c;如何有效地管理共享資源的訪問是核心挑戰之一。傳統的排他鎖&#xff08;如ReentrantLock&#xff09;在讀多寫少的場景下&#xff0c;性能瓶頸尤為突出&#xff0c;因為它不允許并發讀取。Java并發包&#xff08;java.util.concurrent.locks&am…

Unity Addressable使用之檢測更新流程

補充知識 關鍵文件說明 Addressable打包后會生成多種文件&#xff0c;主要包括 .hash、.json 和 .bundle 文件&#xff0c;它們各自有不同的作用。 .hash 文件&#xff08;哈希文件&#xff09; 作用&#xff1a; 用于 版本對比&#xff0c;檢查資源是否有更新。存儲的是 資…

Elasticsearch 中實現推薦搜索(方案設想)

1. 存儲商品數據的數據類型 為了支持推薦搜索&#xff0c;商品數據通常需要包含以下字段&#xff1a; 商品索引結構 PUT /products {"mappings": {"properties": {"product_id": {"type": "keyword" // 商品 ID},"…

Aerotech系列(4)Aerotech.A3200名空間

IconTypeDescriptionAxisMask Represents a selection of axes Controller Represents a controller Allows configuring and c

React Router 是怎么實現靈活導航的?

&#x1f399; 歡迎來到《前端達人 React播客書單》第 21 期。 視頻版&#xff08;播客風格更精彩&#xff09; 今天我們不講 Hook&#xff0c;來拆解前端開發中另一個高頻組件&#xff1a;React Router 的進階導航模式。 你可能用過 <Link> 或 <Route>&#xff0…

Modbus TCP轉Profibus DP網關與JF - 600MT 稱重變送器輕松實現數據互換

Modbus TCP轉Profibus DP網關與JF - 600MT 稱重變送器輕松實現數據互換 在工業自動化領域&#xff0c;不同設備之間的通信與數據交互至關重要。Modbus TCP轉Profibus DP網關作為連接不同協議設備的關鍵橋梁&#xff0c;發揮著不可或缺的作用。本文將以JF - 600MT稱重變送器與3…

聊聊 SQL 注入那些事兒

相信大家對于學校們糟糕的網絡環境和運維手段都早有體會&#xff0c;在此就不多做吐槽了。今天我們來聊一聊SQL注入相關的內容。 何謂SQL注入&#xff1f; SQL注入是一種非常常見的數據庫攻擊手段&#xff0c;SQL注入漏洞也是網絡世界中最普遍的漏洞之一。大家也許都聽過某某學…

多傳感器融合

目錄 多傳感器融合 多傳感器融合的方向 傳感器融合方案介紹 LOAM LIO-SAM LVI-SAM 多線激光雷達性質 什么是運動畸變 兩步優化的幀間里程記 IMU 器件介紹及選型建議 IMU 標定方法簡介 視覺里程計 VS 激光里程計 LVI-SAM 激光視覺融合思路簡介 多傳感器融合工程實踐經驗與技巧 多…

Auto-GPT vs ReAct:兩種智能體思路對決

目錄 Auto-GPT vs ReAct&#xff1a;兩種智能體思路對決 &#x1f9e0; 一、智能體的演化背景 &#x1f9e9; 二、Auto-GPT&#xff1a;自循環的執行體 &#x1f50d; 三、ReAct&#xff1a;推理 行動的交錯協同 ?? 四、對比總結 &#x1f6e0; 五、你該選誰&#xff…

本地部署大模型性能測試,DeepSeek-R1-0528-Qwen-8B 依然是我的不二之選

大家好&#xff0c;我是 ai 學習的老章 介紹一個大模型并發性能測試工具 看一下我高頻使用的&#xff0c;在2*4090顯卡上部署的 DeepSeek-R1-0528-Qwen-8B 性能如何 _我_特別喜歡的三個DeepSeek版本 DeepSeek-R1-0528 蒸餾 Qwen3:8B 大模型&#xff0c;雙 4090 本地部署&am…