LangChain MarkdownHeaderTextSplitterのTips

# はじめに
* 生成AIを使ったRAG（Retrieval-Augmented Generation）を行うための前処理の話
* 目的は、langchainのMarkdownHeaderTextSplitterを使って、Markdownファイルをセクションごとに分割したかった
* が、投入したMarkdownが全く分割されず、ハマったので共有したい

# 結論
* 連続するセクションのタイトルが同じだと、一つのセクションとみなされるので、分割したい場合はちゃんと分けよう！

# ハマった内容
## どういうドキュメントをどのように分割したいか
* セクションごとに分割したい
```
# セクション1
セクション1の内容です。

## サブセクション1-1
これは
サブセクション1-1の内容です。

## サブセクション1-2
これは
サブセクション1-2の内容です。

# セクション2
セクション2の内容です。

## サブセクション2-1
これは
サブセクション2-1の内容です。

# セクション3
セクション3の内容です。
```

* 期待する分割結果
    * 以下のように3分割したい

```
合計で3個のテキストに分割されました:

分割 1:
# セクション1
セクション1の内容です。  
## サブセクション1-1
これは
サブセクション1-1の内容です。  
## サブセクション1-2
これは
サブセクション1-2の内容です。
--------------------
分割 2:
# セクション2
セクション2の内容です。  
## サブセクション2-1
これは
サブセクション2-1の内容です。
--------------------
分割 3:
# セクション3
セクション3の内容です。
--------------------
```

## ハマった事例

```
# セクション
セクション1の内容です。

# セクション
セクション2の内容です。

# セクション
セクション3の内容です。
```
↓ 結果
```
合計で1個のテキストに分割されました:

分割 1:
# セクション
セクション1の内容です。  
# セクション
セクション2の内容です。  
# セクション
セクション3の内容です。
```

# Tips：連続するセクションで異なっていればよい
* 同じタイトルが存在すること自体は問題ないようだ

```
# セクション1
セクション1の内容です。

# セクション2
セクション2の内容です。

# セクション1
セクション3の内容です。
```
↓ 結果
```
合計で3個のテキストに分割されました:

分割 1:
# セクション1
セクション1の内容です。
--------------------
分割 2:
# セクション2
セクション2の内容です。
--------------------
分割 3:
# セクション1
セクション3の内容です。
--------------------
```

# 最後に
* めっちゃ悩んで、文字コード変えたり、ファイルサイズ変えたり、日本語無くしてみたりしてもわからなかったので、危うくCharacterTextSplitterで力わざで実装しようとしかけたところで、ギリギリ気づけて命拾いしたw

## 参考コード
```python
import os
from typing import List
from langchain.text_splitter import MarkdownHeaderTextSplitter

# Markdownファイルを読み込む関数
def read_markdown_file(file_path: str) -> str:
    """
    指定されたファイルパスからMarkdownファイルを読み込みます。
    
    :param file_path: Markdownファイルのパス
    :return: ファイルの内容
    """
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            content = file.read()
        return content
    except FileNotFoundError:
        print(f"エラー: ファイル '{file_path}' が見つかりません。")
        return ""
    except Exception as e:
        print(f"ファイルを読み込む際にエラーが発生しました: {e}")
        return ""

# Markdownテキストを「#'記号で分割する関数
def split_markdown_text(md_text: str) -> List[str]:
    """
    Markdownテキストを「#'記号で分割します。
    
    :param md_text: Markdown形式のテキスト
    :return: 分割されたテキストのリスト
    """
    headers_to_split_on = [("#", "H1")]
    markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on, strip_headers=False)
    md_header_splits = markdown_splitter.split_text(md_text)
    split_texts = [split_md.page_content for split_md in md_header_splits]
    return split_texts

# メイン関数
def main():
    # Markdownファイルのパスを定義
    markdown_file_path = 'data/easymarkdown.md'  # ここに正しいパスを設定してください
    
    # Markdownファイルを読み込む
    markdown_content = read_markdown_file(markdown_file_path)
    
    # ファイルの内容が読み込まれた場合にのみ処理を実行
    if markdown_content:
        # Markdownテキストを「#'記号で分割
        split_texts = split_markdown_text(markdown_content)
        
        # 分割されたテキストの総数を表示
        total_splits = len(split_texts)
        print(f"合計で{total_splits}個のテキストに分割されました:\n")
        
        # 分割されたテキストを表示
        for i, text in enumerate(split_texts):
            print(f"分割 {i+1}:")
            print(text)
            print("-" * 20)  # 分割されたテキストを視覚的に分けるために区切￥り線を表示
    else:
        print("Markdownファイルの読み込みに失敗しました。")

if __name__ == "__main__":
    main()
```