This walkthrough guides you through deploying and using the SageMaker UDOP Processor sample application, which demonstrates specialized document processing using a fine-tuned Hugging Face RVL-CDIP model deployed on Amazon SageMaker.
Overview
The SageMaker UDOP RVL-CDIP sample showcases how to:
Classify documents using a fine-tuned RVL-CDIP model on SageMaker
Process domain-specific documents that require specialized classification
Extract information using Amazon Bedrock foundation models
Track document processing status through a GraphQL API
View and manage documents through a web interface
Architecture
The sample deploys the following components:
S3 buckets for input documents and processing results
Amazon SageMaker endpoint for document classification
AWS Step Functions workflow for orchestration
AWS Lambda functions for processing tasks
Amazon DynamoDB tables for configuration and tracking
Amazon AppSync GraphQL API for querying processing status
Amazon CloudFront distribution for the web interface
Prerequisites
Before you begin, ensure you have:
AWS Account: With permissions to create the required resources
AWS CLI: Configured with appropriate credentials
Node.js: Version 18 or later (use NVM to install the version specified in .nvmrc)
AWS CDK: Version 2.x installed globally
Docker: For building Lambda functions
Amazon Bedrock Access: Ensure your account has access to Amazon Bedrock and the required models
SageMaker Quota: Ensure you have sufficient quota for the required SageMaker instance types (g5.2xlarge)
Step 1: Clone the Repository
First, clone the GenAI IDP Accelerator repository and navigate to the sample directory:
// src/rvl-cdip-stack.tsimport{InstanceType}from"@aws-cdk/aws-sagemaker-alpha";import{ProcessingEnvironment,ProcessingEnvironmentApi,UserIdentity,WebApplication,ConfigurationTable,TrackingTable,}from"@cdklabs/genai-idp";import{SagemakerUdopProcessor,SagemakerClassifier,SagemakerUdopProcessorConfiguration,}from"@cdklabs/genai-idp-sagemaker-udop-processor";import{CfnOutput,RemovalPolicy,Stack}from"aws-cdk-lib";import{AuthorizationType,UserPoolDefaultAction,}from"aws-cdk-lib/aws-appsync";import{ServicePrincipal}from"aws-cdk-lib/aws-iam";import{Key}from"aws-cdk-lib/aws-kms";import{Bucket}from"aws-cdk-lib/aws-s3";import{Construct}from"constructs";import{RvlCdipModel}from"./rvl-cdip-model";exportclassRvlCdipStackextendsStack{constructor(scope:Construct,id:string){super(scope,id);constmetricNamespace=this.stackName;// Create KMS key for encryptionconstkey=newKey(this,"Key");key.grantEncryptDecrypt(newServicePrincipal("logs.amazonaws.com"));// Create S3 buckets for document processingconstinputBucket=newBucket(this,"InputBucket",{encryptionKey:key,eventBridgeEnabled:true,// Required for event-driven processingremovalPolicy:RemovalPolicy.DESTROY,autoDeleteObjects:true,});constworkingBucket=newBucket(this,"WorkingBucket",{encryptionKey:key,removalPolicy:RemovalPolicy.DESTROY,autoDeleteObjects:true,});constoutputBucket=newBucket(this,"OutputBucket",{encryptionKey:key,removalPolicy:RemovalPolicy.DESTROY,autoDeleteObjects:true,});// Create user identity for authenticationconstuserIdentity=newUserIdentity(this,"UserIdentity");// Grant bucket access to authenticated usersinputBucket.grantRead(userIdentity.identityPool.authenticatedRole);outputBucket.grantRead(userIdentity.identityPool.authenticatedRole);// Create the RVL-CDIP model for document classificationconst{modelData}=newRvlCdipModel(this,"RvlCdipModel");// Create SageMaker classifier with the RVL-CDIP modelconstclassifier=newSagemakerClassifier(this,"RvlCdipClassifier",{key,outputBucket,modelData,instanceType:InstanceType.G5_2XLARGE,// GPU instance for model inference});// Create DynamoDB tables for configuration and trackingconstconfigurationTable=newConfigurationTable(this,"ConfigurationTable",{encryptionKey:key,});consttrackingTable=newTrackingTable(this,"TrackingTable",{encryptionKey:key,});// Create the GraphQL API for document trackingconstapi=newProcessingEnvironmentApi(this,"EnvironmentApi",{inputBucket,outputBucket,encryptionKey:key,configurationTable,trackingTable,authorizationConfig:{defaultAuthorization:{authorizationType:AuthorizationType.USER_POOL,userPoolConfig:{userPool:userIdentity.userPool,defaultAction:UserPoolDefaultAction.ALLOW,},},additionalAuthorizationModes:[{authorizationType:AuthorizationType.IAM,},],},});// Create the processing environmentconstenvironment=newProcessingEnvironment(this,"Environment",{key,inputBucket,outputBucket,workingBucket,configurationTable,trackingTable,api,metricNamespace,});// Create the SageMaker UDOP processor with RVL-CDIP configurationconstprocessor=newSagemakerUdopProcessor(this,"Processor",{environment,classifier,configuration:SagemakerUdopProcessorConfiguration.rvlCdipPackageSample()});// Add the processor's state machine to the APIapi.addStateMachine(processor.stateMachine);// Grant API permissions to authenticated usersapi.grantQuery(userIdentity.identityPool.authenticatedRole);api.grantSubscription(userIdentity.identityPool.authenticatedRole);// Create web application for document managementconstwebApplication=newWebApplication(this,"WebApp",{webAppBucket:newBucket(this,"WebAppBucket",{websiteIndexDocument:"index.html",websiteErrorDocument:"index.html",removalPolicy:RemovalPolicy.DESTROY,autoDeleteObjects:true,}),userIdentity,environment,apiUrl:api.graphqlUrl,});// Output the web application URLnewCfnOutput(this,"WebSiteUrl",{value:`https://${webApplication.distribution.distributionDomainName}`,description:"URL of the web application for document management",});}}
# src/rvl_cdip_stack.pyfromaws_cdkimport(Stack,RemovalPolicy,CfnOutput,)fromaws_cdk.aws_s3importBucketfromaws_cdk.aws_kmsimportKeyfromaws_cdk.aws_iamimportServicePrincipalfromaws_cdk.aws_ec2importInstanceTypefromaws_cdk.aws_appsyncimport(AuthorizationType,UserPoolDefaultAction)fromcdklabs.genai_idpimport(ProcessingEnvironment,ProcessingEnvironmentApi,UserIdentity,WebApplication,ConfigurationTable,TrackingTable,)fromcdklabs.genai_idp_sagemaker_udop_processorimport(SagemakerUdopProcessor,BedrockFoundationModel)fromconstructsimportConstructclassRvlCdipStack(Stack):def__init__(self,scope:Construct,construct_id:str,**kwargs)->None:super().__init__(scope,construct_id,**kwargs)metric_namespace=self.stack_name# Create KMS key for encryptionkey=Key(self,"CustomerManagedEncryptionKey")key.grant_encrypt_decrypt(ServicePrincipal("logs.amazonaws.com"))# Create S3 buckets for document processinginput_bucket=Bucket(self,"InputBucket",encryption_key=key,event_bridge_enabled=True,removal_policy=RemovalPolicy.DESTROY,auto_delete_objects=True)output_bucket=Bucket(self,"OutputBucket",encryption_key=key,removal_policy=RemovalPolicy.DESTROY,auto_delete_objects=True)working_bucket=Bucket(self,"WorkingBucket",encryption_key=key,removal_policy=RemovalPolicy.DESTROY,auto_delete_objects=True)# Create user identity for authenticationuser_identity=UserIdentity(self,"UserIdentity")# Grant bucket access to authenticated usersinput_bucket.grant_read(user_identity.identity_pool.authenticated_role)output_bucket.grant_read(user_identity.identity_pool.authenticated_role)# Create the RVL-CDIP modelmodel=RvlCdipModel(self,"RvlCdipModel")model_data=model.model_data# Create the SageMaker classifierclassifier=SagemakerClassifier(self,"RvlCdipClassifier",key=key,output_bucket=output_bucket,model_data=model_data,instance_type=InstanceType.G5_2XLARGE)# Create DynamoDB tables for configuration and trackingconfiguration_table=ConfigurationTable(self,"ConfigurationTable",encryption_key=key)tracking_table=TrackingTable(self,"TrackingTable",encryption_key=key)# Create the GraphQL API for document trackingapi=ProcessingEnvironmentApi(self,"EnvironmentApi",input_bucket=input_bucket,output_bucket=output_bucket,encryption_key=key,configuration_table=configuration_table,tracking_table=tracking_table,authorization_config={"default_authorization":{"authorization_type":AuthorizationType.USER_POOL,"user_pool_config":{"user_pool":user_identity.user_pool,"default_action":UserPoolDefaultAction.ALLOW,},},"additional_authorization_modes":[{"authorization_type":AuthorizationType.IAM,},],},)# Create the processing environmentenvironment=ProcessingEnvironment(self,"Environment",key=key,input_bucket=input_bucket,output_bucket=output_bucket,working_bucket=working_bucket,configuration_table=configuration_table,tracking_table=tracking_table,api=api,metric_namespace=metric_namespace)# Create the SageMaker UDOP processor with RVL-CDIP configurationprocessor=SagemakerUdopProcessor(self,"Processor",environment=environment,classifier=classifier,configuration=SagemakerUdopProcessorConfiguration.rvl_cdip_package_sample())# Add the processor's state machine to the APIapi.add_state_machine(processor.state_machine)# Grant API permissions to authenticated usersapi.grant_query(user_identity.identity_pool.authenticated_role)api.grant_subscription(user_identity.identity_pool.authenticated_role)# Create web application for document managementweb_application=WebApplication(self,"WebApp",web_app_bucket=Bucket(self,"WebAppBucket",website_index_document="index.html",website_error_document="index.html",removal_policy=RemovalPolicy.DESTROY,auto_delete_objects=True,),user_identity=user_identity,environment=environment,api_url=api.graphql_url,)# Output the web application URLCfnOutput(self,"WebSiteUrl",value=f"https://{web_application.distribution.distribution_domain_name}",description="URL of the web application for document management")
// src/RvlCdipStack.csusingAmazon.CDK;usingAmazon.CDK.AWS.S3;usingAmazon.CDK.AWS.KMS;usingAmazon.CDK.AWS.IAM;usingAmazon.CDK.AWS.EC2;usingAmazon.CDK.AWS.AppSync;usingCdklabs.GenaiIdp;usingCdklabs.GenaiIdpSagemakerUdopProcessor;usingConstructs;namespaceRvlCdip{publicclassRvlCdipStack:Stack{publicRvlCdipStack(Constructscope,stringid,IStackPropsprops=null):base(scope,id,props){varmetricNamespace=this.StackName;// Create KMS key for encryptionvarkey=newKey(this,"CustomerManagedEncryptionKey");key.GrantEncryptDecrypt(newServicePrincipal("logs.amazonaws.com"));// Create S3 buckets for document processingvarinputBucket=newBucket(this,"InputBucket",newBucketProps{EncryptionKey=key,EventBridgeEnabled=true,RemovalPolicy=RemovalPolicy.DESTROY,AutoDeleteObjects=true});varoutputBucket=newBucket(this,"OutputBucket",newBucketProps{EncryptionKey=key,RemovalPolicy=RemovalPolicy.DESTROY,AutoDeleteObjects=true});varworkingBucket=newBucket(this,"WorkingBucket",newBucketProps{EncryptionKey=key,RemovalPolicy=RemovalPolicy.DESTROY,AutoDeleteObjects=true});// Create user identity for authenticationvaruserIdentity=newUserIdentity(this,"UserIdentity");// Grant bucket access to authenticated usersinputBucket.GrantRead(userIdentity.IdentityPool.AuthenticatedRole);outputBucket.GrantRead(userIdentity.IdentityPool.AuthenticatedRole);// Create the RVL-CDIP modelvarrvlCdipModel=newRvlCdipModel(this,"RvlCdipModel");varmodelData=rvlCdipModel.ModelData;// Create the SageMaker classifiervarclassifier=newSagemakerClassifier(this,"RvlCdipClassifier",newSagemakerClassifierProps{Key=key,OutputBucket=outputBucket,ModelData=modelData,InstanceType=InstanceType.G5_2XLARGE});// Create DynamoDB tables for configuration and trackingvarconfigurationTable=newConfigurationTable(this,"ConfigurationTable",newConfigurationTableProps{EncryptionKey=key});vartrackingTable=newTrackingTable(this,"TrackingTable",newTrackingTableProps{EncryptionKey=key});// Create the GraphQL API for document trackingvarapi=newProcessingEnvironmentApi(this,"EnvironmentApi",newProcessingEnvironmentApiProps{InputBucket=inputBucket,OutputBucket=outputBucket,EncryptionKey=key,ConfigurationTable=configurationTable,TrackingTable=trackingTable,AuthorizationConfig=newAuthorizationConfig{DefaultAuthorization=newAuthorizationMode{AuthorizationType=AuthorizationType.USER_POOL,UserPoolConfig=newUserPoolConfig{UserPool=userIdentity.UserPool,DefaultAction=UserPoolDefaultAction.ALLOW,},},AdditionalAuthorizationModes=new[]{newAuthorizationMode{AuthorizationType=AuthorizationType.IAM,},},},});// Create the processing environmentvarenvironment=newProcessingEnvironment(this,"Environment",newProcessingEnvironmentProps{Key=key,InputBucket=inputBucket,OutputBucket=outputBucket,WorkingBucket=workingBucket,ConfigurationTable=configurationTable,TrackingTable=trackingTable,Api=api,MetricNamespace=metricNamespace});// Create the SageMaker UDOP processor with RVL-CDIP configurationvarprocessor=newSagemakerUdopProcessor(this,"Processor",newSagemakerUdopProcessorProps{Environment=environment,Classifier=classifier,Configuration=SagemakerUdopProcessorConfiguration.RvlCdipPackageSample()});// Add the processor's state machine to the APIapi.AddStateMachine(processor.StateMachine);// Grant API permissions to authenticated usersapi.GrantQuery(userIdentity.IdentityPool.AuthenticatedRole);api.GrantSubscription(userIdentity.IdentityPool.AuthenticatedRole);// Create web application for document managementvarwebApplication=newWebApplication(this,"WebApp",newWebApplicationProps{WebAppBucket=newBucket(this,"WebAppBucket",newBucketProps{WebsiteIndexDocument="index.html",WebsiteErrorDocument="index.html",RemovalPolicy=RemovalPolicy.DESTROY,AutoDeleteObjects=true}),UserIdentity=userIdentity,Environment=environment,ApiUrl=api.GraphqlUrl,});// Output the web application URLnewCfnOutput(this,"WebSiteUrl",newCfnOutputProps{Value=$"https://{webApplication.Distribution.DistributionDomainName}",Description="URL of the web application for document management"});}}}OutputBucket=outputBucket,WorkingBucket=workingBucket,ConfigurationTable=configurationTable,TrackingTable=trackingTable,Api=api,MetricNamespace=metricNamespace});// Create the SageMaker UDOP processornewSagemakerUdopProcessor(this,"Processor",newSagemakerUdopProcessorProps{Environment=environment,SummarizationInvokable=BedrockFoundationModel.ANTHROPIC_CLAUDE_3_5_SONNET_V2_0,Classifier=classifier});
Step 5: Deploy the Stack
Deploy the stack to your AWS account:
# Install dependencies
yarninstall
# Build the project
yarnbuild
# Deploy the stack
cdkdeploy
# Install dependencies
pipinstall-rrequirements.txt
# Deploy the stack
cdkdeploy
# Build the project
dotnetbuild
# Deploy the stack
cdkdeploy
The deployment will take several minutes. Once complete, the command will output the URL of the web application.
SageMaker Model Deployment
The deployment includes creating and deploying a SageMaker model, which can take 10-15 minutes. The stack will automatically handle downloading the pre-trained RVL-CDIP model and deploying it to SageMaker.
Step 6: Configure Bedrock Model Access
Ensure you have access to the required Bedrock models: