
如何高效爬取全球新聞網站 – 整合Scrapy、Selenium與Mediastack API實現自動化新聞采集
最常見的分塊方法是基于規則的,采用了諸如固定分塊大小或相鄰分塊重疊等技巧。對于多級文檔,我們可以使用 Langchain 提供的 RecursiveCharacterTextSplitter。它允許我們定義多級分隔符。
然而,在實際應用中,由于預定義規則(如分塊大小或重疊部分的大小)的刻板,基于規則的分塊方法很容易導致諸如檢索上下文不完整或分塊過大含有噪聲等問題。因此,在分塊方面,最優雅的方法顯然是基于語義進行分塊。語義分塊的宗旨是確保每個分塊盡可能包含語義上獨立的信息。
本文將探討語義分塊的方法,我們將介紹三種類型的方法:
LlamaIndex 和 Langchain 都提供了基于嵌入的語義分塊器。以 LlamaIndex 為例,核心代碼流程為:
# load documents
dir_path = "YOUR_DIR_PATH"
documents = SimpleDirectoryReader(dir_path).load_data()
embed_model = OpenAIEmbedding()
splitter = SemanticSplitterNodeParser(
buffer_size=1, breakpoint_percentile_threshold=95, embed_model=embed_model
)
nodes = splitter.get_nodes_from_documents(documents)
對 semantic_splitter.py 文件中的流程進行跟蹤,可以發現其主要流程為:
上面提到的“sentences 是一個 Python 列表,列表中的每個元素都是一個包含四個鍵值對的字典。下面是這些鍵的含義:
sentence
:當前的句子index
:當前句子的序號combined_sentence
:一個滑動窗口,默認包含[index - self.buffer_size, index, index + self.buffer_size]
這三個句子(通常,self.buffer_size = 1
)。這個窗口是用來計算句子之間的語義相關性的。將前后的句子結合起來,目的是為了減少噪聲,更好地捕捉連續句子之間的關系。combined_sentence_embedding
:句子的 embedding 向量通過以上分析,我們可以看出,基于嵌入的語義分塊本質上是通過一個滑動窗口(combined_sentence
)來計算相似度。那些相鄰并且滿足閾值的句子會被歸為一個分塊。
實驗表明,基于 embedding 的分塊方法產出的結果似乎有些“粗獷”。而且對源代碼的分析表明此方法是建立在頁面基礎之上的,對于跨越多頁的內容分塊問題,它并沒有直接給出答案。在很大程度上,embedding 方法的效能與所選用的嵌入模型息息相關。至于它的實際表現如何,還需經過時間的考驗和進一步的評估。
BERT 的預訓練過程中包含了一個二元分類任務——下一句預測(NSP),旨在讓模型學習兩個句子之間的關系。在這個過程中,BERT 會同時接收兩個句子作為輸入,并預測第二個句子是否緊隨第一個句子。
我們可以根據這個原理設計一個簡單的分塊方法。對于一篇文檔,首先將其拆分成獨立的句子。然后,通過滑動窗口的方式,將相鄰的兩個句子送入 BERT 模型進行 NSP 判斷,如下圖所示:
如果預測的分數低于預設的閾值,這表明兩個句子之間的語義關系較弱。這時,我們就可以將這個點作為文本分割點,如上圖中句子 2 和句子 3 之間的分割。
這種方法的一個優點是,它可以直接使用,無需進行額外的訓練或微調。然而,這種方法在確定文本分割點時,只考慮了相鄰的句子,而忽略了更遠距離段落的信息。此外,這種方法的預測效率也相對較低。
論文?《Text Segmentation by Cross Segment Attention》[1]提出了三種基于跨片段注意力的模型,如下圖所示:
圖(a)展示了跨片段 BERT 模型,它將文本分割定義為逐句分類任務。潛在分割點兩側的上下文(左右各 個標記)被輸入到模型中。對應于 [CLS]
的隱藏狀態被傳遞到 softmax 分類器,以決定在潛在分割點是否進行分割。論文還介紹了另外兩種模型。一種是使用 BERT 模型獲取每個句子的向量表示。這些連續多個句子的向量表示隨后被輸入到一個雙向 LSTM(或另一個 BERT)中,以預測每個句子是否為文本分割邊界。
這三種模型取得了最先進的結果,結果如下圖所示:
然而,到目前為止,只找到了這篇論文的訓練實現[2]。尚未發現可供推理使用的公開模型。因此要將它們應用到實際的文本分割任務中,還需要自己動手訓練模型。
跨片段模型獨立地向量化每個句子,沒有考慮到更廣泛的上下文信息。論文?《Sequence Model with Self-Adaptive Sliding Window for Efficient Spoken Document Segmentation》[3]提出了進一步的改進,即 SeqModel。SeqModel 利用 BERT 同時編碼多個句子,在進行句子向量計算之前,建模了更長上下文內的依賴關系。然后,它預測每個句子之后是否會發生文本分割。此外,這個模型采用了自適應性滑動窗口方法來提高推理速度,同時不犧牲準確性。SeqModel 的示意圖如下圖所示。
當前,SeqModel 可以通過?ModelScope 框架[4]使用。比如以下測試代碼:
from modelscope.outputs import OutputKeys
from modelscope.pipelines import pipeline
from modelscope.utils.constant import Tasks
p = pipeline(
task = Tasks.document_segmentation,
model = 'damo/nlp_bert_document-segmentation_english-base'
)
result = p(documents='We demonstrate the importance of bidirectional pre-training for language representations. Unlike Radford et al. (2018), which uses unidirectional language models for pre-training, BERT uses masked language models to enable pretrained deep bidirectional representations. This is also in contrast to Peters et al. (2018a), which uses a shallow concatenation of independently trained left-to-right and right-to-left LMs. ? We show that pre-trained representations reduce the need for many heavily-engineered taskspecific architectures. BERT is the first finetuning based representation model that achieves state-of-the-art performance on a large suite of sentence-level and token-level tasks, outperforming many task-specific architectures. Today is a good day')
print(result[OutputKeys.TEXT])
總的來說,基于模型的語義分塊方法仍有很大的提升空間。作者的建議的一種改進方法是創建針對特定項目的訓練數據,以進行領域微調。
論文?《Dense X Retrieval: What Retrieval Granularity Should We Use?》[5]介紹了一種新的檢索單元,稱為 proposition。proposition 被定義為文本中的原子表達式,每個表達式都封裝了一個獨特的事實,并以簡潔、自包含的自然語言格式呈現。通過構建 prompt 并與 LLM 結合可以來實現這一點。LlamaIndex 和 Langchain 都已實現了相關算法,LlamaIndex 的實現思想是使用論文中提供的 prompt 來生成 proposition:
Decompose the "Content" into clear and simple propositions, ensuring they are interpretable out of
context.
1. Split compound sentence into simple sentences. Maintain the original phrasing from the input
whenever possible.
2. For any named entity that is accompanied by additional descriptive information, separate this
information into its own distinct proposition.
3. Decontextualize the proposition by adding necessary modifier to nouns or entire sentences
and replacing pronouns (e.g., "it", "he", "she", "they", "this", "that") with the full name of the
entities they refer to.
4. Present the results as a list of strings, formatted in JSON.
Input: Title: ˉEostre. Section: Theories and interpretations, Connection to Easter Hares. Content:
The earliest evidence for the Easter Hare (Osterhase) was recorded in south-west Germany in
1678 by the professor of medicine Georg Franck von Franckenau, but it remained unknown in
other parts of Germany until the 18th century. Scholar Richard Sermon writes that "hares were
frequently seen in gardens in spring, and thus may have served as a convenient explanation for the
origin of the colored eggs hidden there for children. Alternatively, there is a European tradition
that hares laid eggs, since a hare’s scratch or form and a lapwing’s nest look very similar, and
both occur on grassland and are first seen in the spring. In the nineteenth century the influence
of Easter cards, toys, and books was to make the Easter Hare/Rabbit popular throughout Europe.
German immigrants then exported the custom to Britain and America where it evolved into the
Easter Bunny."
Output: [ "The earliest evidence for the Easter Hare was recorded in south-west Germany in
1678 by Georg Franck von Franckenau.", "Georg Franck von Franckenau was a professor of
medicine.", "The evidence for the Easter Hare remained unknown in other parts of Germany until
the 18th century.", "Richard Sermon was a scholar.", "Richard Sermon writes a hypothesis about
the possible explanation for the connection between hares and the tradition during Easter", "Hares
were frequently seen in gardens in spring.", "Hares may have served as a convenient explanation
for the origin of the colored eggs hidden in gardens for children.", "There is a European tradition
that hares laid eggs.", "A hare’s scratch or form and a lapwing’s nest look very similar.", "Both
hares and lapwing’s nests occur on grassland and are first seen in the spring.", "In the nineteenth
century the influence of Easter cards, toys, and books was to make the Easter Hare/Rabbit popular
throughout Europe.", "German immigrants exported the custom of the Easter Hare/Rabbit to
Britain and America.", "The custom of the Easter Hare/Rabbit evolved into the Easter Bunny in
Britain and America." ]
Input: {node_text}
Output:
對應的中文為:
將“內容”分解為清晰簡單的命題,確保它們在脫離上下文的情況下也能被理解。
1. 將復合句拆分為簡單句。盡可能保持輸入原文的措辭。
2. 對于任何帶有附加描述信息的命名實體,將此信息分離成其獨有的命題。
3. 通過為名詞或整個句子添加必要的修飾語,并將代詞(例如,“它”、“他”、“她”、“他們”、“這個”、“那個”)替換為它們所指實體的全名,使命題脫離上下文。
4. 以JSON格式的字符串列表呈現結果。
輸入:標題:歐斯特雷。章節:理論與解釋,與復活節野兔的聯系。內容:復活節野兔(Osterhase)最早的證據記錄于1678年德國西南部,由醫學教授喬治·弗蘭克·馮·弗蘭肯瑙記錄,但在18世紀之前,德國其他地區對此并不了解。學者理查德·塞爾蒙寫道:“春天在花園里經常看到野兔,因此它們可能為孩子們藏在花園里的彩色雞蛋提供了一個方便的解釋。另外,有一個歐洲傳統,認為野兔下蛋,因為野兔的抓痕或形態和一種叫做 lapwing 的鳥的巢非常相似,而且兩者都出現在草地上,并且都是在春天首次被看到。在19世紀,復活節卡片、玩具和書籍的影響使得復活節野兔/兔子在整個歐洲流行起來。德國移民隨后將這一習俗帶到英國和美國,在那里它演變成了復活節兔子。”
輸出:[ "復活節野兔最早的證據在1678年由喬治·弗蘭克·馮·弗蘭肯瑙在德國西南部被記錄下來。", "喬治·弗蘭克·馮·弗蘭肯瑙是一位醫學教授。", "復活節野兔的證據在德國其他地區直到18世紀才為人所知。", "理查德·塞爾蒙是一位學者。", "理查德·塞爾蒙提出了關于復活節期間野兔與這一傳統可能聯系的假設。", "春天在花園里經常看到野兔。", "野兔可能為孩子們藏在花園里的彩色雞蛋提供了一個方便的解釋。", "有一個歐洲傳統認為野兔下蛋。", "野兔的抓痕或形態和一種叫做 lapwing 的鳥的巢非常相似。", "野兔和 lapwing 的鳥巢都出現在草地上,并且都是在春天首次被看到。", "在19世紀,復活節卡片、玩具和書籍的影響使得復活節野兔/兔子在整個歐洲流行起來。", "德國移民將復活節野兔/兔子的習俗帶到了英國和美國。", "復活節野兔/兔子的習俗在英國和美國演變成了復活節兔子。" ]
輸入:{node_text}
輸出:
總體而言,這種利用 LLM 構建命題的切塊方法已經實現了更為精細的文本塊。它與原始節點形成了一種從小到大的索引結構,為語義切塊提供了一種新穎的思路。然而,這種方法依賴于 LLM,成本相對較高。
相對于使用特定的規則進行塊切分,語義切分可以在一定程度上保留上下文關系。因此召回的內容也會相對更全面,更有助于得到優質的回答。
《Dense X Retrieval: What Retrieval Granularity Should We Use?》:?https://arxiv.org/pdf/2312.06648.pdf[1]
《Text Segmentation by Cross Segment Attention》: https://arxiv.org/abs/2004.14535[2]
訓練實現: https://github.com/aakash222/text-segmentation-NLP/[3]
《Sequence Model with Self-Adaptive Sliding Window for Efficient Spoken Document Segmentation》: https://arxiv.org/abs/2107.09278[4]
ModelScope框架: https://github.com/modelscope/modelscope/[5]
文章轉自微信公眾號@差分隱私