수집 중에 문서 보강 - Amazon Kendra

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

수집 중에 문서 보강

문서 수집 프로세스 중 콘텐츠 및 문서 메타데이터 필드 또는 속성을 변경할 수 있습니다. Amazon Kendra의 사용자 지정 문서 보강 기능을 사용하면 문서를 Amazon Kendra로 수집할 때 문서 속성 및 콘텐츠를 생성, 수정 또는 삭제할 수 있습니다. 즉, 필요에 따라 데이터를 조작하고 수집할 수 있습니다.

이 기능을 사용하면 문서가 처리되고 Amazon Kendra로 수집되는 방식을 제어할 수 있습니다. 예를 들어 문서를 Amazon Kendra로 수집하는 동안 문서 메타데이터에서 개인 식별 정보를 스크러빙할 수 있습니다.

이 기능을 사용할 수 있는 또 한 가지 방법은 AWS Lambda의 Lambda 함수를 호출하여 이미지의 광학 문자 인식(OCR), 텍스트 번역 및 기타 검색 또는 분석을 위한 데이터 준비 작업을 실행하는 것입니다. 예를 들어, 이미지에서 OCR을 실행하는 함수를 호출할 수 있습니다. 함수는 이미지의 텍스트를 해석하고 각 이미지를 텍스트 문서로 취급할 수 있습니다. 우편으로 고객 설문조사를 받아 설문조사를 이미지로 저장하는 회사는 이러한 이미지를 Amazon Kendra에 텍스트 문서로 수집할 수 있습니다. 그러면 회사는 Amazon Kendra에서 중요한 고객 설문조사 정보를 검색할 수 있습니다.

기본 작업을 사용하여 데이터의 첫 번째 구문 분석으로 적용한 다음, Lambda 함수를 사용하여 데이터에 더 복잡한 작업을 적용할 수 있습니다. 예를 들어, 기본 작업을 사용하여 문서 메타데이터 필드 'Customer_ID'에서 모든 값을 간단히 제거한 다음, Lambda 함수를 적용하여 문서의 텍스트 이미지에서 텍스트를 추출할 수 있습니다.

사용자 지정 문서 보강 작동 방식

사용자 지정 문서 보강의 전체 프로세스는 다음과 같습니다.

  1. 사용자 지정 문서 보강은 데이터 소스를 만들거나 업데이트할 때 구성하거나 문서를 Amazon Kendra로 직접 인덱싱합니다.

  2. Amazon Kendra는 인라인 구성 또는 기본 로직을 적용하여 데이터를 변경합니다. 자세한 내용은 메타데이터를 변경하는 기본 작업 섹션을 참조하세요.

  3. 고급 데이터 조작을 구성하기로 선택한 경우 Amazon Kendra가 원본, 원시 문서 또는 구조화되고 파싱된 문서에 이를 적용할 수 있습니다. 자세한 내용은 Lambda 함수: 메타데이터 또는 콘텐츠 추출 및 변경 섹션을 참조하세요.

  4. 변경된 문서는 Amazon Kendra에 수집됩니다.

구성이 유효하지 않으면 이 프로세스의 어느 시점에서든 Amazon Kendra에 오류가 발생합니다.

CreateDataSource, UpdateDataSource 또는 BatchPutDocument API를 호출하면 사용자 지정 문서 보강 구성을 제공합니다. BatchPutDocument를 호출하는 경우 각 요청마다 사용자 지정 문서 보강을 구성해야 합니다. 콘솔을 사용하는 경우 인덱스를 선택한 다음, 문서 보강을 선택하여 사용자 지정 문서 보강을 구성합니다.

콘솔에서 문서 보강을 사용하는 경우, API를 사용하는 것처럼 기본 작업만 구성하거나 Lambda 함수만 구성하거나 둘 다 구성하도록 선택할 수 있습니다. 콘솔 단계에서 다음을 선택하여 기본 작업을 구성하지 않고 Lambda 함수만 구성하도록 선택할 수 있습니다. 여기에는 원본 (추출 전) 데이터에 적용할지 아니면 구조화된 (추출 후) 데이터에 적용할지 여부가 포함됩니다. 콘솔에서 모든 단계를 완료해야만 구성을 저장할 수 있습니다. 모든 단계를 완료하지 않으면 문서 구성이 저장되지 않습니다.

메타데이터를 변경하는 기본 작업

기본 로직을 사용하여 문서 필드와 콘텐츠를 조작할 수 있습니다. 여기에는 필드의 값 제거, 조건을 사용한 필드 값 수정 또는 필드 생성이 포함됩니다. 기본 로직을 사용하여 조작할 수 있는 범위를 넘어서는 고급 조작의 경우 Lambda 함수를 호출합니다. 자세한 내용은 Lambda 함수: 메타데이터 또는 콘텐츠 추출 및 변경 섹션을 참조하세요.

기본 로직을 적용하려면 DocumentAttributeTarget 객체를 사용하여 조작하려는 대상 필드를 지정합니다. 속성 키를 제공합니다. 예를 들어, 'Department' 키는 문서와 연결된 모든 부서 이름을 포함한 필드 또는 속성입니다. 특정 조건이 충족되는 경우 대상 필드에 사용할 값을 지정할 수도 있습니다. 이 조건은 DocumentAttributeCondition 객체를 사용하여 설정합니다. 예를 들어 'Source_URI' 필드의 URI 값에 'financial'이 포함된 경우 대상 필드인 'Department'를 문서의 대상 값인 'Finance'로 미리 채웁니다. 대상 문서 속성 값도 삭제할 수 있습니다.

콘솔을 사용하여 기본 로직을 적용하려면 인덱스를 선택한 다음, 탐색 메뉴에서 문서 보강을 선택합니다. 기본 작업 구성으로 이동하여 문서 필드 및 콘텐츠에 기본 조작을 적용합니다.

다음은 기본 로직을 사용하여 'Customer_ID'라는 문서 필드의 모든 고객 식별 번호를 제거하는 예제입니다.

예 1: 문서와 관련된 고객 식별 번호 제거

기본 조작이 적용되기 전의 데이터.

Document_ID Body_Text Customer_ID
1 Lorem Ipsum. CID1234
2 Lorem Ipsum. CID1235
3 Lorem Ipsum. CID1236

기본 조작이 적용된 이후의 데이터.

Document_ID Body_Text Customer_ID
1 Lorem Ipsum.
2 Lorem Ipsum.
3 Lorem Ipsum.

다음은 기본 로직을 사용하여 'Department'라는 필드를 만들고 'Source_URI' 필드의 정보에 기반한 부서 이름을 이 필드에 미리 채우는 예제입니다. 이 경우는 'Source_URI' 필드의 URI 값에 'financial'이 포함된 경우 대상 필드인 'Department'를 문서의 대상 값인 'Finance'로 미리 채우는 조건을 사용합니다.

예 2: '부서' 필드를 만들고 조건을 사용하여 문서와 관련된 부서 이름으로 필드를 미리 채웁니다.

기본 조작이 적용되기 전의 데이터.

Document_ID Body_Text Source_URI
1 Lorem Ipsum. financial/1
2 Lorem Ipsum. financial/2
3 Lorem Ipsum. financial/3

기본 조작이 적용된 이후의 데이터.

Document_ID Body_Text Source_URI Department
1 Lorem Ipsum. financial/1 Finance
2 Lorem Ipsum. financial/2 Finance
3 Lorem Ipsum. financial/3 Finance
참고

Amazon Kendra는 아직 인덱스 필드로 생성되지 않은 대상 문서 필드를 생성할 수 없습니다. 인덱스 필드를 만든 후 DocumentAttributeTarget을 사용하여 문서 필드를 생성할 수 있습니다. 그러면 Amazon Kendra가 새로 만든 문서 메타데이터 필드를 인덱스 필드에 매핑합니다.

다음 코드는 문서와 관련된 고객 식별 번호를 제거하도록 기본 데이터 조작을 구성하는 예제입니다.

Console
고객 식별 번호를 제거하도록 기본 데이터 조작을 구성하려면
  1. 왼쪽 탐색 창의 인덱스에서 문서 보강을 선택한 다음, 문서 보강 추가를 선택합니다.

  2. 기본 작업 구성 페이지의 드롭다운에서 문서 필드 및 콘텐츠를 변경하려는 데이터 소스를 선택합니다. 그런 다음 드롭다운에서 문서 필드 이름 'Customer_ID'를 선택하고 드롭다운에서 인덱스 필드 이름 'Customer_ID'를 선택한 다음, 드롭다운에서 대상 작업 삭제를 선택합니다. 그런 다음 기본 작업 추가를 선택합니다.

CLI

고객 식별 번호를 제거하도록 기본 데이터 조작을 구성하려면

aws kendra create-data-source \ --name data-source-name \ --index-id index-id \ --role-arn arn:aws:iam::account-id:role/role-name \ --type S3 \ --configuration '{"S3Configuration":{"BucketName":"S3-bucket-name"}}' \ --custom-document-enrichment-configuration '{"InlineConfigurations":[{"Target":{"TargetDocumentAttributeKey":"Customer_ID", "TargetDocumentAttributeValueDeletion": true}}]}'
Python

고객 식별 번호를 제거하도록 기본 데이터 조작을 구성하려면

import boto3 from botocore.exceptions import ClientError import pprint import time kendra = boto3.client("kendra") print("Create a data source with customizations") # Provide the name of the data source name = "data-source-name" # Provide the index ID for the data source index_id = "index-id" # Provide the IAM role ARN required for data sources role_arn = "arn:aws:iam::${account-id}:role/${role-name}" # Provide the data source connection information data_source_type = "S3" S3_bucket_name = "S3-bucket-name" # Configure the data source with Custom Document Enrichment configuration = {"S3Configuration": { "BucketName": S3_bucket_name } } custom_document_enrichment_configuration = {"InlineConfigurations":[ { "Target":{"TargetDocumentAttributeKey":"Customer_ID", "TargetDocumentAttributeValueDeletion": True} }] } try: data_source_response = kendra.create_data_source( Name = name, IndexId = index_id, RoleArn = role_arn, Type = data_source_type Configuration = configuration CustomDocumentEnrichmentConfiguration = custom_document_enrichment_configuration ) pprint.pprint(data_source_response) data_source_id = data_source_response["Id"] print("Wait for Amazon Kendra to create the data source with your customizations.") while True: # Get the details of the data source, such as the status data_source_description = kendra.describe_data_source( Id = data_source_id, IndexId = index_id ) status = data_source_description["Status"] print(" Creating data source. Status: "+status) time.sleep(60) if status != "CREATING": break print("Synchronize the data source.") sync_response = kendra.start_data_source_sync_job( Id = data_source_id, IndexId = index_id ) pprint.pprint(sync_response) print("Wait for the data source to sync with the index.") while True: jobs = kendra.list_data_source_sync_jobs( Id= data_source_id, IndexId= index_id ) # For this example, there should be one job status = jobs["History"][0]["Status"] print(" Syncing data source. Status: "+status) time.sleep(60) if status != "SYNCING": break except ClientError as e: print("%s" % e) print("Program ends.")
Java

고객 식별 번호를 제거하도록 기본 데이터 조작을 구성하려면

package com.amazonaws.kendra; import java.util.concurrent.TimeUnit; import software.amazon.awssdk.services.kendra.KendraClient; import software.amazon.awssdk.services.kendra.model.CreateDataSourceRequest; import software.amazon.awssdk.services.kendra.model.CreateDataSourceResponse; import software.amazon.awssdk.services.kendra.model.CreateIndexRequest; import software.amazon.awssdk.services.kendra.model.CreateIndexResponse; import software.amazon.awssdk.services.kendra.model.DataSourceConfiguration; import software.amazon.awssdk.services.kendra.model.DataSourceStatus; import software.amazon.awssdk.services.kendra.model.DataSourceSyncJob; import software.amazon.awssdk.services.kendra.model.DataSourceSyncJobStatus; import software.amazon.awssdk.services.kendra.model.DataSourceType; import software.amazon.awssdk.services.kendra.model.DescribeDataSourceRequest; import software.amazon.awssdk.services.kendra.model.DescribeDataSourceResponse; import software.amazon.awssdk.services.kendra.model.DescribeIndexRequest; import software.amazon.awssdk.services.kendra.model.DescribeIndexResponse; import software.amazon.awssdk.services.kendra.model.IndexStatus; import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsRequest; import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsResponse; import software.amazon.awssdk.services.kendra.model.S3DataSourceConfiguration; import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobRequest; import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobResponse; public class CreateDataSourceWithCustomizationsExample { public static void main(String[] args) throws InterruptedException { System.out.println("Create a data source with customizations"); String dataSourceName = "data-source-name"; String indexId = "index-id"; String dataSourceRoleArn = "arn:aws:iam::account-id:role/role-name"; String s3BucketName = "S3-bucket-name" KendraClient kendra = KendraClient.builder().build(); CreateDataSourceRequest createDataSourceRequest = CreateDataSourceRequest .builder() .name(dataSourceName) .description(experienceDescription) .roleArn(experienceRoleArn) .type(DataSourceType.S3) .configuration( DataSourceConfiguration .builder() .s3Configuration( S3DataSourceConfiguration .builder() .bucketName(s3BucketName) .build() ).build() ) .customDocumentEnrichmentConfiguration( CustomDocumentEnrichmentConfiguration .builder() .inlineConfigurations(Arrays.asList( InlineCustomDocumentEnrichmentConfiguration .builder() .target( DocumentAttributeTarget .builder() .targetDocumentAttributeKey("Customer_ID") .targetDocumentAttributeValueDeletion(true) .build()) .build() )).build(); CreateDataSourceResponse createDataSourceResponse = kendra.createDataSource(createDataSourceRequest); System.out.println(String.format("Response of creating data source: %s", createDataSourceResponse)); String dataSourceId = createDataSourceResponse.id(); System.out.println(String.format("Waiting for Kendra to create the data source %s", dataSourceId)); DescribeDataSourceRequest describeDataSourceRequest = DescribeDataSourceRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); while (true) { DescribeDataSourceResponse describeDataSourceResponse = kendra.describeDataSource(describeDataSourceRequest); DataSourceStatus status = describeDataSourceResponse.status(); System.out.println(String.format("Creating data source. Status: %s", status)); TimeUnit.SECONDS.sleep(60); if (status != DataSourceStatus.CREATING) { break; } } System.out.println(String.format("Synchronize the data source %s", dataSourceId)); StartDataSourceSyncJobRequest startDataSourceSyncJobRequest = StartDataSourceSyncJobRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); StartDataSourceSyncJobResponse startDataSourceSyncJobResponse = kendra.startDataSourceSyncJob(startDataSourceSyncJobRequest); System.out.println(String.format("Waiting for the data source to sync with the index %s for execution ID %s", indexId, startDataSourceSyncJobResponse.executionId())); // For this example, there should be one job ListDataSourceSyncJobsRequest listDataSourceSyncJobsRequest = ListDataSourceSyncJobsRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); while (true) { ListDataSourceSyncJobsResponse listDataSourceSyncJobsResponse = kendra.listDataSourceSyncJobs(listDataSourceSyncJobsRequest); DataSourceSyncJob job = listDataSourceSyncJobsResponse.history().get(0); System.out.println(String.format("Syncing data source. Status: %s", job.status())); TimeUnit.SECONDS.sleep(60); if (job.status() != DataSourceSyncJobStatus.SYNCING) { break; } } System.out.println("Data source creation with customizations is complete"); } }

Lambda 함수: 메타데이터 또는 콘텐츠 추출 및 변경

Lambda 함수를 사용하여 문서 필드와 콘텐츠를 조작할 수 있습니다. 기본 로직을 넘어 고급 데이터 조작을 적용하려는 경우에 유용합니다. 이미지에서 텍스트를 해석하고 각 이미지를 텍스트 문서로 처리하는 광학 문자 인식(OCR) 사용을 예로 들 수 있습니다. 또는 특정 시간대의 현재 날짜-시간을 검색하고 날짜 필드에 빈 값이 있을 경우 날짜-시간을 삽입하는 경우에도 해당합니다.

기본 로직을 먼저 적용한 다음 Lambda 함수를 사용하여 데이터를 추가로 조작하거나 그 반대로 적용할 수 있습니다. Lambda 함수만 적용하도록 선택할 수도 있습니다.

Amazon Kendra는 Lambda 함수를 호출하여 수집 프로세스 중에 CustomDocumentEnrichmentConfiguration의 일부로 고급 데이터 조작을 적용할 수 있습니다. Lambda 함수를 실행하고 Amazon S3 버킷에 액세스하여 데이터 조작의 출력을 저장할 권한이 포함된 역할을 지정합니다. IAM 액세스 역할을 참조하세요.

Amazon Kendra는 원본, 원시 문서 또는 구문 분석된 정형 문서에 Lambda 함수를 적용할 수 있습니다. 원본 또는 원시 데이터를 가져와 PreExtractionHookConfiguration을 사용하여 데이터 조작을 적용하는 Lambda 함수를 구성할 수 있습니다. 또한 PostExtractionHookConfiguration을 사용하여 구조화된 문서를 가져와 데이터 조작을 적용하는 Lambda 함수를 구성할 수 있습니다. Amazon Kendra는 문서 메타데이터와 텍스트를 추출하여 문서를 구조화합니다. Lambda 함수는 필수 요청 및 응답 구조를 따라야 합니다. 자세한 내용은 Lambda 함수에 대한 데이터 계약 섹션을 참조하세요.

콘솔에서 Lambda 함수를 구성하려면 인덱스를 선택한 다음 탐색 메뉴에서 문서 보강을 선택합니다. Lambda 함수 구성으로 이동하여 Lambda 함수를 구성합니다.

PreExtractionHookConfigurationPostExtractionHookConfiguration에 대해 각각 Lambda 함수를 하나씩만 구성할 수 있습니다. 그러나 Lambda 함수는 필요한 다른 함수를 호출할 수 있습니다. PreExtractionHookConfigurationPostExtractionHookConfiguration 또는 둘 중 하나를 구성할 수 있습니다. PreExtractionHookConfiguration의 Lambda 함수는 실행 시간 5분을 초과할 수 없고 PostExtractionHookConfiguration의 Lambda 함수는 실행 시간 1분을 초과할 수 없습니다. 사용자 지정 문서 보강을 구성하면 당연히 구성하지 않은 경우보다 Amazon Kendra에 문서를 수집하는 시간이 더 오래 걸립니다.

조건이 충족되는 경우에만 Lambda 함수를 호출하도록 Amazon Kendra를 구성할 수 있습니다. 예를 들어, 빈 날짜/시간 값이 있는 경우 Amazon Kendra가 현재 날짜/시간을 삽입하는 함수를 호출해야 한다는 조건을 지정할 수 있습니다.

다음은 Lambda 함수를 사용하여 이미지의 텍스트를 해석하는 OCR을 실행하고 이 텍스트를 'Document_Image_Text'라는 필드에 저장하는 예제입니다.

예 1: 이미지에서 텍스트를 추출하여 텍스트 문서 생성

고급 조작이 적용되기 전의 데이터.

Document_ID Document_Image
1 image_1.png
2 image_2.png
3 image_3.png

고급 조작이 적용된 이후의 데이터.

Document_ID Document_Image Document_Image_Text
1 image_1.png 우편으로 보낸 설문조사 응답
2 image_2.png 우편으로 보낸 설문조사 응답
3 image_3.png 우편으로 보낸 설문조사 응답

다음은 Lambda 함수를 사용하여 빈 날짜 값에 현재 날짜-시간을 삽입하는 예제입니다. 날짜 필드 값이 'null'인 경우 이를 현재 날짜-시간으로 대체한다는 조건을 사용합니다.

예 2: Last_Update 필드의 빈 값을 현재 날짜-시간으로 교체.

고급 조작이 적용되기 전의 데이터.

Document_ID Body_Text Last_Updated
1 Lorem Ipsum. 2020년 1월 1일
2 Lorem Ipsum.
3 Lorem Ipsum. 2020년 7월 1일

고급 조작이 적용된 이후의 데이터.

Document_ID Body_Text Last_Updated
1 Lorem Ipsum. 2020년 1월 1일
2 Lorem Ipsum. 2021년 12월 1일
3 Lorem Ipsum. 2020년 7월 1일

다음 코드는 원시, 원본 데이터에 대한 고급 데이터 조작을 위해 Lambda 함수를 구성하는 예제입니다.

Console
원시, 원본 데이터에 대한 고급 데이터 조작을 위해 Lambda 함수를 구성하려면
  1. 왼쪽 탐색 창의 인덱스에서 문서 보강을 선택한 다음, 문서 보강 추가를 선택합니다.

  2. Lambda 함수 구성 페이지의 사전 추출용 Lambda 섹션에서 드롭다운의 Lambda 함수 ARN 및 Amazon S3 버킷을 선택합니다. 드롭다운에서 새 역할을 생성하는 옵션을 선택하여 IAM 액세스 역할을 추가합니다. 이렇게 하면 문서 보강을 만드는 데 필요한 Amazon Kendra 권한이 생성됩니다.

CLI

원시, 원본 데이터에 대한 고급 데이터 조작을 위해 Lambda 함수를 구성하려면

aws kendra create-data-source \ --name data-source-name \ --index-id index-id \ --role-arn arn:aws:iam::account-id:role/role-name \ --type S3 \ --configuration '{"S3Configuration":{"BucketName":"S3-bucket-name"}}' \ --custom-document-enrichment-configuration '{"PreExtractionHookConfiguration":{"LambdaArn":"arn:aws:iam::account-id:function/function-name", "S3Bucket":"S3-bucket-name"}, "RoleArn": "arn:aws:iam:account-id:role/cde-role-name"}'
Python

원시, 원본 데이터에 대한 고급 데이터 조작을 위해 Lambda 함수를 구성하려면

import boto3 from botocore.exceptions import ClientError import pprint import time kendra = boto3.client("kendra") print("Create a data source with customizations.") # Provide the name of the data source name = "data-source-name" # Provide the index ID for the data source index_id = "index-id" # Provide the IAM role ARN required for data sources role_arn = "arn:aws:iam::${account-id}:role/${role-name}" # Provide the data source connection information data_source_type = "S3" S3_bucket_name = "S3-bucket-name" # Configure the data source with Custom Document Enrichment configuration = {"S3Configuration": { "BucketName": S3_bucket_name } } custom_document_enrichment_configuration = {"PreExtractionHookConfiguration": { "LambdaArn":"arn:aws:iam::account-id:function/function-name", "S3Bucket":"S3-bucket-name" } "RoleArn":"arn:aws:iam::account-id:role/cde-role-name" } try: data_source_response = kendra.create_data_source( Name = name, IndexId = index_id, RoleArn = role_arn, Type = data_source_type Configuration = configuration CustomDocumentEnrichmentConfiguration = custom_document_enrichment_configuration ) pprint.pprint(data_source_response) data_source_id = data_source_response["Id"] print("Wait for Amazon Kendra to create the data source with your customizations.") while True: # Get the details of the data source, such as the status data_source_description = kendra.describe_data_source( Id = data_source_id, IndexId = index_id ) status = data_source_description["Status"] print(" Creating data source. Status: "+status) time.sleep(60) if status != "CREATING": break print("Synchronize the data source.") sync_response = kendra.start_data_source_sync_job( Id = data_source_id, IndexId = index_id ) pprint.pprint(sync_response) print("Wait for the data source to sync with the index.") while True: jobs = kendra.list_data_source_sync_jobs( Id = data_source_id, IndexId = index_id ) # For this example, there should be one job status = jobs["History"][0]["Status"] print(" Syncing data source. Status: "+status) time.sleep(60) if status != "SYNCING": break except ClientError as e: print("%s" % e) print("Program ends.")
Java

원시, 원본 데이터에 대한 고급 데이터 조작을 위해 Lambda 함수를 구성하려면

package com.amazonaws.kendra; import java.util.concurrent.TimeUnit; import software.amazon.awssdk.services.kendra.KendraClient; import software.amazon.awssdk.services.kendra.model.CreateDataSourceRequest; import software.amazon.awssdk.services.kendra.model.CreateDataSourceResponse; import software.amazon.awssdk.services.kendra.model.CreateIndexRequest; import software.amazon.awssdk.services.kendra.model.CreateIndexResponse; import software.amazon.awssdk.services.kendra.model.DataSourceConfiguration; import software.amazon.awssdk.services.kendra.model.DataSourceStatus; import software.amazon.awssdk.services.kendra.model.DataSourceSyncJob; import software.amazon.awssdk.services.kendra.model.DataSourceSyncJobStatus; import software.amazon.awssdk.services.kendra.model.DataSourceType; import software.amazon.awssdk.services.kendra.model.DescribeDataSourceRequest; import software.amazon.awssdk.services.kendra.model.DescribeDataSourceResponse; import software.amazon.awssdk.services.kendra.model.DescribeIndexRequest; import software.amazon.awssdk.services.kendra.model.DescribeIndexResponse; import software.amazon.awssdk.services.kendra.model.IndexStatus; import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsRequest; import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsResponse; import software.amazon.awssdk.services.kendra.model.S3DataSourceConfiguration; import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobRequest; import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobResponse; public class CreateDataSourceWithCustomizationsExample { public static void main(String[] args) throws InterruptedException { System.out.println("Create a data source with customizations"); String dataSourceName = "data-source-name"; String indexId = "index-id"; String dataSourceRoleArn = "arn:aws:iam::account-id:role/role-name"; String s3BucketName = "S3-bucket-name" KendraClient kendra = KendraClient.builder().build(); CreateDataSourceRequest createDataSourceRequest = CreateDataSourceRequest .builder() .name(dataSourceName) .description(experienceDescription) .roleArn(experienceRoleArn) .type(DataSourceType.S3) .configuration( DataSourceConfiguration .builder() .s3Configuration( S3DataSourceConfiguration .builder() .bucketName(s3BucketName) .build() ).build() ) .customDocumentEnrichmentConfiguration( CustomDocumentEnrichmentConfiguration .builder() .preExtractionHookConfiguration( HookConfiguration .builder() .lambdaArn("arn:aws:iam::account-id:function/function-name") .s3Bucket("S3-bucket-name") .build()) .roleArn("arn:aws:iam::account-id:role/cde-role-name") .build(); CreateDataSourceResponse createDataSourceResponse = kendra.createDataSource(createDataSourceRequest); System.out.println(String.format("Response of creating data source: %s", createDataSourceResponse)); String dataSourceId = createDataSourceResponse.id(); System.out.println(String.format("Waiting for Kendra to create the data source %s", dataSourceId)); DescribeDataSourceRequest describeDataSourceRequest = DescribeDataSourceRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); while (true) { DescribeDataSourceResponse describeDataSourceResponse = kendra.describeDataSource(describeDataSourceRequest); DataSourceStatus status = describeDataSourceResponse.status(); System.out.println(String.format("Creating data source. Status: %s", status)); TimeUnit.SECONDS.sleep(60); if (status != DataSourceStatus.CREATING) { break; } } System.out.println(String.format("Synchronize the data source %s", dataSourceId)); StartDataSourceSyncJobRequest startDataSourceSyncJobRequest = StartDataSourceSyncJobRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); StartDataSourceSyncJobResponse startDataSourceSyncJobResponse = kendra.startDataSourceSyncJob(startDataSourceSyncJobRequest); System.out.println(String.format("Waiting for the data source to sync with the index %s for execution ID %s", indexId, startDataSourceSyncJobResponse.executionId())); // For this example, there should be one job ListDataSourceSyncJobsRequest listDataSourceSyncJobsRequest = ListDataSourceSyncJobsRequest .builder() .indexId(indexId) .id(dataSourceId) .build(); while (true) { ListDataSourceSyncJobsResponse listDataSourceSyncJobsResponse = kendra.listDataSourceSyncJobs(listDataSourceSyncJobsRequest); DataSourceSyncJob job = listDataSourceSyncJobsResponse.history().get(0); System.out.println(String.format("Syncing data source. Status: %s", job.status())); TimeUnit.SECONDS.sleep(60); if (job.status() != DataSourceSyncJobStatus.SYNCING) { break; } } System.out.println("Data source creation with customizations is complete"); } }

Lambda 함수에 대한 데이터 계약

고급 데이터 조작을 위한 Lambda 함수는 Amazon Kendra 데이터 계약과 상호 작용합니다. 이 계약은 Lambda 함수의 필수 요청 및 응답 구조입니다. Lambda 함수가 이러한 구조를 따르지 않으면 Amazon Kendra에 오류가 발생합니다.

PreExtractionHookConfiguration의 Lambda 함수는 다음과 같은 요청 구조를 예상해야 합니다.

{ "version": <str>, "dataBlobStringEncodedInBase64": <str>, //In the case of a data blob "s3Bucket": <str>, //In the case of an S3 bucket "s3ObjectKey": <str>, //In the case of an S3 bucket "metadata": <Metadata> }

CustomDocumentAttribute 구조를 포함하는 metadata 구조는 다음과 같습니다.

{ "attributes": [<CustomDocumentAttribute<] } CustomDocumentAttribute { "name": <str>, "value": <CustomDocumentAttributeValue> } CustomDocumentAttributeValue { "stringValue": <str>, "integerValue": <int>, "longValue": <long>, "stringListValue": list<str>, "dateValue": <str> }

PreExtractionHookConfiguration에 대한 Lambda 함수는 다음 응답 구조를 준수해야 합니다.

{ "version": <str>, "dataBlobStringEncodedInBase64": <str>, //In the case of a data blob "s3ObjectKey": <str>, //In the case of an S3 bucket "metadataUpdates": [<CustomDocumentAttribute>] }

PostExtractionHookConfiguration의 Lambda 함수는 다음과 같은 요청 구조를 예상해야 합니다.

{ "version": <str>, "s3Bucket": <str>, "s3ObjectKey": <str>, "metadata": <Metadata> }

PostExtractionHookConfiguration에 대한 Lambda 함수는 다음 응답 구조를 준수해야 합니다.

PostExtractionHookConfiguration Lambda Response { "version": <str>, "s3ObjectKey": <str>, "metadataUpdates": [<CustomDocumentAttribute>] }

변경된 문서가 Amazon S3버킷에 업로드됩니다. 변경된 문서는 구조화된 문서 형식에 표시된 형식을 따라야 합니다.

구조화된 문서 형식

Amazon Kendra는 구조화된 문서를 지정된 Amazon S3 버킷에 업로드합니다. 구조화된 문서는 다음 형식을 따릅니다.

Kendra document { "textContent": <TextContent> } TextContent { "documentBodyText": <str> }

데이터 계약을 준수하는 Lambda 함수의 예

다음 Python 코드는 원시 또는 원본 문서의 본문 콘텐츠와 메타데이터 필드 _authors, _document_title의 고급 조작을 적용하는 Lambda 함수의 예입니다.

본문 콘텐츠가 Amazon S3 버킷에 있는 경우

import json import boto3 s3 = boto3.client("s3") # Lambda function for advanced data manipulation def lambda_handler(event, context): # Get the value of "S3Bucket" key name or item from the given event input s3_bucket = event.get("s3Bucket") # Get the value of "S3ObjectKey" key name or item from the given event input s3_object_key = event.get("s3ObjectKey") content_object_before_CDE = s3.get_object(Bucket = s3_bucket, Key = s3_object_key) content_before_CDE = content_object_before_CDE["Body"].read().decode("utf-8"); content_after_CDE = "CDEInvolved " + content_before_CDE # Get the value of "metadata" key name or item from the given event input metadata = event.get("metadata") # Get the document "attributes" from the metadata document_attributes = metadata.get("attributes") s3.put_object(Bucket = s3_bucket, Key = "dummy_updated_kendra_document", Body=json.dumps(content_after_CDE)) return { "version": "v0", "s3ObjectKey": "dummy_updated_kendra_document", "metadataUpdates": [ {"name":"_document_title", "value":{"stringValue":"title_from_pre_extraction_lambda"}}, {"name":"_authors", "value":{"stringListValue":["author1", "author2"]}} ] }

본문 콘텐츠가 데이터 블롭에 있는 경우

import json import boto3 import base64 # Lambda function for advanced data manipulation def lambda_handler(event, context): # Get the value of "dataBlobStringEncodedInBase64" key name or item from the given event input data_blob_string_encoded_in_base64 = event.get("dataBlobStringEncodedInBase64") # Decode the data blob string in UTF-8 data_blob_string = base64.b64decode(data_blob_string_encoded_in_base64).decode("utf-8") # Get the value of "metadata" key name or item from the given event input metadata = event.get("metadata") # Get the document "attributes" from the metadata document_attributes = metadata.get("attributes") new_data_blob = "This should be the modified data in the document by pre processing lambda ".encode("utf-8") return { "version": "v0", "dataBlobStringEncodedInBase64": base64.b64encode(new_data_blob).decode("utf-8"), "metadataUpdates": [ {"name":"_document_title", "value":{"stringValue":"title_from_pre_extraction_lambda"}}, {"name":"_authors", "value":{"stringListValue":["author1", "author2"]}} ] }

다음 Python 코드는 구조화되었거나 구문 분석된 문서의 본문 콘텐츠와 메타데이터 필드 _authors, _document_title의 고급 조작을 적용하는 Lambda 함수의 예입니다.

import json import boto3 import time s3 = boto3.client("s3") # Lambda function for advanced data manipulation def lambda_handler(event, context): # Get the value of "S3Bucket" key name or item from the given event input s3_bucket = event.get("s3Bucket") # Get the value of "S3ObjectKey" key name or item from the given event input s3_key = event.get("s3ObjectKey") # Get the value of "metadata" key name or item from the given event input metadata = event.get("metadata") # Get the document "attributes" from the metadata document_attributes = metadata.get("attributes") kendra_document_object = s3.get_object(Bucket = s3_bucket, Key = s3_key) kendra_document_string = kendra_document_object['Body'].read().decode('utf-8') kendra_document = json.loads(kendra_document_string) kendra_document["textContent"]["documentBodyText"] = "Changing document body to a short sentence." s3.put_object(Bucket = s3_bucket, Key = "dummy_updated_kendra_document", Body=json.dumps(kendra_document)) return { "version" : "v0", "s3ObjectKey": "dummy_updated_kendra_document", "metadataUpdates": [ {"name": "_document_title", "value":{"stringValue": "title_from_post_extraction_lambda"}}, {"name": "_authors", "value":{"stringListValue":["author1", "author2"]}} ] }