Разбивка текста по заголовкам Markdown

Мотивация

Многие приложения чата или вопросно-ответные приложения включают разделение входных документов перед их встраиванием и векторизацией. После разделения текста часто желательно группировать текстовые фрагменты с похожими темами вместе.

Например, файл Markdown организован с многоуровневыми заголовками, такими как h1, h2 и h3. Мы можем организовать текстовые фрагменты с тем же заголовком на основе заголовков Markdown.

Эта глава представляет, как LangChain разбивает содержимое текста на основе заголовков Markdown, используя разделитель текста MarkdownHeaderTextSplitter.

Например, если мы хотим разбить этот Markdown:

md = '# Foo\\n\\n ## Bar\\n\\nHi this is Jim  \\nHi this is Joe\\n\\n ## Baz\\n\\n Hi this is Molly'

Установим правила заголовков для разделения, на основе заголовков уровня 1 и уровня 2:

[("#", "Заголовок 1"),("##", "Заголовок 2")]

Вот пример разделенного содержимого на основе заголовков, где поле метаданных записывает, к какому заголовку принадлежит текущий фрагмент содержимого:

{'content': 'Hi this is Jim  \nHi this is Joe', 'metadata': {'Заголовок 1': 'Foo', 'Заголовок 2': 'Bar'}}
{'content': 'Hi this is Molly', 'metadata': {'Заголовок 1': 'Foo', 'Заголовок 2': 'Baz'}}

Теперь давайте посмотрим, как написать код.

Установите зависимости:

%pip install -qU langchain-text-splitters
from langchain_text_splitters import MarkdownHeaderTextSplitter

Справочник API:

  • Создание разделителя текста с использованием MarkdownHeaderTextSplitter
markdown_document = "# Foo\n\n    ## Bar\n\nПривет, это Джим\n\nПривет, это Джо\n\n ### Boo \n\n Привет, это Лэнс \n\n ## Baz\n\n Привет, это Молли"

headers_to_split_on = [
    ("#", "Заголовок 1"),
    ("##", "Заголовок 2"),
    ("###", "Заголовок 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='Привет, это Джим  \nПривет, это Джо', metadata={'Заголовок 1': 'Foo', 'Заголовок 2': 'Bar'}),
     Document(page_content='Привет, это Лэнс', metadata={'Заголовок 1': 'Foo', 'Заголовок 2': 'Bar', 'Заголовок 3': 'Boo'}),
     Document(page_content='Привет, это Молли', metadata={'Заголовок 1': 'Foo', 'Заголовок 2': 'Baz'})]
type(md_header_splits[0])
langchain.schema.Document

В каждой группе Markdown мы можем применить любой текстовый разделитель.

markdown_document = "# Вступление \n\n    ## История \n\n Markdown[9] - это легкий язык разметки для создания форматированного текста с использованием редактора обычного текста. Джон Грубер создал Markdown в 2004 году как язык разметки, привлекательный для читателей в исходном коде.[9] \n\n Markdown широко используется в блогах, мгновенных сообщениях, онлайн-форумах, совместном программном обеспечении, страницах документации и файлы readme. \n\n ## Рост и расхождение \n\n Поскольку популярность Markdown быстро росла, появилось множество его реализаций, вызванных в основном потребностью в \n\n дополнительных возможностях, таких как таблицы, сноски, списки определений,[прим 1] и Markdown внутри HTML-блоков. \n\n #### Стандартизация \n\n С 2012 года группа людей, включая Джеффа Атвуда и Джона МакФарлейна, начала то, что Атвуд охарактеризовал как усилие стандартизации. \n\n ## Реализации \n\n Реализации Markdown доступны для более чем десятка языков программирования."

headers_to_split_on = [
    ("#", "Заголовок 1"),
    ("##", "Заголовок 2"),
]

markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
md_header_splits = markdown_splitter.split_text(markdown_document)

from langchain.text_splitter import RecursiveCharacterTextSplitter

chunk_size = 250
chunk_overlap = 30
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=chunk_size, chunk_overlap=chunk_overlap
)

splits = text_splitter.split_documents(md_header_splits)
splits

Результаты:

[Document(page_content='Markdown[9] - это легкий язык разметки для создания форматированного текста с использованием редактора обычного текста. Джон Грубер создал Markdown в 2004 году как язык разметки, привлекательный для читателей в исходном коде.[9]', metadata={'Заголовок 1': 'Вступление', 'Заголовок 2': 'История'}),
     Document(page_content='Markdown широко используется в блогах, мгновенных сообщениях, онлайн-форумах, совместном программном обеспечении, страницах документации и файлы readme.', metadata={'Заголовок 1': 'Вступление', 'Заголовок 2': 'История'}),
     Document(page_content='Поскольку популярность Markdown быстро росла, появилось множество его реализаций, вызванных в основном потребностью в  \nдополнительных возможностях, таких как таблицы, сноски, списки определений,[прим 1] и Markdown внутри HTML-блоков.  \n#### Стандартизация', metadata={'Заголовок 1': 'Вступление', 'Заголовок 2': 'Рост и расхождение'}),
     Document(page_content='#### Стандартизация  \nС 2012 года группа людей, включая Джеффа Атвуда и Джона МакФарлейна, начала то, что Атвуд охарактеризовал как усилие стандартизации.', metadata={'Заголовок 1': 'Вступление', 'Заголовок 2': 'Рост и расхождение'}),
     Document(page_content='Реализации Markdown доступны для более чем десятка языков программирования.', metadata={'Заголовок 1': 'Вступление', 'Заголовок 2': 'Реализации'})]