From 4dd1a49aef728c0cb42abca95327ec797a30e39c Mon Sep 17 00:00:00 2001 From: Eric Schmidt Date: Thu, 15 Oct 2020 12:18:40 -0700 Subject: [PATCH] docs(samples): new Doc AI samples for v1beta3 (#101) * docs(samples): new Doc AI samples for v1beta3 * feat: add a new version to the library * fix: adds processor ID as literal in tests * fix: removed apiEndpoint from client instantiation Co-authored-by: Sofia Leon Co-authored-by: sofisl <55454395+sofisl@users.noreply.github.com> Co-authored-by: Justin Beckwith --- document-ai/.eslintrc.yml | 4 +- document-ai/batch-process-document.v1beta3.js | 145 ++++++++++++++++++ document-ai/package.json | 6 +- document-ai/process-document.v1beta3.js | 107 +++++++++++++ document-ai/quickstart.js | 62 +++++--- document-ai/resources/invoice.pdf | Bin 0 -> 58980 bytes .../batch-process-document.v1beta3.test.js | 62 ++++++++ .../test/process-document.v1beta3.test.js | 53 +++++++ document-ai/test/quickstart.test.js | 30 +++- 9 files changed, 435 insertions(+), 34 deletions(-) create mode 100644 document-ai/batch-process-document.v1beta3.js create mode 100644 document-ai/process-document.v1beta3.js create mode 100644 document-ai/resources/invoice.pdf create mode 100644 document-ai/test/batch-process-document.v1beta3.test.js create mode 100644 document-ai/test/process-document.v1beta3.test.js diff --git a/document-ai/.eslintrc.yml b/document-ai/.eslintrc.yml index eef2752ae8..98634adbef 100644 --- a/document-ai/.eslintrc.yml +++ b/document-ai/.eslintrc.yml @@ -1,6 +1,4 @@ --- rules: no-console: off - node/no-missing-require: off - node/no-extraneous-require: off - \ No newline at end of file + node/no-unsupported-features/node-builtins: off diff --git a/document-ai/batch-process-document.v1beta3.js b/document-ai/batch-process-document.v1beta3.js new file mode 100644 index 0000000000..75921524d0 --- /dev/null +++ b/document-ai/batch-process-document.v1beta3.js @@ -0,0 +1,145 @@ +/** + * Copyright 2020 Google LLC + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const uuid = require('uuid'); + +async function main( + projectId = 'YOUR_PROJECT_ID', + location = 'YOUR_PROJECT_LOCATION', + processorId = 'YOUR_PROCESSOR_ID', // Create this in the Cloud Console + gcsInputUri = 'gs://cloud-samples-data/documentai/invoice.pdf', + gcsOutputUri = 'output-bucket', + gcsOutputUriPrefix = uuid.v4() +) { + // [START documentai_batch_process_document] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu' + // const processorId = 'YOUR_PROCESSOR_ID'; + // const gcsInputUri = 'YOUR_SOURCE_PDF'; + // const gcsOutputUri = 'YOUR_STORAGE_BUCKET'; + // const gcsOutputUriPrefix = 'YOUR_STORAGE_PREFIX'; + + // Imports the Google Cloud client library + const { + DocumentProcessorServiceClient, + } = require('@google-cloud/documentai').v1beta3; + const {Storage} = require('@google-cloud/storage'); + + // Instantiates Document AI, Storage clients + const client = new DocumentProcessorServiceClient(); + const storage = new Storage(); + + const {default: PQueue} = require('p-queue'); + + async function batchProcessDocument() { + const name = `projects/${projectId}/locations/${location}/processors/${processorId}`; + + // Configure the batch process request. + const request = { + name, + inputConfigs: [ + { + gcsSource: gcsInputUri, + mimeType: 'application/pdf', + }, + ], + outputConfig: { + gcsDestination: `${gcsOutputUri}/${gcsOutputUriPrefix}/`, + }, + }; + + // Batch process document using a long-running operation. + // You can wait for now, or get results later. + // Note: first request to the service takes longer than subsequent + // requests. + const [operation] = await client.batchProcessDocuments(request); + + // Wait for operation to complete. + await operation.promise(); + + console.log('Document processing complete.'); + + // Query Storage bucket for the results file(s). + const query = { + prefix: gcsOutputUriPrefix, + }; + + console.log('Fetching results ...'); + + // List all of the files in the Storage bucket + const [files] = await storage.bucket(gcsOutputUri).getFiles(query); + + // Add all asynchronous downloads to queue for execution. + const queue = new PQueue({concurrency: 15}); + const tasks = files.map((fileInfo, index) => async () => { + // Get the file as a buffer + const [file] = await fileInfo.download(); + + console.log(`Fetched file #${index + 1}:`); + + // The results stored in the output Storage location + // are formatted as a document object. + const document = JSON.parse(file.toString()); + const {text} = document; + + // Extract shards from the text field + const getText = textAnchor => { + 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 text.substring(startIndex, endIndex); + }; + + // Read the text recognition output from the processor + console.log('The document contains the following paragraphs:'); + + const [page1] = document.pages; + const {paragraphs} = page1; + for (const paragraph of paragraphs) { + const paragraphText = getText(paragraph.layout.textAnchor); + console.log(`Paragraph text:\n${paragraphText}`); + } + + // Form parsing provides additional output about + // form-formatted PDFs. You must create a form + // processor in the Cloud Console to see full field details. + console.log('\nThe following form key/value pairs were detected:'); + + const {formFields} = page1; + for (const field of formFields) { + const fieldName = getText(field.fieldName.textAnchor); + const fieldValue = getText(field.fieldValue.textAnchor); + + console.log('Extracted key value pair:'); + console.log(`\t(${fieldName}, ${fieldValue})`); + } + }); + await queue.addAll(tasks); + } + // [END documentai_batch_process_document] + + batchProcessDocument(); +} +main(...process.argv.slice(2)); diff --git a/document-ai/package.json b/document-ai/package.json index e84be17d21..8d166d1dd4 100644 --- a/document-ai/package.json +++ b/document-ai/package.json @@ -4,7 +4,7 @@ "license": "Apache-2.0", "author": "Google LLC", "engines": { - "node": ">=8" + "node": ">= 10.17.0" }, "files": [ "*.js" @@ -14,7 +14,9 @@ }, "dependencies": { "@google-cloud/documentai": "^2.1.1", - "@google-cloud/storage": "^5.0.0" + "@google-cloud/storage": "^5.0.0", + "p-queue": "^6.6.2", + "uuid": "^8.3.1" }, "devDependencies": { "chai": "^4.2.0", diff --git a/document-ai/process-document.v1beta3.js b/document-ai/process-document.v1beta3.js new file mode 100644 index 0000000000..3213f3a563 --- /dev/null +++ b/document-ai/process-document.v1beta3.js @@ -0,0 +1,107 @@ +/** + * Copyright 2020, Google, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +async function main(projectId, location, processorId, filePath) { + // [START documentai_process_document] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu' + // const processor = 'YOUR_PROCESSOR_ID'; // Create processor in Cloud Console + // const filePath = '/path/to/local/pdf'; + + const { + DocumentProcessorServiceClient, + } = require('@google-cloud/documentai').v1beta3; + + // Instantiates a client + const client = new DocumentProcessorServiceClient(); + + async function processDocument() { + // 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 name = `projects/${projectId}/locations/${location}/processors/${processorId}`; + + // Read the file into memory. + const fs = require('fs').promises; + const imageFile = await fs.readFile(filePath); + + // Convert the image data to a Buffer and base64 encode it. + const encodedImage = Buffer.from(imageFile).toString('base64'); + + const request = { + name, + document: { + content: encodedImage, + mimeType: 'application/pdf', + }, + }; + + // Recognizes text entities in the PDF document + const [result] = await client.processDocument(request); + const {document} = result; + + // Get all of the document text as one big string + const {text} = document; + + // Extract shards from the text field + const getText = textAnchor => { + 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 text.substring(startIndex, endIndex); + }; + + // Read the text recognition output from the processor + console.log('The document contains the following paragraphs:'); + const [page1] = document.pages; + const {paragraphs} = page1; + + for (const paragraph of paragraphs) { + const paragraphText = getText(paragraph.layout.textAnchor); + console.log(`Paragraph text:\n${paragraphText}`); + } + + // Form parsing provides additional output about + // form-formatted PDFs. You must create a form + // processor in the Cloud Console to see full field details. + console.log('\nThe following form key/value pairs were detected:'); + + const {formFields} = page1; + for (const field of formFields) { + const fieldName = getText(field.fieldName.textAnchor); + const fieldValue = getText(field.fieldValue.textAnchor); + + console.log('Extracted key value pair:'); + console.log(`\t(${fieldName}, ${fieldValue})`); + } + } + // [END documentai_process_document] + await processDocument(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err); + process.exitCode = 1; +}); diff --git a/document-ai/quickstart.js b/document-ai/quickstart.js index de56ea4597..2d6c4a6fbb 100644 --- a/document-ai/quickstart.js +++ b/document-ai/quickstart.js @@ -15,56 +15,72 @@ 'use strict'; -async function main( - projectId, - location, - gcsInputUri = 'gs://cloud-samples-data/documentai/invoice.pdf' -) { +async function main(projectId, location, processorId, filePath) { // [START documentai_quickstart] /** * TODO(developer): Uncomment these variables before running the sample. */ // const projectId = 'YOUR_PROJECT_ID'; // const location = 'YOUR_PROJECT_LOCATION'; // Format is 'us' or 'eu' - // const gcsInputUri = 'YOUR_SOURCE_PDF'; + // const processor = 'YOUR_PROCESSOR_ID'; // Create processor in Cloud Console + // const filePath = '/path/to/local/pdf'; const { - DocumentUnderstandingServiceClient, - } = require('@google-cloud/documentai').v1beta2; - const client = new DocumentUnderstandingServiceClient(); + DocumentProcessorServiceClient, + } = require('@google-cloud/documentai').v1beta3; + + // Instantiates a client + const client = new DocumentProcessorServiceClient(); async function quickstart() { - // Configure the request for processing the PDF - const parent = `projects/${projectId}/locations/${location}`; + // 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 name = `projects/${projectId}/locations/${location}/processors/${processorId}`; + + // Read the file into memory. + const fs = require('fs').promises; + const imageFile = await fs.readFile(filePath); + + // Convert the image data to a Buffer and base64 encode it. + const encodedImage = Buffer.from(imageFile).toString('base64'); + const request = { - parent, - inputConfig: { - gcsSource: { - uri: gcsInputUri, - }, + name, + document: { + content: encodedImage, mimeType: 'application/pdf', }, }; // Recognizes text entities in the PDF document const [result] = await client.processDocument(request); + const {document} = result; // Get all of the document text as one big string - const {text} = result; + const {text} = document; // Extract shards from the text field - function extractText(textAnchor) { + const getText = textAnchor => { + 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 text.substring(startIndex, endIndex); - } + }; + + // Read the text recognition output from the processor + console.log('The document contains the following paragraphs:'); + const [page1] = document.pages; + const {paragraphs} = page1; - for (const entity of result.entities) { - console.log(`\nEntity text: ${extractText(entity.textAnchor)}`); - console.log(`Entity type: ${entity.type}`); - console.log(`Entity mention text: ${entity.mentionText}`); + for (const paragraph of paragraphs) { + const paragraphText = getText(paragraph.layout.textAnchor); + console.log(`Paragraph text:\n${paragraphText}`); } } // [END documentai_quickstart] diff --git a/document-ai/resources/invoice.pdf b/document-ai/resources/invoice.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7722734a4305b3e2f4f473b2c5783f90062ffdc7 GIT binary patch literal 58980 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%0AE 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 literal 0 HcmV?d00001 diff --git a/document-ai/test/batch-process-document.v1beta3.test.js b/document-ai/test/batch-process-document.v1beta3.test.js new file mode 100644 index 0000000000..5cd8b41147 --- /dev/null +++ b/document-ai/test/batch-process-document.v1beta3.test.js @@ -0,0 +1,62 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const {Storage} = require('@google-cloud/storage'); +const { + DocumentProcessorServiceClient, +} = require('@google-cloud/documentai').v1beta3; +const client = new DocumentProcessorServiceClient({ + apiEndpoint: 'us-documentai.googleapis.com', +}); + +const cp = require('child_process'); +const assert = require('assert'); +const {describe, it, before, after} = require('mocha'); +const uuid = require('uuid'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const storage = new Storage(); +const bucketName = `nodejs-docs-samples-test-${uuid.v4()}`; +const cmd = 'node batch-process-document.v1beta3.js'; + +const testProcessDocument = { + projectId: '', + location: 'us', + processorId: '8f1123c1b125e0b7', + gcsInputUri: 'gs://cloud-samples-data/documentai/invoice.pdf', + gcsOutputUriPrefix: uuid.v4(), +}; + +describe('Document AI batch parse form', () => { + before(async () => { + testProcessDocument.projectId = await client.getProjectId(); + await storage.createBucket(bucketName); + }); + + after(async () => { + const bucket = storage.bucket(bucketName); + await bucket.deleteFiles({force: true}); + await bucket.delete(); + }); + + it('should parse the GCS invoice example as a form', async () => { + const output = execSync( + `${cmd} ${testProcessDocument.projectId} ${testProcessDocument.location} ${testProcessDocument.processorId} ${testProcessDocument.gcsInputUri} gs://${bucketName} ${testProcessDocument.gcsOutputUriPrefix}` + ); + assert.notStrictEqual(output.indexOf('Extracted'), -1); + }); +}); diff --git a/document-ai/test/process-document.v1beta3.test.js b/document-ai/test/process-document.v1beta3.test.js new file mode 100644 index 0000000000..48a46f0916 --- /dev/null +++ b/document-ai/test/process-document.v1beta3.test.js @@ -0,0 +1,53 @@ +/** + * Copyright 2019, Google, Inc. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const path = require('path'); +const assert = require('assert'); +const cp = require('child_process'); + +const { + DocumentProcessorServiceClient, +} = require('@google-cloud/documentai').v1beta3; +const client = new DocumentProcessorServiceClient({ + apiEndpoint: 'us-documentai.googleapis.com', +}); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); +const LOCATION = 'us'; +const PROCESSOR_ID = '8f1123c1b125e0b7'; + +const fileName = 'invoice.pdf'; +const filePath = path.resolve(path.join(__dirname, `../resources/${fileName}`)); + +describe('Process document', () => { + let projectId; + before(async () => { + projectId = await client.getProjectId(); + }); + it('should run document (process invoice)', async () => { + const stdout = execSync( + `node ./process-document.v1beta3.js ${projectId} ${LOCATION} ${PROCESSOR_ID} ${filePath}`, + { + cwd, + } + ); + assert.notStrictEqual(stdout.indexOf('Paragraph'), -1); + assert.notStrictEqual(stdout.indexOf('Extracted'), -1); + }); +}); diff --git a/document-ai/test/quickstart.test.js b/document-ai/test/quickstart.test.js index 8a44c2d6c8..d26e563275 100644 --- a/document-ai/test/quickstart.test.js +++ b/document-ai/test/quickstart.test.js @@ -16,20 +16,38 @@ 'use strict'; const path = require('path'); -const {assert} = require('chai'); +const assert = require('assert'); const cp = require('child_process'); +const { + DocumentProcessorServiceClient, +} = require('@google-cloud/documentai').v1beta3; +const client = new DocumentProcessorServiceClient({ + apiEndpoint: 'us-documentai.googleapis.com', +}); + const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); const cwd = path.join(__dirname, '..'); -const projectId = process.env.GCLOUD_PROJECT; const LOCATION = 'us'; +const PROCESSOR_ID = '8f1123c1b125e0b7'; + +const fileName = 'invoice.pdf'; +const filePath = path.resolve(path.join(__dirname, `../resources/${fileName}`)); describe('Quickstart', () => { + let projectId; + before(async () => { + projectId = await client.getProjectId(); + }); + it('should run quickstart', async () => { - const stdout = execSync(`node ./quickstart.js ${projectId} ${LOCATION}`, { - cwd, - }); - assert.match(stdout, /Entity/); + const stdout = execSync( + `node ./quickstart.js ${projectId} ${LOCATION} ${PROCESSOR_ID} ${filePath}`, + { + cwd, + } + ); + assert.notStrictEqual(stdout.indexOf('Paragraph'), -1); }); });