🦜️🔗LangChain : モジュール : 検索 – ドキュメント変換 : テキストスプリッター : MarkdownHeaderTextSplitter / 再帰的に文字で分割 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 09/05/2023
* 本ページは、LangChain の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
- Modules : Retrieval – Document transformers : Text splitters : MarkdownHeaderTextSplitter
- Modules : Retrieval – Document transformers : Text splitters : Recursively split by character
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- 人工知能研究開発支援
- 人工知能研修サービス(経営者層向けオンサイト研修)
- テクニカルコンサルティングサービス
- 実証実験(プロトタイプ構築)
- アプリケーションへの実装
- 人工知能研修サービス
- PoC(概念実証)を失敗させないための支援
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
- 株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
- sales-info@classcat.com ; Web: www.classcat.com ; ClassCatJP
🦜️🔗 LangChain : モジュール : 検索 – ドキュメント変換 : テキストスプリッター : MarkdownHeaderTextSplitter
モチベーション
多くのチャットや Q+A アプリケーションは埋め込みとベクトルストレージの前に入力ドキュメントのチャンク化を伴います。
Pinecone からの これらのノート は幾つかの有用なヒントを提供します :
完全なパラグラフやドキュメントが埋め込まれるとき、埋め込みプロセスは全体的なコンテキストと、テキスト内のセンテンスとフレーズの間の関係の両方を考慮します。これは、テキストの広範な意味と主題 (テーマ) を捕捉する包括的なベクトル表現という結果になります。
述べられているように、チャンク化は共通のコンテキストを一緒に持つテキストを保持することを目標にする場合が多いです。これを念頭に置くと、ドキュメント自身の構造を特に重視 (honor) したいかもしれません。例えば、マークダウンファイルはヘッダで体系化されます。特定のヘッダグループ内でチャンクを作成することは直感的なアイデアです。この課題に対処するには、MarkdownHeaderTextSplitter を使用できます。これはマークダウンファイルをヘッダの指定されたセットで分割します。
例えば、このマークダウンを分割したい場合 :
md = '# Foo\n\n ## Bar\n\nHi this is Jim \nHi this is Joe\n\n ## Baz\n\n Hi this is Molly'
それで分割したいヘッダを指定できます :
[("#", "Header 1"),("##", "Header 2")]
そしてコンテンツは共通のヘッダでグループ化、または分割されます :
{'content': 'Hi this is Jim \nHi this is Joe', 'metadata': {'Header 1': 'Foo', 'Header 2': 'Bar'}}
{'content': 'Hi this is Molly', 'metadata': {'Header 1': 'Foo', 'Header 2': 'Baz'}}
下で幾つかの例を見てみましょう。
from langchain.text_splitter import MarkdownHeaderTextSplitter
API リファレンス :
markdown_document = "# Foo\n\n ## Bar\n\nHi this is Jim\n\nHi this is Joe\n\n ### Boo \n\n Hi this is Lance \n\n ## Baz\n\n Hi this is Molly"
headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
md_header_splits = markdown_splitter.split_text(markdown_document)
md_header_splits
[Document(page_content='Hi this is Jim \nHi this is Joe', metadata={'Header 1': 'Foo', 'Header 2': 'Bar'}), Document(page_content='Hi this is Lance', metadata={'Header 1': 'Foo', 'Header 2': 'Bar', 'Header 3': 'Boo'}), Document(page_content='Hi this is Molly', metadata={'Header 1': 'Foo', 'Header 2': 'Baz'})]
type(md_header_splits[0])
langchain.schema.Document
各マークダウングループ内で、次に任意の望むテキストスプリッターを適用できます :
markdown_document = "# Intro \n\n ## History \n\n Markdown[9] is a lightweight markup language for creating formatted text using a plain-text editor. John Gruber created Markdown in 2004 as a markup language that is appealing to human readers in its source code form.[9] \n\n Markdown is widely used in blogging, instant messaging, online forums, collaborative software, documentation pages, and readme files. \n\n ## Rise and divergence \n\n As Markdown popularity grew rapidly, many Markdown implementations appeared, driven mostly by the need for \n\n additional features such as tables, footnotes, definition lists,[note 1] and Markdown inside HTML blocks. \n\n #### Standardization \n\n From 2012, a group of people, including Jeff Atwood and John MacFarlane, launched what Atwood characterised as a standardisation effort. \n\n ## Implementations \n\n Implementations of Markdown are available for over a dozen programming languages."
headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
]
# MD splits
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
md_header_splits = markdown_splitter.split_text(markdown_document)
# Char-level splits
from langchain.text_splitter import RecursiveCharacterTextSplitter
chunk_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
API リファレンス :
[Document(page_content='Markdown[9] is a lightweight markup language for creating formatted text using a plain-text editor. John Gruber created Markdown in 2004 as a markup language that is appealing to human readers in its source code form.[9]', metadata={'Header 1': 'Intro', 'Header 2': 'History'}), Document(page_content='Markdown is widely used in blogging, instant messaging, online forums, collaborative software, documentation pages, and readme files.', metadata={'Header 1': 'Intro', 'Header 2': 'History'}), Document(page_content='As Markdown popularity grew rapidly, many Markdown implementations appeared, driven mostly by the need for \nadditional features such as tables, footnotes, definition lists,[note 1] and Markdown inside HTML blocks. \n#### Standardization', metadata={'Header 1': 'Intro', 'Header 2': 'Rise and divergence'}), Document(page_content='#### Standardization \nFrom 2012, a group of people, including Jeff Atwood and John MacFarlane, launched what Atwood characterised as a standardisation effort.', metadata={'Header 1': 'Intro', 'Header 2': 'Rise and divergence'}), Document(page_content='Implementations of Markdown are available for over a dozen programming languages.', metadata={'Header 1': 'Intro', 'Header 2': 'Implementations'})]
🦜️🔗 LangChain : モジュール : 検索 – ドキュメント変換 : テキストスプリッター : 再帰的に文字で分割
このテキストスプリッターは汎用テキストのために推奨されます。それは文字のリストによってパラメータ化されます。チャンクが十分に小さくなるまで順番に分割しようとします。デフォルトのリストは [“\n\n”, “\n”, ” “, “”] です。これは、すべての段落 (それからセンテンス、そして単語) をできる限り長くまとめて保持しようとする効果があります、何故ならばそれらは一般的には最も意味的に関連性の強いテキスト断片と見えるからです。
- テキストが分割される方法: 文字のリストによります。
- チャンクサイズが測定される方法: 文字数によります。
# This is a long document we can split up.
with open('../../../state_of_the_union.txt') as f:
state_of_the_union = f.read()
from langchain.text_splitter import RecursiveCharacterTextSplitter
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,
)
texts = text_splitter.create_documents([state_of_the_union])
print(texts[0])
print(texts[1])
page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and' lookup_str='' metadata={} lookup_index=0 page_content='of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.' lookup_str='' metadata={} lookup_index=0
text_splitter.split_text(state_of_the_union)[:2]
['Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and', 'of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.']
以上