2020import org .apache .hc .client5 .http .impl .auth .BasicCredentialsProvider ;
2121import org .apache .hc .core5 .http .HttpHost ;
2222import org .opensearch .client .opensearch .OpenSearchClient ;
23+ import org .opensearch .client .transport .OpenSearchTransport ;
24+ import org .opensearch .client .transport .aws .AwsSdk2Transport ;
25+ import org .opensearch .client .transport .aws .AwsSdk2TransportOptions ;
2326import org .opensearch .client .transport .httpclient5 .ApacheHttpClient5TransportBuilder ;
2427import org .springframework .ai .embedding .EmbeddingModel ;
2528import org .springframework .ai .vectorstore .OpenSearchVectorStore ;
2629import org .springframework .boot .autoconfigure .AutoConfiguration ;
2730import org .springframework .boot .autoconfigure .condition .ConditionalOnClass ;
2831import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
32+ import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingClass ;
2933import org .springframework .boot .context .properties .EnableConfigurationProperties ;
3034import org .springframework .context .annotation .Bean ;
35+ import org .springframework .context .annotation .Configuration ;
36+ import software .amazon .awssdk .auth .credentials .AwsBasicCredentials ;
37+ import software .amazon .awssdk .auth .credentials .StaticCredentialsProvider ;
38+ import software .amazon .awssdk .http .SdkHttpClient ;
39+ import software .amazon .awssdk .http .apache .ApacheHttpClient ;
40+ import software .amazon .awssdk .regions .Region ;
3141
3242import java .net .URISyntaxException ;
3343import java .util .List ;
@@ -48,45 +58,76 @@ PropertiesOpenSearchConnectionDetails openSearchConnectionDetails(OpenSearchVect
4858 @ ConditionalOnMissingBean
4959 OpenSearchVectorStore vectorStore (OpenSearchVectorStoreProperties properties , OpenSearchClient openSearchClient ,
5060 EmbeddingModel embeddingModel ) {
51- return new OpenSearchVectorStore (
52- Optional .ofNullable (properties .getIndexName ()). orElse ( OpenSearchVectorStore . DEFAULT_INDEX_NAME ),
53- openSearchClient , embeddingModel , Optional . ofNullable ( properties . getMappingJson ())
54- . orElse ( OpenSearchVectorStore . DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION_1536 ) );
61+ var indexName = Optional . ofNullable ( properties . getIndexName ()). orElse ( OpenSearchVectorStore . DEFAULT_INDEX_NAME );
62+ var mappingJson = Optional .ofNullable (properties .getMappingJson ())
63+ . orElse ( OpenSearchVectorStore . DEFAULT_MAPPING_EMBEDDING_TYPE_KNN_VECTOR_DIMENSION_1536 );
64+ return new OpenSearchVectorStore ( indexName , openSearchClient , embeddingModel , mappingJson );
5565 }
5666
57- @ Bean
58- @ ConditionalOnMissingBean
59- OpenSearchClient openSearchClient (OpenSearchConnectionDetails connectionDetails ) {
60- HttpHost [] httpHosts = connectionDetails .getUris ()
61- .stream ()
62- .map (s -> createHttpHost (s ))
63- .toArray (HttpHost []::new );
64- ApacheHttpClient5TransportBuilder transportBuilder = ApacheHttpClient5TransportBuilder .builder (httpHosts );
65-
66- Optional .ofNullable (connectionDetails .getUsername ())
67- .map (username -> createBasicCredentialsProvider (httpHosts [0 ], username , connectionDetails .getPassword ()))
68- .ifPresent (basicCredentialsProvider -> transportBuilder
69- .setHttpClientConfigCallback (httpAsyncClientBuilder -> httpAsyncClientBuilder
70- .setDefaultCredentialsProvider (basicCredentialsProvider )));
71-
72- return new OpenSearchClient (transportBuilder .build ());
73- }
67+ @ Configuration (proxyBeanMethods = false )
68+ @ ConditionalOnMissingClass ({ "software.amazon.awssdk.regions.Region" ,
69+ "software.amazon.awssdk.http.apache.ApacheHttpClient" })
70+ static class OpenSearchConfiguration {
71+
72+ @ Bean
73+ @ ConditionalOnMissingBean
74+ OpenSearchClient openSearchClient (OpenSearchVectorStoreProperties properties ) {
75+ HttpHost [] httpHosts = properties .getUris ().stream ().map (s -> createHttpHost (s )).toArray (HttpHost []::new );
76+ ApacheHttpClient5TransportBuilder transportBuilder = ApacheHttpClient5TransportBuilder .builder (httpHosts );
77+
78+ Optional .ofNullable (properties .getUsername ())
79+ .map (username -> createBasicCredentialsProvider (httpHosts [0 ], username , properties .getPassword ()))
80+ .ifPresent (basicCredentialsProvider -> transportBuilder
81+ .setHttpClientConfigCallback (httpAsyncClientBuilder -> httpAsyncClientBuilder
82+ .setDefaultCredentialsProvider (basicCredentialsProvider )));
83+ return new OpenSearchClient (transportBuilder .build ());
84+ }
85+
86+ private BasicCredentialsProvider createBasicCredentialsProvider (HttpHost httpHost , String username ,
87+ String password ) {
88+ BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider ();
89+ basicCredentialsProvider .setCredentials (new AuthScope (httpHost ),
90+ new UsernamePasswordCredentials (username , password .toCharArray ()));
91+ return basicCredentialsProvider ;
92+ }
93+
94+ private HttpHost createHttpHost (String s ) {
95+ try {
96+ return HttpHost .create (s );
97+ }
98+ catch (URISyntaxException e ) {
99+ throw new RuntimeException (e );
100+ }
101+ }
74102
75- private BasicCredentialsProvider createBasicCredentialsProvider (HttpHost httpHost , String username ,
76- String password ) {
77- BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider ();
78- basicCredentialsProvider .setCredentials (new AuthScope (httpHost ),
79- new UsernamePasswordCredentials (username , password .toCharArray ()));
80- return basicCredentialsProvider ;
81103 }
82104
83- private HttpHost createHttpHost (String s ) {
84- try {
85- return HttpHost .create (s );
105+ @ Configuration (proxyBeanMethods = false )
106+ @ ConditionalOnClass ({ Region .class , ApacheHttpClient .class })
107+ static class AwsOpenSearchConfiguration {
108+
109+ @ Bean
110+ @ ConditionalOnMissingBean
111+ OpenSearchClient openSearchClient (OpenSearchVectorStoreProperties properties , AwsSdk2TransportOptions options ) {
112+ OpenSearchVectorStoreProperties .Aws aws = properties .getAws ();
113+ Region region = Region .of (aws .getRegion ());
114+
115+ SdkHttpClient httpClient = ApacheHttpClient .builder ().build ();
116+ OpenSearchTransport transport = new AwsSdk2Transport (httpClient , aws .getHost (), aws .getServiceName (),
117+ region , options );
118+ return new OpenSearchClient (transport );
86119 }
87- catch (URISyntaxException e ) {
88- throw new RuntimeException (e );
120+
121+ @ Bean
122+ @ ConditionalOnMissingBean
123+ AwsSdk2TransportOptions options (OpenSearchVectorStoreProperties properties ) {
124+ OpenSearchVectorStoreProperties .Aws aws = properties .getAws ();
125+ return AwsSdk2TransportOptions .builder ()
126+ .setCredentials (StaticCredentialsProvider
127+ .create (AwsBasicCredentials .create (aws .getAccessKey (), aws .getSecretKey ())))
128+ .build ();
89129 }
130+
90131 }
91132
92133 static class PropertiesOpenSearchConnectionDetails implements OpenSearchConnectionDetails {
0 commit comments