AWS 기술 블로그

Amazon Bedrock Knowledge Bases로 멀티테넌트 RAG 구성하기

이 글은 AWS Machine Learning 블로그에 게시된 글 (Multi-tenant RAG with Amazon Bedrock Knowledge Bases)를 한국어로 번역 및 편집하였습니다.

조직들은 지속적으로 자사의 독점적 지식과 도메인 전문성을 활용하여 경쟁 우위를 확보하는 방법을 모색하고 있습니다. 기초 모델(Foundation Model, FM)과 그들의 놀라운 자연어 처리 능력의 출현으로, 데이터 자산의 가치를 실현할 수 있는 새로운 기회가 생겼습니다.

조직들이 생성형 AI를 사용하여 고객에게 개인화된 경험을 제공하고자 노력함에 따라, 자사와 고객의 데이터를 사용하여 FM의 동작을 특화하는 것이 더욱 중요해졌습니다. Retrieval Augmented Generation(RAG)은 원하는 수준의 특화를 달성하기 위한 간단하면서도 효과적인 접근 방식으로 등장했습니다.

Amazon Bedrock Knowledge Bases는 전체 RAG 워크플로우의 관리를 단순화하는 완전 관리형 기능으로, 조직이 FM과 에이전트에게 회사의 비공개 데이터 소스에서 상황에 맞는 정보를 제공하여 특정 요구에 맞춘 더 관련성 있고 정확한 응답을 제공할 수 있도록 지원합니다.

독립 소프트웨어 벤더(ISV)가 SaaS 제품을 만드는 것과 같이 멀티테넌트 제품을 개발하는 조직의 경우, 각 고객(SaaS 애플리케이션의 테넌트)에 대한 경험을 개인화할 수 있는 능력이 특히 중요합니다. 이러한 개인화는 테넌트별 데이터를 선택적으로 사용하는 RAG 접근 방식을 구현함으로써 달성할 수 있습니다.

이 포스트에서는 Amazon Bedrock Knowledge Bases를 사용하여 개인화를 달성하는 방법을 예시와 함께 알아봅니다. 특히 ISV가 직면하는 데이터 격리, 보안, 테넌트 관리, 비용 관리 등 멀티테넌시 과제를 해결하는 데 중점을 둡니다. 여기서는 RAG 아키텍처가 ISV 애플리케이션에 통합되고, 테넌트에게 직접 노출되지 않는 시나리오에 초점을 맞춥니다. 이 포스트에서 제시된 구체적인 구현 방법은 테넌트의 데이터를 저장하기 위해 Amazon OpenSearch Service를 벡터 데이터베이스로 사용하지만, 글에서 제안한 과제와 아키텍처는 다른 벡터 저장소 구현으로 확장하고 맞춤화 될 수 있습니다.

멀티테넌시 설계 고려 사항

멀티테넌트 RAG 시스템을 설계할 때 다음과 같은 사항을 고려해야 합니다:

  • 테넌트 격리 – 멀티테넌트 시스템을 설계할 때 중요한 고려사항 중 하나는 각 테넌트와 관련된 데이터 및 리소스 간의 격리 수준입니다. 이러한 리소스에는 데이터 소스, 수집 파이프라인, 벡터 데이터베이스 및 RAG 클라이언트 애플리케이션이 포함됩니다. 격리 수준은 일반적으로 규제 요구사항과 함께 솔루션의 보안, 성능 및 확장성 요구사항에 의해 결정됩니다. 예를 들어, 각 테넌트와 관련된 데이터를 서로 다른 암호화 키를 사용하여 암호화해야 할 수 있습니다. 또한 한 테넌트에서 생성된 높은 활동이 다른 테넌트에 영향을 미치지 않도록 해야 할 수도 있습니다.
  • 테넌트 가변성 – 유사하지만 구별되는 고려사항은 각 테넌트에게 제공되는 기능의 가변성 수준입니다. RAG 시스템의 맥락에서 테넌트는 데이터 수집 빈도, 문서 청킹 전략 또는 벡터 검색 구성에 대해 다양한 요구사항을 가질 수 있습니다.
  • 테넌트 관리 단순성 – 멀티테넌트 솔루션은 테넌트를 온보딩하고 오프보딩하는 메커니즘이 필요합니다. 이 차원은 데이터 소스, 수집 파이프라인, 벡터 데이터베이스 및 RAG 클라이언트 애플리케이션과 같은 테넌트별 인프라를 프로비저닝하거나 해체하는 과정을 포함할 수 있는 이 프로세스의 복잡성 정도를 결정합니다. 이 프로세스에는 데이터 소스에서 테넌트별 데이터를 추가하거나 삭제하는 작업도 포함될 수 있습니다.
  • 비용 효율성 – 멀티테넌트 솔루션의 운영 비용은 테넌트에 대한 격리 메커니즘을 제공하는 방식에 따라 달라지므로 솔루션을 위한 비용 효율적인 아키텍처를 설계하는 것이 중요합니다.

이 네 가지 고려사항은 특정 솔루션의 요구사항에 맞게 신중하게 균형을 잡고 가중치를 두어야 합니다. 이 포스트에서는 의사 결정 과정을 단순화하기 위한 모델을 제시합니다. SaaS 테넌트 격리 전략 백서에 정의된 사일로, 풀, 브리지의 핵심 격리 개념을 사용하여 Amazon Bedrock Knowledge Bases, Amazon Simple Storage Service(Amazon S3) 및 OpenSearch Service를 사용하여 멀티테넌트 RAG 솔루션을 구현하기 위한 세 가지 패턴을 제안합니다.

Amazon Bedrock Knowledge Bases를 사용하는 일반적인 RAG 솔루션은 다음과 같이 여러 구성 요소로 이루어져 있습니다:

이 아키텍처를 멀티테넌시에 맞게 적용하는 주요 과제는 각 구성 요소에 대해 테넌트 간 격리를 어떻게 제공할 것인지 결정하는 것입니다. 우리는 다양한 사용 사례에 대응하고 격리, 가변성, 관리 단순성 및 비용 효율성의 다양한 수준을 제공하는 세 가지 규범적 패턴을 제안합니다. 다음 그림은 테넌트 격리, 가변성, 비용 효율성 및 테넌트 관리 용이성 측면에서 이 세 가지 아키텍처 패턴 간의 상충 관계를 보여줍니다.

멀티테넌시 패턴

이 섹션에서는 Amazon Bedrock Knowledge Bases를 기반으로 한 RAG 아키텍처에서 세 가지의 다른 멀티테넌시 패턴의 구현에 대해 설명하고, 그 사용 사례와 장단점에 대해 논의합니다.

사일로(Silo)

다음 그림에 나타난 사일로 패턴은 전체 스택이 각 단일 테넌트에 대해 독립적으로 배포되고 관리되기 때문에 가장 높은 수준의 테넌트 격리를 제공합니다.

Amazon Bedrock Knowledge Bases로 구현된 RAG 아키텍처의 맥락에서 사일로 패턴은 다음을 규정합니다:

  • 테넌트별 별도 데이터 소스 – 이 포스트에서는 벡터화될 테넌트 문서가 Amazon S3에 저장되는 시나리오를 고려하므로 테넌트별로 별도의 S3 버킷이 프로비저닝됩니다. 이를 통해 테넌트별 AWS Key Management Service(AWS KMS) 암호화 키와 객체 만료를 관리하기 위한 테넌트별 S3 수명 주기 정책, 그리고 객체의 여러 버전을 유지하기 위한 객체 버전 관리 정책을 사용할 수 있습니다. 테넌트별로 별도의 버킷을 가지면 격리를 제공하고 테넌트 요구사항에 따라 맞춤형 구성이 가능합니다.
  • 테넌트별 별도 knowledge base – 이 구조를 통해 테넌트별로 별도의 청킹 전략을 사용할 수 있으며, 테넌트의 문서가 본질적으로 다를 것으로 예상되는 경우 특히 유용합니다. 예를 들어, 한 테넌트는 고정 크기 청킹으로 처리할 수 있는 평문 문서로 구성된 문서 기반을 가질 수 있고, 다른 테넌트는 의미론적 청킹이 더 적합한 명시적 섹션이 있는 문서 기반을 가질 수 있습니다. 테넌트별로 다른 knowledge base를 가지면 다른 임베딩 모델을 선택할 수 있어 정확성, 비용, 지연 시간의 균형을 맞추면서 다른 벡터 차원을 선택할 수 있습니다. Amazon Bedrock이 엔드투엔드 테넌트별 암호화에 사용하는 일시적 데이터 저장소에 대해 테넌트별로 다른 KMS 키를 선택할 수 있습니다. 또한 knowledge base가 삭제될 때 벡터 데이터베이스에서 벡터를 삭제할지 여부를 제어하기 위해 테넌트별 데이터 삭제 정책을 선택할 수 있습니다. 개별 knowledge base를 사용하면 테넌트별로 다른 데이터 수집 일정을 가질 수 있어 고객과 다른 데이터 최신성 기준을 합의할 수 있습니다.
  • 테넌트별 별도 OpenSearch Serverless 컬렉션 – 테넌트별로 별도의 OpenSearch Serverless 컬렉션을 가지면 테넌트별로 별도의 KMS 암호화 키를 가질 수 있어 테넌트별 엔드투엔드 암호화를 유지할 수 있습니다. 테넌트별 컬렉션마다 별도의 벡터 인덱스를 생성할 수 있으므로 각 테넌트에 대해 유클리드 거리와 내적 둘 중 거리 메트릭을 하나 선택하여 문서 길이에 얼마나 중요성을 부여할지 결정할 수 있습니다. 또한 테넌트별로 HNSW 알고리즘의 특정 설정을 선택하여 메모리 소비, 비용 및 인덱싱 시간을 제어할 수 있습니다. 각 벡터 인덱스는 knowledge base의 메타데이터 매핑 설정과 함께 테넌트별로 다른 메타데이터 세트를 가질 수 있으며, 이는 필터링된 검색을 수행하는 데 사용할 수 있습니다. 메타데이터 필터링은 사일로 패턴에서 특정 특징을 가진 문서의 하위 집합으로 검색을 제한하는 데 사용할 수 있습니다. 예를 들어, 한 테넌트는 날짜가 있는 문서를 업로드하고 특정 연도에 관한 문서를 필터링하기를 원할 수 있고, 다른 테넌트는 다른 회사 부서에서 오는 문서를 업로드하고 특정 회사 부서의 문서를 필터링하기를 원할 수 있습니다.

사일로 패턴은 테넌트 아키텍처 독립성을 제공하므로 테넌트를 온보딩하고 오프보딩하는 것은 해당 테넌트의 S3 버킷, knowledge base 및 OpenSearch Serverless 컬렉션으로 구성된 RAG 스택을 생성하고 파괴하는 것을 의미합니다. 일반적으로 IaC(Infrastructure as Code)를 사용하여 이를 수행합니다. 애플리케이션 아키텍처에 따라 각 테넌트에 대한 로그 싱크 및 모니터링 시스템을 업데이트해야 할 수도 있습니다.

사일로 패턴은 가장 높은 수준의 테넌트 격리를 제공하지만, 테넌트별로 별도의 OpenSearch Serverless 컬렉션을 생성하기 때문에 구현하는 데 가장 비용이 많이 듭니다. 자세한 이유는 다음과 같습니다:

  • 최소 용량 요금 – 별도의 KMS 키로 암호화된 각 OpenSearch Serverless 컬렉션에는 시간당 최소 2개의 OpenSearch Compute Units(OCU)가 청구됩니다. (참고) 이러한 OCU는 사용량과 독립적으로 청구되므로 테넌트별로 별도의 KMS 암호화 키를 선택하면 비활성 테넌트에 대해 요금이 발생합니다.
  • 확장성 오버헤드 – 각 컬렉션은 사용량에 따라 6GB의 메모리 단위로 OCU를 별도로 확장하며, 관련 vCPU 및 빠른 액세스 스토리지도 함께 확장됩니다. 이는 테넌트 전체에서 리소스가 완전히 최적으로 활용되지 않을 수 있음을 의미합니다.

사일로 패턴을 선택할 때 각 AWS 계정에서 최대 100개의 knowledge base가 지원된다는 점에 유의하셔야 합니다. 이는 사일로 패턴이 특정 격리 요구사항이 있는 가장 큰 테넌트에게 적합하다 것을 의미합니다. 테넌트별로 별도의 knowledge base를 가지면 동시에 일어나는 데이터 수집 작업(KB당 최대 1개의 동시 작업, 계정당 5개), 작업 크기(작업당 100GB) 및 데이터 소스(데이터 소스당 최대 500만 개의 문서)에 대한 할당량의 영향도 줄어듭니다. 또한 각 테넌트가 다른 테넌트의 활동에 영향을 받지 않기 때문에 각 테넌트가 체감하는 성능이 일관되게 유지됩니다.

테넌트를 오프보딩하는 동안 knowledge base를 삭제하는 것은 데이터 소스의 크기와 동기화 프로세스에 따라 시간이 많이 걸릴 수 있습니다. 이를 완화하기 위해 테넌트의 knowledge base에서 데이터 삭제 정책을 RETAIN 으로 설정할 수 있습니다. 이렇게 하면 knowledge base 삭제 프로세스가 OpenSearch Service 인덱스에서 테넌트의 데이터를 삭제하지 않습니다. 이 경우 OpenSearch Serverless 컬렉션을 삭제하여 인덱스를 삭제할 수 있습니다.

풀(Pool)

사일로 패턴과 대조적으로, 그림의 풀 패턴에서는 전체 엔드투엔드 RAG 아키텍처가 테넌트들 간에 공유되어 많은 소규모 테넌트를 수용하는 데 특히 적합합니다.

풀 패턴은 다음을 규정합니다:

  • 단일 데이터 소스 – 테넌트의 데이터는 동일한 S3 버킷 내에 저장됩니다. 이는 풀 모델이 저장 시 암호화를 위한 공유 KMS 키를 지원하며, 테넌트별로 암호화 키를 제공하지 않음을 의미합니다. Amazon S3에 업로드된 각 문서에 대해 downstream에서 테넌트 소유권을 식별하기 위해서는 해당하는 JSON 메타데이터 파일을 생성하고 업로드해야 합니다. 메타데이터 파일 생성 프로세스는 비동기적일 수 있으며, Amazon Bedrock Knowledge Bases가 수집 작업의 명시적 트리거링을 요구하기 때문에 여러 파일에 배치로 처리될 수도 있습니다. 메타데이터 파일은 관련 소스 문서 파일과 동일한 이름을 사용해야 하며, 파일 이름 끝에 .metadata.json이 추가되어야 하고, S3 버킷의 소스 파일과 동일한 폴더 또는 위치에 저장되어야 합니다. 다음 코드는 메타데이터 파일 예시입니다.
{
  "metadataAttributes" : {
    "tenantId" : "tenant_1",
  ...
  }
}
JSON

위의 JSON 구조에서 tenantId 키는 의도적으로 선택되었으며, 테넌시를 표현하는 데 사용하고자 하는 키로 변경할 수 있습니다. 테넌시 필드는 런타임에 특정 테넌트에 속하는 문서를 필터링하는 데 사용되므로, 런타임의 필터링 키는 문서 인덱싱에 사용된 JSON의 메타데이터 키와 일치해야 합니다. 또한 테넌시 기반이 아닌 추가 필터링을 수행하기 위해 다른 메타데이터 키를 포함할 수 있습니다. object.metadata.json 파일을 업로드하지 않으면 클라이언트 애플리케이션이 메타데이터 필터링을 사용하여 문서를 찾을 수 없습니다.

  • 단일 knowledge base – 테넌트의 데이터 수집을 처리하기 위해 단일 knowledge base가 생성됩니다. 이는 테넌트들이 동일한 청킹 전략과 임베딩 모델을 공유하며, 저장 시에 동일한 암호화 KMS 키를 공유한다는 것을 의미합니다. 또한 수집 작업이 KB당 데이터 소스별로 트리거되기 때문에 테넌트에게 동일한 데이터 최신성 기준을 제공하는 것으로 제한됩니다.
  • 단일 OpenSearch Serverless 컬렉션 및 인덱스 – 테넌트 데이터는 단일 OpenSearch Service 벡터 인덱스에 통합되어있으므로 테넌트들은 벡터 데이터에 대해 동일한 KMS 암호화 키와 인덱싱 및 쿼리에 대한 동일한 HNSW 매개변수를 공유합니다. 테넌트 데이터가 물리적으로 분리되지 않기 때문에 RAG 클라이언트 어플리케이션이 단일 테넌트에 대한 결과를 필터링할 수 있는 것이 중요합니다. 이는 Amazon Bedrock Knowledge Bases의 Retrieve 또는 RetrieveAndGenerate를 사용하여 retrievalConfiguration의 일부로 테넌트 필터링 조건을 표현함으로써 효율적으로 구현할 수 있습니다 (자세한 내용은 Amazon Bedrock Knowledge Bases now supports metadata filtering to improve retrieval accuracy 참조). tenant_1에 대한 결과만 반환하도록 벡터 검색을 제한하려면 다음은 AWS SDK for Python (Boto3)을 기반으로 RetrieveAndGenerate를 수행하는 클라이언트 구현 예시입니다:
import boto3

bedrock_agent_runtime = boto3.client(
    service_name = "bedrock-agent-runtime"
)

tenant_filter = {
    "equals": {
        "key": "tenantId",
        "value": "tenant_1"
    }
}

retrievalConfiguration = {
    "vectorSearchConfiguration": {
        "filter": tenant_filter
    }
}

bedrock_agent_runtime.retrieve_and_generate(
    input = {
        'text': 'The original user query'
    },
    retrieveAndGenerateConfiguration = {
        'type': 'KNOWLEDGE_BASE',
        'knowledgeBaseConfiguration': {
            'knowledgeBaseId': <YOUR_KNOWLEDGEBASE_ID>,
            'modelArn': <FM_ARN>,
            'retrievalConfiguration': retrievalConfiguration
        }
    }
)
Python

text에는 답변이 필요한 원래 사용자 쿼리가 포함되어 있습니다. 문서의 기반을 고려할 때, <YOUR_KNOWLEDGEBASE_ID>는 테넌트를 풀링하는 데 사용된 knowledge base의 식별자로 대체되어야 하며, <FM_ARN>은 사용자 쿼리에 응답하는 데 사용하고자 하는 Amazon Bedrock 모델의 Amazon Resource Name(ARN)으로 대체되어야 합니다. 위 코드에 제시된 클라이언트는 테넌트 필터링 기능을 보여주기 위해 간소화되었습니다. 실제 프로덕션 환경에서는 세션 및 오류 처리, 로깅 및 재시도 로직을 구현하고, 테넌트 필터링 로직을 클라이언트 호출과 분리하여 개발자가 접근할 수 없도록 하는 것이 좋습니다.

이 패턴에서는 엔드투엔드 아키텍처가 통합되어 있기 때문에 테넌트를 온보딩하고 오프보딩하는 데 새로운 물리적 또는 논리적 구조를 생성할 필요가 없으며, 특정 테넌트 문서를 Amazon S3에 업로드하거나 업로드하는 것을 중단하는 것만큼 간단합니다. 이는 특정 테넌트를 오프보딩하고 완전히 잊어버리는 데 사용할 수 있는 AWS 관리형 API가 없음을 의미합니다. 특정 테넌트에 속한 과거 문서를 삭제하려면 Amazon S3에 있는 관련 객체들을 삭제하면 됩니다. 일반적으로 고객은 사용 가능한 테넌트 목록과 그 상태를 유지하는 외부 애플리케이션을 가지고 있어 온보딩 및 오프보딩 프로세스를 용이하게 합니다.

이 패턴에서 모니터링 시스템과 로깅 기능을 공유하면 많은 수의 테넌트를 운영하는 복잡성이 줄어듭니다. 하지만 특정 테넌트별로 모니터링을 수행하기를 원할 경우, 클라이언트 측에서 테넌트별 메트릭을 수집해야 합니다.

풀 패턴은 테넌트 간에 OCU를 공유함으로써 각 OCU의 사용을 최대화하고 테넌트의 유휴 시간을 최소화하여 RAG 아키텍처의 엔드투엔드 비용을 최적화합니다. 테넌트 간에 동일한 OCU 풀을 공유한다는 것은 이 패턴이 벡터 저장소 수준에서 성능 격리를 제공하지 않는다는 것을 의미하므로, 가장 크고 활발한 테넌트가 다른 테넌트의 경험에 영향을 미칠 수 있습니다.

풀 패턴을 RAG 아키텍처에 선택할 때 다음 사항을 유의해야 합니다:

단일 데이터 수집 작업은 최대 100GB를 수집하거나 삭제할 수 있습니다. 또한 데이터 소스는 최대 500만 개의 문서를 가질 수 있습니다. 솔루션에 분산된 많은 테넌트가 통합되어 있는 경우, 수집 작업 크기 제한에 걸리지 않도록 하루에 여러 번 수집 작업을 트리거하는 것을 고려해야 합니다. 또한 동기화할 문서의 수와 크기에 따라 수집 시간은 임베딩 모델 호출 빈도에 의해 결정됩니다.

예를 들어, 다음 시나리오를 고려해보세요:

  • 동기화할 테넌트 수 = 10
  • 테넌트당 평균 문서 수 = 100
  • 문서당 평균 크기 = 2 MB, 약 200,000개의 토큰을 포함하며 오버랩하기 위해 1,000개의 토큰으로 이루어진 220개의 청크로 나뉨
  • Amazon Titan Embeddings v2를 온디맨드로 사용, 이 모델은 분당 2,000번 요청(RPM)과 300,000 토큰(TPM)의 할당량을 가지고 있음

이는 다음과 같은 결과를 초래합니다:

  • 총 임베딩 요청 수 = 10 * 100 * 220 = 220,000
  • 처리할 총 토큰 = 10 * 100 * 1,000 = 1,000,000
  • 임베딩에 걸리는 총 시간은 RPM에 의해 결정되므로, 220,000 / 2,000 = 1시간 50분

이는 하루에 12번 수집 작업을 트리거하여 수집될 데이터의 시간 분포를 적절히 할 수 있음을 의미합니다. 이 계산은 최상의 시나리오이며, FM이 청크에서 벡터를 생성할 때 발생하는 지연 시간을 고려하지 않은 것입니다. 동시에 많은 수의 테넌트를 동기화해야 할 것으로 예상되는 경우, 프로비저닝된 처리량을 사용하여 벡터 임베딩 생성에 소요되는 시간을 줄이는 것을 고려해보세요. 이 접근 방식은 또한 임베딩 모델의 부하를 분산시켜 Amazon Bedrock 런타임 API 호출의 스로틀링을 제한하는 데 도움이 될 것입니다.

브릿지(Bridge)

브리지 패턴은 다음 그림에 나타난 대로 사일로 패턴과 풀 패턴 사이의 균형을 이루며, 테넌트 데이터 격리와 보안을 균형 있게 조절하는 중간 지점을 제공합니다.

브리지 패턴은 다음과 같은 특징이 있습니다:

  • 공통 S3 버킷 내 테넌트별 개별 데이터 소스 – 테넌트 데이터는 동일한 S3 버킷에 저장되지만 테넌트 식별자로 접두사가 붙습니다. 테넌트별로 다른 접두사를 사용하는 것이 테넌트별 암호화 키를 사용할 수 있는 가능성을 제공하지는 않지만, knowledge base downstream에서 데이터를 분리하는 데 사용할 수 있는 논리적 분리를 생성합니다.
  • 테넌트별 별도 knowledge base – 이 패턴은 사일로 패턴과 유사하게 테넌트별로 별도의 knowledge base를 생성하도록 규정합니다. 따라서 사일로 패턴의 고려사항이 적용됩니다. 브리지 패턴을 사용하여 구축된 애플리케이션은 일반적으로 테넌트 간에 쿼리 클라이언트를 공유하므로 쿼리할 특정 테넌트의 knowledge base를 식별해야 합니다. 테넌트별 구성을 관리하는 외부 데이터베이스에 테넌트-knowledge base 매핑을 저장하여 knowledge base를 식별할 수 있습니다. 다음 예시는 이러한 테넌트별 정보를 Amazon DynamoDB 테이블에 저장하는 방법을 보여줍니다:
    import boto3
    # Create a DynamoDB resource
    dynamodb = boto3.resource('dynamodb')
    
    table_name = 'tenantKbConfig'
    attribute_definitions = [
        {'AttributeName': 'tenantId', 'AttributeType': 'S'}
    ]
    
    key_schema = [
        {'AttributeName': 'tenantId', 'KeyType': 'HASH'}
    ]
    
    #Create the table holding KB tenant configurations
    tenant_kb_config_table = dynamodb.create_table(
        TableName=table_name,
        AttributeDefinitions=attribute_definitions,
        KeySchema=key_schema,
        BillingMode='PAY_PER_REQUEST' # Use on-demand billing mode for illustration
    )
    
    #Create a tenant
        tenant_kb_config_table.put_item(
        Item={
            'tenantId': 'tenant_1',
            'knowledgebaseId': <YOUR_KNOWLEDGEBASE_ID>,
            'modelArn': <FM_ARN>     }
    )
    Python

    프로덕션 환경에서는 애플리케이션이 다른 기능에 속하는 테넌트별 매개변수를 데이터 저장소에 저장할 것입니다. 애플리케이션 아키텍처에 따라 knowledgebaseIdmodelARN을 테넌트별 매개변수와 함께 저장하거나, RAG 아키텍처를 위한 별도의 데이터 저장소(예: tenantKbConfig 테이블)를 생성하는 것을 선택할 수 있습니다.

    이 매핑은 그 후 RetrieveAndGenerate API를 호출하는 클라이언트 애플리케이션에서 사용될 수 있습니다.
    다음은 구현 예시입니다:

    import json
    import boto3
    
    # Create a DynamoDB resource
    dynamodb = boto3.resource('dynamodb')
    
    # Create a Bedrock Runtime client
    bedrock_runtime = boto3.client('bedrock-agent-runtime')
    
    # Define the table name
    table_name = 'tenantKbConfig'
    
    # Define function returning tenant config
    def get_tenant_config(tenant_id):
        table = dynamodb.Table(table_name)
        response = table.get_item(
            Key = {
                'tenantId': tenant_id
            }
        )
    if 'Item' in response:
        return { 'knowledgebaseId':response['Item'].get('knowledgebaseId'), 'modelArn': response['Item'].get('modelArn')}
    else:
        return None
        
    # Retrieve the tenant configurations from DynamoDB
    tenant_config = get_tenant_config('tenant_1')
    
    #Invoke the Retrieve and Generate API
    bedrock_runtime.retrieve_and_generate(
        input = {
            'text': 'What type of info do your documents contain?'
        },
        retrieveAndGenerateConfiguration = {
            'type': 'KNOWLEDGE_BASE',
            'knowledgeBaseConfiguration': {
                'knowledgeBaseId': tenant_config['knowledgebaseId'],
                'modelArn': tenant_config['modelArn']
            }
        }
    )
    Python
  • 테넌트별 별도 OpenSearch Service 인덱스 – 동일한 OpenSearch Serverless 컬렉션 내에 데이터를 저장하지만 테넌트별로 벡터 인덱스를 생성합니다. 이는 테넌트들이 동일한 KMS 암호화 키와 동일한 OCU 풀을 공유하여 데이터 수집 및 쿼리에 대한 OpenSearch Service 리소스 사용을 최적화함을 의미합니다. 벡터 인덱스의 분리는 테넌트별로 다른 HNSW 매개변수를 선택할 수 있는 유연성을 제공하여 다양한 테넌트에 대한 k-NN 인덱싱 및 쿼리 성능을 맞춤화할 수 있게 합니다.

브리지 패턴은 최대 100개의 테넌트를 지원하며, 테넌트를 온보딩하고 오프보딩하려면 knowledge base와 OpenSearch Service 벡터 인덱스를 생성하고 삭제해야 합니다. 특정 테넌트와 관련된 데이터를 삭제하려면 생성된 리소스를 삭제하고 Amazon S3 API 호출에서 테넌트별 접두사를 논리적 매개변수로 사용할 수 있습니다. 사일로 패턴과 달리 브리지 패턴은 각 테넌트별 엔드투엔드 암호화를 허용하지 않습니다. 대신, 비용을 최적화하면서 사일로 패턴이 제공하는 것과 동일한 수준의 테넌트 맞춤화를 제공합니다.

차이점 정리

다음 그림과 표는 다양한 멀티테넌트 RAG 아키텍처 패턴의 특성을 비교하는 통합된 뷰를 제공합니다. 이 포괄적인 오버뷰는 풀, 브리지, 사일로 패턴과 관련된 주요 속성과 상충 관계를 강조하여 특정 요구사항에 기반한 정보에 입각한 의사결정을 가능하게 합니다.

다음 그림은 설계 특성을 RAG 아키텍처의 구성 요소에 매핑한 것을 보여줍니다.

다음 표는 멀티테넌트 RAG 아키텍처 패턴의 특성을 요약합니다.

특징 구성 요소 풀(Pool) 브릿지(Bridge) 사일로(Silo)
테넌트별 청킹 전략 선택 Amazon Bedrock Knowledge Base Data Source No Yes Yes
일시적 데이터 및 데이터 저장 시 암호화를 위한 고객 관리 키 지정 Amazon Bedrock Knowledge Base Data Source No No Yes
테넌트별 거리(distance) 측정 방식 지정 Amazon OpenSearch Service Index No Yes Yes
테넌트별 ANN 인덱스 구성 Amazon OpenSearch Service Index No Yes Yes
테넌트별 데이터 삭제 정책 지정 Amazon Bedrock Knowledge Base Data Source No Yes Yes
테넌트별 벡터 크기 지정 Amazon Bedrock Knowledge Base Data Source No Yes Yes
테넌트별 성능 격리(isolation) Vector database No No Yes
테넌트 온보딩 및 오프보딩 복잡성 Overall solution 가장 간단, 기존 인프라에서 새 테넌트 관리 필요 중간, 엔드투엔드 인프라의 최소한의 관리 필요 가장 어려움, 엔드투엔드 인프라 관리 필요
쿼리 클라이언트 구현 방식 Original Data Source 중간, 동적 필터링 필요 가장 어려움, 외부 테넌트 매핑 테이블 필요 가장 간단, 단일 테넌트 구현과 동일
Amazon S3 테넌트 관리 복잡성 Amazon S3 buckets and objects 가장 어려움, 각 객체에 대한 테넌트별 메타데이터 파일 유지 필요 중간, 각 테넌트는 다른 S3 경로 필요 가장 간단, 각 테넌트는 다른 S3 버킷 필요
비용 Vector database 가장 낮음 중간 가장 높음
테넌트별로 벡터 임베딩에 사용하는 FM 지정 Amazon Bedrock Knowledge Base No Yes Yes

결론

이 글에서는 Amazon Bedrock Knowledge Bases와 OpenSearch Service를 사용하여 멀티테넌트 RAG 아키텍처를 구현하기 위한 세 가지 고유한 패턴을 살펴보았습니다. 사일로, 풀, 브리지 패턴은 테넌트 격리, 가변성, 관리 단순성 및 비용 효율성 측면에서 다양한 수준을 제공하며, 서로 다른 사용 사례와 요구사항에 맞춰 설계되었습니다. 각 패턴과 관련된 상충 관계와 고려사항을 이해함으로써, 조직은 정보에 기반한 결정을 내리고 자신들의 요구에 가장 잘 부합하는 접근 방식을 선택할 수 있습니다.

지금 Amazon Bedrock Knowledge Bases로 시작해보세요.

Seungwon Choi

Seungwon Choi

최승원 솔루션즈 아키텍트는 고객이 최적의 솔루션을 선택하여 비즈니스 성과를 달성할 수 있도록 고객과 함께 효율적인 아키텍처를 구성하는 역할을 수행하고 있습니다.