Microsoft MarkItDown徹底解剖

![表紙](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/a9a93f71-35f9-c5b0-a639-980a91bf7d23.png)

# MarkItDownとは？

[MarkItDown](https://github.com/microsoft/markitdown/)は、Microsoftが開発したPythonライブラリで、さまざまなファイル形式をMarkdownに変換することができます。

リリースされてからわずか2週間でGitHubで25k以上のスターを獲得し、急速に人気を集めています！🤯

![MarkItDownのスター履歴](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/ddbf6d37-0b9e-e61a-ddff-5bd197c610da.png)


## なぜMarkItDownはこんなに人気なのか？

MarkItDownは以下のような幅広いファイル形式に対応しています：

- Officeドキュメント: PowerPoint、Word、Excel
- リッチメディアファイル: 画像（EXIFおよび画像説明付き）、音声（文字起こし付き）
- ウェブ・構造化データ: HTML、CSV、JSON、XML
- アーカイブ: ZIPファイル

WordやExcelなどの一般的な形式に対応しているだけでなく、OCRや音声認識を活用してコンテンツを抽出することで、マルチモーダルなファイルにも対応しています。

これにより、あらゆるものをMarkdownに変換できるMarkItDownは、LLM（大規模言語モデル）トレーニングにおいて非常に強力なツールとなります。ドメイン特化型の文書を処理することで、LLM搭載アプリケーションにおいてより正確で関連性の高い応答を生成するためのリッチなコンテキストを提供します。

# MarkItDownの使い方

MarkItDownの使用は驚くほど簡単で、わずか4行のコードで済みます：

```py
from markitdown import MarkItDown

md = MarkItDown()
result = md.convert("test.xlsx")
print(result.text_content)
```

以下はMarkItDownの使用例です。

Wordファイルを変換すると、正確なMarkdownが出力されます：

![Word例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/2458a1be-87ed-2af5-78f0-4addda912be4.png)

マルチシートのExcelファイルもお手のもの：

![Excel例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/82775167-2752-3555-9988-417a5c03693f.png)

ZIPファイルも処理可能で、アーカイブ内の全てのコンテンツが再帰的に解析されます：

![ZIP例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/f050ddf5-eef2-ebcc-2b0d-ca1b72c0066c.png)

画像からコンテンツを抽出しようとすると、結果は何も得られません：

![画像例（失敗）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/9cfc3df2-1634-6fda-18f6-54dc4d19da83.png)

なぜ結果が得られないのでしょうか？MarkItDownは画像ファイルをサポートしています！

問題は、画像説明を抽出するためにLLMが必要な点にあります。以下のように、MarkItDownに適合したLLMクライアントを統合してください：

```py
from openai import OpenAI

client = OpenAI(api_key="i-am-not-an-api-key")

md = MarkItDown(llm_client=client, llm_model="gpt-4o")
```

これで画像コンテンツが正常に変換されます：

![画像例（成功）](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/94502bd3-bbed-5730-1d08-1e8df8e3dd27.png)

注意：LLMは画像に対してのみ機能します。PDFからコンテンツを抽出するには、事前にOCRで処理されている必要があります。

![PDF画像例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/ee0f0773-d273-7f97-4e5d-18ae2075a215.png)

しかし、PDFから抽出されたテキストは全てのフォーマットを失い、見出しと通常のテキストの区別がつきません。

![PDFテキスト例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/516cc5eb-6c9b-e0c4-6940-25de208f40e7.png)

## MarkItDownの制限事項

上記の例からも分かるように、MarkItDownにはいくつかの制限があります：

- OCR未処理のPDFは処理できません。
- PDFから抽出したテキストにはフォーマットがありません。

しかし、MarkItDownはオープンソースツールなので、拡張性が高く、そのシンプルなコードベースにより、開発者は新しい機能を簡単に追加できます。

# MarkItDownの仕組み

MarkItDownのアーキテクチャはシンプルで、コア実装は[わずか1つのファイル](https://github.com/microsoft/markitdown/blob/main/src/markitdown/_markitdown.py)に収められています。

コードベースには、`DocumentConverter`クラスが定義されており、`convert()`メソッドを持っています：

```py
class DocumentConverter:
    """Abstract superclass of all DocumentConverters."""

    def convert(
        self, local_path: str, **kwargs: Any
    ) -> Union[None, DocumentConverterResult]:
        raise NotImplementedError()
```

さまざまなコンバーターがこの基底クラスを継承し、初期化時に登録されます：

```py
self.register_page_converter(PlainTextConverter())
self.register_page_converter(HtmlConverter())
self.register_page_converter(DocxConverter())
self.register_page_converter(XlsxConverter())
self.register_page_converter(Mp3Converter())
self.register_page_converter(ImageConverter())
# ...
```

このモジュラー設計により、開発者は必要に応じて独自のコンバーターを簡単に作成できます。

## 各ファイル形式の変換方法

### Officeファイル

Officeファイルは最初に`mammoth`、`pandas`、`pptx`などのライブラリを使ってHTMLに変換され、その後`BeautifulSoup`でMarkdownに解析されます。

![Officeワークフロー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/49c4c3ac-9d9e-72e4-06d8-a0dd71ffe254.png)

### 音声ファイル

音声ファイルは`speech_recognition`ライブラリを使って処理され、GoogleのAPIを活用して文字起こしが行われます。

(Microsoftさん、Azureにはまだ忠誠を誓っていますよね？💔)

![音声ワークフロー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/83a4f0f9-622b-3e29-05ab-4a2216c07b21.png)

### 画像

画像は以下のプロンプトを使用してLLMに処理されます：
`"Write a detailed caption for this image."`

![画像ワークフロー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/b145c34a-1cc8-59ce-a4ea-f3d1efd2f70f.png)

### PDF

PDFは`pdfminer`ライブラリを使って解析されます。ただし、OCRが内蔵されていないため、PDFの内容が事前に抽出可能であることを確認する必要があります。

![PDFワークフロー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/3f94232a-d48c-4cbc-5ad4-84e18c29cb66.png)

# MarkItDownをAPIとして利用する方法（無料でホスティング可能）

MarkItDownはローカルで実行できますが、APIとしてホスティングすると、Zapier、n8n、またはファイル変換サービスを提供する独自のウェブサイトなどのワークフローに統合しやすくなります。

以下は`FastAPI`を使用してMarkItDownをAPIとしてホスティングする簡単な例です：

```py
import shutil
from markitdown import MarkItDown
from fastapi import FastAPI, UploadFile
from uuid import uuid4

md = MarkItDown()

app = FastAPI()

@app.post("/convert")
async def convert_markdown(file: UploadFile):
    hash = uuid4()
    folder_path = f"./tmp/{hash}"

    shutil.os.makedirs(folder_path, exist_ok=True)

    file_path = f"{folder_path}/{file.filename}"
    with open(file_path, "wb") as f:
        shutil.copyfileobj(file.file, f)
    result = md.convert(file_path)
    text = result.text_content

    shutil.rmtree(folder_path)

    return {"result": text}
```

APIを次のように呼び出すことができます：

```js
const formData = new FormData();
formData.append('file', file);

const response = await fetch('http://localhost:8000/convert', {
  method: 'POST',
  body: formData,
});
```

## APIを無料でホスティングする方法

Python APIのホスティングは難しいことがあります。AWS EC2やDigitalOceanのような従来のサービスは、サーバー全体をレンタルする必要があり、常にコストがかかります。

しかし、今では[Leapcell](https://leapcell.io/?lc_t=q_mid)を利用できます。

LeapcellはPythonコードベースをサーバーレス方式でホスティングできるプラットフォームで、APIコールごとに課金され、無料の利用枠も寛大です。

GitHubリポジトリを接続し、ビルドと開始コマンドを定義するだけで準備完了です：

![デプロイメント](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/27b00ae6-3b2b-0857-c80f-45310b9c7f0c.png)

これでMarkItDown APIがクラウドにホストされ、ワークフローに統合できるようになります。そして何より、実際に呼び出されたときだけ課金されます。

---

今すぐ[Leapcell](https://leapcell.io/?lc_t=q_mid)で自分のMarkItDown APIを構築しましょう！😎

[![Leapcell](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3967621/be24bd10-b391-3979-b144-7bc688445b20.png)](https://leapcell.io/?lc_t=q_mid)

LeapcellをXでフォローしましょう: https://x.com/LeapcellHQ