.NET 用 Azure Form Recognizer クライアント ライブラリ - バージョン 4.1.0

注: 2023 年 7 月に、Azure Cognitive Services Form Recognizer サービスの名前が Azure AI ドキュメント インテリジェンスに変更されました。 ドキュメントのForm Recognizerまたはドキュメント インテリジェンスに関する言及は、同じ Azure サービスを参照します。

Azure AI Document Intelligence は、機械学習を使用してドキュメントのテキストと構造化データを分析するクラウド サービスです。 これには、次のメイン機能が含まれています。

  • レイアウト - テキスト、選択マーク、表の構造、スタイル、段落、および境界領域の座標をドキュメントから抽出します。
  • 一般的なドキュメント - ドキュメントの一般的なレイアウトに加えて、キーと値のペアを分析します。
  • 読み取り - テキスト言語情報に加えて、ページの単語や行などのテキスト要素に関する情報を読み取ります。
  • 事前構築済み - 事前構築済みモデルを使用して、特定の種類の一般的なドキュメントのデータを分析します。 サポートされているドキュメントには、領収書、請求書、名刺、ID ドキュメント、US W2 税フォームなどが含まれます。
  • カスタム分析 - ドキュメントからテキスト、フィールド値、選択マーク、テーブル構造、スタイル、段落を分析するためのカスタム ドキュメント モデルを構築します。 カスタム モデルは独自のデータを使用して構築されるため、ドキュメントに合わせて調整されます。
  • カスタム分類 - レイアウト機能と言語機能を組み合わせて、アプリケーション内で処理するドキュメントを正確に検出して識別するカスタム分類子モデルを構築します。

ソースコード | パッケージ (NuGet) | API リファレンス ドキュメント | 製品ドキュメント | サンプル

作業の開始

パッケージをインストールする

NuGet を使用して .NET 用 Azure Form Recognizer クライアント ライブラリをインストールします。

dotnet add package Azure.AI.FormRecognizer

注: このバージョンのクライアント ライブラリは、既定でサービスの 2023-07-31 バージョンになります。

SDK のバージョンとサービスのサポートされる API バージョンの関係を次の表に示します。

SDK バージョン サポートされている API バージョンのサービス
4.1.0 2.0, 2.1, 2022-08-31, 2023-07-31
4.0.0 2.0, 2.1, 2022-08-31
3.1.X 2.0, 2.1
3.0.X 2.0

注: バージョン 4.0.0以降では、ドキュメント インテリジェンス サービスの最新機能を活用するために、新しいクライアント セットが導入されました。 クライアント ライブラリのバージョン以下から最新バージョン3.1.Xにアプリケーション コードを更新する方法の詳細については、移行ガイドを参照してください。 さらに、詳細については 、Changelog を参照してください。 次の表では、各クライアントとそのサポートされている API バージョンの関係について説明します。

API バージョン サポートされるクライアント
2023-07-31 DocumentAnalysisClient と DocumentModelAdministrationClient
2022-08-31 DocumentAnalysisClient と DocumentModelAdministrationClient
2.1 FormRecognizerClient と FormTrainingClient
2.0 FormRecognizerClient と FormTrainingClient

前提条件

Cognitive Services または Form Recognizer リソースを作成する

ドキュメント インテリジェンスでは、 マルチサービス アクセスと単一サービス アクセスの両方がサポートされます。 1 つのエンドポイント/キーで複数の Cognitive Services にアクセスする予定の場合は、Cognitive Services リソースを作成します。 ドキュメント インテリジェンス アクセスのみの場合は、Form Recognizer リソースを作成します。 Azure Active Directory 認証を使用する場合は、単一サービス リソースが必要であることに注意してください。

次を使用して、いずれかのリソースを作成できます。

CLI を使用してForm Recognizer リソースを作成する方法の例を次に示します。

# Create a new resource group to hold the Form Recognizer resource
# If using an existing resource group, skip this step
az group create --name <your-resource-name> --location <location>
# Create the Form Recognizer resource
az cognitiveservices account create \
    --name <resource-name> \
    --resource-group <resource-group-name> \
    --kind FormRecognizer \
    --sku <sku> \
    --location <location> \
    --yes

リソースの作成の詳細、または場所と SKU の情報を取得する方法については、 こちらを参照してください

クライアントを認証する

ドキュメント インテリジェンス サービスを操作するには、 クラスの DocumentAnalysisClient インスタンスを作成する必要があります。 クライアント オブジェクトをインスタンス化するには、 エンドポイント資格情報 が必要です。

エンドポイントを取得する

Form Recognizer リソースのエンドポイントは、Azure Portal または Azure CLI を使用して確認できます。

# Get the endpoint for the Form Recognizer resource
az cognitiveservices account show --name "<resource-name>" --resource-group "<resource-group-name>" --query "properties.endpoint"

リージョン エンドポイントまたはカスタム サブドメインを認証に使用できます。 これらは次のように書式設定されます。

Regional endpoint: https://<region>.api.cognitive.microsoft.com/
Custom subdomain: https://<resource-name>.cognitiveservices.azure.com/

リージョン エンドポイントは、リージョン内のすべてのリソースで同じです。 サポートされているリージョン エンドポイントの完全な一覧については、こちらを参照 してください。 リージョン エンドポイントでは AAD 認証がサポートされないことに注意してください。

一方、カスタム サブドメインは、Form Recognizer リソースに固有の名前です。 これらは、単一サービス リソースでのみ使用できます。

API キーを取得する

API キーは 、Azure Portal で、または次の Azure CLI コマンドを実行して見つけることができます。

az cognitiveservices account keys list --name "<resource-name>" --resource-group "<resource-group-name>"

AzureKeyCredential を使用して DocumentAnalysisClient を作成する

API キーの値を取得したら、 を作成します AzureKeyCredential。 エンドポイントとキーの資格情報を使用して、 を DocumentAnalysisClient作成できます。

string endpoint = "<endpoint>";
string apiKey = "<apiKey>";
var credential = new AzureKeyCredential(apiKey);
var client = new DocumentAnalysisClient(new Uri(endpoint), credential);

Azure Active Directory 資格情報を使用して DocumentAnalysisClient を作成する

AzureKeyCredential 認証は、この入門ガイドの例で使用しますが、Azure Id ライブラリを使用して Azure Active Directory で認証することもできます。 リージョン エンドポイントでは AAD 認証がサポートされないことに注意してください。 この種類の認証を使用するために、リソースのカスタム サブドメインを作成します。

下に示した DefaultAzureCredential プロバイダーか、Azure SDK で提供されている他の資格情報プロバイダーを使用するには、Azure.Identity パッケージをインストールしてください。

dotnet add package Azure.Identity

また、サービス プリンシパルにロールを割り当てることで、新しい AAD アプリケーション"Cognitive Services User"登録し、ドキュメント インテリジェンスへのアクセス権を付与する必要もあります。

AAD アプリケーションのクライアント ID、テナント ID、クライアント シークレットの値を環境変数として設定します(AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_CLIENT_SECRET)。

string endpoint = "<endpoint>";
var client = new DocumentAnalysisClient(new Uri(endpoint), new DefaultAzureCredential());

主要な概念

DocumentAnalysisClient

DocumentAnalysisClient には、以下を目的とした操作が用意されています。

  • API と API を使用した事前構築済みモデルとカスタム モデルを使用した入力ドキュメントのAnalyzeDocumentAnalyzeDocumentFromUri分析。
  • API と API を使用したカスタム入力ドキュメントの ClassifyDocument 検出と ClassifyDocumentFromUri 識別。

サンプル コード スニペットは、DocumentAnalysisClient の使用方法を示すために 提供されています。 サポートされている機能、ロケール、ドキュメントの種類など、ドキュメントの分析の詳細については、 サービス ドキュメントを参照してください

DocumentModelAdministrationClient

DocumentModelAdministrationClient には、以下を目的とした操作が用意されています。

  • カスタム ドキュメントにラベルを付けることで、指定した特定のフィールドを分析するカスタム モデルを構築します。 DocumentModelDetailsモデルが分析できるドキュメントの種類、ドキュメントの種類ごとに分析できるフィールド、および各フィールドの推定信頼度を示すインスタンスが返されます。 詳細な説明については、 サービスのドキュメント を参照してください。
  • 既存のモデルのコレクションからモデルを作成します。
  • アカウントに作成されたモデルを管理する。
  • Form Recognizer リソース間でカスタム モデルをコピーする。
  • ビルド操作を一覧表示するか、過去 24 時間以内に作成された特定の操作を取得します。
  • アプリケーション内で処理するドキュメントを正確に検出して識別するためのドキュメント分類モデルの構築と管理。

「カスタム モデルの構築」、「モデル管理」、「ドキュメント分類子の作成」の例を参照してください。

モデルと分類子は、 Document Intelligence Studio などのグラフィカル ユーザー インターフェイスを使用して構築することもできます。

Long-Running 操作

ドキュメントの分析とモデルの構築には時間がかかるため、これらの操作は 実行時間の長い操作として実装されます。 実行時間の長い操作は、操作を開始するためにサービスに送信された最初の要求で構成され、その後、間隔を指定してサービスをポーリングして、操作が完了したか失敗したか、成功したかどうかを判断して結果を取得します。

Azure SDK での実行時間の長い操作の場合、クライアントは オブジェクトを返すメソッドを Operation<T> 公開します。 そのパラメーター waitUntil を に WaitUntil.Completed 設定すると、操作が完了して結果が取得されるのを待ちます。または、操作を開始して後で結果を使用するだけの場合は に設定 WaitUntil.Started できます。 以下では、実行時間の長い操作の使用を示すサンプル コード スニペットが提供されています。

スレッド セーフ

すべてのクライアント インスタンス メソッドがスレッド セーフであり、相互に独立していることを保証します (ガイドライン)。 これにより、クライアント インスタンスの再利用に関する推奨事項は、スレッド間でも常に安全になります。

その他の概念

クライアント オプション | 応答 | へのアクセスエラーの | 処理診断 | あざける | クライアントの有効期間

次のセクションでは、Form Recognizer .NET API で使用される一般的なパターンを示すコード スニペットをいくつか示します。 以下のスニペットのほとんどは非同期サービス呼び出しを利用していますが、Azure.AI.FormRecognizer パッケージでは同期 API と非同期 API の両方がサポートされていることに注意してください。

非同期の例

同期の例

これらのサンプルでは、SDK バージョン 4.1.0が使用されることに注意してください。 バージョン 3.1.1 以降については、「V3.1.X のForm Recognizerサンプル」を参照してください。

レイアウトの抽出

テキスト、選択マーク、表の構造、スタイル、段落、および境界領域の座標をドキュメントから抽出します。

Uri fileUri = new Uri("<fileUri>");

AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-layout", fileUri);
AnalyzeResult result = operation.Value;

foreach (DocumentPage page in result.Pages)
{
    Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
    Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");

    for (int i = 0; i < page.Lines.Count; i++)
    {
        DocumentLine line = page.Lines[i];
        Console.WriteLine($"  Line {i} has content: '{line.Content}'.");

        Console.WriteLine($"    Its bounding polygon (points ordered clockwise):");

        for (int j = 0; j < line.BoundingPolygon.Count; j++)
        {
            Console.WriteLine($"      Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
        }
    }

    for (int i = 0; i < page.SelectionMarks.Count; i++)
    {
        DocumentSelectionMark selectionMark = page.SelectionMarks[i];

        Console.WriteLine($"  Selection Mark {i} is {selectionMark.State}.");
        Console.WriteLine($"    Its bounding polygon (points ordered clockwise):");

        for (int j = 0; j < selectionMark.BoundingPolygon.Count; j++)
        {
            Console.WriteLine($"      Point {j} => X: {selectionMark.BoundingPolygon[j].X}, Y: {selectionMark.BoundingPolygon[j].Y}");
        }
    }
}

Console.WriteLine("Paragraphs:");

foreach (DocumentParagraph paragraph in result.Paragraphs)
{
    Console.WriteLine($"  Paragraph content: {paragraph.Content}");

    if (paragraph.Role != null)
    {
        Console.WriteLine($"    Role: {paragraph.Role}");
    }
}

foreach (DocumentStyle style in result.Styles)
{
    // Check the style and style confidence to see if text is handwritten.
    // Note that value '0.8' is used as an example.

    bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;

    if (isHandwritten && style.Confidence > 0.8)
    {
        Console.WriteLine($"Handwritten content found:");

        foreach (DocumentSpan span in style.Spans)
        {
            Console.WriteLine($"  Content: {result.Content.Substring(span.Index, span.Length)}");
        }
    }
}

Console.WriteLine("The following tables were extracted:");

for (int i = 0; i < result.Tables.Count; i++)
{
    DocumentTable table = result.Tables[i];
    Console.WriteLine($"  Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");

    foreach (DocumentTableCell cell in table.Cells)
    {
        Console.WriteLine($"    Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
    }
}

詳細とサンプルについては、 こちらを参照してください

事前構築済みの一般ドキュメント モデルを使用する

事前構築済みの一般的なドキュメント モデルを使用して、ドキュメントのテキスト、選択マーク、テーブル構造、スタイル、段落、キーと値のペアを分析します。

Uri fileUri = new Uri("<fileUri>");

AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-document", fileUri);
AnalyzeResult result = operation.Value;

Console.WriteLine("Detected key-value pairs:");

foreach (DocumentKeyValuePair kvp in result.KeyValuePairs)
{
    if (kvp.Value == null)
    {
        Console.WriteLine($"  Found key with no value: '{kvp.Key.Content}'");
    }
    else
    {
        Console.WriteLine($"  Found key-value pair: '{kvp.Key.Content}' and '{kvp.Value.Content}'");
    }
}

foreach (DocumentPage page in result.Pages)
{
    Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
    Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");

    for (int i = 0; i < page.Lines.Count; i++)
    {
        DocumentLine line = page.Lines[i];
        Console.WriteLine($"  Line {i} has content: '{line.Content}'.");

        Console.WriteLine($"    Its bounding polygon (points ordered clockwise):");

        for (int j = 0; j < line.BoundingPolygon.Count; j++)
        {
            Console.WriteLine($"      Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
        }
    }

    for (int i = 0; i < page.SelectionMarks.Count; i++)
    {
        DocumentSelectionMark selectionMark = page.SelectionMarks[i];

        Console.WriteLine($"  Selection Mark {i} is {selectionMark.State}.");
        Console.WriteLine($"    Its bounding polygon (points ordered clockwise):");

        for (int j = 0; j < selectionMark.BoundingPolygon.Count; j++)
        {
            Console.WriteLine($"      Point {j} => X: {selectionMark.BoundingPolygon[j].X}, Y: {selectionMark.BoundingPolygon[j].Y}");
        }
    }
}

foreach (DocumentStyle style in result.Styles)
{
    // Check the style and style confidence to see if text is handwritten.
    // Note that value '0.8' is used as an example.

    bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;

    if (isHandwritten && style.Confidence > 0.8)
    {
        Console.WriteLine($"Handwritten content found:");

        foreach (DocumentSpan span in style.Spans)
        {
            Console.WriteLine($"  Content: {result.Content.Substring(span.Index, span.Length)}");
        }
    }
}

Console.WriteLine("The following tables were extracted:");

for (int i = 0; i < result.Tables.Count; i++)
{
    DocumentTable table = result.Tables[i];
    Console.WriteLine($"  Table {i} has {table.RowCount} rows and {table.ColumnCount} columns.");

    foreach (DocumentTableCell cell in table.Cells)
    {
        Console.WriteLine($"    Cell ({cell.RowIndex}, {cell.ColumnIndex}) has kind '{cell.Kind}' and content: '{cell.Content}'.");
    }
}

詳細とサンプルについては、 こちらを参照してください

事前構築済みの読み取りモデルを使用する

事前構築済みの読み取りモデルを使用して、ドキュメントのページの単語や行、スタイル、段落、テキスト言語情報などのテキスト要素を分析します。

Uri fileUri = new Uri("<fileUri>");

AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-read", fileUri);
AnalyzeResult result = operation.Value;

Console.WriteLine("Detected languages:");

foreach (DocumentLanguage language in result.Languages)
{
    Console.WriteLine($"  Found language with locale '{language.Locale}' and confidence {language.Confidence}.");
}

foreach (DocumentPage page in result.Pages)
{
    Console.WriteLine($"Document Page {page.PageNumber} has {page.Lines.Count} line(s), {page.Words.Count} word(s),");
    Console.WriteLine($"and {page.SelectionMarks.Count} selection mark(s).");

    for (int i = 0; i < page.Lines.Count; i++)
    {
        DocumentLine line = page.Lines[i];
        Console.WriteLine($"  Line {i} has content: '{line.Content}'.");

        Console.WriteLine($"    Its bounding polygon (points ordered clockwise):");

        for (int j = 0; j < line.BoundingPolygon.Count; j++)
        {
            Console.WriteLine($"      Point {j} => X: {line.BoundingPolygon[j].X}, Y: {line.BoundingPolygon[j].Y}");
        }
    }
}

foreach (DocumentStyle style in result.Styles)
{
    // Check the style and style confidence to see if text is handwritten.
    // Note that value '0.8' is used as an example.

    bool isHandwritten = style.IsHandwritten.HasValue && style.IsHandwritten == true;

    if (isHandwritten && style.Confidence > 0.8)
    {
        Console.WriteLine($"Handwritten content found:");

        foreach (DocumentSpan span in style.Spans)
        {
            Console.WriteLine($"  Content: {result.Content.Substring(span.Index, span.Length)}");
        }
    }
}

詳細とサンプルについては、 こちらを参照してください

事前構築済みモデルを使用する

ドキュメント インテリジェンス サービスによって提供される事前構築済みモデルを使用して、特定の種類の一般的なドキュメントのデータを分析します。

たとえば、請求書からフィールドを分析するには、モデル ID を メソッドに渡 prebuilt-invoice すことによって提供される事前構築済みの請求書モデルを AnalyzeDocumentAsync 使用します。

string filePath = "<filePath>";

using var stream = new FileStream(filePath, FileMode.Open);

AnalyzeDocumentOperation operation = await client.AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-invoice", stream);
AnalyzeResult result = operation.Value;

// To see the list of all the supported fields returned by service and its corresponding types for the
// prebuilt-invoice model, consult:
// https://aka.ms/azsdk/formrecognizer/invoicefieldschema

for (int i = 0; i < result.Documents.Count; i++)
{
    Console.WriteLine($"Document {i}:");

    AnalyzedDocument document = result.Documents[i];

    if (document.Fields.TryGetValue("VendorName", out DocumentField vendorNameField))
    {
        if (vendorNameField.FieldType == DocumentFieldType.String)
        {
            string vendorName = vendorNameField.Value.AsString();
            Console.WriteLine($"Vendor Name: '{vendorName}', with confidence {vendorNameField.Confidence}");
        }
    }

    if (document.Fields.TryGetValue("CustomerName", out DocumentField customerNameField))
    {
        if (customerNameField.FieldType == DocumentFieldType.String)
        {
            string customerName = customerNameField.Value.AsString();
            Console.WriteLine($"Customer Name: '{customerName}', with confidence {customerNameField.Confidence}");
        }
    }

    if (document.Fields.TryGetValue("Items", out DocumentField itemsField))
    {
        if (itemsField.FieldType == DocumentFieldType.List)
        {
            foreach (DocumentField itemField in itemsField.Value.AsList())
            {
                Console.WriteLine("Item:");

                if (itemField.FieldType == DocumentFieldType.Dictionary)
                {
                    IReadOnlyDictionary<string, DocumentField> itemFields = itemField.Value.AsDictionary();

                    if (itemFields.TryGetValue("Description", out DocumentField itemDescriptionField))
                    {
                        if (itemDescriptionField.FieldType == DocumentFieldType.String)
                        {
                            string itemDescription = itemDescriptionField.Value.AsString();

                            Console.WriteLine($"  Description: '{itemDescription}', with confidence {itemDescriptionField.Confidence}");
                        }
                    }

                    if (itemFields.TryGetValue("Amount", out DocumentField itemAmountField))
                    {
                        if (itemAmountField.FieldType == DocumentFieldType.Currency)
                        {
                            CurrencyValue itemAmount = itemAmountField.Value.AsCurrency();

                            Console.WriteLine($"  Amount: '{itemAmount.Symbol}{itemAmount.Amount}', with confidence {itemAmountField.Confidence}");
                        }
                    }
                }
            }
        }
    }

    if (document.Fields.TryGetValue("SubTotal", out DocumentField subTotalField))
    {
        if (subTotalField.FieldType == DocumentFieldType.Currency)
        {
            CurrencyValue subTotal = subTotalField.Value.AsCurrency();
            Console.WriteLine($"Sub Total: '{subTotal.Symbol}{subTotal.Amount}', with confidence {subTotalField.Confidence}");
        }
    }

    if (document.Fields.TryGetValue("TotalTax", out DocumentField totalTaxField))
    {
        if (totalTaxField.FieldType == DocumentFieldType.Currency)
        {
            CurrencyValue totalTax = totalTaxField.Value.AsCurrency();
            Console.WriteLine($"Total Tax: '{totalTax.Symbol}{totalTax.Amount}', with confidence {totalTaxField.Confidence}");
        }
    }

    if (document.Fields.TryGetValue("InvoiceTotal", out DocumentField invoiceTotalField))
    {
        if (invoiceTotalField.FieldType == DocumentFieldType.Currency)
        {
            CurrencyValue invoiceTotal = invoiceTotalField.Value.AsCurrency();
            Console.WriteLine($"Invoice Total: '{invoiceTotal.Symbol}{invoiceTotal.Amount}', with confidence {invoiceTotalField.Confidence}");
        }
    }
}

請求書に限定されません。 選択できる事前構築済みモデルがいくつかあります。それぞれのモデルには、サポートされているフィールドの独自のセットがあります。 サポートされているドキュメントの種類の詳細については、 サービス ドキュメントを参照してください

詳細とサンプルについては、こちらを参照 してください

カスタム モデルを構築する

独自のドキュメントの種類に基づいてカスタム モデルを構築します。 結果のモデルを使用して、構築されたドキュメントの種類の値を分析できます。

// For this sample, you can use the training documents found in the `trainingFiles` folder.
// Upload the documents to your storage container and then generate a container SAS URL. Note
// that a container URI without SAS is accepted only when the container is public or has a
// managed identity configured.
//
// For instructions to set up documents for training in an Azure Blob Storage Container, please see:
// https://aka.ms/azsdk/formrecognizer/buildcustommodel

Uri blobContainerUri = new Uri("<blobContainerUri>");
var client = new DocumentModelAdministrationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));

// We are selecting the Template build mode in this sample. For more information about the available
// build modes and their differences, please see:
// https://aka.ms/azsdk/formrecognizer/buildmode

BuildDocumentModelOperation operation = await client.BuildDocumentModelAsync(WaitUntil.Completed, blobContainerUri, DocumentBuildMode.Template);
DocumentModelDetails model = operation.Value;

Console.WriteLine($"  Model Id: {model.ModelId}");
Console.WriteLine($"  Created on: {model.CreatedOn}");

Console.WriteLine("  Document types the model can recognize:");
foreach (KeyValuePair<string, DocumentTypeDetails> documentType in model.DocumentTypes)
{
    Console.WriteLine($"    Document type: {documentType.Key} which has the following fields:");
    foreach (KeyValuePair<string, DocumentFieldSchema> schema in documentType.Value.FieldSchema)
    {
        Console.WriteLine($"    Field: {schema.Key} with confidence {documentType.Value.FieldConfidence[schema.Key]}");
    }
}

詳細とサンプルについては、 こちらを参照してください

カスタム ドキュメントの分析

独自のドキュメントの種類で作成したモデルを使用して、カスタム ドキュメントのテキスト、フィールド値、選択マーク、テーブル構造、スタイル、段落を分析します。

string modelId = "<modelId>";
Uri fileUri = new Uri("<fileUri>");

AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, modelId, fileUri);
AnalyzeResult result = operation.Value;

Console.WriteLine($"Document was analyzed with model with ID: {result.ModelId}");

foreach (AnalyzedDocument document in result.Documents)
{
    Console.WriteLine($"Document of type: {document.DocumentType}");

    foreach (KeyValuePair<string, DocumentField> fieldKvp in document.Fields)
    {
        string fieldName = fieldKvp.Key;
        DocumentField field = fieldKvp.Value;

        Console.WriteLine($"Field '{fieldName}': ");

        Console.WriteLine($"  Content: '{field.Content}'");
        Console.WriteLine($"  Confidence: '{field.Confidence}'");
    }
}

詳細とサンプルについては、 こちらを参照してください

モデルの管理

アカウントに格納されているモデルを管理します。

var client = new DocumentModelAdministrationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));

// Check number of custom models in the Form Recognizer resource, and the maximum number of custom models that can be stored.
ResourceDetails resourceDetails = await client.GetResourceDetailsAsync();
Console.WriteLine($"Resource has {resourceDetails.CustomDocumentModelCount} custom models.");
Console.WriteLine($"It can have at most {resourceDetails.CustomDocumentModelLimit} custom models.");

// List the first ten or fewer models currently stored in the resource.
AsyncPageable<DocumentModelSummary> models = client.GetDocumentModelsAsync();

int count = 0;
await foreach (DocumentModelSummary modelSummary in models)
{
    Console.WriteLine($"Custom Model Summary:");
    Console.WriteLine($"  Model Id: {modelSummary.ModelId}");
    if (string.IsNullOrEmpty(modelSummary.Description))
        Console.WriteLine($"  Model description: {modelSummary.Description}");
    Console.WriteLine($"  Created on: {modelSummary.CreatedOn}");
    if (++count == 10)
        break;
}

// Create a new model to store in the resource.
Uri blobContainerUri = new Uri("<blobContainerUri>");
BuildDocumentModelOperation operation = await client.BuildDocumentModelAsync(WaitUntil.Completed, blobContainerUri, DocumentBuildMode.Template);
DocumentModelDetails model = operation.Value;

// Get the model that was just created.
DocumentModelDetails newCreatedModel = await client.GetDocumentModelAsync(model.ModelId);

Console.WriteLine($"Custom Model with Id {newCreatedModel.ModelId} has the following information:");

Console.WriteLine($"  Model Id: {newCreatedModel.ModelId}");
if (string.IsNullOrEmpty(newCreatedModel.Description))
    Console.WriteLine($"  Model description: {newCreatedModel.Description}");
Console.WriteLine($"  Created on: {newCreatedModel.CreatedOn}");

// Delete the model from the resource.
await client.DeleteDocumentModelAsync(newCreatedModel.ModelId);

詳細とサンプルについては、 こちらを参照してください

モデルを同期的に管理する

同期 API を使用して、アカウントに格納されているモデルを管理します。

var client = new DocumentModelAdministrationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));

// Check number of custom models in the Form Recognizer resource, and the maximum number of custom models that can be stored.
ResourceDetails resourceDetails = client.GetResourceDetails();
Console.WriteLine($"Resource has {resourceDetails.CustomDocumentModelCount} custom models.");
Console.WriteLine($"It can have at most {resourceDetails.CustomDocumentModelLimit} custom models.");

// List the first ten or fewer models currently stored in the resource.
Pageable<DocumentModelSummary> models = client.GetDocumentModels();

foreach (DocumentModelSummary modelSummary in models.Take(10))
{
    Console.WriteLine($"Custom Model Summary:");
    Console.WriteLine($"  Model Id: {modelSummary.ModelId}");
    if (string.IsNullOrEmpty(modelSummary.Description))
        Console.WriteLine($"  Model description: {modelSummary.Description}");
    Console.WriteLine($"  Created on: {modelSummary.CreatedOn}");
}

// Create a new model to store in the resource.

Uri blobContainerUri = new Uri("<blobContainerUri>");
BuildDocumentModelOperation operation = client.BuildDocumentModel(WaitUntil.Completed, blobContainerUri, DocumentBuildMode.Template);
DocumentModelDetails model = operation.Value;

// Get the model that was just created.
DocumentModelDetails newCreatedModel = client.GetDocumentModel(model.ModelId);

Console.WriteLine($"Custom Model with Id {newCreatedModel.ModelId} has the following information:");

Console.WriteLine($"  Model Id: {newCreatedModel.ModelId}");
if (string.IsNullOrEmpty(newCreatedModel.Description))
    Console.WriteLine($"  Model description: {newCreatedModel.Description}");
Console.WriteLine($"  Created on: {newCreatedModel.CreatedOn}");

// Delete the created model from the resource.
client.DeleteDocumentModel(newCreatedModel.ModelId);

ドキュメント分類子を作成する

カスタム トレーニング ドキュメントをアップロードして、ドキュメント分類子を作成します。

// For this sample, you can use the training documents found in the `classifierTrainingFiles` folder.
// Upload the documents to your storage container and then generate a container SAS URL. Note
// that a container URI without SAS is accepted only when the container is public or has a
// managed identity configured.
//
// For instructions to set up documents for training in an Azure Blob Storage Container, please see:
// https://aka.ms/azsdk/formrecognizer/buildclassifiermodel

Uri trainingFilesUri = new Uri("<trainingFilesUri>");
var client = new DocumentModelAdministrationClient(new Uri(endpoint), new AzureKeyCredential(apiKey));

var sourceA = new BlobContentSource(trainingFilesUri) { Prefix = "IRS-1040-A/train" };
var sourceB = new BlobContentSource(trainingFilesUri) { Prefix = "IRS-1040-B/train" };

var documentTypes = new Dictionary<string, ClassifierDocumentTypeDetails>()
{
    { "IRS-1040-A", new ClassifierDocumentTypeDetails(sourceA) },
    { "IRS-1040-B", new ClassifierDocumentTypeDetails(sourceB) }
};

BuildDocumentClassifierOperation operation = await client.BuildDocumentClassifierAsync(WaitUntil.Completed, documentTypes);
DocumentClassifierDetails classifier = operation.Value;

Console.WriteLine($"  Classifier Id: {classifier.ClassifierId}");
Console.WriteLine($"  Created on: {classifier.CreatedOn}");

Console.WriteLine("  Document types the classifier can recognize:");
foreach (KeyValuePair<string, ClassifierDocumentTypeDetails> documentType in classifier.DocumentTypes)
{
    Console.WriteLine($"    {documentType.Key}");
}

詳細とサンプルについては、 こちらを参照してください

ドキュメントを分類する

ドキュメント分類子を使用して、アプリケーション内で処理するドキュメントを正確に検出して識別します。

string classifierId = "<classifierId>";
Uri fileUri = new Uri("<fileUri>");

ClassifyDocumentOperation operation = await client.ClassifyDocumentFromUriAsync(WaitUntil.Completed, classifierId, fileUri);
AnalyzeResult result = operation.Value;

Console.WriteLine($"Document was classified by classifier with ID: {result.ModelId}");

foreach (AnalyzedDocument document in result.Documents)
{
    Console.WriteLine($"Document of type: {document.DocumentType}");
}

詳細とサンプルについては、 こちらを参照してください

トラブルシューティング

全般

.NET SDK を使用して Form Recognizer クライアント ライブラリを操作すると、サービスによって返されるエラーにより、REST API 要求によって返されるのと同じ HTTP 状態コードが生成されますRequestFailedException

たとえば、無効な Uri400 を含む領収書の画像を送信すると、"Bad Request" を示すエラーが返されます。

try
{
    AnalyzeDocumentOperation operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, "prebuilt-receipt", new Uri("http://invalid.uri"));
}
catch (RequestFailedException e)
{
    Console.WriteLine(e.ToString());
}

操作のクライアント要求 ID など、追加情報がログに記録されていることがわかります。

Message:
    Azure.RequestFailedException: Service request failed.
    Status: 400 (Bad Request)
    ErrorCode: InvalidRequest

Content:
    {"error":{"code":"InvalidRequest","message":"Invalid request.","innererror":{"code":"InvalidContent","message":"The file is corrupted or format is unsupported. Refer to documentation for the list of supported formats."}}}

Headers:
    Transfer-Encoding: chunked
    x-envoy-upstream-service-time: REDACTED
    apim-request-id: REDACTED
    Strict-Transport-Security: REDACTED
    X-Content-Type-Options: REDACTED
    Date: Fri, 01 Oct 2021 02:55:44 GMT
    Content-Type: application/json; charset=utf-8

ドキュメント インテリジェンス サービスによって発生するエラー コードとメッセージは、 サービス ドキュメントにあります。

一般的な問題の詳細については、 トラブルシューティング ガイドを参照してください。

コンソール ログの設定

ログを表示する最も簡単な方法は、コンソール ログを有効にすることです。 コンソールにメッセージを出力する Azure SDK ログ リスナーを作成するには、AzureEventSourceListener.CreateConsoleLogger メソッドを使用します。

// Setup a listener to monitor logged events.
using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

その他のログメカニズムの詳細については、「 診断サンプル」を参照してください。

次の手順

Form Recognizer ライブラリの使用方法を示すサンプルは、この GitHub リポジトリで入手できます。 メイン機能領域ごとにサンプルが提供されます。

これらのサンプルでは、SDK バージョン 4.1.0が使用されることに注意してください。 バージョン 3.1.1 以降については、「V3.1.X のForm Recognizerサンプル」を参照してください。

共同作成

このプロジェクトでは、共同作成と提案を歓迎しています。 ほとんどの共同作成では、共同作成者使用許諾契約書 (CLA) にご同意いただき、ご自身の共同作成内容を使用する権利を Microsoft に供与する権利をお持ちであり、かつ実際に供与することを宣言していただく必要があります。 詳細については、「 cla.microsoft.com」を参照してください。

pull request を送信すると、CLA を提供して PR (ラベル、コメントなど) を適宜装飾する必要があるかどうかを CLA ボットが自動的に決定します。 ボットによって提供される手順にそのまま従ってください。 この操作は、Microsoft の CLA を使用するすべてのリポジトリについて、1 回だけ行う必要があります。

このプロジェクトでは、Microsoft オープン ソースの倫理規定を採用しています。 詳しくは、「Code of Conduct FAQ (倫理規定についてよくある質問)」を参照するか、opencode@microsoft.com 宛てに質問またはコメントをお送りください。

インプレッション数