【Markitdown】あらゆるファイルをマークダウンに変換するPythonライブラリ

# 概要

- **Markitdownとは？**
    - Microsoftが提供しているライブラリ
        - Microsoftがオフィス系のファイル（パワポやExcel等）をマークダウンに変換するためのライブラリを作ってくれたのか！と思っていたら、どうやら裏では、`pdfminer`、`markdownify`などの既存ライブラリをラッピングして統一のインターフェースで使えるようにしてくれているだけの模様。ちょっと残念。
        - とはいえ、インターフェースが統一されているだけでも開発する側からすればかなり便利なので、ありがたく使わせていただく。
- 何に使える？
    - LLMに対してインプットするためのテキストデータを用意するのにかなり便利。
    - 例えば、パワポやExcel、画像データ（jpgやpng）など、LLMに直接インプットすることに適していないデータ形式もマークダウン形式に変換できる。
- マークダウン形式に変換できると何がうれしいのか？
    - テキストデータであるため、LLMに投入しやすい。
    - （筆者の推測だが）LLMはマークダウン形式の情報の解釈が得意であるため、回答精度が高くなりやすい。
    - `markitdown`が対応しているファイルフォーマットであれば、全てマークダウンという統一したデータになるため、データ管理が容易になる（はず）。
    - 上記全てはRAGで特に性能向上に寄与してくれるメリットだと思います。

# 今回試してみること

すでにいろんな方がmarkitdownの検証をしていますが、Microsoft社が用意しているサンプルデータを使っており、筆者の実用性の検証としてあまり参考にできませんでした。
具体的には、筆者が実際に仕事でよく見る形式（後述）のデータをマークダウン形式に変換していないので、自分で試してみることとしました。


▼筆者がよく見る形式のデータ

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/1a4663d7-4f3a-440b-78ba-4111513ab1d3.png)

筆者はデータサイエンティストとして仕事をしているので、データパイプラインやアーキテクチャ図をよく資料として作成したり読んだりします。
この形式のデータを食わせて（RAGっぽく）検索させたり、過去のPJ内容を要約させたりできるのかどうかを検証してみたく、やらせてみることにしました。


# 検証

[**今回作成したコードはこちら**]()

## 必要なライブラリ

```text
markitdown
openai
python-dotenv
```

## 

## とはいえまずは動作テストのためにサンプルデータで動かしてみる

Microsoft社が用意しているサンプルデータを使います。

- 今回使用するサンプルデータ：https://github.com/microsoft/markitdown/tree/main/tests/test_files


### Excel
シートが2つ存在している状態で、ちょっとした数値データが入っている状態。

- シート1：Sheet1
- シート2：09060124-b5e7-4717-9d07-3c046eb

```python
from markitdown import MarkItDown

DATA_DIR = "data/"

markitdown = MarkItDown()
result = markitdown.convert(DATA_DIR + "test.xlsx")
print(result.text_content)
```

▼出力
```shell
## Sheet1
| Alpha | Beta | Gamma | Delta |
| --- | --- | --- | --- |
| 89 | 82 | 100 | 12 |
| 76 | 89 | 33 | 42 |
| 60 | 84 | 19 | 19 |
| 7 | 69 | 10 | 17 |
| 87 | 89 | 86 | 54 |
| 23 | 4 | 89 | 25 |
| 70 | 84 | 62 | 59 |
| 83 | 37 | 43 | 21 |
| 71 | 15 | 88 | 32 |
| 20 | 62 | 20 | 67 |
| 67 | 18 | 15 | 48 |
| 42 | 5 | 15 | 67 |
| 58 | 6ff4173b-42a5-4784-9b19-f49caff4d93d | 22 | 9 |
| 49 | 93 | 6 | 38 |
| 82 | 28 | 1 | 39 |
| 95 | 55 | 18 | 82 |
| 50 | 46 | 98 | 86 |
| 31 | 46 | 47 | 82 |
| 40 | 65 | 19 | 31 |
| 95 | 65 | 29 | 62 |
| 68 | 57 | 34 | 54 |
| 96 | 66 | 63 | 14 |
| 87 | 93 | 95 | 80 |

## 09060124-b5e7-4717-9d07-3c046eb
| ColA | ColB | ColC | ColD |
| --- | --- | --- | --- |
| 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | affc7dad-52dc-4b98-9b5d-51e65d8a8ad0 |
```

シート単位で出力してくれるのは地味に便利。
同様の書き方で、htmlやwordファイルも読み取れます。

### 画像の場合

▼今回インプットする画像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/72fd301c-6f37-100d-e118-19de7ffa9b29.png)

文字主体（というか論文）を画像化しているもの。

画像データの場合、画像を解釈させるために、ChatGPTを使っている。そのため、OpenAI社のAPIキーが必要。

```python
import os
from dotenv import load_dotenv
from openai import OpenAI
from markitdown import MarkItDown


# set environmental variables
load_dotenv()

DATA_DIR = "data/"

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
)

md = MarkItDown(mlm_client=client,
                mlm_model="gpt-4o"
)
result = md.convert(DATA_DIR + "test.jpg")
print(result.text_content)
```

▼出力
```shell
# Description:
This image features the title and abstract page of a research paper titled "AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation." The paper is authored by researchers from Microsoft Research, Pennsylvania State University, University of Washington, and Xidian University. The focus is on AutoGen, an open-source framework designed for developing applications using large language models (LLMs) through multi-agent conversations. The visual includes a diagram illustrating how agents can be customized and participate in flexible conversations to carry out tasks, potentially involving human interaction. The abstract highlights AutoGen’s versatility in creating complex applications across various domains, emphasizing its empirical success in areas like mathematics, coding, and decision-making. A GitHub link and contact email for further details are provided. The publication is cataloged under arXiv on 3 Oct 2023.
```

画像をマークダウンとして説明させることに成功した。
推測だが、裏でプロンプトが設定されており、それに沿って出力してくれているのだと思われる。
何回か出力させてみたが、必ず「# Description」から出力が始まる。そういう出力をさせるためのプロンプトが組まれているのだろう。


## 今回の実験：データパイプラインのような抽象度高いものもちゃんとマークダウン形式に変換できるのか？

2種類のフォーマットでインプットしてみる。

- ①：画像データ
- ②：パワポデータ

### ①：画像データ
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/1a4663d7-4f3a-440b-78ba-4111513ab1d3.png)


```python
import os
from dotenv import load_dotenv
from openai import OpenAI
from markitdown import MarkItDown


# set environmental variables
load_dotenv()

DATA_DIR = "data/"

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
)
md = MarkItDown(mlm_client=client,
                mlm_model="gpt-4o"
)

result = md.convert(DATA_DIR + "図1.png")
print(result.text_content)
```

▼出力結果
```shell
# Description:
This image illustrates a data processing pipeline using various tools and technologies, all containerized with Docker. The workflow begins with CSV files, which are ingested by Airbyte and processed in a Docker environment. The data is then stored in a PostgreSQL database and transformed using dbt. The transformed data is utilized by Metabase for data visualization and by Jupyter Lab for further analysis, both running in Docker containers. Apache Airflow, also deployed in a Docker container, orchestrates the entire workflow, ensuring seamless data integration and processing from start to finish.
```

特に、この図がデータパイプラインという説明とかしていないが、データパイプラインの図であることを認識してくれている..！実用に足る精度だと個人的には思う。
（筆者のデータパイプラインのお絵描きが素晴らしいのかもしれない（殴））




### ②：パワポデータ
先ほどのデータパイプラインの画像を作成した時に使ったパワポをmarkitdownに食わせてみる。同様にうまく出力できるかを検証する。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687015/fa6b1d6d-38b4-7679-5125-b3ced0c225f6.png)



```python
from markitdown import MarkItDown

DATA_DIR = "data/"

markitdown = MarkItDown()
result = markitdown.convert(DATA_DIR + "ローカルデータパイプライン説明図作成.pptx")
print(result.text_content)
```

注意点：上記のコードでは、ChatGPTを利用していない点に注意。画像解釈性能が弱まる。

▼出力結果
```shell
<!-- Slide number: 1 -->
csv

Airbyte

Docker

PostgreSQL
dbt

Docker

Metabase

Docker

Jupyter Lab

Docker

Airflow

Docker
```

パワポで表示されている単語を並べているだけになってしまっている。

もしかしたらパワポに関しては、画像化させてしまった方が、適切に情報を処理させることができるかもしれない。

#### おまけ：パワポをChatGPT使えないか検証してみた。

```python
import os
from dotenv import load_dotenv
from openai import OpenAI
from markitdown import MarkItDown

# set environmental variables
load_dotenv()

DATA_DIR = "data/"

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
)
md = MarkItDown(mlm_client=client,
                mlm_model="gpt-4o"
)

result = md.convert(DATA_DIR + "ローカルデータパイプライン説明図作成.pptx")
print(result.text_content)
```

▼出力結果

```shell
<!-- Slide number: 1 -->
csv

Airbyte

Docker

PostgreSQL
dbt

Docker

Metabase

Docker

Jupyter Lab

Docker

Airflow

Docker
```

結果は変わらなかった。おそらく、ファイルの種類（拡張子）に応じて、呼び出す処理が変更される仕様となっているのだろう。
今回の場合は、拡張子が「.pptx」なので、画像解釈のためにChatGPTを呼び出すことはせずに、パワポ用のマークダウン変換処理が実行されたのだと推測される。





# まとめ

- 文字が多めのコンテンツであれば、ChatGPTを使わずとも精度よくマークダウン形式に変換することができる。
- 一方で、今回実験したデータパイプラインのように抽象度が高い場合は、画像化したうえでChatGPT経由で文字起こし（マークダウン形式に変換）しないと、目も当てられないような結果になることが分かった。
- `markitdown`は冒頭でも書いた通り、`pdfminer`のような既存ツールをラッピングしているだけなので、そちらのツールの精度次第ということも想像される。
- 筆者なりに使うべきケースとそうではないケースを考えると以下のようになると思う。
    - 簡易的にマークダウン形式に変換してRAGシステムを作ったりLLMのアプリケーションを開発する分には`markitdown`は非常に便利である。→ モックの作成やMVPの作成。外には出さずに内部で簡易的に検証したい時。
    - しかし、回答精度が求められたりするようなケースには向いていない。→ しっかりとしたサービスや製品として利用する時。