From d035e0fa1df7addc9c0ffa5b4ed10ce3736e250e Mon Sep 17 00:00:00 2001 From: krokoko Date: Wed, 2 Apr 2025 17:13:00 -0500 Subject: [PATCH] feat(oss): replace custom resource with l1 cfnindex --- .../opensearch_vectorindex/README.md | 20 +- .../classes/VectorIndex.md | 64 +-- .../enumerations/AlgorithmNameType.md | 21 + .../enumerations/EngineType.md | 33 ++ .../enumerations/OpensearchFieldType.md | 21 + .../enumerations/SpaceType.md | 45 ++ .../interfaces/Analyzer.md | 33 -- .../interfaces/IVectorIndex.md | 101 ++++ .../interfaces/IndexSettings.md | 33 ++ .../interfaces/MappingsProperty.md | 15 + .../MetadataManagementFieldProps.md | 33 -- .../interfaces/Method.md | 41 ++ .../interfaces/MethodParameters.md | 25 + .../interfaces/PropertyMapping.md | 55 +++ .../interfaces/VectorIndexAttributes.md | 23 + .../interfaces/VectorIndexProps.md | 44 +- .../variables/OpenSearchIndexCRProvider.md | 15 - .../Dockerfile | 24 - .../custom_resources/__init__.py | 50 -- .../custom_resources/cr_types.py | 34 -- .../custom_resources/exceptions.py | 49 -- .../custom_resources/opensearch_index.py | 298 ------------ .../opensearch_vpc_endpoint.py | 169 ------- .../poetry.lock | 452 ------------------ .../pyproject.toml | 20 - .../knowledge-bases/vector-knowledge-base.ts | 50 +- src/cdk-lib/opensearch-vectorindex/README.md | 117 ++--- .../opensearch-vectorindex/vector-index.ts | 314 ++++++------ .../vector-index.test.ts | 203 +------- .../custom-resource-provider-helper.test.ts | 2 +- 30 files changed, 718 insertions(+), 1686 deletions(-) create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/AlgorithmNameType.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/EngineType.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/OpensearchFieldType.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/SpaceType.md delete mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Analyzer.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IVectorIndex.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IndexSettings.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MappingsProperty.md delete mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MetadataManagementFieldProps.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Method.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MethodParameters.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/PropertyMapping.md create mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexAttributes.md delete mode 100644 apidocs/@cdklabs/namespaces/opensearch_vectorindex/variables/OpenSearchIndexCRProvider.md delete mode 100644 lambda/opensearch-serverless-custom-resources/Dockerfile delete mode 100644 lambda/opensearch-serverless-custom-resources/custom_resources/__init__.py delete mode 100644 lambda/opensearch-serverless-custom-resources/custom_resources/cr_types.py delete mode 100644 lambda/opensearch-serverless-custom-resources/custom_resources/exceptions.py delete mode 100644 lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_index.py delete mode 100644 lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_vpc_endpoint.py delete mode 100644 lambda/opensearch-serverless-custom-resources/poetry.lock delete mode 100644 lambda/opensearch-serverless-custom-resources/pyproject.toml diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/README.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/README.md index b94150fb..0aeeb17c 100644 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/README.md +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/README.md @@ -6,16 +6,24 @@ # opensearch\_vectorindex +## Enumerations + +- [AlgorithmNameType](enumerations/AlgorithmNameType.md) +- [EngineType](enumerations/EngineType.md) +- [OpensearchFieldType](enumerations/OpensearchFieldType.md) +- [SpaceType](enumerations/SpaceType.md) + ## Classes - [VectorIndex](classes/VectorIndex.md) ## Interfaces -- [Analyzer](interfaces/Analyzer.md) -- [MetadataManagementFieldProps](interfaces/MetadataManagementFieldProps.md) +- [IndexSettings](interfaces/IndexSettings.md) +- [IVectorIndex](interfaces/IVectorIndex.md) +- [MappingsProperty](interfaces/MappingsProperty.md) +- [Method](interfaces/Method.md) +- [MethodParameters](interfaces/MethodParameters.md) +- [PropertyMapping](interfaces/PropertyMapping.md) +- [VectorIndexAttributes](interfaces/VectorIndexAttributes.md) - [VectorIndexProps](interfaces/VectorIndexProps.md) - -## Variables - -- [OpenSearchIndexCRProvider](variables/OpenSearchIndexCRProvider.md) diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/classes/VectorIndex.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/classes/VectorIndex.md index cb34830e..fc45cd36 100644 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/classes/VectorIndex.md +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/classes/VectorIndex.md @@ -6,11 +6,11 @@ # Class: VectorIndex -Deploy a vector index on the collection. +Provides a vector index in Amazon OpenSearch Serverless. ## Extends -- `Resource` +- `VectorIndexBase` ## Constructors @@ -38,10 +38,22 @@ Deploy a vector index on the collection. #### Overrides -`cdk.Resource.constructor` +`VectorIndexBase.constructor` ## Properties +### collectionEndpoint + +> `readonly` **collectionEndpoint**: `string` + +The endpoint of the collection + +#### Overrides + +`VectorIndexBase.collectionEndpoint` + +*** + ### env > `readonly` **env**: `ResourceEnvironment` @@ -56,7 +68,7 @@ that might be different than the stack they were imported into. #### Inherited from -`cdk.Resource.env` +`VectorIndexBase.env` *** @@ -66,6 +78,10 @@ that might be different than the stack they were imported into. The name of the index. +#### Overrides + +`VectorIndexBase.indexName` + *** ### node @@ -76,7 +92,7 @@ The tree node. #### Inherited from -`cdk.Resource.node` +`VectorIndexBase.node` *** @@ -95,7 +111,7 @@ This value will resolve to one of the following: #### Inherited from -`cdk.Resource.physicalName` +`VectorIndexBase.physicalName` *** @@ -107,23 +123,7 @@ The stack in which this resource is defined. #### Inherited from -`cdk.Resource.stack` - -*** - -### vectorDimensions - -> `readonly` **vectorDimensions**: `number` - -The number of dimensions in the vector. - -*** - -### vectorField - -> `readonly` **vectorField**: `string` - -The name of the vector field. +`VectorIndexBase.stack` ## Methods @@ -144,7 +144,7 @@ through its absolute name/arn. #### Inherited from -`cdk.Resource._enableCrossEnvironment` +`VectorIndexBase._enableCrossEnvironment` *** @@ -174,7 +174,7 @@ account for data recovery and cleanup later (`RemovalPolicy.RETAIN`). #### Inherited from -`cdk.Resource.applyRemovalPolicy` +`VectorIndexBase.applyRemovalPolicy` *** @@ -188,7 +188,7 @@ account for data recovery and cleanup later (`RemovalPolicy.RETAIN`). #### Inherited from -`cdk.Resource.generatePhysicalName` +`VectorIndexBase.generatePhysicalName` *** @@ -228,7 +228,7 @@ cross-environment references to work. #### Inherited from -`cdk.Resource.getResourceArnAttribute` +`VectorIndexBase.getResourceArnAttribute` *** @@ -258,7 +258,7 @@ Commonly this is the resource's `ref`. #### Inherited from -`cdk.Resource.getResourceNameAttribute` +`VectorIndexBase.getResourceNameAttribute` *** @@ -274,7 +274,7 @@ Returns a string representation of this construct. #### Inherited from -`cdk.Resource.toString` +`VectorIndexBase.toString` *** @@ -314,7 +314,7 @@ true if `x` is an object created from a class which extends `Construct`. #### Inherited from -`cdk.Resource.isConstruct` +`VectorIndexBase.isConstruct` *** @@ -336,7 +336,7 @@ Returns true if the construct was created by CDK, and false otherwise #### Inherited from -`cdk.Resource.isOwnedResource` +`VectorIndexBase.isOwnedResource` *** @@ -358,4 +358,4 @@ Check whether the given construct is a Resource #### Inherited from -`cdk.Resource.isResource` +`VectorIndexBase.isResource` diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/AlgorithmNameType.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/AlgorithmNameType.md new file mode 100644 index 00000000..e6c08fac --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/AlgorithmNameType.md @@ -0,0 +1,21 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / AlgorithmNameType + +# Enumeration: AlgorithmNameType + +The algorithm name for k-NN search. + +## Enumeration Members + +### HNSW + +> **HNSW**: `"hnsw"` + +*** + +### IVF + +> **IVF**: `"ivf"` diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/EngineType.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/EngineType.md new file mode 100644 index 00000000..63c42d74 --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/EngineType.md @@ -0,0 +1,33 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / EngineType + +# Enumeration: EngineType + +The k-NN search engine to use. + +## Enumeration Members + +### FAISS + +> **FAISS**: `"faiss"` + +C++ implementation. + +*** + +### LUCENE + +> **LUCENE**: `"lucene"` + +Java implementation. + +*** + +### NMSLIB + +> **NMSLIB**: `"nmslib"` + +C++ implementation. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/OpensearchFieldType.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/OpensearchFieldType.md new file mode 100644 index 00000000..305170ad --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/OpensearchFieldType.md @@ -0,0 +1,21 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / OpensearchFieldType + +# Enumeration: OpensearchFieldType + +The field data type. Must be a valid OpenSearch field type. + +## Enumeration Members + +### KNN\_VECTOR + +> **KNN\_VECTOR**: `"knn_vector"` + +*** + +### TEXT + +> **TEXT**: `"text"` diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/SpaceType.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/SpaceType.md new file mode 100644 index 00000000..24aaa9ab --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/enumerations/SpaceType.md @@ -0,0 +1,45 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / SpaceType + +# Enumeration: SpaceType + +The distance function used for k-NN search. + +## Enumeration Members + +### COSINESIMILARITY + +> **COSINESIMILARITY**: `"cosinesimil"` + +*** + +### HAMMING + +> **HAMMING**: `"hamming"` + +*** + +### INNERPRODUCT + +> **INNERPRODUCT**: `"innerproduct"` + +*** + +### L1 + +> **L1**: `"l1"` + +*** + +### L2 + +> **L2**: `"l2"` + +*** + +### LINF + +> **LINF**: `"linf"` diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Analyzer.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Analyzer.md deleted file mode 100644 index aeffe9aa..00000000 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Analyzer.md +++ /dev/null @@ -1,33 +0,0 @@ -[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) - -*** - -[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / Analyzer - -# Interface: Analyzer - -Properties for the Analyzer. - -## Properties - -### characterFilters - -> `readonly` **characterFilters**: [`ICU_NORMALIZER`](../../opensearchserverless/enumerations/CharacterFilterType.md#icu_normalizer)[] - -The analyzers to use. - -*** - -### tokenFilters - -> `readonly` **tokenFilters**: [`TokenFilterType`](../../opensearchserverless/enumerations/TokenFilterType.md)[] - -The token filters to use. - -*** - -### tokenizer - -> `readonly` **tokenizer**: [`TokenizerType`](../../opensearchserverless/enumerations/TokenizerType.md) - -The tokenizer to use. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IVectorIndex.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IVectorIndex.md new file mode 100644 index 00000000..874b643d --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IVectorIndex.md @@ -0,0 +1,101 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / IVectorIndex + +# Interface: IVectorIndex + +Interface representing a vector index + +## Extends + +- `IResource` + +## Properties + +### collectionEndpoint + +> `readonly` **collectionEndpoint**: `string` + +The endpoint of the collection + +*** + +### env + +> `readonly` **env**: `ResourceEnvironment` + +The environment this resource belongs to. +For resources that are created and managed by the CDK +(generally, those created by creating new class instances like Role, Bucket, etc.), +this is always the same as the environment of the stack they belong to; +however, for imported resources +(those obtained from static methods like fromRoleArn, fromBucketName, etc.), +that might be different than the stack they were imported into. + +#### Inherited from + +`cdk.IResource.env` + +*** + +### indexName + +> `readonly` **indexName**: `string` + +The name of the index + +*** + +### node + +> `readonly` **node**: `Node` + +The tree node. + +#### Inherited from + +`cdk.IResource.node` + +*** + +### stack + +> `readonly` **stack**: `Stack` + +The stack in which this resource is defined. + +#### Inherited from + +`cdk.IResource.stack` + +## Methods + +### applyRemovalPolicy() + +> **applyRemovalPolicy**(`policy`): `void` + +Apply the given removal policy to this resource + +The Removal Policy controls what happens to this resource when it stops +being managed by CloudFormation, either because you've removed it from the +CDK application or because you've made a change that requires the resource +to be replaced. + +The resource can be deleted (`RemovalPolicy.DESTROY`), or left in your AWS +account for data recovery and cleanup later (`RemovalPolicy.RETAIN`). + +#### Parameters + +##### policy + +`RemovalPolicy` + +#### Returns + +`void` + +#### Inherited from + +`cdk.IResource.applyRemovalPolicy` diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IndexSettings.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IndexSettings.md new file mode 100644 index 00000000..74619024 --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/IndexSettings.md @@ -0,0 +1,33 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / IndexSettings + +# Interface: IndexSettings + +Index settings for the OpenSearch Serverless index. + +## Properties + +### knn? + +> `readonly` `optional` **knn**: `boolean` + +Enable or disable k-nearest neighbor search capability. + +*** + +### knnAlgoParamEfSearch? + +> `readonly` `optional` **knnAlgoParamEfSearch**: `number` + +The size of the dynamic list for the nearest neighbors. + +*** + +### refreshInterval? + +> `readonly` `optional` **refreshInterval**: `Duration` + +How often to perform a refresh operation. For example, 1s or 5s. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MappingsProperty.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MappingsProperty.md new file mode 100644 index 00000000..84f51ebd --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MappingsProperty.md @@ -0,0 +1,15 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / MappingsProperty + +# Interface: MappingsProperty + +The mappings for the OpenSearch Serverless index. + +## Properties + +### properties + +> `readonly` **properties**: `Record`\<`string`, [`PropertyMapping`](PropertyMapping.md)\> diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MetadataManagementFieldProps.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MetadataManagementFieldProps.md deleted file mode 100644 index 349968bb..00000000 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MetadataManagementFieldProps.md +++ /dev/null @@ -1,33 +0,0 @@ -[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) - -*** - -[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / MetadataManagementFieldProps - -# Interface: MetadataManagementFieldProps - -Metadata field definitions. - -## Properties - -### dataType - -> `readonly` **dataType**: `string` - -The data type of the field. - -*** - -### filterable - -> `readonly` **filterable**: `boolean` - -Whether the field is filterable. - -*** - -### mappingField - -> `readonly` **mappingField**: `string` - -The name of the field. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Method.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Method.md new file mode 100644 index 00000000..26adbe7f --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/Method.md @@ -0,0 +1,41 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / Method + +# Interface: Method + +Configuration for k-NN search method. + +## Properties + +### engine + +> `readonly` **engine**: [`EngineType`](../enumerations/EngineType.md) + +The k-NN search engine to use. + +*** + +### name + +> `readonly` **name**: [`AlgorithmNameType`](../enumerations/AlgorithmNameType.md) + +The algorithm name for k-NN search. + +*** + +### parameters? + +> `readonly` `optional` **parameters**: [`MethodParameters`](MethodParameters.md) + +Additional parameters for the k-NN algorithm. + +*** + +### spaceType? + +> `readonly` `optional` **spaceType**: [`SpaceType`](../enumerations/SpaceType.md) + +The distance function used for k-NN search. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MethodParameters.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MethodParameters.md new file mode 100644 index 00000000..6bb68a7d --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/MethodParameters.md @@ -0,0 +1,25 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / MethodParameters + +# Interface: MethodParameters + +Additional parameters for the k-NN algorithm. + +## Properties + +### efConstruction? + +> `readonly` `optional` **efConstruction**: `number` + +The size of the dynamic list used during k-NN graph creation. + +*** + +### m? + +> `readonly` `optional` **m**: `number` + +Number of neighbors to consider during k-NN search. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/PropertyMapping.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/PropertyMapping.md new file mode 100644 index 00000000..8ca29673 --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/PropertyMapping.md @@ -0,0 +1,55 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / PropertyMapping + +# Interface: PropertyMapping + +## Properties + +### dimension? + +> `readonly` `optional` **dimension**: `number` + +Dimension size for vector fields, defines the number of dimensions in the vector. + +*** + +### index? + +> `readonly` `optional` **index**: `boolean` + +Whether the index is indexed. Previously, this was called `filterable`. + +*** + +### method? + +> `readonly` `optional` **method**: [`Method`](Method.md) + +Configuration for k-NN search method. + +*** + +### properties? + +> `readonly` `optional` **properties**: `Record`\<`string`, `PropertyMapping`\> + +Defines the fields within the mapping, including their types and configurations. + +*** + +### type + +> `readonly` **type**: [`OpensearchFieldType`](../enumerations/OpensearchFieldType.md) + +The field data type. Must be a valid OpenSearch field type. + +*** + +### value? + +> `readonly` `optional` **value**: `string` + +Default value for the field when not specified in a document. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexAttributes.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexAttributes.md new file mode 100644 index 00000000..f6a1e955 --- /dev/null +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexAttributes.md @@ -0,0 +1,23 @@ +[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) + +*** + +[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / VectorIndexAttributes + +# Interface: VectorIndexAttributes + +## Properties + +### collectionEndpoint + +> `readonly` **collectionEndpoint**: `string` + +The endpoint of the collection + +*** + +### indexName + +> `readonly` **indexName**: `string` + +The name of the index diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexProps.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexProps.md index b7e3e487..19c02e7c 100644 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexProps.md +++ b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/interfaces/VectorIndexProps.md @@ -10,20 +10,6 @@ Properties for the VectorIndex. ## Properties -### analyzer? - -> `readonly` `optional` **analyzer**: [`Analyzer`](Analyzer.md) - -The analyzer to use. - -#### Default - -```ts -- No analyzer. -``` - -*** - ### collection > `readonly` **collection**: [`VectorCollection`](../../opensearchserverless/classes/VectorCollection.md) @@ -32,12 +18,6 @@ The OpenSearch Vector Collection. *** -### distanceType - -> `readonly` **distanceType**: `string` - -*** - ### indexName > `readonly` **indexName**: `string` @@ -46,30 +26,16 @@ The name of the index. *** -### mappings +### mappings? -> `readonly` **mappings**: [`MetadataManagementFieldProps`](MetadataManagementFieldProps.md)[] +> `readonly` `optional` **mappings**: [`MappingsProperty`](MappingsProperty.md) The metadata management fields. *** -### precision - -> `readonly` **precision**: `string` - -*** - -### vectorDimensions - -> `readonly` **vectorDimensions**: `number` - -The number of dimensions in the vector. - -*** - -### vectorField +### settings? -> `readonly` **vectorField**: `string` +> `readonly` `optional` **settings**: [`IndexSettings`](IndexSettings.md) -The name of the vector field. +The settings for the index. diff --git a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/variables/OpenSearchIndexCRProvider.md b/apidocs/@cdklabs/namespaces/opensearch_vectorindex/variables/OpenSearchIndexCRProvider.md deleted file mode 100644 index 4e69e0b6..00000000 --- a/apidocs/@cdklabs/namespaces/opensearch_vectorindex/variables/OpenSearchIndexCRProvider.md +++ /dev/null @@ -1,15 +0,0 @@ -[**@cdklabs/generative-ai-cdk-constructs**](../../../../README.md) - -*** - -[@cdklabs/generative-ai-cdk-constructs](../../../../README.md) / [opensearch\_vectorindex](../README.md) / OpenSearchIndexCRProvider - -# Variable: OpenSearchIndexCRProvider - -> `const` **OpenSearchIndexCRProvider**: `ICRProviderClass` - -**`Internal`** - -Custom Resource provider for OpenSearch Index operations. - - This is an internal core function and should not be called directly by Solutions Constructs clients. diff --git a/lambda/opensearch-serverless-custom-resources/Dockerfile b/lambda/opensearch-serverless-custom-resources/Dockerfile deleted file mode 100644 index 88f714ae..00000000 --- a/lambda/opensearch-serverless-custom-resources/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# - -FROM public.ecr.aws/sam/build-python3.12:1 - -RUN mkdir /asset -RUN pip install poetry -COPY . . -RUN rm -rf dist/* -RUN poetry install -RUN poetry build -RUN poetry run pip install --upgrade -t /asset dist/*.whl - -CMD ["echo", "Build completed"] \ No newline at end of file diff --git a/lambda/opensearch-serverless-custom-resources/custom_resources/__init__.py b/lambda/opensearch-serverless-custom-resources/custom_resources/__init__.py deleted file mode 100644 index ac2c3ba7..00000000 --- a/lambda/opensearch-serverless-custom-resources/custom_resources/__init__.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# - -__version__ = "0.1.0" - -import logging -import os -import time - -LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") - -logger = logging.getLogger(__name__) -logger.setLevel(LOG_LEVEL) - -try: - from .cr_types import CustomResourceRequest, CustomResourceResponse - from .opensearch_index import on_event as on_event_opensearch_index - from .opensearch_vpc_endpoint import on_event as on_event_opensearch_vpc_endpoint -except ImportError as e: - logger.error(f"Error importing modules: {e}") - logger.exception(e) - - -def on_event(event: CustomResourceRequest, context): - logger.debug(f"Received event: {event}") - resource_type = event["ResourceType"] - - if resource_type == "Custom::OpenSearchIndex": - return on_event_opensearch_index(event, context) - if resource_type == "Custom::VpcEndpoint": - return on_event_opensearch_vpc_endpoint(event, context) - if resource_type == "Custom::NoOp": - logger.info("NoOp resource type") - # Return a response with a physical resource ID that is not empty. - # This is required by CloudFormation to avoid a race condition. - time.sleep(event["ResourceProperties"].get("delay", 0)) - return CustomResourceResponse( - PhysicalResourceId=event["ResourceProperties"].get("message", "no-op") - ) - raise Exception("Invalid resource type: %s" % resource_type) diff --git a/lambda/opensearch-serverless-custom-resources/custom_resources/cr_types.py b/lambda/opensearch-serverless-custom-resources/custom_resources/cr_types.py deleted file mode 100644 index 3f73a531..00000000 --- a/lambda/opensearch-serverless-custom-resources/custom_resources/cr_types.py +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# - -from typing import TypeVar, TypedDict, Generic, Literal, NotRequired - -T = TypeVar("T") - - -class CustomResourceRequest(TypedDict, Generic[T]): - RequestType: Literal["Create", "Update", "Delete"] - ResponseURL: str - StackId: str - RequestId: str - ResourceType: str - LogicalResourceId: str - PhysicalResourceId: NotRequired[str] - ResourceProperties: NotRequired[T] - # OldResourceProperties: NotRequired[T] - - -class CustomResourceResponse(TypedDict): - PhysicalResourceId: NotRequired[str] - NoEcho: NotRequired[bool] - Data: NotRequired[dict[str, str]] diff --git a/lambda/opensearch-serverless-custom-resources/custom_resources/exceptions.py b/lambda/opensearch-serverless-custom-resources/custom_resources/exceptions.py deleted file mode 100644 index 60e0b45d..00000000 --- a/lambda/opensearch-serverless-custom-resources/custom_resources/exceptions.py +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# -import os - -import botocore.exceptions - -import logging - -LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") - -logger = logging.getLogger(__name__) -logger.setLevel(LOG_LEVEL) - - -class AWSRetryableError(Exception): - Errors = ( - "ThrottlingException", - "AccessDeniedException", - "RequestLimitExceededException", - "ProvisionedThroughputExceededException", - "ResourceInUseException", - "ServiceUnavailableException", - "TooManyRequestsException", - "InternalServerException", - "ValidationException", # "[security_exception] all shards failed" possible race condition - ) - - -def can_retry(e: botocore.exceptions.ClientError): - if ( - e.response["Error"]["Code"] in AWSRetryableError.Errors - or "index_not_found_exception" in e.response["Error"]["Message"] - ): - logger.info( - f"Retrying after {e.response['Error']['Code']}: {e.response['Error']['Message']}" - ) - raise AWSRetryableError(e) - logger.exception(e) - raise e diff --git a/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_index.py b/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_index.py deleted file mode 100644 index f06a9a4c..00000000 --- a/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_index.py +++ /dev/null @@ -1,298 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# - -import logging -import os -import time -from typing import Sequence, TypedDict - -import boto3 -from custom_resources.cr_types import CustomResourceRequest, CustomResourceResponse -from opensearchpy import ( - AuthorizationException, - AWSV4SignerAuth, - OpenSearch, - RequestsHttpConnection, -) -from tenacity import ( - retry, - retry_if_exception_type, - stop_after_attempt, - wait_exponential_jitter, -) - -LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") - -logger = logging.getLogger(__name__) -logger.setLevel(LOG_LEVEL) - - -class MetadataManagementField(TypedDict): - MappingField: str - DataType: str - Filterable: bool - - -class AnalyzerProperties(TypedDict): - CharacterFilters: Sequence[str] - Tokenizer: str - TokenFilters: Sequence[str] - - -class VectorIndexProperties(TypedDict): - Endpoint: str - Precision: str - DistanceType: str - IndexName: str - VectorField: str - Dimensions: int | str - MetadataManagement: Sequence[MetadataManagementField] - Analyzer: AnalyzerProperties | None - - -def validate_event(event: CustomResourceRequest[VectorIndexProperties]) -> bool: - if event["ResourceProperties"] is None: - raise ValueError("ResourceProperties is required") - if event["ResourceProperties"]["Endpoint"] is None: - raise ValueError("Endpoint is required") - if event["ResourceProperties"]["IndexName"] is None: - raise ValueError("IndexName is required") - if event["RequestType"] in ["Create", "Update"]: - if event["ResourceProperties"]["VectorField"] is None: - raise ValueError("VectorField is required") - if event["ResourceProperties"]["Dimensions"] is None: - raise ValueError("Dimensions is required") - if event["ResourceProperties"]["Precision"] is None: - raise ValueError("Precision is required") - if event["ResourceProperties"]["DistanceType"] is None: - raise ValueError("DistanceType is required") - if isinstance(int(event["ResourceProperties"]["Dimensions"]), int) is False: - raise ValueError("Dimensions must be an integer") - if event["ResourceProperties"]["MetadataManagement"] is None: - raise ValueError("MetadataManagement is required") - if event["RequestType"] == "Update" and event["PhysicalResourceId"] is None: - raise ValueError("PhysicalResourceId is required") - if event["ResourceProperties"].get("Analyzer") is not None: - analyzer = event["ResourceProperties"]["Analyzer"] - if analyzer["CharacterFilters"] is None: - raise ValueError("CharacterFilters is required") - if analyzer["Tokenizer"] is None: - raise ValueError("Tokenizer is required") - if analyzer["TokenFilters"] is None: - raise ValueError("TokenFilters is required") - elif event["RequestType"] == "Delete": - if event["PhysicalResourceId"] is None: - raise ValueError("PhysicalResourceId is required") - else: - raise ValueError(f"Unsupported RequestType: {event['RequestType']}") - if event["ResponseURL"] is None: - raise ValueError("ResponseURL is required") - if event["StackId"] is None: - raise ValueError("StackId is required") - if event["RequestId"] is None: - raise ValueError("RequestId is required") - if event["ResourceType"] is None: - raise ValueError("ResourceType is required") - if event["LogicalResourceId"] is None: - raise ValueError("LogicalResourceId is required") - return True - - -def connect_opensearch(endpoint: str) -> OpenSearch: - service = "aoss" if "aoss" in endpoint else "es" - logger.debug(f"Connecting to OpenSearch service: {service} at {endpoint}") - return OpenSearch( - hosts=[ - { - "host": endpoint, - "port": 443, - } - ], - http_auth=AWSV4SignerAuth( - boto3.Session().get_credentials(), os.getenv("AWS_REGION"), service - ), - use_ssl=True, - verify_certs=True, - connection_class=RequestsHttpConnection, - pool_maxsize=10, - ) - - -def create_mapping( - vector_field: str, - dimensions: int, - precision: str, - distance_type: str, - metadata_management: Sequence[MetadataManagementField], -) -> dict: - mapping = { - "properties": { - vector_field: { - "type": "knn_vector", - "dimension": dimensions, - "data_type": precision, - "method": { - "engine": "faiss", - "space_type": distance_type, - "name": "hnsw", - "parameters": {}, - }, - }, - "id": { - "type": "text", - "fields": {"keyword": {"type": "keyword", "ignore_above": 256}}, - }, - }, - } - for field in metadata_management: - is_filterable = field["Filterable"].lower() == "true" - mapping["properties"][field["MappingField"]] = { - "type": field["DataType"], - "index": "true" if is_filterable else "false", - } - return mapping - - -def create_setting(analyzer: AnalyzerProperties | None) -> dict: - setting = { - "index": { - "number_of_shards": "2", - "knn.algo_param": {"ef_search": "512"}, - "knn": "true", - }, - } - if analyzer: - setting["analysis"] = { - "analyzer": { - "custom_analyzer": { - "type": "custom", - "tokenizer": analyzer["Tokenizer"], - "char_filter": analyzer["CharacterFilters"], - "filter": analyzer["TokenFilters"], - } - } - } - - return setting - - -def create_index( - client: OpenSearch, index_name: str, mapping: dict[str, str], setting: dict[str, str] -) -> None: - logger.debug(f"creating index {index_name}") - logger.debug(f"setting: {setting}") - logger.debug(f"mapping: {mapping}") - client.indices.create( - index_name, - body={ - "settings": setting, - "mappings": mapping, - }, - params={"wait_for_active_shards": "all"}, - ) - logger.debug(f"sleep for 30 seconds for bedrock KB {index_name}") - time.sleep(30) - - -# Add retry on AuthorizationException to mitigate policy creation race condition -@retry( - retry=retry_if_exception_type(AuthorizationException), - stop=stop_after_attempt(30), - wait=wait_exponential_jitter(1, 3), -) -def handle_create( - client: OpenSearch, - index_name: str, - vector_field: str, - dimensions: int, - precision: str, - distance_type: str, - metadata_management: Sequence[MetadataManagementField], - analyzer: AnalyzerProperties | None, -): - if client.indices.exists(index_name): - raise ValueError(f"Index {index_name} already exists") - - try: - mapping = create_mapping(vector_field, dimensions, precision, distance_type, metadata_management) - setting = create_setting(analyzer) - create_index(client, index_name, mapping, setting) - except Exception as e: - logger.error(f"Error creating index {index_name}") - logger.exception(e) - raise e - return index_name - - -@retry( - retry=retry_if_exception_type(AuthorizationException), - stop=stop_after_attempt(30), - wait=wait_exponential_jitter(1, 3), -) -def handle_delete(client: OpenSearch, index_name: str): - try: - client.indices.delete(index_name) - except Exception as e: - logger.error(f"Error deleting index {index_name}") - logger.exception(e) - raise e - - -def on_create( - event: CustomResourceRequest[VectorIndexProperties], -) -> CustomResourceResponse: - validate_event(event) - client = connect_opensearch(event["ResourceProperties"]["Endpoint"]) - - physical_id = handle_create( - client, - event["ResourceProperties"]["IndexName"], - event["ResourceProperties"]["VectorField"], - int(event["ResourceProperties"]["Dimensions"]), - event["ResourceProperties"]["Precision"], - event["ResourceProperties"]["DistanceType"], - event["ResourceProperties"]["MetadataManagement"], - event["ResourceProperties"].get("Analyzer", None), - ) - return {"PhysicalResourceId": physical_id} - - -def on_update( - _event: CustomResourceRequest[VectorIndexProperties], -) -> CustomResourceResponse: - raise ValueError("Update not supported") - - -def on_delete( - event: CustomResourceRequest[VectorIndexProperties], -) -> CustomResourceResponse: - validate_event(event) - client = connect_opensearch(event["ResourceProperties"]["Endpoint"]) - handle_delete(client, event["PhysicalResourceId"]) - return {"PhysicalResourceId": event["PhysicalResourceId"]} - - -def on_event(event: CustomResourceRequest[VectorIndexProperties], context): - logger.debug(f"Received event: {event}") - request_type = event["RequestType"] - - if "ServiceToken" in event["ResourceProperties"]: - del event["ResourceProperties"]["ServiceToken"] - - if request_type == "Create": - return on_create(event) - if request_type == "Update": - return on_update(event) - if request_type == "Delete": - return on_delete(event) - raise Exception("Invalid request type: %s" % request_type) diff --git a/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_vpc_endpoint.py b/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_vpc_endpoint.py deleted file mode 100644 index a6006662..00000000 --- a/lambda/opensearch-serverless-custom-resources/custom_resources/opensearch_vpc_endpoint.py +++ /dev/null @@ -1,169 +0,0 @@ -# -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance -# with the License. A copy of the License is located at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES -# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions -# and limitations under the License. -# - -from opensearchpy import (OpenSearch, AuthorizationException) - -import boto3 -import logging -import os -import uuid - -from tenacity import ( - retry, - retry_if_exception_type, - stop_after_attempt, - wait_exponential_jitter, -) - -from typing import List, TypedDict - -from custom_resources.cr_types import CustomResourceRequest, CustomResourceResponse -from custom_resources.opensearch_index import connect_opensearch - -LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") - -logger = logging.getLogger(__name__) -logger.setLevel(LOG_LEVEL) - - -class VpcEndpointProperties(TypedDict): - Endpoint: str - DomainArn: str - SubnetIds: List[str] - SecurityGroupIds: List[str] - -def validate_event(event: CustomResourceRequest[VpcEndpointProperties]) -> bool: - if event["ResourceProperties"] is None: - raise ValueError("ResourceProperties is required") - if event["ResourceProperties"]["Endpoint"] is None: - raise ValueError("Endpoint is required") - if event["ResourceProperties"]["DomainArn"] is None: - raise ValueError("DomainArn is required") - if event["ResourceProperties"]["SubnetIds"] is None: - raise ValueError("SubnetIds is required") - if event["ResourceProperties"]["SecurityGroupIds"] is None: - raise ValueError("SecurityGroupIds is required") - -@retry( - retry=retry_if_exception_type(AuthorizationException), - stop=stop_after_attempt(30), - wait=wait_exponential_jitter(1, 3), -) -def handle_create( - client: OpenSearch, - domain_arn: str, - subnet_ids: List[str], - security_group_ids: List[str], - client_token: str -): - try: - response = client.create_vpc_endpoint( - DomainArn= domain_arn, - VpcOptions={ - "SubnetIds": subnet_ids, - "SecurityGroupIds": security_group_ids, - }, - ClientToken=client_token, - ) - except Exception as e: - logger.error(f"Error creating VPC endpoint for domain: {domain_arn}") - logger.exception(e) - raise e - return response["VpcEndpoint"]["VpcEndpointId"] - -@retry( - retry=retry_if_exception_type(AuthorizationException), - stop=stop_after_attempt(30), - wait=wait_exponential_jitter(1, 3), -) -def handle_update( - client: OpenSearch, - vpc_endpoint_id: str, - subnet_ids: List[str], - security_group_ids: List[str] -): - try: - response = client.update_vpc_endpoint( - VpcEndpointId=vpc_endpoint_id, - VpcOptions={ - "SubnetIds": subnet_ids, - "SecurityGroupIds": security_group_ids, - }, - ) - except Exception as e: - logger.error(f"Error updating VPC endpoint: {vpc_endpoint_id}") - logger.exception(e) - raise e - return response["VpcEndpoint"]["VpcEndpointId"] - -@retry( - retry=retry_if_exception_type(AuthorizationException), - stop=stop_after_attempt(30), - wait=wait_exponential_jitter(1, 3), -) -def handle_delete( - client: OpenSearch, - vpc_endpoint_id: str, -): - try: - response = client.delete_vpc_endpoint( - VpcEndpointId=vpc_endpoint_id, - ) - except Exception as e: - logger.error(f"Error deleting VPC endpoint: {vpc_endpoint_id}") - logger.exception(e) - raise e - return response["VpcEndpointSummary"]["VpcEndpointId"] - -def on_create(event: CustomResourceRequest[VpcEndpointProperties]) -> CustomResourceResponse: - validate_event(event) - client = connect_opensearch(event["ResourceProperties"]["Endpoint"]) - physical_id = handle_create(client, - event["ResourceProperties"]["DomainArn"], - event["ResourceProperties"]["SubnetIds"], - event["ResourceProperties"]["SecurityGroupIds"], - str(uuid.uuid4()) - ) - return {"PhysicalResourceId": physical_id} - -def on_update( - event: CustomResourceRequest[VpcEndpointProperties], -) -> CustomResourceResponse: - validate_event(event) - client = connect_opensearch(event["ResourceProperties"]["Endpoint"]) - physical_id = handle_update(client, - event["PhysicalResourceId"], - event["ResourceProperties"]["SubnetIds"], - event["ResourceProperties"]["SecurityGroupIds"] - ) - return {"PhysicalResourceId": physical_id} -def on_delete( - event: CustomResourceRequest[VpcEndpointProperties], -) -> CustomResourceResponse: - validate_event(event) - client = connect_opensearch(event["ResourceProperties"]["Endpoint"]) - pyhiscal_id = handle_delete(client, event["PhysicalResourceId"]) - - return {"PhysicalResourceId": pyhiscal_id} - - -def on_event(event, context): - logger.info(f"event: {event}") - request_type = event["RequestType"] - if request_type == "Create": - return on_create(event, context) - if request_type == "Update": - return on_update(event, context) - if request_type == "Delete": - return on_delete(event, context) - raise Exception("Invalid request type: %s" % request_type) \ No newline at end of file diff --git a/lambda/opensearch-serverless-custom-resources/poetry.lock b/lambda/opensearch-serverless-custom-resources/poetry.lock deleted file mode 100644 index f33e71aa..00000000 --- a/lambda/opensearch-serverless-custom-resources/poetry.lock +++ /dev/null @@ -1,452 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. - -[[package]] -name = "boto3" -version = "1.36.17" -description = "The AWS SDK for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "boto3-1.36.17-py3-none-any.whl", hash = "sha256:59bcf0c4b04d9cc36f8b418ad17ab3c4a99a21a175d2fad7096aa21cbe84630b"}, - {file = "boto3-1.36.17.tar.gz", hash = "sha256:5ecae20e780a3ce9afb3add532b61c466a8cb8960618e4fa565b3883064c1346"}, -] - -[package.dependencies] -botocore = ">=1.36.17,<1.37.0" -jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.11.0,<0.12.0" - -[package.extras] -crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] - -[[package]] -name = "botocore" -version = "1.36.17" -description = "Low-level, data-driven core of boto 3." -optional = false -python-versions = ">=3.8" -files = [ - {file = "botocore-1.36.17-py3-none-any.whl", hash = "sha256:069858b2fd693548035d7fd53a774e37e4260fea64e0ac9b8a3aee904f9321df"}, - {file = "botocore-1.36.17.tar.gz", hash = "sha256:cec13e0a7ce78e71aad0b397581b4e81824c7981ef4c261d2e296d200c399b09"}, -] - -[package.dependencies] -jmespath = ">=0.7.1,<2.0.0" -python-dateutil = ">=2.1,<3.0.0" -urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} - -[package.extras] -crt = ["awscrt (==0.23.8)"] - -[[package]] -name = "certifi" -version = "2025.1.31" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, - {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "events" -version = "0.5" -description = "Bringing the elegance of C# EventHandler to Python" -optional = false -python-versions = "*" -files = [ - {file = "Events-0.5-py3-none-any.whl", hash = "sha256:a7286af378ba3e46640ac9825156c93bdba7502174dd696090fdfcd4d80a1abd"}, -] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "jmespath" -version = "1.0.1" -description = "JSON Matching Expressions" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "opensearch-py" -version = "2.8.0" -description = "Python client for OpenSearch" -optional = false -python-versions = "<4,>=3.8" -files = [ - {file = "opensearch_py-2.8.0-py3-none-any.whl", hash = "sha256:52c60fdb5d4dcf6cce3ee746c13b194529b0161e0f41268b98ab8f1624abe2fa"}, - {file = "opensearch_py-2.8.0.tar.gz", hash = "sha256:6598df0bc7a003294edd0ba88a331e0793acbb8c910c43edf398791e3b2eccda"}, -] - -[package.dependencies] -certifi = ">=2024.07.04" -Events = "*" -python-dateutil = "*" -requests = ">=2.32.0,<3.0.0" -urllib3 = {version = ">=1.26.19,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1,<3", markers = "python_version >= \"3.10\""} - -[package.extras] -async = ["aiohttp (>=3.9.4,<4)"] -develop = ["black (>=24.3.0)", "botocore", "coverage (<8.0.0)", "jinja2", "myst_parser", "pytest (>=3.0.0)", "pytest-cov", "pytest-mock (<4.0.0)", "pytz", "pyyaml", "requests (>=2.0.0,<3.0.0)", "sphinx", "sphinx_copybutton", "sphinx_rtd_theme"] -docs = ["aiohttp (>=3.9.4,<4)", "myst_parser", "sphinx", "sphinx_copybutton", "sphinx_rtd_theme"] -kerberos = ["requests_kerberos"] - -[[package]] -name = "packaging" -version = "24.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, -] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "s3transfer" -version = "0.11.2" -description = "An Amazon S3 Transfer Manager" -optional = false -python-versions = ">=3.8" -files = [ - {file = "s3transfer-0.11.2-py3-none-any.whl", hash = "sha256:be6ecb39fadd986ef1701097771f87e4d2f821f27f6071c872143884d2950fbc"}, - {file = "s3transfer-0.11.2.tar.gz", hash = "sha256:3b39185cb72f5acc77db1a58b6e25b977f28d20496b6e58d6813d75f464d632f"}, -] - -[package.dependencies] -botocore = ">=1.36.0,<2.0a.0" - -[package.extras] -crt = ["botocore[crt] (>=1.36.0,<2.0a.0)"] - -[[package]] -name = "six" -version = "1.17.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, - {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, -] - -[[package]] -name = "tenacity" -version = "8.5.0" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, - {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, -] - -[package.extras] -doc = ["reno", "sphinx"] -test = ["pytest", "tornado (>=4.5)", "typeguard"] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.11" -content-hash = "4bdceed1e9b7b922f8788752b49e42c79fdf11bcd150f0145b2e8df3427b27c2" diff --git a/lambda/opensearch-serverless-custom-resources/pyproject.toml b/lambda/opensearch-serverless-custom-resources/pyproject.toml deleted file mode 100644 index 502cc3a0..00000000 --- a/lambda/opensearch-serverless-custom-resources/pyproject.toml +++ /dev/null @@ -1,20 +0,0 @@ -[build-system] -requires = [ "poetry_core>=1.0.0" ] -build-backend = "poetry.core.masonry.api" - -[tool.poetry] -name = "custom_resources" -version = "0.1.0" -description = "" -authors = [ "Amazon Web Services - Prototyping and Cloud Engineering" ] - -[tool.poetry.dependencies] -boto3 = "^1.33.6" -opensearch-py = "^2.4.2" -python = "^3.11" -tenacity = "^8.2.3" - -[tool.poetry.dev-dependencies] -mypy = "^1.2.0" -pytest = "^7.4.3" - diff --git a/src/cdk-lib/bedrock/knowledge-bases/vector-knowledge-base.ts b/src/cdk-lib/bedrock/knowledge-bases/vector-knowledge-base.ts index 409f9d3d..ec65225b 100644 --- a/src/cdk-lib/bedrock/knowledge-bases/vector-knowledge-base.ts +++ b/src/cdk-lib/bedrock/knowledge-bases/vector-knowledge-base.ts @@ -24,7 +24,7 @@ import { } from './knowledge-base'; import { generatePhysicalNameV2 } from '../../../common/helpers/utils'; import { ExistingAmazonAuroraVectorStore, AmazonAuroraVectorStore } from '../../amazonaurora'; -import { VectorIndex } from '../../opensearch-vectorindex'; +import { VectorIndex, SpaceType, OpensearchFieldType, EngineType, AlgorithmNameType } from '../../opensearch-vectorindex'; import { VectorCollection } from '../../opensearchserverless'; import { PineconeVectorStore } from '../../pinecone'; import { Agent } from '../agents/agent'; @@ -424,7 +424,7 @@ export class VectorKnowledgeBase extends VectorKnowledgeBaseBase { validateModel(embeddingsModel, vectorType); validateVectorIndex(props.vectorStore, props.vectorIndex, props.vectorField, props.indexName); if (props.vectorIndex) { - validateIndexParameters(props.vectorIndex, indexName, vectorField); + validateIndexParameters(props.vectorIndex, indexName); } this.name = props.name ?? generatePhysicalNameV2(this, 'KB', { maxLength: 32 }); @@ -531,22 +531,32 @@ export class VectorKnowledgeBase extends VectorKnowledgeBaseBase { this.vectorIndex = new VectorIndex(this, 'KBIndex', { collection: this.vectorStore as VectorCollection, indexName, - vectorField, - vectorDimensions: embeddingsModel.vectorDimensions!, - precision: props.vectorType === VectorType.BINARY ? 'Binary' : 'float', - distanceType: props.vectorType === VectorType.BINARY ? 'hamming' : 'l2', - mappings: [ - { - mappingField: 'AMAZON_BEDROCK_TEXT_CHUNK', - dataType: 'text', - filterable: true, - }, - { - mappingField: 'AMAZON_BEDROCK_METADATA', - dataType: 'text', - filterable: false, + settings: { + knn: true, + }, + mappings: { + properties: { + vectorField: { + type: OpensearchFieldType.KNN_VECTOR, + dimension: embeddingsModel.vectorDimensions!, + //data_type: props.vectorType === VectorType.BINARY ? 'Binary' : 'float', <- This is missing in L1 CfnIndex props + method: { + engine: EngineType.FAISS, + spaceType: props.vectorType === VectorType.BINARY ? SpaceType.HAMMING : SpaceType.L2, + name: AlgorithmNameType.HNSW, + parameters: {}, + }, + }, + AMAZON_BEDROCK_TEXT_CHUNK: { + type: OpensearchFieldType.TEXT, + index: true, + }, + AMAZON_BEDROCK_METADATA: { + type: OpensearchFieldType.TEXT, + index: false, + }, }, - ], + }, }); this.vectorIndex.node.addDependency(this.vectorStore); @@ -834,7 +844,7 @@ function validateVectorIndex(vectorStore: any, vectorIndex: any, vectorField: an * * @internal This is an internal core function and should not be called directly. */ -function validateIndexParameters(vectorIndex: VectorIndex, indexName: string, vectorField: string) { +function validateIndexParameters(vectorIndex: VectorIndex, indexName: string) { if (vectorIndex.indexName !== 'bedrock-knowledge-base-default-index') { if (vectorIndex.indexName !== indexName) { throw new Error( @@ -846,7 +856,7 @@ function validateIndexParameters(vectorIndex: VectorIndex, indexName: string, ve ); } } - if (vectorIndex.vectorField !== 'bedrock-knowledge-base-default-vector') { + /*if (vectorIndex.vectorField !== 'bedrock-knowledge-base-default-vector') { if (vectorIndex.vectorField !== vectorField) { throw new Error( 'Default value of vectorField is `bedrock-knowledge-base-default-vector`.' + @@ -856,7 +866,7 @@ function validateIndexParameters(vectorIndex: VectorIndex, indexName: string, ve ' then do not assign vectorField in KnowledgeBase construct.', ); } - } + }*/ } /** diff --git a/src/cdk-lib/opensearch-vectorindex/README.md b/src/cdk-lib/opensearch-vectorindex/README.md index f74a2d4d..74a05e80 100644 --- a/src/cdk-lib/opensearch-vectorindex/README.md +++ b/src/cdk-lib/opensearch-vectorindex/README.md @@ -51,102 +51,39 @@ const vectorStore = new opensearchserverless.VectorCollection( 'VectorCollection' ); -new opensearch_vectorindex.VectorIndex(this, 'VectorIndex', { - collection: vectorStore, - indexName: 'bedrock-knowledge-base-default-index', - vectorField: 'bedrock-knowledge-base-default-vector', - vectorDimensions: 1536, - precision: 'float', - distanceType: 'l2', - mappings: [ - { - mappingField: 'AMAZON_BEDROCK_TEXT_CHUNK', - dataType: 'text', - filterable: true, - }, - { - mappingField: 'AMAZON_BEDROCK_METADATA', - dataType: 'text', - filterable: false, +new opensearch_vectorindex.VectorIndex(this, 'KBIndex', { + collection: vectorStore as VectorCollection, + indexName, + settings: { + knn: true, + }, + mappings: { + properties: { + vectorField: { + type: opensearch_vectorindex.OpensearchFieldType.KNN_VECTOR, + dimension: embeddingsModel.vectorDimensions!, + method: { + engine: opensearch_vectorindex.EngineType.FAISS, + spaceType: SpaceType.L2, + name: AlgorithmNameType.HNSW, + parameters: {}, + } + }, + 'AMAZON_BEDROCK_TEXT_CHUNK': { + type: OpensearchFieldType.TEXT, + index: true, + }, + 'AMAZON_BEDROCK_METADATA': { + type: OpensearchFieldType.TEXT, + index: false, + } }, - ], - analyzer: { - characterFilters: [opensearchserverless.CharacterFilterType.ICU_NORMALIZER], - tokenizer: opensearchserverless.TokenizerType.KUROMOJI_TOKENIZER, - tokenFilters: [ - opensearchserverless.TokenFilterType.KUROMOJI_BASEFORM, - opensearchserverless.TokenFilterType.JA_STOP, - ], }, }); ``` -Python - -```python -from cdklabs.generative_ai_cdk_constructs import ( - opensearchserverless, - opensearch_vectorindex, -) - -vectorCollection = opensearchserverless.VectorCollection(self, "VectorCollection") - -vectorIndex = opensearch_vectorindex.VectorIndex(self, "VectorIndex", - vector_dimensions= 1536, - collection=vectorCollection, - index_name='bedrock-knowledge-base-default-index', - vector_field='bedrock-knowledge-base-default-vector', - precision='float', - distance_type='l2', - mappings= [ - opensearch_vectorindex.MetadataManagementFieldProps( - mapping_field='AMAZON_BEDROCK_TEXT_CHUNK', - data_type='text', - filterable=True - ), - opensearch_vectorindex.MetadataManagementFieldProps( - mapping_field='AMAZON_BEDROCK_METADATA', - data_type='text', - filterable=False - ) - ], - analyzer=opensearchserverless.AnalyzerProps( - character_filters=[opensearchserverless.CharacterFilterType.ICU_NORMALIZER], - tokenizer=opensearchserverless.TokenizerType.KUROMOJI_TOKENIZER, - token_filters=[ - opensearchserverless.TokenFilterType.KUROMOJI_BASEFORM, - opensearchserverless.TokenFilterType.JA_STOP, - ], - ) -) -``` - ## Default values -Behind the scenes, the custom resource creates a k-NN vector in the OpenSearch index, allowing to perform different kinds of k-NN search. The knn_vector field is highly configurable and can serve many different k-NN workloads. It is created as follows: - -Python - -```py -"properties": { - vector_field: { - "type": "knn_vector", - "dimension": dimensions, - "data_type": precision, - "method": { - "engine": "faiss", - "space_type": distance_type, - "name": "hnsw", - "parameters": {}, - }, - }, - "id": { - "type": "text", - "fields": {"keyword": {"type": "keyword", "ignore_above": 256}}, - }, - }, -``` - -Users can currently configure the ```vector_field```, ```dimension```, ```data_type```, and ```distance_type``` fields through the construct interface. +Behind the scenes, the custom resource creates a k-NN vector in the OpenSearch index, allowing to perform different kinds of k-NN search. The knn_vector field is highly configurable and can serve many different k-NN workloads. For details on the different settings, you can refer to the [Knn plugin documentation](https://opensearch.org/docs/latest/search-plugins/knn/knn-index/). \ No newline at end of file diff --git a/src/cdk-lib/opensearch-vectorindex/vector-index.ts b/src/cdk-lib/opensearch-vectorindex/vector-index.ts index 8085c7ab..ca43b006 100644 --- a/src/cdk-lib/opensearch-vectorindex/vector-index.ts +++ b/src/cdk-lib/opensearch-vectorindex/vector-index.ts @@ -11,135 +11,144 @@ * and limitations under the License. */ -import * as path from 'path'; import * as cdk from 'aws-cdk-lib'; -import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as oss from 'aws-cdk-lib/aws-opensearchserverless'; import { Construct } from 'constructs'; -import { buildCustomResourceProvider } from '../../common/helpers/custom-resource-provider-helper'; import { generatePhysicalNameV2 } from '../../common/helpers/utils'; import { VectorCollection } from '../opensearchserverless'; -import { - CharacterFilterType, - TokenFilterType, - TokenizerType, -} from '../opensearchserverless/analysis-plugins'; /** - * Metadata field definitions. + * The field data type. Must be a valid OpenSearch field type. */ -export interface MetadataManagementFieldProps { +export enum OpensearchFieldType { + TEXT = 'text', + KNN_VECTOR = 'knn_vector', +} + +/** + * The k-NN search engine to use. + */ +export enum EngineType { /** - * The name of the field. + * C++ implementation. */ - readonly mappingField: string; + FAISS = 'faiss', /** - * The data type of the field. + * C++ implementation. */ - readonly dataType: string; + NMSLIB = 'nmslib', /** - * Whether the field is filterable. + * Java implementation. */ - readonly filterable: boolean; + LUCENE = 'lucene', } /** - * Metadata field definitions as the API expects them. - * - * @internal - JSII requires the exported interface to have camel camelCase properties, - * but the API expect PascalCase properties + * The algorithm name for k-NN search. */ -type MetadataManagementField = { - /** - * The name of the field. - */ - readonly MappingField: string; +export enum AlgorithmNameType { + HNSW = 'hnsw', + IVF = 'ivf', +} + +/** + * The distance function used for k-NN search. + */ +export enum SpaceType { + L2 = 'l2', + L1 = 'l1', + LINF = 'linf', + COSINESIMILARITY = 'cosinesimil', + INNERPRODUCT = 'innerproduct', + HAMMING = 'hamming', +} + +/** + * Additional parameters for the k-NN algorithm. + */ +export interface MethodParameters { /** - * The data type of the field. + * The size of the dynamic list used during k-NN graph creation. */ - readonly DataType: string; + readonly efConstruction?: number; /** - * Whether the field is filterable. + * Number of neighbors to consider during k-NN search. */ - readonly Filterable: boolean; -}; + readonly m?: number; +} /** - * Properties for the Custom::OpenSearchIndex custom resource. - * - * @internal + * Configuration for k-NN search method. */ -interface VectorIndexResourceProps { +export interface Method { + /** + * The k-NN search engine to use. + */ + readonly engine: EngineType; /** - * The OpenSearch Endpoint. + * The algorithm name for k-NN search. */ - readonly Endpoint: string; + readonly name: AlgorithmNameType; /** - * The name of the index. + * Additional parameters for the k-NN algorithm. */ - readonly IndexName: string; + readonly parameters?: MethodParameters; /** - * The name of the vector field. + * The distance function used for k-NN search. */ - readonly VectorField: string; + readonly spaceType?: SpaceType; +} + +export interface PropertyMapping { /** - * The number of dimensions in the vector. + * Dimension size for vector fields, defines the number of dimensions in the vector. */ - readonly Dimensions: number; + readonly dimension?: number; /** - * The data_type of the binary vector index. + * Whether the index is indexed. Previously, this was called `filterable`. */ - readonly Precision: string; + readonly index?: boolean; /** - * The space_type of the binary vector index. + * Configuration for k-NN search method. */ - readonly DistanceType: string; + readonly method?: Method; /** - * The metadata management fields. + * Defines the fields within the mapping, including their types and configurations. */ - readonly MetadataManagement: MetadataManagementField[]; + readonly properties?: Record; /** - * The analyzer to use. + * The field data type. Must be a valid OpenSearch field type. */ - readonly Analyzer?: AnalyzerProps; + readonly type: OpensearchFieldType; + /** + * Default value for the field when not specified in a document. + */ + readonly value?: string; } /** - * Properties for the Analyzer used in Custom::OpenSearchIndex custom resource. - * - * @internal - JSII requires the exported interface to have camel camelCase properties + * Index settings for the OpenSearch Serverless index. */ -interface AnalyzerProps { +export interface IndexSettings { /** - * The analyzers to use. + * Enable or disable k-nearest neighbor search capability. */ - readonly CharacterFilters: CharacterFilterType[]; + readonly knn?: boolean; /** - * The tokenizer to use. + * The size of the dynamic list for the nearest neighbors. */ - readonly Tokenizer: TokenizerType; + readonly knnAlgoParamEfSearch?: number; /** - * The token filters to use. + * How often to perform a refresh operation. For example, 1s or 5s. */ - readonly TokenFilters: TokenFilterType[]; + readonly refreshInterval?: cdk.Duration; } /** - * Properties for the Analyzer. + * The mappings for the OpenSearch Serverless index. */ -export interface Analyzer { - /** - * The analyzers to use. - */ - readonly characterFilters: CharacterFilterType[]; - /** - * The tokenizer to use. - */ - readonly tokenizer: TokenizerType; - /** - * The token filters to use. - */ - readonly tokenFilters: TokenFilterType[]; +export interface MappingsProperty { + readonly properties: Record; } /** @@ -155,52 +164,76 @@ export interface VectorIndexProps { */ readonly indexName: string; /** - * The name of the vector field. + * The metadata management fields. */ - readonly vectorField: string; + readonly mappings?: MappingsProperty; /** - * The number of dimensions in the vector. + * The settings for the index. */ - readonly vectorDimensions: number; - readonly precision: string; - readonly distanceType: string; + readonly settings?: IndexSettings; +} + +export interface VectorIndexAttributes { /** - * The metadata management fields. + * The endpoint of the collection */ - readonly mappings: MetadataManagementFieldProps[]; + readonly collectionEndpoint: string; /** - * The analyzer to use. - * @default - No analyzer. + * The name of the index */ - readonly analyzer?: Analyzer; + readonly indexName: string; +} + +/** + * Interface representing a vector index + */ +export interface IVectorIndex extends cdk.IResource { + /** + * The endpoint of the collection + */ + readonly collectionEndpoint: string; + /** + * The name of the index + */ + readonly indexName: string; } /** - * Deploy a vector index on the collection. + * A new or imported vector index. */ -export class VectorIndex extends cdk.Resource { +abstract class VectorIndexBase extends cdk.Resource implements IVectorIndex { + public abstract readonly collectionEndpoint: string; + public abstract readonly indexName: string; + + //TODO: add the fromVectorIndexAttributes method +} + +/** + * Provides a vector index in Amazon OpenSearch Serverless. + */ +export class VectorIndex extends VectorIndexBase { /** * The name of the index. */ public readonly indexName: string; /** - * The name of the vector field. + * The endpoint of the collection */ - public readonly vectorField: string; + public readonly collectionEndpoint: string; + /** - * The number of dimensions in the vector. + * Instance of CfnIndex. */ - public readonly vectorDimensions: number; + private readonly _resource: oss.CfnIndex; + constructor(scope: Construct, id: string, props: VectorIndexProps) { super(scope, id); + // ------------------------------------------------------ + // Set attributes or defaults + // ------------------------------------------------------ this.indexName = props.indexName; - this.vectorField = props.vectorField; - this.vectorDimensions = props.vectorDimensions; - - const crProvider = OpenSearchIndexCRProvider.getProvider(this); - crProvider.role.addManagedPolicy(props.collection.aossPolicy); const manageIndexPolicyName = generatePhysicalNameV2( this, @@ -232,58 +265,57 @@ export class VectorIndex extends cdk.Resource { ResourceType: 'collection', }, ], - Principal: [crProvider.role.roleArn], + Principal: ['*'], Description: '', }, ]), }, ); - const analyzerProps = props.analyzer - ? { - CharacterFilters: props.analyzer.characterFilters, - Tokenizer: props.analyzer.tokenizer, - TokenFilters: props.analyzer.tokenFilters, - } - : undefined; - const vectorIndex = new cdk.CustomResource(this, 'VectorIndex', { - serviceToken: crProvider.serviceToken, - properties: { - Endpoint: `${props.collection.collectionId}.${ - cdk.Stack.of(this).region - }.aoss.amazonaws.com`, - IndexName: props.indexName, - VectorField: props.vectorField, - Dimensions: props.vectorDimensions, - Precision: props.precision, - DistanceType: props.distanceType, - MetadataManagement: props.mappings.map((m) => { - return { - MappingField: m.mappingField, - DataType: m.dataType, - Filterable: m.filterable, - }; - }), - Analyzer: analyzerProps, - } as VectorIndexResourceProps, - resourceType: 'Custom::OpenSearchIndex', + // ------------------------------------------------------ + // L1 Instantiation + // ------------------------------------------------------ + this._resource = new oss.CfnIndex(this, 'VectorIndex', { + indexName: props.indexName, + collectionEndpoint: props.collection.collectionEndpoint, + mappings: this._renderMappings(props.mappings), + settings: this._renderIndexSettings(props.settings), }); - vectorIndex.node.addDependency(manageIndexPolicy); - vectorIndex.node.addDependency(props.collection); - vectorIndex.node.addDependency(props.collection.dataAccessPolicy); + this.collectionEndpoint = this._resource.collectionEndpoint; + + this._resource.addDependency(manageIndexPolicy); + this._resource.addDependency(props.collection.dataAccessPolicy); } -} -/** - * Custom Resource provider for OpenSearch Index operations. - * - * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. - */ -export const OpenSearchIndexCRProvider = buildCustomResourceProvider({ - providerName: 'OpenSearchIndexCRProvider', - codePath: path.join( - __dirname, '../../../lambda/opensearch-serverless-custom-resources'), - handler: 'custom_resources.on_event', - runtime: lambda.Runtime.PYTHON_3_12, -}); + /** + * Render the index settings. + */ + private _renderIndexSettings(props?: IndexSettings): oss.CfnIndex.IndexSettingsProperty { + if (!props) return {}; + + return { + index: { + knn: props?.knn, + knnAlgoParamEfSearch: props?.knnAlgoParamEfSearch, + refreshInterval: props?.refreshInterval?.toString(), + }, + }; + } + + /** + * Render the mappings. + */ + private _renderMappings(props?: MappingsProperty): oss.CfnIndex.MappingsProperty { + if (!props) return {}; + + const convertedProps: Record = {}; + for (const [key, value] of Object.entries(props.properties)) { + convertedProps[key] = value as unknown as oss.CfnIndex.PropertyMappingProperty; + } + + return { + properties: convertedProps, + }; + } +} diff --git a/test/cdk-lib/opensearch-vectorindex/vector-index.test.ts b/test/cdk-lib/opensearch-vectorindex/vector-index.test.ts index 47a9ff0f..eda6abee 100644 --- a/test/cdk-lib/opensearch-vectorindex/vector-index.test.ts +++ b/test/cdk-lib/opensearch-vectorindex/vector-index.test.ts @@ -14,22 +14,9 @@ import * as cdk from 'aws-cdk-lib'; import { Annotations, Match, Template } from 'aws-cdk-lib/assertions'; import * as iam from 'aws-cdk-lib/aws-iam'; -import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag'; -import { OpenSearchIndexCRProvider, VectorIndex } from '../../../src/cdk-lib/opensearch-vectorindex'; -import { VectorCollection, CharacterFilterType, TokenizerType, TokenFilterType } from '../../../src/cdk-lib/opensearchserverless'; - -// mock lambda.Code.fromDockerBuild() -jest.mock('aws-cdk-lib/aws-lambda', () => { - const actualLambda = jest.requireActual('aws-cdk-lib/aws-lambda'); - return { - ...actualLambda, - Code: { - ...actualLambda.Code, - fromDockerBuild: jest.fn(() => actualLambda.Code.fromInline('mockCode')), - fromAsset: jest.fn(() => actualLambda.Code.fromInline('mockCode')), - }, - }; -}); +import { AwsSolutionsChecks } from 'cdk-nag'; +import { AlgorithmNameType, EngineType, OpensearchFieldType, SpaceType, VectorIndex } from '../../../src/cdk-lib/opensearch-vectorindex'; +import { VectorCollection } from '../../../src/cdk-lib/opensearchserverless'; describe('OpenSearch Serverless Vector Index', () => { let template: Template; @@ -54,149 +41,30 @@ describe('OpenSearch Serverless Vector Index', () => { aossVectorIndex = new VectorIndex(stack, 'test-aoss-vector-index', { collection: aossVector, indexName: 'test-index', - distanceType: 'euclidian', - precision: 'fp32', - vectorField: 'vector', - vectorDimensions: 1536, - mappings: [ - { - mappingField: 'AMAZON_BEDROCK_TEXT_CHUNK', - dataType: 'text', - filterable: true, - }, - ], - }); - - NagSuppressions.addResourceSuppressionsByPath( - stack, - '/test-stack/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole', - [ - { - id: 'AwsSolutions-IAM4', - reason: 'CDK CustomResource LogRetention Lambda uses the AWSLambdaBasicExecutionRole AWS Managed Policy. Managed by CDK.', - }, - { - id: 'AwsSolutions-IAM5', - reason: 'CDK CustomResource LogRetention Lambda uses a wildcard to manage log streams created at runtime. Managed by CDK.', - }, - ], - true, - ); - - - aossVectorIndex.node.addDependency(aossVector.dataAccessPolicy); - - testRole = new iam.Role(stack, 'TestRole', { - assumedBy: new iam.AccountRootPrincipal(), - }); - - aossVector.grantDataAccess(testRole); - - app.synth(); - template = Template.fromStack(stack); - }); - - - test('Should have the correct resources', () => { - template.resourceCountIs('AWS::OpenSearchServerless::Collection', 1); - template.resourceCountIs('Custom::OpenSearchIndex', 1); - template.resourceCountIs('AWS::OpenSearchServerless::AccessPolicy', 2); - template.resourceCountIs('AWS::Lambda::Function', 3); - }); - - test('ManageIndexPolicy should allow CRProvider', () => { - const crProvider = OpenSearchIndexCRProvider.getProvider(stack); - const crRoleLogicalId = stack.getLogicalId(crProvider.role.node.defaultChild as iam.CfnRole); - - template.hasResource('AWS::OpenSearchServerless::AccessPolicy', { - Properties: { - Name: Match.stringLikeRegexp('^manageindexpolicy[a-z0-9]+'), - Policy: { - 'Fn::Join': Match.arrayWith([ - Match.arrayWith([ - Match.objectEquals({ - 'Fn::GetAtt': Match.arrayWith([ - crRoleLogicalId, - ]), - }), - ]), - ]), - }, - Type: 'data', + settings: { + knn: true, }, - }); - }); - - test('No unsuppressed Errors', () => { - const errors = Annotations.fromStack(stack).findError( - '*', - Match.stringLikeRegexp('AwsSolutions-.*'), - ); - expect(errors).toHaveLength(0); - }); -}); - -describe('OpenSearch Serverless Vector Index with analyzer', () => { - let template: Template; - let app: cdk.App; - let stack: cdk.Stack; - let aossVector: VectorCollection; - let aossVectorIndex: VectorIndex; - let testRole: iam.Role; - - beforeAll(() => { - app = new cdk.App(); - cdk.Aspects.of(app).add(new AwsSolutionsChecks()); - stack = new cdk.Stack(app, 'test-stack', { - env: { - account: '123456789012', - region: 'us-east-1', - }, - }); - - aossVector = new VectorCollection(stack, 'test-aoss-vector'); - - aossVectorIndex = new VectorIndex(stack, 'test-aoss-vector-index', { - collection: aossVector, - indexName: 'test-index', - vectorField: 'vector', - vectorDimensions: 1536, - distanceType: 'euclidian', - precision: 'fp32', - mappings: [ - { - mappingField: 'AMAZON_BEDROCK_TEXT_CHUNK', - dataType: 'text', - filterable: true, + mappings: { + properties: { + vectorField: { + type: OpensearchFieldType.KNN_VECTOR, + dimension: 1536, + //data_type: props.vectorType === VectorType.BINARY ? 'Binary' : 'float', <- This is missing in L1 CfnIndex props + method: { + engine: EngineType.FAISS, + spaceType: SpaceType.L2, + name: AlgorithmNameType.HNSW, + parameters: {}, + }, + }, + AMAZON_BEDROCK_TEXT_CHUNK: { + type: OpensearchFieldType.TEXT, + index: true, + }, }, - ], - analyzer: { - characterFilters: [CharacterFilterType.ICU_NORMALIZER], - tokenizer: TokenizerType.KUROMOJI_TOKENIZER, - tokenFilters: [ - TokenFilterType.KUROMOJI_BASEFORM, - TokenFilterType.JA_STOP, - ], }, }); - NagSuppressions.addResourceSuppressionsByPath( - stack, - '/test-stack/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole', - [ - { - id: 'AwsSolutions-IAM4', - reason: 'CDK CustomResource LogRetention Lambda uses the AWSLambdaBasicExecutionRole AWS Managed Policy. Managed by CDK.', - }, - { - id: 'AwsSolutions-IAM5', - reason: 'CDK CustomResource LogRetention Lambda uses a wildcard to manage log streams created at runtime. Managed by CDK.', - }, - ], - true, - ); - - aossVectorIndex.node.addDependency(aossVector.dataAccessPolicy); testRole = new iam.Role(stack, 'TestRole', { @@ -211,34 +79,9 @@ describe('OpenSearch Serverless Vector Index with analyzer', () => { test('Should have the correct resources', () => { - console.log(template.toJSON()); template.resourceCountIs('AWS::OpenSearchServerless::Collection', 1); - template.resourceCountIs('Custom::OpenSearchIndex', 1); + template.resourceCountIs('AWS::OpenSearchServerless::Index', 1); template.resourceCountIs('AWS::OpenSearchServerless::AccessPolicy', 2); - template.resourceCountIs('AWS::Lambda::Function', 3); - }); - - test('ManageIndexPolicy should allow CRProvider', () => { - const crProvider = OpenSearchIndexCRProvider.getProvider(stack); - const crRoleLogicalId = stack.getLogicalId(crProvider.role.node.defaultChild as iam.CfnRole); - - template.hasResource('AWS::OpenSearchServerless::AccessPolicy', { - Properties: { - Name: Match.stringLikeRegexp('^manageindexpolicy[a-z0-9]+'), - Policy: { - 'Fn::Join': Match.arrayWith([ - Match.arrayWith([ - Match.objectEquals({ - 'Fn::GetAtt': Match.arrayWith([ - crRoleLogicalId, - ]), - }), - ]), - ]), - }, - Type: 'data', - }, - }); }); test('No unsuppressed Errors', () => { diff --git a/test/common/helpers/custom-resource-provider-helper.test.ts b/test/common/helpers/custom-resource-provider-helper.test.ts index 52647524..2e92b7cc 100644 --- a/test/common/helpers/custom-resource-provider-helper.test.ts +++ b/test/common/helpers/custom-resource-provider-helper.test.ts @@ -20,7 +20,7 @@ import { buildCustomResourceProvider } from '../../../src/common/helpers/custom- const AOSSCRProvider = buildCustomResourceProvider({ providerName: 'OpenSearchIndexCRProvider', codePath: path.join( - __dirname, '../../../lambda/opensearch-serverless-custom-resources'), + __dirname, '../../../lambda/amazon-aurora-pgvector-custom-resources'), handler: 'custom_resources.on_event', runtime: lambda.Runtime.PYTHON_3_12, });