記事公開日
Azure AI Document Intelligence で、マークダウン出力をしてみた

別の記事「【AI活用】MarkItDownを使ってRAGを構築してみた」では、Pythonのライブラリを使用したマークダウン出力を試していますが、今回は、Azure AI Document Intelligence を使用して、マークダウン出力を試してみたいと思います。
変換文書の用意
変換用のお試し文書を用意しました。
(生成AI を使って作成しました。内容に深い意味はありません)
「スーパーヒーローQESマンの月曜日の憂鬱」(全5ページ)
著者: Azure OpenAI
(➡PDF版)
同じ内容で、Word(docx)版も用意しています。
1-2ページのイメージは、こちらです。
マークダウン出力
Word版、PDF版をそれぞれマークダウン出力してみます。
マークダウン出力は、begin_analyze_document を呼び出す際に以下を指定します。
output_content_format=ContentFormat.MARKDOWN
実装例は、以下のようになります。(該当部分のみの抜粋)
# クライアントの作成 client = DocumentIntelligenceClient( endpoint=endpoint, credential=AzureKeyCredential(key) ) # ローカルPDFファイルを読み込んでバイトデータを取得 with open(file_path, "rb") as pdf_file: pdf_bytes = pdf_file.read() # バイトデータを使用してドキュメントを解析(マークダウン出力) poller = client.begin_analyze_document( model, AnalyzeDocumentRequest(bytes_source=pdf_bytes), output_content_format=ContentFormat.MARKDOWN, )
result: AnalyzeResult = poller.result() # Markdown形式の取得 markdown_content = result.content
Word版の出力
テキストだけが抽出できました。画像の抽出は無く、ページ区切りも識別できません。1-3ページ部の出力結果はこちら。
※1-2ページでは、マークダウン感が出なかったので、3ページ目も追加しました。
スーパーヒーロー QESマンの月曜日の憂鬱 平凡なヒーローの非凡な一日 月曜日の朝、QESマンは目覚まし時計のけたたましい音で目を覚ました。その音が彼の超人的な聴覚に刺さるようだった。彼はスーパーヒーローでありながら、どうにもこの月曜日という日に苦手意識を持っていた。世界を救う力はあっても、月曜日を快適にする力はまだ発明されていない。窓を開けると、どんよりとした曇り空が広がり、さらに彼の気分を沈ませた。 「今日も始まったな…」彼は深いため息をつきながら、スーツを手に取った。そのスーツは彼のヒーロー活動を象徴するものであり、街の人々からは絶対的な信頼を寄せられていた。しかしそのスーツを着る度に、責任の重さが肩にのしかかるような気がしてならなかった。 QESマンの朝のルーティンはいたって普通だった。朝食はいつものシリアルとコーヒー。スーパーヒーローもエネルギー源が必要である。しかし、何かが違った。彼はスプーンでシリアルを食べながらも、その心はどことなく落ち着かない。「何か大きな問題が起きる気がする…」彼は予感を拭い去ることができなかった。 # ミッションの開始 午前10時、QESマンの通信デバイスが鳴り響いた。「市内中心部で大規模な混乱が発生しています。急行してください!」と緊急メッセージが届く。彼は一瞬ためらったものの、すぐにスーツを身にまとい、空へと飛び立った。月曜日の憂鬱を吹き飛ばすように、彼はその場へ向かう。 中心部に到着すると、巨大なロボットが暴れ回っていた。そのロボットは何者かによって遠隔操作されているようで、「破壊」のみを目的としているようだった。QESマンはその場を見渡しながら、どのように対処すれば効率的かを瞬時に計算した。「このロボットの制御装置を見つけなければ!」彼は自分の能力を駆使して、ロボットの弱点を探した。
PDF版の出力
テキストの抽出に加え、画像部分は <figure>タグとして出力されました。
<figure>タグの内容は、単純にOCRで文字だけを抽出した形になっており、どのような画像であるか識別できません。
ページ区切りは認識し、<!-- PageBreak --> が挿入されていました。
# スーパーヒーロー QES マンの月曜日の憂鬱 平凡なヒーローの非凡な一日 月曜日の朝、QES マンは目覚まし時計のけたたましい音で目を覚ました。その音が彼の超 人的な聴覚に刺さるようだった。彼はスーパーヒーローでありながら、どうにもこの月曜日 という日に苦手意識を持っていた。世界を救う力はあっても、月曜日を快適にする力はまだ 発明されていない。窓を開けると、どんよりとした曇り空が広がり、さらに彼の気分を沈ま せた。 <figure> MONDAYS! QES MAN </figure> <!-- PageBreak --> 「今日も始まったな…」彼は深いため息をつきながら、スーツを手に取った。そのスーツは 彼のヒーロー活動を象徴するものであり、街の人々からは絶対的な信頼を寄せられていた。 しかしそのスーツを着る度に、責任の重さが肩にのしかかるような気がしてならなかった。 QES マンの朝のルーティンはいたって普通だった。朝食はいつものシリアルとコーヒー。 スーパーヒーローもエネルギー源が必要である。しかし、何かが違った。彼はスプーンで シリアルを食べながらも、その心はどことなく落ち着かない。「何か大きな問題が起きる 気がする…」彼は予感を拭い去ることができなかった。 <figure> DIS DEEPLY ENTRUSTED ANOTHER DAY HAS STARTED ... </figure> <!-- PageBreak -->
PDF文書の場合は、ページ番号の抽出も対応していますが、ページ中にページ番号が文字として埋め込まれている場合のみとなります。
ページ番号が埋め込まれたPDF文書から出力した場合は、 <!-- PageNumber="2" --> のように出力されます。こちらのページ番号は、埋め込まれているページ番号を抽出しており、実際のPDFファイルとしてのページ番号とは異なることがあります。
<!-- PageNumber="2" --> <!-- PageBreak -->
<figure>タグで抽出された画像については、レイアウト分析結果として座標情報を取得することができます。
レイアウト分析結果の figuresリスト(上記実装例の場合は、result.figures)に以下のような形で格納されます。
➡レイアウト分析結果(AnalyzeResult Class)
ページ番号と座標情報が設定されており、この情報をもとに PDFファイルから画像情報を抜き出すことができます。
{ 'id': '1.1', 'boundingRegions': [ { 'pageNumber': 1, 'polygon': [1.1759, 4.818, 6.6063, 4.8184, 6.6067, 10.2534, 1.1762, 10.2531] } ], 'spans': [ { 'offset': 216, 'length': 38} ], 'elements': ['/paragraphs/3', '/paragraphs/4'] } }
画像情報の説明を追加
別記事の「【Azure AI Search】取込み機能の「マルチモーダルRAG」を試してみた」では、抽出した画像情報を Azure OpenAIを使って説明させることができました。同様に画像の説明を生成してみます。どのような説明文を生成するかはプロンプト次第となりますが、図に位置関係が考えられるものは「マーメイド記法」で表現するように指示も追加しています。
画像を説明した文章をマークダウンの <figure>ブロックに埋め込むことで、文書の流れに合わせて画像の説明が付加されます。また、ページ番号が無いPDF(PageNumber が出力されていない)ファイルの場合は、[PageBreak]でページ単位で分割してページ番号も埋め込むようにしてみました。
生成した内容は、こちら。
※本文より、画像の説明文の方が長くなってしまいました・・・・。このあたりのバランスもプロンプトの調整次第です。
# スーパーヒーロー QES マンの月曜日の憂鬱 平凡なヒーローの非凡な一日 月曜日の朝、QES マンは目覚まし時計のけたたましい音で目を覚ました。その音が彼の超 人的な聴覚に刺さるようだった。彼はスーパーヒーローでありながら、どうにもこの月曜日 という日に苦手意識を持っていた。世界を救う力はあっても、月曜日を快適にする力はまだ 発明されていない。窓を開けると、どんよりとした曇り空が広がり、さらに彼の気分を沈ま せた。 <figure> この画像はコミックスタイルのイラストで、筋肉質なスーパーヒーロー風の人物が「QES MAN」と書かれたコスチュームを着ています。人物は赤いマントを纏い、青いスーツの胸元には「QES MAN」と書かれたエンブレムがプリントされています。 場面は室内で、右側にその人物、左側の窓辺に古典的なベル式目覚まし時計が置かれています。外の空は曇っていて、鳥が何羽か飛んでおり、やや憂鬱な雰囲気が漂っています。 人物の口からは青い稲妻のようなエネルギーが発せられており、そのエネルギーはセリフの吹き出し「MONDAYS!(月曜日!)」とつながっています。この流れは、人物が月曜日に対して強い感情(おそらく嫌悪感や闘志)を持って発していることを示唆しています。 加えて、目覚まし時計は傾き、振動しているような線が描き加えられています。これは「月曜日の朝」を象徴するアイテムであり、QES MANがこれから新しい週に立ち向かおうとしている状況を表現しています。 主な構図(マーメイド記法): ```mermaid graph LR A[曇り空と鳥] B[窓辺と目覚まし時計] C[スーパーヒーロー型の人物(QES MAN)] D[吹き出し「MONDAYS!」] B -- 月曜の朝を象徴 --> C C -- 発する稲妻のエネルギー --> D A -- 憂鬱な雰囲気 --> 全体構図 ``` 全体として、「月曜日の始まり」に立ち向かう力強さや矛盾する気持ちをユーモラスに表現したイラストになっています。 </figure> <!-- PageNumber="1" --> <!-- PageBreak --> 「今日も始まったな…」彼は深いため息をつきながら、スーツを手に取った。そのスーツは 彼のヒーロー活動を象徴するものであり、街の人々からは絶対的な信頼を寄せられていた。 しかしそのスーツを着る度に、責任の重さが肩にのしかかるような気がしてならなかった。 QES マンの朝のルーティンはいたって普通だった。朝食はいつものシリアルとコーヒー。 スーパーヒーローもエネルギー源が必要である。しかし、何かが違った。彼はスプーンで シリアルを食べながらも、その心はどことなく落ち着かない。「何か大きな問題が起きる 気がする…」彼は予感を拭い去ることができなかった。 <figure> この画像は、コマ割りされたコミック風のイラストで、サラリーマンの日常の一コマを「ヒーロー」のように劇的に描いています。 左側のコマ: フィットしたスーツを着た筋肉質な人物が、ロボットのような無表情のマスクをつけ、スーツのジャケットを腕にかけています。背筋を伸ばし、まるでこれから大きな任務に出発するヒーローのような姿勢です。背景には家族写真らしきものが壁に飾られています。 右上のコマ: 人物がシリアルのような朝食を食べており、「DIS DEEPLY ENTRUSTED...」(「深く託されたこの…」)というテキストが添えられています。 右下のコマ: 同じ人物が窓際のテーブルで朝食を食べており、「ANOTHER DAY HAS STARTED...」(「また新しい一日が始まった…」)というナレーションが表示されています。 構図を簡単なマーメイド記法で表すと: graph LR A[自室でヒーロー風の装い] B[朝食を食べる] C[新しい一日の開始] A --> B --> C 全体を通して、「会社に出勤する社会人の日常」を、スーパーヒーローの朝のようにドラマチックに描いた、ユーモラスかつ風刺的な作品となっています。 </figure> <!-- PageNumber="2" --> <!-- PageBreak -->
この形にすることで、ドキュメントの一連の流れで画像情報を埋め込むことができました。
この情報を RAG検索の元ネタとすることで、検索精度の向上が見込めるかもしれません。
ページ番号を埋め込んだことで、RAGで回答を生成した根拠となる該当ページの案内をすることができるようになります。
おわりに
今回は、Document Intelligence のレイアウト分析機能を用いたマークダウン出力を試してみました。
単純にテキスト出力やマークダウン出力するだけであれば、markItDownのような無償ライブラリを使用するだけで良いかもしれません。有償サービスとなりますが、より複雑なレイアウト情報等を必要とする場合は、Document Intelligence も選択肢になるかと思います。
QUICK E-Solutions では、各AIサービスを利用したシステム導入のお手伝いをしております。それ以外でも様々なアプリケーションの開発・導入を行っております。提供するサービス・ソリューションにつきましては こちら に掲載しております。
システム開発・構築でお困りの問題や弊社が提供するサービス・ソリューションにご興味を抱かれましたら、是非一度 お問い合わせ ください。
※このブログで参照されている、Microsoft、Azure AI Search、Azure OpenAI、Document Intelligence、その他のマイクロソフト製品およびサービスは、米国およびその他の国におけるマイクロソフトの商標または登録商標です。
※その他の会社名、製品名は各社の登録商標または商標です。