RAGで使用するHTMLの前処理を検証（マークダウン形式→チャンク分割）

# 内容
ローカルのHTMLファイルを使用してRAGシステムの構築を想定。前処理を行い、適切な形にチャンク分割出来るかの検証になります。HTMLを一旦マークダウン形式に変換した後、マークダウンの見出し（#）で分割してみます。
![rag03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b2c03ae8-8830-4a8e-9998-1b6f31073d5c.png)

# サンプルデータ
[AWS Transfer Family SFTPで使用される暗号化アルゴリズムと決定プロセス](https://qiita.com/infra365/items/bf2918625d6d3c8038bf)の記事のデータを右クリックしてsample.htmlとして保存します。

![rag04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/cfb6976e-6818-489c-bba7-0681bb4f2d69.png)

# マークダウン形式に変更

```python:1_html_conv_md.py
import html2text

def html_to_markdown(html):
    h = html2text.HTML2Text()
    h.ignore_links = True
    h.ignore_images = True
    h.ignore_emphasis = False
    return h.handle(html)

# HTML読み込み
with open("sample.html", "r", encoding="utf-8") as f:
    html = f.read()

markdown_text = html_to_markdown(html)

# ファイルに保存
with open("output.md", "w", encoding="utf-8") as f:
    f.write(markdown_text)
```
```shell
python 1_html_conv_md.py
```

sample.htmlを同じディレクトリに保存後、上記プログラム実行。出力ファイルの一部を記載します。

```
#  __確認したい内容

Transfer FamilyでSFTP通信をする際、使用される暗号化アルゴリズムとその決定プロセス

#  __構成

  * SFTPサーバを作成する。
  * SFTPサーバは内部接続とするため、VPCエンドポイントが作成される。
  * SFTPサーバ内にマネージドユーザとしてsftp_userを作成する。
  * sftp_userにロジカルディレクトを使用してS3のフォルダを割り当てる。
  * EC2サーバ内でSSHのキーペア(keyとkey.pub)を作成する。
  * sftp_userに公開鍵(key.pub)を登録する。

EC2から`sftp -v -i key sftp_user@xxxx.vpce.amazonaws.com`コマンドを実行しTransfer
Family経由でS3に接続する。

#  __SFTP通信の流れ

最初にSFTP通信の流れを確認します。（SSH情報のバージョン交換等一部の処理を割愛して記載しています。）

②③④でクライアント側、サーバ側で利用可能な暗号化アルゴリズムを比較しクライアント側の優先順位によって利用する暗号化アルゴリズムを決定します。暗号スイート（SshCiphers）、鍵交換アルゴリズム（SshKexs）、メッセージ認証コード（SshMacs）の3つを決定します。鍵交換アルゴリズムは緑色の箇所、暗号スイートとメッセージ認証コードは赤色の箇所で使用されます。

#  __Tranifer Familyサーバ側の設定

サーバのセキュリティポリシーの設定で使用する暗号化アルゴリズムを制限することが可能です。

TransferSecurityPolicy-2024-01のSshCiphersの箇所を抜粋、暗号化スイートでは下記5つが使用可能です。

```
# チャンク分割

```python:2_text_split_md.py
import os
import re
import argparse

def sanitize_title(title):
    return title.strip().replace(" ", "_").replace("/", "_").replace("\\", "_")

def split_by_h1(input_file, output_dir):
    with open(input_file, "r", encoding="utf-8") as f:
        lines = f.readlines()

    os.makedirs(output_dir, exist_ok=True)

    chunks = []
    current_chunk = []
    current_title = "intro"
    index = 0

    for line in lines:
        if line.startswith("# "):  # H1見出し
            if current_chunk:
                chunks.append((index, current_title, current_chunk))
                index += 1
            current_title = sanitize_title(line[2:])
            current_chunk = [line]
        else:
            current_chunk.append(line)

    if current_chunk:
        chunks.append((index, current_title, current_chunk))

    for idx, title, chunk in chunks:
        filename = f"{idx:03d}_{title}.md"
        with open(os.path.join(output_dir, filename), "w", encoding="utf-8") as f:
            f.writelines(chunk)

    print(f"✅ 完了: {len(chunks)} ファイルを出力しました")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Markdown を H1 見出しで分割")
    parser.add_argument("input_file", help="入力 Markdown ファイル")
    parser.add_argument("--output_dir", default="./chunks", help="出力ディレクトリ")
    args = parser.parse_args()

    split_by_h1(args.input_file, args.output_dir)
```

```shell
python 2_text_split_md.py output.md --output_dir ./chunks
✅ 完了: 9 ファイルを出力しました
```
下記の様に見出しで分割されてファイルが作成されました。

![rag02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/c60c6ba6-14e2-44c1-940b-12ff1925a68a.png)

```shell:003__構成.md
#  __構成

  * SFTPサーバを作成する。
  * SFTPサーバは内部接続とするため、VPCエンドポイントが作成される。
  * SFTPサーバ内にマネージドユーザとしてsftp_userを作成する。
  * sftp_userにロジカルディレクトを使用してS3のフォルダを割り当てる。
  * EC2サーバ内でSSHのキーペア(keyとkey.pub)を作成する。
  * sftp_userに公開鍵(key.pub)を登録する。

EC2から`sftp -v -i key sftp_user@xxxx.vpce.amazonaws.com`コマンドを実行しTransfer
Family経由でS3に接続する。
```