마크다운 파일의 구조를 이해하고 효율적으로 다루는 것은 문서 작업에 있어 매우 중요할 수 있습니다. 특히, 문서의 전체적인 맥락과 구조를 고려하여 의미 있는 방식으로 텍스트를 임베딩하는 과정은, 광범위한 의미와 주제를 더 잘 포착할 수 있는 포괄적인 벡터 표현을 생성하는 데 큰 도움이 됩니다.
이러한 맥락에서, 마크다운 파일의 특정 부분, 즉 헤더별로 내용을 나누고 싶을 때가 있습니다. 예를 들어, 문서 내에서 각각의 헤더 아래에 있는 내용을 기반으로 서로 연관된 정보 덩어리, 즉 ’청크’를 만들고 싶은 경우가 그러합니다. 이는 텍스트의 공통된 맥락을 유지하면서도, 문서의 구조적 요소를 효과적으로 활용하려는 시도입니다.
이런 과제를 해결하기 위해, MarkdownHeaderTextSplitter 라는 도구를 활용할 수 있습니다. 이 도구는 문서를 지정된 헤더 집합에 따라 분할하여, 각 헤더 그룹 아래의 내용을 별도의 청크로 관리할 수 있게 합니다. 이 방법을 통해, 문서의 전반적인 구조를 유지하면서도 내용을 더 세밀하게 다룰 수 있게 되며, 이는 다양한 처리 과정에서 유용하게 활용될 수 있습니다.
MarkdownHeaderTextSplitter를 사용하여 마크다운 형식의 텍스트를 헤더 단위로 분할합니다.
마크다운 문서의 헤더(
#,##,###등)를 기준으로 텍스트를 분할하는 역할을 합니다.markdown_document변수에 마크다운 형식의 문서가 할당됩니다.headers_to_split_on리스트에는 마크다운 헤더 레벨과 해당 레벨의 이름이 튜플 형태로 정의됩니다.MarkdownHeaderTextSplitter클래스를 사용하여markdown_splitter객체를 생성하며,headers_to_split_on매개변수로 분할 기준이 되는 헤더 레벨을 전달합니다.split_text메서드를 호출하여markdown_document를 헤더 레벨에 따라 분할합니다.
from langchain_text_splitters import MarkdownHeaderTextSplitter
# 마크다운 형식의 문서를 문자열로 정의합니다.
markdown_document = "# Title\n\n## 1. SubTitle\n\nHi this is Jim\n\nHi this is Joe\n\n### 1-1. Sub-SubTitle \n\nHi this is Lance \n\n## 2. Baz\n\nHi this is Molly"
print(markdown_document)headers_to_split_on = [ # 문서를 분할할 헤더 레벨과 해당 레벨의 이름을 정의합니다.
(
"#",
"Header 1",
), # 헤더 레벨 1은 '#'로 표시되며, 'Header 1'이라는 이름을 가집니다.
(
"##",
"Header 2",
), # 헤더 레벨 2는 '##'로 표시되며, 'Header 2'라는 이름을 가집니다.
(
"###",
"Header 3",
), # 헤더 레벨 3은 '###'로 표시되며, 'Header 3'이라는 이름을 가집니다.
]
# 마크다운 헤더를 기준으로 텍스트를 분할하는 MarkdownHeaderTextSplitter 객체를 생성합니다.
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# markdown_document를 헤더를 기준으로 분할하여 md_header_splits에 저장합니다.
md_header_splits = markdown_splitter.split_text(markdown_document)
# 분할된 결과를 출력합니다.
for header in md_header_splits:
print(f"{header.page_content}")
print(f"{header.metadata}", end="\n=====================\n")1 Title
1.1 1. SubTitle
Hi this is Jim
Hi this is Joe
1.1.1 1-1. Sub-SubTitle
Hi this is Lance
1.2 2. Baz
Hi this is Molly
기본적으로 MarkdownHeaderTextSplitter는 분할되는 헤더를 출력 청크의 내용에서 제거합니다.
이는 strip_headers = False로 설정하여 비활성화할 수 있습니다.
markdown_splitter = MarkdownHeaderTextSplitter(
# 분할할 헤더를 지정합니다.
headers_to_split_on=headers_to_split_on,
# 헤더를 제거하지 않도록 설정합니다.
strip_headers=False,
)
# 마크다운 문서를 헤더를 기준으로 분할합니다.
md_header_splits = markdown_splitter.split_text(markdown_document)
# 분할된 결과를 출력합니다.
for header in md_header_splits:
print(f"{header.page_content}")
print(f"{header.metadata}", end="\n=====================\n")각 마크다운 그룹 내에서는 원하는 텍스트 분할기(text splitter)를 적용할 수 있습니다.
from langchain_text_splitters import RecursiveCharacterTextSplitter
markdown_document = "# Intro \n\n## History \n\nMarkdown[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\nMarkdown is widely used in blogging, instant messaging, online forums, collaborative software, documentation pages, and readme files. \n\n## Rise and divergence \n\nAs Markdown popularity grew rapidly, many Markdown implementations appeared, driven mostly by the need for \n\nadditional features such as tables, footnotes, definition lists,[note 1] and Markdown inside HTML blocks. \n\n#### Standardization \n\nFrom 2012, a group of people, including Jeff Atwood and John MacFarlane, launched what Atwood characterised as a standardisation effort. \n\n# Implementations \n\nImplementations of Markdown are available for over a dozen programming languages."
print(markdown_document)먼저, MarkdownHeaderTextSplitter 사용하여 마크다운 문서를 헤더를 기준으로 분할합니다.
headers_to_split_on = [
("#", "Header 1"), # 분할할 헤더 레벨과 해당 레벨의 이름을 지정합니다.
# ("##", "Header 2"),
]
# Markdown 문서를 헤더 레벨에 따라 분할합니다.
markdown_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=headers_to_split_on, strip_headers=False
)
md_header_splits = markdown_splitter.split_text(markdown_document)
# 분할된 결과를 출력합니다.
for header in md_header_splits:
print(f"{header.page_content}")
print(f"{header.metadata}", end="\n=====================\n")이전의 MarkdownHeaderTextSplitter 로 분할된 결과를 다시 RecursiveCharacterTextSplitter 로 분할합니다.
chunk_size = 200 # 분할된 청크의 크기를 지정합니다.
chunk_overlap = 20 # 분할된 청크 간의 중복되는 문자 수를 지정합니다.
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size, chunk_overlap=chunk_overlap
)
# 문서를 문자 단위로 분할합니다.
splits = text_splitter.split_documents(md_header_splits)
# 분할된 결과를 출력합니다.
for header in splits:
print(f"{header.page_content}")
print(f"{header.metadata}", end="\n=====================\n")