透過 Document AI 聰明處理手寫表單 (Node.js)

1. 總覽

什麼是 Document AI?

Document AI API 是一種文件解讀解決方案,能擷取文件、電子郵件等非結構化資料,讓資料更容易理解、分析及使用。這個 API 透過內容分類、實體擷取、進階搜尋等功能提供結構。

在本教學課程中,您將專注於透過 Node.js 使用 Document AI API。本教學課程示範如何剖析簡單的醫療登記表單。

課程內容

  • 如何啟用 Document AI API
  • 如何驗證 API 要求
  • 如何安裝 Node.js 適用的用戶端程式庫
  • 如何剖析掃描表單中的資料

軟硬體需求

  • Google Cloud 專案
  • 瀏覽器,例如 ChromeFirefox
  • 瞭解 Node.js

問卷調查

您會如何使用這個教學課程?

僅供閱讀 閱讀並完成練習

您對 Node.js 的使用體驗有何評價?

新手 中級 還算容易

針對使用 Google Cloud 服務的經驗,您會給予什麼評價?

新手 中級 還算容易

2. 設定和需求

自修環境設定

  1. 登入 Cloud 控制台建立新專案,或是重複使用現有專案。(如果您還沒有 Gmail 或 G Suite 帳戶,請先建立帳戶)。

請記住專案 ID,這是所有 Google Cloud 專案中的專屬名稱。(很抱歉,上方名稱已經有人使用,很抱歉讓您沒用!)。您之後必須於 PROJECT_ID 提供這個 ID。

  1. 接下來,您必須在 Cloud 控制台中啟用計費功能,才能使用 Google Cloud 資源。

請務必依照「清除所用資源」一節指示專區。本節將說明如何關閉資源,這樣您才不會產生本教學課程結束後產生的費用。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

啟動 Cloud Shell

雖然 Google Cloud 可以從筆電遠端操作 Google Cloud,但本程式碼研究室會使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。

啟用 Cloud Shell

  1. 在 Cloud 控制台中,按一下「啟用 Cloud Shell」圖示 H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfpXXLZUzLzLZLZDZLZD

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

如果您先前從未啟動 Cloud Shell,您會看見中繼畫面 (需捲動位置),說明螢幕內容。如果出現這種情況,請按一下「繼續」 (之後不會再顯示)。以下是單次畫面的外觀:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

佈建並連線至 Cloud Shell 只需幾分鐘的時間。

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

在 Cloud Shell 中,您可以透過終端機存取託管於雲端的虛擬機器。虛擬機器包含您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。在本程式碼研究室中,您的大部分作業都可以透過瀏覽器或 Chromebook 完成。

連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為您的專案 ID。

  1. 在 Cloud Shell 中執行下列指令,確認您已通過驗證:
gcloud auth list

指令輸出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如果尚未設定,請使用下列指令進行設定:

gcloud config set project <PROJECT_ID>

指令輸出

Updated property [core/project].

3. 啟用 Cloud Document AI API

您必須先啟用 API,才能開始使用 Document AI。在瀏覽器中開啟 Cloud 控制台

  1. 依序點選「導覽選單」圖示 ⋮ >API 與服務 >媒體庫Search API
  2. 搜尋「Document AI API」。接著按一下「啟用」,即可在 Google Cloud 專案中使用 API

4. 建立及測試處理器

您必須先建立表單剖析器處理器的執行個體,才能在該教學課程中使用 Document AI 平台。

  1. 在控制台中,前往 Document AI Platform Overview (Document AI 平台總覽)
  2. 按一下「建立處理器」,然後選取「表單剖析器」處理器
  3. 指定處理器名稱,然後從清單中選取您的區域。
  4. 點選「建立」來建立處理器
  5. 複製處理器 ID。您稍後必須在程式碼中使用此 ID。

(選用) 您可以在控制台中上傳文件,測試處理器。按一下「上傳文件」,然後選取要剖析的表單。如果沒有可用的範例表單,可以下載並使用此範例表單。

健康表

輸出內容應如下所示:剖析後的格式

5. 驗證 API 要求

您必須使用服務帳戶,才能向 Document AI API 提出要求。服務帳戶屬於您的專案,可供 Google Client Node.js 程式庫使用這個帳戶發出 API 要求。就像任何其他使用者帳戶一樣,服務帳戶都是以電子郵件地址表示。在本節中,您將使用 Cloud SDK 建立服務帳戶,然後建立必要憑證以服務帳戶身分進行驗證。

首先,使用 PROJECT_ID 設定環境變數,您在本程式碼研究室中都會使用這個變數:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)

接下來,使用下列方法建立新的服務帳戶來存取 Document AI API:

gcloud iam service-accounts create my-docai-sa \
  --display-name "my-docai-service-account"

接著,建立 Node.js 程式碼用來登入新服務帳戶的憑證。建立這些憑證,並將其儲存為 JSON 檔案「~/key.json」使用以下指令:

gcloud iam service-accounts keys create ~/key.json \
  --iam-account  my-docai-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

最後設定 GOOGLE_APPLICATION_CREDENTIALS 環境變數,程式庫會使用這個變數尋找您的憑證。如要進一步瞭解這份表單驗證,請參閱指南。使用以下指令,環境變數應設為所建立 JSON 憑證檔案的完整路徑:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"

6. 下載範例表單

有一個範例表單,可用來儲存在公開的 Google Cloud Storage 範例值區中。使用下列指令,將其下載至工作目錄。

gsutil cp gs://cloud-samples-data/documentai/form.pdf .

使用下列指令,確認檔案已下載至 Cloud Shell:

ls -ltr form.pdf

7. 安裝用戶端程式庫

接下來,請在工作目錄中設定程式碼。

初始化新的 Node.js 套件:

npm init

安裝 Document AI 用戶端程式庫

npm install @google-cloud/documentai

8. 提出同步程序文件要求

在這個步驟中,您會使用同步端點發出處理文件呼叫。如要一次處理大量文件,也可以使用非同步 API。如要進一步瞭解如何使用表單剖析器 API,請參閱這篇指南

建立 index.js 檔案並貼上下列程式碼。在適用變數中填入處理器資訊。

const { DocumentProcessorServiceClient } = require('@google-cloud/documentai').v1;
const fs = require('fs');

/**
 * Runs the sample document through Document AI to get key/value pairs and
 * confidence scores.
 */
async function processDocument(projectId, location, processorId, filePath, mimeType) {
    // Instantiates a client
    const documentaiClient = new DocumentProcessorServiceClient();

    // The full resource name of the processor, e.g.:
    // projects/project-id/locations/location/processor/processor-id
    // You must create new processors in the Cloud Console first
    const resourceName = documentaiClient.processorPath(projectId, location, processorId);

    // Read the file into memory.
    const imageFile = fs.readFileSync(filePath);

    // Convert the image data to a Buffer and base64 encode it.
    const encodedImage = Buffer.from(imageFile).toString('base64');

    // Load Binary Data into Document AI RawDocument Object
    const rawDocument = {
        content: encodedImage,
        mimeType: mimeType,
    };

    // Configure ProcessRequest Object
    const request = {
        name: resourceName,
        rawDocument: rawDocument
    };

    // Use the Document AI client to process the sample form
    const [result] = await documentaiClient.processDocument(request);

    return result.document;
}

/**
 * Run the codelab.
 */
async function main() {
    const projectId = 'YOUR_PROJECT_ID';
    const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu'
    const processorId = 'YOUR_PROCESSOR_ID'; // Should be a Hexadecimal string

    // Supported File Types
    // https://cloud.google.com/document-ai/docs/processors-list#processor_form-parser
    filePath = 'form.pdf'; // The local file in your current working directory
    mimeType = 'application/pdf';

    const document = await processDocument(projectId, location, processorId, filePath, mimeType);
    console.log("Document Processing Complete");

    // Print the document text as one big string
    console.log(`Text: ${document.text}`);
}

main(...process.argv.slice(2)).catch(err => {
    console.error(err);
    process.exitCode = 1;
});

現在執行程式碼,控制台中應該會顯示下列文字。

Text: FakeDoc M.D.
HEALTH INTAKE FORM
Please fill out the questionnaire carefully. The information you provide will be used to complete
your health profile and will be kept confidential.
Name:
Date:
Sally
Walker
DOB: 09/04/1986
Address: 24 Barney Lane City: Towalo State: NJ Zip: 07082
Email: Sally, waller@cmail.com Phone #: (906) 917-3486
Gender:
Marital Status: Single Occupation: Software Engineer
Referred By: None
Emergency Contact: Eva Walker Emergency Contact Phone: (906) 334-8926
Describe your medical concerns (symptoms, diagnoses, etc):
Runny nose, mucas in throat, weakness,
aches, chills, tired
Are you currently taking any medication? (If yes, please describe):
Vyvanse (25mg) daily for attention

在接下來的步驟中,您會擷取可輕鬆儲存在資料庫或其他應用程式的結構化資料。

9. 擷取表單鍵/值組合

您現在可以從表單中擷取鍵/值組合及其對應的可信度分數。文件回應物件包含輸入文件中的網頁清單。每個 page 物件在文字中都包含表單欄位清單及其位置。

下列程式碼會反覆查看每個網頁,並擷取每個鍵、值和可信度分數,

在程式碼中加入下列函式。

/**
 * Extract form data and confidence from processed document.
 */
function extractFormData(document) {
    // Extract shards from the text field
    function getText(textAnchor, document) {
        if (!textAnchor.textSegments || textAnchor.textSegments.length === 0) {
            return '';
        }

        // First shard in document doesn't have startIndex property
        const startIndex = textAnchor.textSegments[0].startIndex || 0;
        const endIndex = textAnchor.textSegments[0].endIndex;

        return document.text.substring(startIndex, endIndex);
    }

    var formData = [];

    const pages = document.pages;

    pages.forEach((page) => {
        const formFields = page.formFields;
        formFields.forEach((field) => {
            // Get the extracted field names and remove extra space from text
            const fieldName = getText(field.fieldName.textAnchor, document);
            // Confidence - How "sure" the API is that the text is correct
            const nameConfidence = field.fieldName.confidence.toFixed(4);

            const fieldValue = getText(field.fieldValue.textAnchor, document);
            const valueConfidence = field.fieldValue.confidence.toFixed(4);

            formData.push({
                fieldName: fieldName,
                fieldValue: fieldValue,
                nameConfidence: nameConfidence,
                valueConfidence: valueConfidence
            });
        });
    });

    return formData;
}

在主函式內新增對 extractFormData() 函式的呼叫,並將產生的物件輸出為資料表。

/**
 * Run the codelab.
 */
async function main() {
    const projectId = 'YOUR_PROJECT_ID';
    const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu'
    const processorId = 'YOUR_PROCESSOR_ID'; // Should be a Hexadecimal string

    // Supported File Types
    // https://cloud.google.com/document-ai/docs/processors-list#processor_form-parser
    filePath = 'form.pdf'; // The local file in your current working directory
    mimeType = 'application/pdf';

    const document = await processDocument(projectId, location, processorId, filePath, mimeType);
    const formData = extractFormData(document);

    console.log('\nThe following form key/value pairs were detected:');
    console.table(formData);
}

現在請執行程式碼。如果使用範例文件,您應該會看到下列輸出結果:

The following form key/value pairs were detected:
┌─────────┬────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────┬────────────────┬─────────────────┐
│ (index) │                           fieldName                            │                            fieldValue                            │ nameConfidence │ valueConfidence │
├─────────┼────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────┼────────────────┼─────────────────┤
│    0    │                       'Marital Status: '                       │                            'Single '                             │    '1.0000'    │    '1.0000'     │
│    1    │                            'DOB: '                             │                          '09/04/1986\n'                          │    '0.9999'    │    '0.9999'     │
│    2    │                            'City: '                            │                            'Towalo '                             │    '0.9996'    │    '0.9996'     │
│    3    │                          'Address: '                           │                        '24 Barney Lane '                         │    '0.9994'    │    '0.9994'     │
│    4    │                        'Referred By: '                         │                             'None\n'                             │    '0.9968'    │    '0.9968'     │
│    5    │                          'Phone #: '                           │                        '(906) 917-3486\n'                        │    '0.9961'    │    '0.9961'     │
│    6    │                           'State: '                            │                              'NJ '                               │    '0.9960'    │    '0.9960'     │
│    7    │                  'Emergency Contact Phone: '                   │                        '(906) 334-8926\n'                        │    '0.9925'    │    '0.9925'     │
│    8    │                           'Name:\n'                            │                        'Sally\nWalker\n'                         │    '0.9922'    │    '0.9922'     │
│    9    │                         'Occupation: '                         │                      'Software Engineer\n'                       │    '0.9914'    │    '0.9914'     │
│   10    │                            'Zip: '                             │                            '07082\n'                             │    '0.9904'    │    '0.9904'     │
│   11    │                           'Email: '                            │                    'Sally, waller@cmail.com '                    │    '0.9681'    │    '0.9681'     │
│   12    │                     'Emergency Contact: '                      │                          'Eva Walker '                           │    '0.9430'    │    '0.9430'     │
│   13    │ 'Describe your medical concerns (symptoms, diagnoses, etc):\n' │ 'Runny nose, mucas in throat, weakness,\naches, chills, tired\n' │    '0.7817'    │    '0.7817'     │
└─────────┴────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────┴────────────────┴─────────────────┘

10. 恭喜!

恭喜!您已成功使用 Document AI API 擷取手寫表單中的資料。我們鼓勵你試用其他表單圖片。

清除

如要避免系統向您的 Google Cloud 帳戶收取您在本教學課程中所用資源的相關費用:

  • 在 Cloud 控制台中,前往「管理資源」頁面。
  • 在專案清單中,選取您的專案,然後按一下「刪除」。
  • 在對話方塊中輸入專案 ID,然後按一下「關閉」,即可刪除專案。

瞭解詳情

授權

這項內容採用的是創用 CC 姓名標示 2.0 通用授權。