Dify中的文本分詞處理技術詳解

Dify中的文本分詞處理技術詳解

    • 引言
    • 核心架構概覽
      • 索引處理器工廠
    • 文本分詞技術詳解
      • 基礎分詞器
      • 增強型遞歸字符分詞器
      • 固定分隔符文本分詞器
      • 遞歸分割算法
    • 索引處理器中的分詞應用
    • 特殊索引處理器的分詞特點
      • 問答索引處理器
      • 父子索引處理器
    • 分詞技術的應用場景
    • 技術亮點與優勢
    • 總結

引言

在現代RAG(檢索增強生成)系統中,文本分詞(Text Splitting)是一個至關重要的環節。它直接影響到檢索的精度和生成內容的質量。本文將深入解析Dify項目中的文本分詞處理技術,探討其實現原理、核心算法和應用場景。

核心架構概覽

Dify采用了工廠模式和策略模式來實現靈活的文本處理流程。整個文本處理架構主要包含兩個核心部分:

  1. 索引處理器(Index Processor):負責文檔的提取、轉換和加載
  2. 文本分詞器(Text Splitter):負責將長文本切分成適合處理的小塊

索引處理器工廠

索引處理器工廠(IndexProcessorFactory)是創建不同類型索引處理器的核心類,它通過工廠模式實現了對不同索引處理策略的封裝和創建:

class IndexProcessorFactory:"""IndexProcessorInit."""def __init__(self, index_type: str | None):self._index_type = index_typedef init_index_processor(self) -> BaseIndexProcessor:"""Init index processor."""if not self._index_type:raise ValueError("Index type must be specified.")if self._index_type == IndexType.PARAGRAPH_INDEX:return ParagraphIndexProcessor()elif self._index_type == IndexType.QA_INDEX:return QAIndexProcessor()elif self._index_type == IndexType.PARENT_CHILD_INDEX:return ParentChildIndexProcessor()else:raise ValueError(f"Index type {self._index_type} is not supported.")

該工廠類支持三種索引處理器:

  1. 段落索引處理器(ParagraphIndexProcessor):將文檔分割成段落級別的塊
  2. 問答索引處理器(QAIndexProcessor):專門處理問答格式的文本
  3. 父子索引處理器(ParentChildIndexProcessor):創建層次化的文檔結構

文本分詞技術詳解

基礎分詞器

Dify的分詞系統建立在抽象基類TextSplitter之上,它定義了分詞的基本接口:

@abstractmethod
def split_text(self, text: str) -> list[str]:"""Split text into multiple components."""

所有具體的分詞器都必須實現這個方法,以提供特定的分詞邏輯。

增強型遞歸字符分詞器

EnhanceRecursiveCharacterTextSplitter是一個關鍵的分詞器實現,它通過遞歸方式處理文本,并支持使用不同的編碼器計算token數量:

class EnhanceRecursiveCharacterTextSplitter(RecursiveCharacterTextSplitter):"""This class is used to implement from_gpt2_encoder, to prevent using of tiktoken"""@classmethoddef from_encoder(cls: type[TS],embedding_model_instance: Optional[ModelInstance],allowed_special: Union[Literal["all"], Set[str]] = set(),disallowed_special: Union[Literal["all"], Collection[str]] = "all",**kwargs: Any,):def _token_encoder(texts: list[str]) -> list[int]:if not texts:return []if embedding_model_instance:return embedding_model_instance.get_text_embedding_num_tokens(texts=texts)else:return [GPT2Tokenizer.get_num_tokens(text) for text in texts]# ... 其他代碼 ...return cls(length_function=_token_encoder, **kwargs)

這個分詞器的特點是可以使用嵌入模型的tokenizer或默認的GPT2 tokenizer來計算文本長度,避免了對tiktoken的依賴。

固定分隔符文本分詞器

FixedRecursiveCharacterTextSplitter是一個更為專業的分詞器,它在增強型遞歸分詞器的基礎上,增加了對固定分隔符的支持:

class FixedRecursiveCharacterTextSplitter(EnhanceRecursiveCharacterTextSplitter):def __init__(self, fixed_separator: str = "\n\n", separators: Optional[list[str]] = None, **kwargs: Any):"""Create a new TextSplitter."""super().__init__(**kwargs)self._fixed_separator = fixed_separatorself._separators = separators or ["\n\n", "\n", " ", ""]def split_text(self, text: str) -> list[str]:"""Split incoming text and return chunks."""if self._fixed_separator:chunks = text.split(self._fixed_separator)else:chunks = [text]final_chunks = []chunks_lengths = self._length_function(chunks)for chunk, chunk_length in zip(chunks, chunks_lengths):if chunk_length > self._chunk_size:final_chunks.extend(self.recursive_split_text(chunk))else:final_chunks.append(chunk)return final_chunks

這個分詞器的工作流程如下:

  1. 首先使用固定分隔符(默認為\n\n)將文本分割成初步的塊
  2. 對每個塊計算token長度
  3. 如果塊的長度超過了設定的最大長度(_chunk_size),則調用recursive_split_text方法進一步分割
  4. 否則直接將塊添加到最終結果中

遞歸分割算法

recursive_split_text方法是固定分隔符分詞器的核心,它實現了復雜的遞歸分割邏輯:

def recursive_split_text(self, text: str) -> list[str]:"""Split incoming text and return chunks."""final_chunks = []separator = self._separators[-1]new_separators = []# 尋找最合適的分隔符for i, _s in enumerate(self._separators):if _s == "":separator = _sbreakif _s in text:separator = _snew_separators = self._separators[i + 1 :]break# 使用找到的分隔符分割文本if separator:if separator == " ":splits = text.split()else:splits = text.split(separator)else:splits = list(text)splits = [s for s in splits if (s not in {"", "\n"})]# ... 處理分割后的文本塊 ...

該算法的精妙之處在于:

  1. 它會按照優先級順序嘗試不同的分隔符(如\n\n, \n, , ""
  2. 一旦找到文本中存在的分隔符,就使用它進行分割
  3. 如果當前分隔符分割后的塊仍然過大,會使用下一級別的分隔符繼續分割
  4. 最終確保所有文本塊都不超過指定的最大token數量

索引處理器中的分詞應用

在實際應用中,索引處理器會根據處理規則選擇合適的分詞器。以ParagraphIndexProcessor為例,它在transform方法中使用分詞器處理文檔:

def transform(self, documents: list[Document], **kwargs) -> list[Document]:# ... 其他代碼 ...splitter = self._get_splitter(processing_rule_mode=process_rule.get("mode"),max_tokens=rules.segmentation.max_tokens,chunk_overlap=rules.segmentation.chunk_overlap,separator=rules.segmentation.separator,embedding_model_instance=kwargs.get("embedding_model_instance"),)all_documents = []for document in documents:# 文檔清洗document_text = CleanProcessor.clean(document.page_content, kwargs.get("process_rule", {}))document.page_content = document_text# 解析文檔為節點document_nodes = splitter.split_documents([document])# ... 處理分割后的節點 ...

分詞器的選擇邏輯在_get_splitter方法中實現:

def _get_splitter(self,processing_rule_mode: str,max_tokens: int,chunk_overlap: int,separator: str,embedding_model_instance: Optional[ModelInstance],) -> TextSplitter:"""Get the NodeParser object according to the processing rule."""if processing_rule_mode in ["custom", "hierarchical"]:# 用戶自定義分割規則# ... 參數驗證 ...character_splitter = FixedRecursiveCharacterTextSplitter.from_encoder(chunk_size=max_tokens,chunk_overlap=chunk_overlap,fixed_separator=separator,separators=["\n\n", "。", ". ", " ", ""],embedding_model_instance=embedding_model_instance,)else:# 自動分割character_splitter = EnhanceRecursiveCharacterTextSplitter.from_encoder(chunk_size=DatasetProcessRule.AUTOMATIC_RULES["segmentation"]["max_tokens"],chunk_overlap=DatasetProcessRule.AUTOMATIC_RULES["segmentation"]["chunk_overlap"],separators=["\n\n", "。", ". ", " ", ""],embedding_model_instance=embedding_model_instance,)return character_splitter

這里的邏輯很清晰:

  1. 對于自定義或層次化處理模式,使用FixedRecursiveCharacterTextSplitter,允許指定固定分隔符
  2. 對于自動處理模式,使用EnhanceRecursiveCharacterTextSplitter,采用預設的參數

特殊索引處理器的分詞特點

問答索引處理器

QAIndexProcessor針對問答格式的文本有特殊的處理邏輯:

def _format_split_text(self, text):regex = r"Q\d+:\s*(.*?)\s*A\d+:\s*([\s\S]*?)(?=Q\d+:|$)"matches = re.findall(regex, text, re.UNICODE)return [{"question": q, "answer": re.sub(r"\n\s*", "\n", a.strip())} for q, a in matches if q and a]

它使用正則表達式識別問題和答案的模式,將文本轉換為結構化的問答對。

父子索引處理器

ParentChildIndexProcessor實現了層次化的文檔處理,它會先將文檔分割成父節點,然后對每個父節點進一步分割成子節點:

def _split_child_nodes(self,document_node: Document,rules: Rule,process_rule_mode: str,embedding_model_instance: Optional[ModelInstance],) -> list[ChildDocument]:# ... 獲取子塊分割規則 ...child_splitter = self._get_splitter(processing_rule_mode=process_rule_mode,max_tokens=rules.subchunk_segmentation.max_tokens,chunk_overlap=rules.subchunk_segmentation.chunk_overlap,separator=rules.subchunk_segmentation.separator,embedding_model_instance=embedding_model_instance,)# 解析文檔為子節點child_nodes = []child_documents = child_splitter.split_documents([document_node])# ... 處理子節點 ...

這種層次化的處理方式特別適合處理結構復雜的長文檔,可以保留文檔的層次關系。

分詞技術的應用場景

Dify中的分詞技術主要應用于以下場景:

  1. 文檔索引:將長文檔分割成適合檢索的小塊
  2. 問答生成:識別和提取文本中的問答對
  3. 層次化處理:保留文檔的層次結構,提高檢索精度
  4. 自定義分割:根據用戶需求定制分割策略

技術亮點與優勢

  1. 靈活的工廠模式:通過工廠模式實現了索引處理器的靈活創建和管理
  2. 多級分隔符策略:采用優先級排序的分隔符列表,適應不同類型的文本
  3. 遞歸分割算法:確保分割后的文本塊不超過指定的token限制
  4. 模型無關的token計算:支持使用不同的embedding模型計算token數量
  5. 自定義與自動模式:同時支持用戶自定義分割規則和智能自動分割

總結

Dify的文本分詞處理系統展示了一個設計良好的文本處理框架。它通過抽象接口、工廠模式和策略模式,實現了高度靈活和可擴展的文本分割功能。這些技術不僅提高了RAG系統的檢索精度,也為開發者提供了豐富的自定義選項。

對于需要構建自己的RAG系統的開發者來說,Dify的分詞處理技術提供了很好的參考和借鑒。特別是其遞歸分割算法和多級分隔符策略,是解決長文本處理問題的有效方案。

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

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

相關文章

如何打包python程序為可執行文件

將 Python 程序打包為可執行文件是一個常見需求,尤其是在希望將應用程序分享給不具備 Python 環境的用戶時。以下是使用 PyInstaller 工具將 Python 程序打包為可執行文件的步驟。 步驟 1:安裝 PyInstaller 如果您還沒有安裝 PyInstaller,請…

美團Java后端二面面經!

場景題是面試的大頭,建議好好準備 Q. [美團]如何設計一個外賣訂單的并發扣減庫存系統? Q.[美團]為啥初始標記和重新標記需要STW? Q.[美團]騎手位置實時更新,如何保證高并發寫入? Q.[美團]訂單表數據量過大導致查詢…

在應用運維過程中,業務數據修改的證據留存和數據留存

在應用運維過程中,業務數據修改的證據留存和數據留存至關重要,以下是相關介紹: 一、證據留存 操作日志記錄 : 詳細記錄每一次業務數據修改的操作日志,包括操作人員、操作時間、修改內容、修改前后數據的對比等。例如,某公司業務系統中,操作日志會精確記錄員工小張在 2…

Eigen迭代求解器類

1. 迭代求解器核心類概覽 Eigen 提供多種迭代法求解稀疏線性方程組 AxbAxb,適用于大規模稀疏矩陣: 求解器類適用矩陣類型算法關鍵特性ConjugateGradient對稱正定(SPD)共軛梯度法(CG)高精度,內…

ORACLE數據庫備份入門:第四部分:2-備份場景舉例

下面以4個常見的場景為例,介紹如何規劃備份方案。備份方案沒有標準答案,需要根據實現情況來制定,也和管理員的個人使用習慣有很大相關性。 1 交易型數據庫備份 以銀行的交易系統為例,除了前一章節提到的關于RPO和RTO的指標外&am…

小白如何學會完整挪用Github項目?(以pix2pix為例)

[目錄] 0.如何完整地復現/應用一個Github項目 1.建立適用于項目的環境 2.數據準備與模型訓練階段 3.訓練過程中的一些命令行調試必備知識0.如何完整地復現/應用一個Github項目 前日在健身房的組間同一位好友交流時,得到了一個一致結論—— ** Github \texttt{Githu…

藍橋杯 5. 交換瓶子

交換瓶子 原題目鏈接 題目描述 有 N 個瓶子,編號為 1 ~ N,放在架子上。 例如有 5 個瓶子,當前排列為: 2 1 3 5 4每次可以拿起 2 個瓶子,交換它們的位置。 要求通過若干次交換,使得瓶子的編號從小到大…

Linux 系統滲透提權

Linux 系統滲透提權 比賽題庫-Linux 系統滲透提權 文章目錄 Linux 系統滲透提權比賽題庫-Linux 系統滲透提權 前言一、解題過程1.使用滲透機對服務器信息收集,并將服務器中 SSH 服務端口號作為 flag 提 交;2.使用滲透機對服務器信息收集,并將…

華為OD機試真題——查找接口成功率最優時間段(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 100分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄…

華為OD機試真題——繪圖機器(2025A卷:100分)Java/python/JavaScript/C++/C/GO最佳實現

2025 A卷 100分 題型 本文涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、測試用例以及綜合分析; 并提供Java、python、JavaScript、C、C語言、GO六種語言的最佳實現方式! 本文收錄于專欄:《2025華為OD真題目錄全流程解析/備考攻略/經驗…

基于 Python(selenium) 的百度新聞定向爬蟲:根據輸入的關鍵詞在百度新聞上進行搜索,并爬取新聞詳情頁的內容

該項目能夠根據輸入的關鍵詞在百度新聞上進行搜索,并爬取新聞詳情頁的內容。 一、項目準備 1. 開發環境配置 操作系統:支持 Windows、macOS、Linux 等主流操作系統,本文以 Windows 為例進行說明。Python 版本:建議使用 Python 3.8 及以上版本,以確保代碼的兼容性和性能。…

MySQL表的操作 -- 表的增刪改查

目錄 1. 表的創建2. 表的查看3. 表的修改4. 表的刪除5. 總結 1. 表的創建 1.查看字符集及效驗規則 2. 表的創建 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校驗規則 engine 存儲引擎;創建用戶表1 創建用…

如何解決極狐GitLab 合并沖突?

極狐GitLab 是 GitLab 在中國的發行版,關于中文參考文檔和資料有: 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 合并沖突 (BASIC ALL) 合并沖突發生在合并請求的兩個分支(源分支和目標分支)對相同代碼行進行了不同…

oracle不同數據庫版本的自增序列

-- 查看數據庫版本 SELECT * FROM v$version WHERE banner LIKE Oracle%; 1. Oracle 12c及以上版本支持 id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) PRIMARY KEY, -- 語法 id NUMBER GENER…

VIC-3D非接觸全場應變測量系統用于小尺寸測量之電子元器件篇—研索儀器DIC數字圖像相關技術

在5G通信、新能源汽車電子、高密度集成電路快速迭代的今天,電子元件的尺寸及連接工藝已進入亞毫米級競爭階段,這種小尺寸下的力學性能評估對測量方式的精度有更高的要求,但傳統應變測量手段常因空間尺寸限制及分辨率不足難以捕捉真實形變場。…

pod 創建私有庫指南

步驟 參考:iOS Pod 私有庫創建指南-百度開發者中心 下面主要是對參考鏈接里面的解釋: 創建兩個倉庫: 一個叫podframe.git,用來存放自定義的framework,比如TestPodFrame.framework一個叫podspec.git,用來…

【JavaEE】Spring AOP的注解實現

目錄 一、AOP 與 Spring AOP二、Spring AOP簡單實現三、詳解Spring AOP3.1 Spring AOP 核心概念3.1.1 切點(Pointcut)3.1.2 連接點(Join Point)3.1.3 通知(Advice)3.1.4 切面(Aspect&#xff09…

協作開發攻略:Git全面使用指南 — 結語

協作開發攻略:Git全面使用指南 — 結語 Git 是一種分布式版本控制系統,用于跟蹤文件和目錄的變更。它能幫助開發者有效管理代碼版本,支持多人協作開發,方便代碼合并與沖突解決,廣泛應用于軟件開發領域。 文中內容僅限技…

如何用AI主動突出畫面主體!涂鴉新方案助剪輯、工業巡檢、醫療影像等領域,實現自動追蹤+智能放大

隨著智能 IPC 設備(如安防攝像頭、寵物陪伴機器人、嬰兒監視器等)日益普及,越來越多的生活場景被實時記錄。然而在實際使用中,由于設備安裝位置不當、廣角鏡頭視野過大等原因,經常會出現拍攝主體占比過小的問題&#x…

數據湖DataLake和傳統數據倉庫Datawarehouse的主要區別是什么?優缺點是什么?

數據湖和傳統數據倉庫的主要區別 以下是數據湖和傳統數據倉庫的主要區別,以表格形式展示: 特性數據湖傳統數據倉庫數據類型支持結構化、半結構化及非結構化數據主要處理結構化數據架構設計扁平化架構,所有數據存儲在一個大的“池”中多層架…