はじめに
Azure Form Recognizerでドキュメントを読み取る際、1枚1枚順番に実行すると枚数が多くなった時に読み取りに時間がかかるのが気になりました。1枚あたりは数秒でも、ドキュメントが数十枚になると数分かかってしまいます。今回はたくさんのドキュメントを素早く読み取る方法について調べてみました。
環境
Microsoft Visual Studio Professional 2022 Version 17.4.1
コンソールアプリ(.NET 6)
Azure.AI.FormRecognizer 4.0.0
Azure Form RecognizerはStandard (S0)を利用
ドキュメントを見てみる
以下のページに注目しました。
この表を見ると1 秒あたりのトランザクション数の制限
が15 (既定値)
となっています。この表から「複数のドキュメントを同時に読み取ることができてそれによって読み取り時間を短縮できるのではないか?」と考えました。
読み取り用のファイルを準備する
まずは読み取りに利用するPDFファイルを同じフォルダ内に複数個用意します。 PDFファイルは以下のように「aaaaaa」など簡単な文字列を入れたものをWordで15個作りました。
内容は何か書いてあればいいと思ったので簡単なものにしました。
読み取りはOCRを使います。
並列処理のコードを書く
今回はコンソールアプリを使うので言語はC#を利用します。 並列処理を使うことによって1つのプログラムからForm Recognizerに対して同時にアクセスすることができます。
Parallel.ForEach(files, item => { //何らかの処理 });
これを使って以下のようにコードを書きます。
using Azure; using Azure.AI.FormRecognizer.DocumentAnalysis; using System.Diagnostics; string endpoint = "[Form Recognizerのエンドポイント]"; string apiKey = "[Form Recognizerのキー]"; string modelId = "prebuilt-read"; List<FileStream> fileList = new(); var dir = new DirectoryInfo("[ファイル保存ディレクトリ]"); FileInfo[] files = dir.GetFiles(); var credential = new AzureKeyCredential(apiKey); var client = new DocumentAnalysisClient(new Uri(endpoint), credential); //時間計測開始 Stopwatch stopwatch = new Stopwatch(); Console.WriteLine("並列処理 開始"); stopwatch.Restart(); Parallel.ForEach(files, item => { using var stream = new FileStream(item.FullName, FileMode.Open); AnalyzeDocumentOperation operation = client.AnalyzeDocument(WaitUntil.Completed, modelId, stream); AnalyzeResult result = operation.Value; Console.WriteLine($"終了 : {item.Name}"); }); Console.WriteLine($"全て終了"); //時間計測終了 stopwatch.Stop(); //経過時間の表示 Console.WriteLine(stopwatch.Elapsed.TotalSeconds.ToString() + "秒");
実行したら以下のような結果になりました。
並列処理 開始 : 全て終了 5.8947188秒
今回の場合は約6秒ですね。すごい、早い!と自分は思ったのですが、比較対象がないと分かりにくいですね。というわけで次の項目で試してみました。
順番に処理する場合
並列処理と比べるため、順番に処理していく方法(1つのファイルを読み終えたら次のファイルを読み取る)も試してみましょう。 コードは以下のようになります。
using Azure; using Azure.AI.FormRecognizer.DocumentAnalysis; using System.Diagnostics; //有料プラン string endpoint = "[Form Recognizerのエンドポイント]"; string apiKey = "[Form Recognizerのキー]"; string modelId = "prebuilt-read"; List<FileStream> fileList = new(); var dir = new DirectoryInfo("[ファイル保存ディレクトリ]"); FileInfo[] files = dir.GetFiles(); var credential = new AzureKeyCredential(apiKey); var client = new DocumentAnalysisClient(new Uri(endpoint), credential); Stopwatch stopwatch = new Stopwatch(); Console.WriteLine("順番に処理 開始"); stopwatch.Start(); for (var i = 0; i < files.Length; i++) { using var stream = new FileStream(files[i].FullName, FileMode.Open); AnalyzeDocumentOperation operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, modelId, stream); AnalyzeResult result = operation.Value; Console.WriteLine($"終了 : {files[i].Name}"); } Console.WriteLine($"全て終了"); stopwatch.Stop(); Console.WriteLine(stopwatch.Elapsed.TotalSeconds.ToString() + "秒");
順番に処理 開始 : 全て終了 49.9780751秒
約50秒です。並列処理(約6秒)がいかに早いかが分かると思います!
まとめ
同じフォーマットの文章を大量に読み取りたいときに今回の方法があれば、素早く読み取りができて業務効率化に役立てそうですね。