AWS上で請求書処理を自動化するためのサーバーレスアプリケーションの構築
Building a serverless application on AWS for automating invoice processing.
このブログ記事では、Amazon Textract、AWS Lambda、およびGoプログラミング言語を使用して、請求書処理のためのサーバーレスソリューションを構築する方法について学習します。Amazon S3にアップロードされた請求書や経費領収書の画像は、Lambda関数をトリガーし、AWS Go SDKを使用して請求書のメタデータ(ID、日付、金額など)を抽出し、Amazon DynamoDBテーブルに保存します。また、AWS CDKのGoバインディングを使用して、ソリューション全体の「インフラストラクチャ・コード」を実装し、AWS Cloud Development Kit(CDK)CLIで展開します。
コードはGitHubで利用可能です。
Amazon Textractの紹介
Amazon Textractは、スキャンされた文書からテキスト、手書き、およびデータを自動的に抽出する機械学習サービスです。簡単な光学的文字認識(OCR)を超えて、フォームや表からデータを識別、理解、および抽出します。ビジネスが文書処理ワークフローを自動化し、手動でのデータ入力を削減し、時間を節約し、エラーを減らし、生産性を向上させるのを支援するアプリケーションにドキュメントテキスト検出と分析を追加するのに役立ちます。
Amazon Textractの一般的な使用例には、次のものがあります。
- Amazon SageMaker Canvas を使用して、更新されたデータセットを使用して ML モデルを再トレーニングし、一括予測を自動化します
- データ体験の再発明:生成的AIと現代的なデータアーキテクチャを使用して、洞察を解き放つ
- インテリジェントな検索インデックスの構築 – 画像やPDFファイルで検出されたテキストのライブラリを作成します。
- 自然言語処理(NLP)のためのインテリジェントなテキスト抽出の使用 – NLPアプリケーションの入力としてテキストがグループ化される方法を制御できます。テキストを単語や行として抽出し、ドキュメントテーブル分析が有効になっている場合は、テーブルセルごとにテキストをグループ化することもできます。
- フォームからのデータキャプチャの自動化 – 構造化データをフォームから抽出し、既存のビジネスワークフローに統合して、フォームを介して提出されたユーザーデータを使用可能な形式に変換できます。
- 文書分類と抽出の自動化 – Amazon TextractのAnalyze Lendingドキュメント処理APIを使用すると、貸出書類をさまざまな書類クラスに自動分類し、分類されたページを正しい分析操作に自動的にルーティングすることができます。
手を動かしてAmazon Textractを学びましょう!
前提条件
先に進む前に、次のものがインストールされていることを確認してください:
- Goプログラミング言語(v1.18以上)
- AWS CDK
- AWS CLI
プロジェクトをクローンして、正しいディレクトリに変更します:
git clone https://github.com/abhirockzz/ai-ml-golang-textract-text-extraction
cd ai-ml-golang-textract-text-extraction
AWS CDKを使用してソリューションを展開する
AWS CDKは、サポートされているプログラミング言語の1つでクラウドインフラストラクチャをコードとして定義し、AWS CloudFormationを介してプロビジョニングするフレームワークです。
展開を開始するには、cdk deploy
コマンドを呼び出します。作成されるリソースのリストが表示され、続行するために確認を求められます。
cd cdk
cdk deploy
# 出力
Bundling asset TextractInvoiceProcessingGolangStack/textract-function/Code/Stage...
✨ Synthesis time: 5.26
//.... 省略
これらの変更をデプロイしますか (y/n)? y
アプリケーションに必要なAWSリソースの作成を開始するには、y
を入力します。
AWS CloudFormationテンプレートを確認するには、cdk synth
を実行し、cdk.out
フォルダを確認します。
スタック作成の進行状況をターミナルで追跡するか、AWSコンソールに移動して確認できます:CloudFormation > スタック > TextractInvoiceProcessingGolangStack
。
スタックの作成が完了すると、次のものがあるはずです:
S3
バケット(画像をアップロードするソースバケット)- Amazon Textractを使用して請求書画像を処理するLambda関数
- 各イメージの請求書データを保存する
DynamoDB
テーブル - その他のいくつかのコンポーネント(IAMロールなど)
ターミナルで次の出力(リソース名はあなたの場合と異なります)も表示されます。これらはCDKによって作成されたS3
バケットの名前です:
✅ TextractInvoiceProcessingGolangStack
✨ デプロイ時間: 113.51秒
出力:
TextractInvoiceProcessingGolangStack.invoiceinputbucketname = textractinvoiceprocessin-invoiceimagesinputbucket-bro1y13pib0r
TextractInvoiceProcessingGolangStack.invoiceoutputtablename = textractinvoiceprocessin-invoiceimagesinputbucket-bro1y13pib0r_invoice_output
.....
エンドツーエンドのソリューションを試す準備ができました!
請求書から経費メタデータを抽出する
ソリューションを試すには、自分自身の画像を使用するか、GitHubリポジトリで提供されているいくつかのサンプル請求書を使用することができます。
私はS3 CLIを使用してファイルをアップロードしますが、AWSコンソールを使用することもできます。
export SOURCE_BUCKET=<CDKの出力からソースS3バケット名を入力してください>
aws s3 cp ./invoice1.jpeg s3://$SOURCE_BUCKET
# アップロードされたファイルを確認する
aws s3 ls s3://$SOURCE_BUCKET
このLambda関数は、画像から請求書データ(ID、総額など)を抽出し、DynamoDB
テーブルに保存します。
他のファイルをアップロードしてください。
export SOURCE_BUCKET=<CDKの出力を確認してソースS3バケット名を入力してください>
aws s3 cp ./invoice2.jpeg s3://$SOURCE_BUCKET
aws s3 cp ./invoice3.jpeg s3://$SOURCE_BUCKET
AWSコンソールでDynamoDB
テーブルを確認してください。抽出された請求書情報が表示されます。
DynamoDB
テーブルは、ソースファイル名をパーティション
キーとして設計されています。これにより、指定されたイメージのすべての請求書データを取得できます。
AWS CLIを使用してテーブルをスキャン
することもできます。
aws dynamodb scan --table-name <CDKの出力を確認してテーブル名を入力してください>
クリーンアップ
完了したら、すべてのサービスを削除するには、単に次のコマンドを使用してください。
cdk destroy
# 出力プロンプト('y'を選択して続行してください)
Are you sure you want to delete: RekognitionLabelDetectionGolangStack (y/n)?
完全なソリューションを設定して試すことができました。締めくくる前に、裏側で何が起こっているかを理解するために、コードの重要な部分をすばやく見てみましょう。
コードの解説
いくつかのコード(エラーハンドリング、ログなど)は簡潔にするために省略されています。
AWS CDK
完全なCDKコードはこちらを参照してください。
bucket := awss3.NewBucket(stack, jsii.String("invoice-images-input-bucket"), &awss3.BucketProps{
BlockPublicAccess: awss3.BlockPublicAccess_BLOCK_ALL(),
RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
AutoDeleteObjects: jsii.Bool(true),
})
最初にソースS3バケットを作成します。
table := awsdynamodb.NewTable(stack, jsii.String("invoice-output-table"),
&awsdynamodb.TableProps{
PartitionKey: &awsdynamodb.Attribute{
Name: jsii.String("source_file"),
Type: awsdynamodb.AttributeType_STRING},
TableName: jsii.String(*bucket.BucketName() + "_invoice_output"),
})
次に、各画像の請求書データを保存するためのDynamoDB
テーブルを作成します。
function := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("textract-function"),
&awscdklambdagoalpha.GoFunctionProps{
Runtime: awslambda.Runtime_GO_1_X(),
Environment: &map[string]*string{"TABLE_NAME": table.TableName()},
Entry: jsii.String(functionDir),
})
table.GrantWriteData(function)
bucket.GrantRead(function, "*")
function.Role().AddManagedPolicy(awsiam.ManagedPolicy_FromAwsManagedPolicyName(jsii.String("AmazonTextractFullAccess")))
次に、DynamoDB
テーブル名を環境変数として関数に渡してLambda関数を作成します。また、関数にDynamoDB
テーブルとS3バケットへのアクセス許可を付与します。さらに、関数にAmazonTextractFullAccess
のマネージドポリシーへのアクセス許可を付与します。
function.AddEventSource(awslambdaeventsources.NewS3EventSource(sourceBucket, &awslambdaeventsources.S3EventSourceProps{
Events: &[]awss3.EventType{awss3.EventType_OBJECT_CREATED},
}))
イベントソースをLambda関数に追加し、ソースS3バケットに請求書画像がアップロードされたときにトリガーされるようにします。
awscdk.NewCfnOutput(stack, jsii.String("invoice-input-bucket-name"),
&awscdk.CfnOutputProps{
ExportName: jsii.String("invoice-input-bucket-name"),
Value: bucket.BucketName()})
awscdk.NewCfnOutput(stack, jsii.String("invoice-output-table-name"),
&awscdk.CfnOutputProps{
ExportName: jsii.String("invoice-output-table-name"),
Value: table.TableName()})
最後に、AWS CloudFormation出力としてバケットとDynamoDB
テーブル名をエクスポートします。
Lambda Function
完全なLambda関数コードについては、こちらを参照してください。
func handler(ctx context.Context, s3Event events.S3Event) {
for _, record := range s3Event.Records {
sourceBucketName := record.S3.Bucket.Name
fileName := record.S3.Object.Key
err := invoiceProcessing(sourceBucketName, fileName)
}
}
請求書がソースバケットにアップロードされるとLambda関数がトリガーされます。関数は請求書のリストを反復処理し、各請求書のためにinvoiceProcessing
関数を呼び出します。
それでは、以下を進めていきましょう。
func invoiceProcessing(sourceBucketName, fileName string) error {
resp, err := textractClient.AnalyzeExpense(context.Background(), &textract.AnalyzeExpenseInput{
Document: &types.Document{
S3Object: &types.S3Object{
Bucket: &sourceBucketName,
Name: &fileName,
},
},
})
for _, doc := range resp.ExpenseDocuments {
item := make(map[string]ddbTypes.AttributeValue)
item["source_file"] = &ddbTypes.AttributeValueMemberS{Value: fileName}
for _, summaryField := range doc.SummaryFields {
if *summaryField.Type.Text == "INVOICE_RECEIPT_ID" {
item["receipt_id"] = &ddbTypes.AttributeValueMemberS{Value: *summaryField.ValueDetection.Text}
} else if *summaryField.Type.Text == "TOTAL" {
item["total"] = &ddbTypes.AttributeValueMemberS{Value: *summaryField.ValueDetection.Text}
} else if *summaryField.Type.Text == "INVOICE_RECEIPT_DATE" {
item["receipt_date"] = &ddbTypes.AttributeValueMemberS{Value: *summaryField.ValueDetection.Text}
} else if *summaryField.Type.Text == "DUE_DATE" {
item["due_date"] = &ddbTypes.AttributeValueMemberS{Value: *summaryField.ValueDetection.Text}
}
}
_, err := dynamodbClient.PutItem(context.Background(), &dynamodb.PutItemInput{
TableName: aws.String(table),
Item: item,
})
}
return nil
}
invoiceProcessing
関数は、Amazon Textract AnalyzeExpense APIを呼び出して請求書データを抽出します。- 関数は、ExpenseDocumentsのリストを反復処理し、特定のフィールドから情報を抽出します –
INVOICE_RECEIPT_ID
、TOTAL
、INVOICE_RECEIPT_DATE
、DUE_DATE
。 - 次に、抽出されたデータを
DynamoDB
テーブルに保存します。
結論と次のステップ
この記事では、Amazon Textractを使用して請求書を処理するサーバーレスソリューションを作成する方法を紹介しました。AWS CDKを使用して、インフラストラクチャのライフサイクル全体を自動化しました。これらすべては、AWS LambdaとAWS CDKでよくサポートされているGoプログラミング言語を使用して行われました。
この解決策を改善/拡張するには、ExpenseDocument
sレスポンス内の他のフィールドで実験して、より多くの情報を抽出してみてください。
楽しいビルディングを!
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles