UiPath Document Understanding APIでUiPathの外部から生成AI抽出機能を活用する方法

# はじめに

UiPath Document Understanding APIで生成AIによるドキュメント分類や抽出も可能になりました。Document Understandingの様なサービスに関わるAPIが公開されることによって、RPAを目的としたUiPathユーザーだけではなく、UiPathをサービスとして外部から利用すると言ったケースも出てくるかな？と言った印象を受けました。
本ブログでは、外部からUiPath Document Understanding APIを用いて、生成AIによる抽出を行った方法を紹介したいと思います。


# 本ブログでやっていること

本ブログで紹介する外部プログラムでは下記の処理を行っています。
1. Document Understanding APIを用いて職務経歴書のpdfファイルをUiPathサービスへアップロードする。
1. アップロードした職務経歴書のpdfファイルから抽出したい項目をDocument Understanding APIを介してプロンプトで要求し、結果を取得する。
1. 結果を整形して、csvファイルに出力する。
### ＜イメージ図＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/5c1f8a08-35e3-559d-8546-c57b4c3640f9.png)

:::note info
生成AIを利用するケースなのでUiPath側でのトレーニングやフォーム定義などの作業は不要です。
:::

:::note warn
本ブログで紹介するDocument Understanding APIを利用する際はUiPath AIユニットライセンスが必要です。
:::

# 本ブログで利用するサンプル帳票と抽出するデータ

### ＜ サンプル帳票 ＞
職務経歴書山田太郎.pdf
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/e1bd82d9-9432-54a5-1529-7c2c36b9b2f5.png)

### ＜ 抽出するデータ ＞
|ID  |プロンプト           |
|:-----------|:-----------|
|名前|氏名を教えてください。|
|現住所|現住所を教えてください。|
|連絡先電話番号|連絡先の電話番号を教えてください。|
|連絡先メールアドレス|連絡先のメールアドレスを教えてください。|
|年齢|年齢を教えてください。|
|学歴1学校名|学歴の１つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。|
|学歴1在籍期間|学歴の１つ目の在籍期間（開始年月日-終了年月日）を教えてください。|
|学歴2学校名|学歴の２つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。|
|学歴2在籍期間|学歴の２つ目の在籍期間（開始年月日-終了年月日）を教えてください。|
|学歴3学校名|学歴の３つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。|
|学歴3在籍期間|学歴の３つ目の在籍期間（開始年月日-終了年月日）を教えてください。|
|職歴1会社名|職歴の１つ目の会社名や所属を教えてください。|
|職歴1在籍期間|職歴の１つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。|
|職歴2会社名|職歴の２つ目の会社名や所属を教えてください。|
|職歴2在籍期間|職歴の２つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。|
|職歴3会社名|職歴の３つ目の会社名や所属を教えてください。|
|職歴3在籍期間|職歴の３つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。|
|スキル|プロフィールや保有技術を要約して教えてください。|
|日付|帳票の日付を教えてください。|

# 手順1：外部からDocument Understandingへアクセスする設定を行う
Automation Cloudポータルで[管理]>[外部アプリケーション]に遷移し、[アプリケーションを追加]をクリック>[範囲を追加]をクリックすると下記の画面が表示されます。上から順に[Document Understanding]を選択し、[アプリケーションの範囲]をクリック、今回利用する最小限の「Du.Digitzation.Api」と「Du.Extraction.Api」をチェックし、保存します。「追加」ボタンで表示されるアプリIDとアプリシークレットをメモしておきます。

### ＜ 外部アプリケーション機能 ＞

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/f6cbd3a2-35a0-f68e-2f06-3cf68f0af416.png)

# 手順2：ドキュメントをアップロードするAPIの仕様を調べる

❶Automation Cloudポータルのメニューから[Document Understanding]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/a8e075ed-1d92-31f5-5ad7-b227b892cf15.png)

:::note warn
利用するテナントでDocument Understandingのサービスが有効化されていない場合は表示されません。
:::

❷画面上部の[RESTAPI]をクリックし、[Framework]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/1fd46086-299e-be1a-c9dc-1764cedf59a0.png)

❸[Document Understanding Cloud APIs]のSwaggerが表示されるので、[Authorize]をクリックします。下図の画面が表示されるので外部アプリケーション設定で取得したアプリID(client_id)とアプリシークレット(client_secret)を入力し、Scopesに「Du.Digitzation.Api」と「Du.Extraction.Api」がチェックされていることを確認の上、[Authorize]ボタンをクリックします。

### ＜ Swagger(Document Understanding Cloud APIs) ＞

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/b2de82d8-80da-4d5c-f36c-cd3801676363.png)

❹Digitizationでドキュメントをアップロードします。「[POST]/projects/{projectId}/digitization/start」の[Try it out]ボタンをクリック、下図の様に設定し、実行してみます。

### ＜ DigitizationのAPI ＞

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/28cf1b4e-e6e5-868f-3575-6d0bac5e79c9.png)

:::note info
設定値の補足
1. [projectId]は「00000000-0000-0000-0000-000000000000」のままにします。Document Understandingのプロジェクトも作成する必要はありません。
1. サンプル帳票の1ページなので、ここでは[x-uipath-page-range]に「1」を設定しています。
:::

❺成功すると、Response bodyにdocumentIdが返ってきます。このIDは抽出する次のステップで識別子として利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/3d6dd5eb-a18a-b133-f1fc-6757d0de9786.png)

# 手順3：生成AIで抽出するAPIの仕様を調べる

❶Extractionで生成AIによる抽出を行います。「[POST]/projects/{projectId}/extractors/{extractorId}/extraction」の[Try it out]ボタンをクリック、下図の様に設定し、実行してみます。
尚、生成AI抽出を行う際のextractorIdは「generative_extractor」を指定します。

### ＜ ExtractionのAPI ＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/46bf3481-7b84-e0dc-822b-1b999b95a1a4.png)

### ＜ Request body部分のコピペ用 ＞
取りあえず、3つ質問して試して見ます。
```ruby:Request body
{
  "documentId": "{Digitizationで返ってきたdocumentIdを入れる}",
  "prompts": [
    {
      "id": "名前",
      "question": "氏名を教えてください。"
    },
    {
      "id": "現住所",
      "question": "現住所を教えてください。"
    },
    {
      "id": "連絡先電話番号",
      "question": "連絡先の電話番号を教えてください。"
    }
  ]
}

```
❷成功すると、Response bodyに生成AIで抽出されてきた結果が返されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/5d01f815-ed01-c5ce-cfe9-33dae0c627aa.png)

# 手順4：外部プログラムを実装する
Swaggerで調べたAPIの仕様で外部プログラムを実装します。下記は、PowerShellで、ざっと作って見たサンプルです。実行すると、抽出した結果をcsvファイルに出力します。

### ＜ サンプルプログラム ＞
```ruby:Document Understanding APIで生成AI抽出機能を利用するサンプル
#トークンを取得する

$uriToken = "https://cloud.uipath.com/identity_/connect/token"
$clientId = "{アプリIDを入れる}"
$clientSecret = '{アプリシークレットを入れる}'
$scopes = "Du.Digitization.Api Du.Extraction.Api"
$bodyToken = @{
  grant_type = "client_credentials"
  client_id = $clientId
  client_secret = $clientSecret
  scope = $scopes
} 
$resToken = Invoke-RestMethod -Uri $uriToken -Method Post -Body $bodyToken -ContentType "application/x-www-form-urlencoded"
$authKey = $resToken.access_token

#ドキュメントをアップロードする

$DigitizationHeader = @{
"accept"="text/plain"
"x-uipath-page-range"="1"
"Authorization"="Bearer $authKey"
}

$path='{ドキュメントのフルパスを入れる}'
$enc = [System.Text.Encoding]::GetEncoding("iso-8859-1")
$fileBin = [IO.File]::ReadAllBytes($Path)
$fileEnc = $enc.GetString($fileBin)
$boundary = "----WebKitFormBoundaryaaUBEnK21nqVaDsE"
$LF = "`r`n"

$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"{ドキュメントのファイル名を入れる}`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF

$DigitizationURL="https://cloud.uipath.com/{組織名を入れる}/{テナント名を入れる}/du_/api/framework/projects/00000000-0000-0000-0000-000000000000/digitization/start?api-version=1"
$DigitizationResult=Invoke-RestMethod -Method POST -Headers $DigitizationHeader -ContentType "multipart/form-data; boundary=$boundary" -Uri $DigitizationURL -Body $bodyLines

#アップロードしたドキュメントからプロンプトで項目のデータを抽出する

$ExtractorHeader = @{
"accept"="text/plain"
"Authorization"="Bearer $authKey"
}

$bodyPrompts = @{
  "documentId"= $DigitizationResult.documentId
  'prompts' = @(
        @{
          "id"="名前"
          "question"="氏名を教えてください。"
        },
        @{
          "id"="現住所"
          "question"="現住所を教えてください。"
        },
        @{
          "id"="連絡先電話番号"
          "question"="連絡先の電話番号を教えてください。"
        },
        @{
          "id"="連絡先メールアドレス"
          "question"="連絡先のメールアドレスを教えてください。"
        },
        @{
          "id"="年齢"
          "question"="年齢を教えてください。"
        },
        @{
          "id"="学歴1学校名"
          "question"="学歴の１つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。"
        },
        @{
          "id"="学歴1在籍期間"
          "question"="学歴の１つ目の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="学歴2学校名"
          "question"="学歴の２つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。"
        },
        @{
          "id"="学歴2在籍期間"
          "question"="学歴の２つ目の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="学歴3学校名"
          "question"="学歴の３つ目の学校名や学部や学科および、その学校を卒業したのか中退したのかを教えてください。"
        },
        @{
          "id"="学歴3在籍期間"
          "question"="学歴の３つ目の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="職歴1会社名"
          "question"="職歴の１つ目の会社名や所属を教えてください。"
        },
        @{
          "id"="職歴1在籍期間"
          "question"="職歴の１つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="職歴2会社名"
          "question"="職歴の２つ目の会社名や所属を教えてください。"
        },
        @{
          "id"="職歴2在籍期間"
          "question"="職歴の２つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="職歴3会社名"
          "question"="職歴の３つ目の会社名や所属を教えてください。"
        },
        @{
          "id"="職歴3在籍期間"
          "question"="職歴の３つ目の会社の在籍期間（開始年月日-終了年月日）を教えてください。"
        },
        @{
          "id"="スキル"
          "question"="プロフィールや保有技術を要約して教えてください。"
        },
        @{
          "id"="日付"
          "question"="帳票の日付を教えてください。"
        }
    )
} | ConvertTo-Json  -Depth 3

$bodyPrompts = [Text.Encoding]::UTF8.GetBytes($bodyPrompts)

$GenerativeExtractorURL="https://cloud.uipath.com/{組織名を入れる}/{テナント名を入れる}/du_/api/framework/projects/00000000-0000-0000-0000-000000000000/extractors/generative_extractor/extraction?api-version=1"

$ExtractorResult=Invoke-RestMethod -Method POST -Headers $ExtractorHeader -ContentType "application/json" -Uri $GenerativeExtractorURL -Body $bodyPrompts


for ($i=0; $i -lt 19; $i++){
    if ( $i -eq 0){
        -join　($ExtractorResult.extractionResult.ResultsDocument.Fields[$i].FieldId,　","　,$ExtractorResult.extractionResult.ResultsDocument.Fields[$i].Values[0].Value) | Out-File  -Encoding default out.csv
    }Else{
        -join　($ExtractorResult.extractionResult.ResultsDocument.Fields[$i].FieldId,　","　,$ExtractorResult.extractionResult.ResultsDocument.Fields[$i].Values[0].Value) | Out-File -Append  -Encoding default out.csv
    }
}

$ExtractorResult | ConvertTo-Json  -Depth 5 | Out-File out.txt


```
### ＜ 出力されたcsvファイル ＞
うまく、抽出されている様ですw
スキルは、要約するように指示しましたが良い感じですw
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/071563e5-e22d-28a6-a37a-8c4b8a690be8.png)

# おわりに
UiPath Document Understanding APIを使えば、どっからでもDocument Understandingの機能を呼び出せるので活用の幅が広がりますね。
ただし、生成AIの結果なので請求書などの帳票処理であれば外部プログラムからの利用よりも、検証ステーションやAction Centerが組み込まれた一連のソリューションとなるDocument Understanding Processの利用がお勧めです。
生成AIを利用したDocument Understanding Processについては、下記のブログをご覧ください！

https://qiita.com/Jun96427231/items/df69a914462087058c15