はじめに
みなさん、こんにちは!業務ハックLabのようです。
この記事は「Microsoft Power Automate Advent Calendar 2025」の12月23日担当分の記事です。
前回は変数の初期化とファイル取得まで完了しましたね!
(8個の変数、ちゃんと作れましたか?)
さあ、いよいよ今回が本番中の本番です!
Azure Document IntelligenceとAzure OpenAIを使って、契約書を分析する部分を作っていきますよ!
(正直、ここが一番ワクワクする部分なんですよね。AIが契約書を読んでリスクを指摘してくれるって、未来感ありませんか?)
今回の目標
第3回では、AIによる分析部分を完成させます。
実装する内容:
- Document Intelligenceで契約書からテキストを抽出
- 非同期処理の結果を取得(Do Untilループ)
- 抽出結果をJSON解析
- Azure OpenAIでリスク分析
- 分析結果をJSON解析
うん、やることが多い!
でも一つずつ丁寧に進めていけば大丈夫です。
では、行ってみましょう!
Phase 5: Document Intelligence でテキスト抽出
5-1. Document Intelligence API 呼び出し
まずは、契約書PDFからテキストを抽出する処理を作ります。
ここで「HTTP」アクションを使います。
(APIを直接叩くやつですね!)
手順:
- 「+新しいステップ」をクリック
- 検索ボックスに「HTTP」と入力
- 「HTTP」アクションを選択
HTTPアクションが追加されたら、以下の設定を入れていきます。
基本設定:
| 項目 | 設定値 |
|---|---|
| メソッド | POST |
| URI | 下記参照(式として入力) |
| ヘッダー | 下記参照 |
| 本文 | 下記参照(式として入力) |

さあ、ここからちょっと複雑になりますが、一つずつ見ていきましょう。
URI の設定
URIは、APIのエンドポイントを指定する部分です。
ここで注意!
普通に入力するんじゃなくて、「式」として入力する必要があります。
手順:
- URI の入力欄をクリック
- 右側のパネルで「式」タブをクリック
- 以下の式を入力
@{variables('var_DocIntelEndpoint')}documentintelligence/documentModels/prebuilt-contract:analyze?api-version=2024-11-30

これ、何をやってるかというと、
前回作った変数「var_DocIntelEndpoint」の値を取り出して、その後ろにAPIのパスを繋げてるんです。
(だから変数の最後に「/」を付けておくのが重要だったんですね!)
ヘッダーの設定
次はヘッダーです。
これはAPIに「こういう形式でデータを送りますよ」って伝える部分。
「ヘッダーの追加」をクリックして、2つのヘッダーを追加します。
ヘッダー1:
- キー:
Content-Type - 値:
application/json
ヘッダー2:
- キー:
Ocp-Apim-Subscription-Key - 値(式として入力):
@{variables('var_DocIntelKey')}

2つ目のヘッダーの値も、式タブから入力してくださいね!
これでAPIキーが変数から取り出されます。
本文の設定
最後に本文です。
ここに、PDFファイルの内容をBase64エンコードして送ります。
本文の入力欄をクリックして、「式」タブから以下を入力します。
{
"base64Source": "@{base64(body('ファイル_コンテンツの取得'))}"
}

⚠️ 重要: 'ファイル_コンテンツの取得' の部分は、前回作ったアクションの実際の名前に合わせてください。
アクション名が違う場合(例:「ファイル コンテンツの取得」)は、そちらに合わせます。
(Power Automateは自動で日本語名を振るので、微妙に違うことがあるんですよね…)
5-2. Operation Location の保存
Document Intelligenceは非同期処理なので、「処理を受け付けました!結果はこのURLで確認してね」という返事が返ってきます。
そのURLを変数に保存しておきます。
手順:
- 「+新しいステップ」をクリック
- 「変数 – 変数の設定」を選択
設定内容:
| 名前 | var_OperationLocation |
| 値(式) | @{outputs('HTTP')?['headers']?['Operation-Location']} |

これで、処理結果を取得するためのURLが変数に保存されました!
Phase 6: 処理結果の取得(Polling)
さあ、ここが少しトリッキーな部分です。
Document Intelligenceは処理に時間がかかるので、「まだかな?まだかな?」って定期的に確認する必要があるんです。
(これをポーリングって言います)
6-1. Do Until ループの追加
「処理が完了するまで繰り返す」という処理を作ります。
手順:
- 「+新しいステップ」をクリック
- 検索ボックスに「Do until」と入力
- 「制御 – Do until」を選択
Do untilのブロックが追加されたら、まず条件を設定します。
条件の設定:
| 左側(式) | @{body('HTTP_結果取得')?['status']} |
| 演算子 | 次の値に等しい |
| 右側 | succeeded |

ん?「HTTP_結果取得」ってまだ作ってないのに、なんでこれが出てくるの?
って思いますよね。
これは、この後作るアクションの名前なんです。
先にこの条件を設定しておいて、後でアクションを作るという順番になります。
(ちょっと不思議な感じだけど、Power Automateではよくあるパターンです)
制限設定
詳細パラメーターの中に「件数」、「タイムアウト」の項目があるので設定します。
制限設定:
| 件数 | 40 |
| タイムアウト | PT2M |

これは「最大2分間、または40回まで繰り返す」という意味です。
(普通の契約書なら1分以内に処理が終わるので、余裕を持たせてます)
6-2. Do Untilの中に遅延を追加
Do Untilのブロックの中に、「アクションの追加」をクリックします。
手順:
- 「スケジュール – 遅延」を選択
- カウント:
3 - 単位:
秒

これで、3秒待ってから次の処理に進むようになります。
(API叩きまくるとレート制限に引っかかるので、ちょっと待つんです)
6-3. Do Untilの中に HTTP を追加
遅延の後に、もう一つHTTPアクションを追加します。
手順:
- 遅延の下にある「アクションの追加」をクリック
- 「HTTP」を選択
設定内容:
| 項目 | 設定値 |
|---|---|
| メソッド | GET |
| URI(式) | @{variables('var_OperationLocation')} |
| ヘッダー | Ocp-Apim-Subscription-Key: @{variables('var_DocIntelKey')} |
⚠️ 超重要: このHTTPアクションの名前を変更します!
HTTPアクションの名前をクリックして名前を HTTP_結果取得 に変更してください。

これで、最初に設定したDo untilの条件と繋がりました!
(だから先に条件で「HTTP_結果取得」って書いてたんですね)

Phase 7: Document Intelligence 結果のJSON解析
Do Untilループが終わったら(つまり処理が完了したら)、結果を解析します。
Do Untilブロックの外側(下)に、新しいアクションを追加します。
(ここ、間違えてDo Untilの中に入れちゃわないように注意!)
7-1. JSON の解析
手順:
- 「+新しいステップ」をクリック(Do Untilの外側!)
- 「データ操作 – JSON の解析」を選択
設定内容:
| コンテンツ(式) | @{body('HTTP_結果取得')} |
| スキーマ | 下記参照 |

スキーマ:
{
"type": "object",
"properties": {
"status": {"type": "string"},
"analyzeResult": {
"type": "object",
"properties": {
"content": {"type": "string"},
"documents": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"properties": {
"Parties": {
"type": "object",
"properties": {
"content": {"type": "string"}
}
},
"Title": {
"type": "object",
"properties": {
"content": {"type": "string"}
}
},
"ContractId": {
"type": "object",
"properties": {
"content": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
}
このスキーマは、Document Intelligenceが返してくる結果の「型」を定義してるんです。
(これがあると、後で「content」とか「fields」とかを簡単に取り出せるようになります)
⚠️ このアクションの名前も変更: JSON解析_DocIntel

Phase 8: Azure OpenAI でリスク分析
さあ、いよいよAIの出番です!
Document Intelligenceで抽出したテキストを、Azure OpenAIに投げてリスク分析してもらいます。
8-1. Azure OpenAI API 呼び出し
またHTTPアクションを使います。
(だんだん慣れてきましたよね?)
手順:
- 「+新しいステップ」をクリック
- 「HTTP」を選択
設定内容:
| 項目 | 設定値 |
|---|---|
| メソッド | POST |
| URI | 下記参照(式) |
| ヘッダー | 下記参照 |
| 本文 | 下記参照(式) |
URI の設定
式として入力:
@{variables('var_OpenAIEndpoint')}openai/deployments/@{variables('var_DeploymentName')}/chat/completions?api-version=2024-02-01
ヘッダーの設定
ヘッダー1:
- キー:
Content-Type - 値:
application/json
ヘッダー2:
- キー:
api-key - 値(式):
@{variables('var_OpenAIKey')}
本文の設定
ここが一番重要です!
システムプロンプトと、Document Intelligenceで抽出したテキストを組み合わせて送ります。
式として入力:
{
"messages": [
{
"role": "system",
"content": "@{variables('var_SystemPrompt')}"
},
{
"role": "user",
"content": "以下の契約書を分析してください:\n\n@{body('JSON解析_DocIntel')?['analyzeResult']?['content']}"
}
],
"temperature": 0.3,
"max_tokens": 3000,
"response_format": { "type": "json_object" }
}

見てください、@{variables('var_SystemPrompt')} で前回作ったプロンプトを取り出して、@{body('JSON解析_DocIntel')?['analyzeResult']?['content']} で契約書のテキストを取り出してるんです。
(ここで変数の威力が発揮されるわけですね!)
⚠️ このアクションの名前も変更: HTTP_OpenAI

Phase 9: OpenAI レスポンスのJSON解析
最後に、Azure OpenAIが返してきた分析結果を解析します。
9-1. JSON の解析
手順:
- 「+新しいステップ」をクリック
- 「データ操作 – JSON の解析」を選択
設定内容:
| コンテンツ(式) | @{body('HTTP_OpenAI')?['choices']?[0]?['message']?['content']} |
| スキーマ | 下記参照 |
スキーマ:
{
"type": "object",
"properties": {
"overall_risk_level": {"type": "string"},
"risk_score": {"type": "number"},
"summary": {"type": "string"},
"high_risk_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {"type": "string"},
"description": {"type": "string"},
"clause_reference": {"type": "string"},
"severity": {"type": "string"},
"recommendation": {"type": "string"}
}
}
},
"medium_risk_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {"type": "string"},
"description": {"type": "string"}
}
}
},
"low_risk_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"category": {"type": "string"},
"description": {"type": "string"}
}
}
},
"positive_points": {
"type": "array",
"items": {"type": "string"}
}
}
}

このスキーマは、前回変数で設定したシステムプロンプトの出力形式と一致してます。
(だからAIがちゃんとこの形式で返してくれるんですね!)
⚠️ このアクションの名前も変更: JSON解析_OpenAI

ここまでの確認
はい、お疲れ様です!
AI分析の核心部分が完成しました!
現在のフロー構成:
- トリガー: ファイルが作成されたとき
- 変数を初期化する × 8回
- ファイル コンテンツの取得
- HTTP(Document Intelligence呼び出し)
- 変数の設定(Operation Location保存)
- Do Until(結果取得まで待機)
– 遅延
– HTTP_結果取得 - JSON解析_DocIntel
- HTTP_OpenAI
- JSON解析_OpenAI

フローを見ると、かなり長くなってきましたね!
でも、もう分析部分は完成です。
テストしてみましょう
一旦、保存してテストしてみましょう。
手順:
- 「保存」をクリック
- 「テスト」をクリック
- SharePointに契約書PDFをアップロード

すべてのステップが緑になれば成功です!
「JSON解析_OpenAI」のアクションを開くと、AIが分析した結果が見えるはずです。overall_risk_level とか high_risk_items とかが表示されてますか?

(ここでちゃんと結果が見えたら、もう感動ものですよ!)
まとめ
はい、如何でしたでしょうか?
第3回では、AI分析の核心部分を実装しました!
今回やったこと:
- Document Intelligence APIを呼び出してテキスト抽出
- Do Untilループで非同期処理の完了を待機
- 抽出結果をJSON解析
- Azure OpenAI APIでリスク分析を実行
- 分析結果をJSON解析
HTTPアクションとJSON解析、最初は難しく見えたかもしれませんが、一つずつ進めれば意外とできちゃいますよね!
(僕も最初は「式?スキーマ?なにそれ?」って感じでしたけど、慣れるとパターンが見えてきます)
次回(第4回)では、いよいよ最終回!
リスクレベルに応じた条件分岐、Teams通知、SharePointへの記録を実装して、システムを完成させます!
(あと少しで完成ですよ!頑張りましょう!)
それでは皆さん、良い業務ハックライフを~
連載記事:
- 第1回:システム概要・準備編
- 第2回:基礎実装編
- 📍 第3回:AI分析実装編(今回)
- 第4回:完成・運用編(次回予告)


コメント