diff --git a/pom.xml b/pom.xml index aa990d5..279853e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.6 + 3.2.5 @@ -19,6 +19,8 @@ 17 + + 8.15.0 @@ -44,28 +46,37 @@ spring-ai-starter-model-deepseek + + + + + - org.springframework.ai - spring-ai-starter-model-zhipuai + com.alibaba.cloud.ai + spring-ai-alibaba-starter-dashscope + + + + org.springframework.ai - spring-ai-starter-vector-store-elasticsearch + spring-ai-elasticsearch-store co.elastic.clients elasticsearch-java - 8.13.4 + ${elasticsearch.version} org.elasticsearch.client elasticsearch-rest-client - 8.13.4 + ${elasticsearch.version} @@ -125,6 +136,17 @@ pom import + + co.elastic.clients + elasticsearch-java + ${elasticsearch.version} + + + + org.elasticsearch.client + elasticsearch-rest-client + ${elasticsearch.version} + diff --git a/src/main/java/com/example/springaidemo/config/ElasticVectorConfig.java b/src/main/java/com/example/springaidemo/config/ElasticVectorConfig.java new file mode 100644 index 0000000..ba63bfa --- /dev/null +++ b/src/main/java/com/example/springaidemo/config/ElasticVectorConfig.java @@ -0,0 +1,72 @@ +package com.example.springaidemo.config; + +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.springframework.ai.embedding.EmbeddingModel; +import org.springframework.ai.vectorstore.VectorStore; +import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStore; +import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStoreOptions; +import org.springframework.ai.vectorstore.elasticsearch.SimilarityFunction; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +@Configuration +public class ElasticVectorConfig { + + @Value("${elasticsearch.host:154.12.80.119}") + private String host; + + @Value("${elasticsearch.port:9200}") + private int port; + + @Value("${elasticsearch.username:elastic}") + private String username; + + @Value("${elasticsearch.password:123456}") + private String password; + + @Value("${elasticsearch.index.name:custom-index}") + private String indexName; + + @Value("${elasticsearch.index.dimensions:1536}") + private int dimensions; + + @Bean + public RestClient restClient() { + RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, null)); + + // 如果提供了用户名和密码,添加基础认证 + if (StringUtils.hasText(username) && StringUtils.hasText(password)) { + String auth = username + ":" + password; + String encodedAuth = Base64.getEncoder() + .encodeToString(auth.getBytes(StandardCharsets.UTF_8)); + + builder.setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "Basic " + encodedAuth) + }); + } + + return builder.build(); + } + + @Bean + public VectorStore vectorStore(RestClient restClient, EmbeddingModel dashscopeEmbeddingModel) { + ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions(); + options.setIndexName(indexName); + options.setSimilarity(SimilarityFunction.cosine); + options.setDimensions(dimensions); + + return ElasticsearchVectorStore.builder(restClient, dashscopeEmbeddingModel) + .options(options) + .initializeSchema(true) + .build(); + } +} diff --git a/src/main/java/com/example/springaidemo/service/VectorService.java b/src/main/java/com/example/springaidemo/service/VectorService.java index 7534bb0..1c449eb 100644 --- a/src/main/java/com/example/springaidemo/service/VectorService.java +++ b/src/main/java/com/example/springaidemo/service/VectorService.java @@ -3,7 +3,6 @@ package com.example.springaidemo.service; import org.springframework.ai.document.Document; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; -import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -20,10 +19,14 @@ public class VectorService { new Document("The World is Big and Salvation Lurks Around the Corner"), new Document("You walk forward facing the past and you turn back toward the future.")); -// Add the documents to Elasticsearch +// Add the documents to Elasticsearch 需要注意的是elasticSearch的版本需要大于8.10.0 vectorStore.add(documents); // Retrieve documents similar to a query - List results = this.vectorStore.similaritySearch(SearchRequest.builder().query("Spring").topK(5).build()); + SearchRequest searchRequest = SearchRequest.builder().query("Spring") + .topK(5) + .build(); + List results = this.vectorStore.similaritySearch(searchRequest); + System.out.println(results); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1fa879e..a4bbb52 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,6 +8,11 @@ spring: ai: deepseek: api-key: sk-3043bb4777404970a22c7544dd30aaa2 + dashscope: + api-key: sk-2f703a41fff0488e9b6888013d2ee58a + chat: + options: + model: qwen-plus zhipuai: api-key: 73f440ddeafc47ba94ed66e35fbd63d7.VmlulRZ4BMWexncF openai: @@ -29,6 +34,9 @@ spring: index-name: custom-index dimensions: 1536 similarity: cosine + uris: http://154.12.80.119:9200 + username: elastic + password: 123456 # ollama: # base-url: ${OLLAMA_BASE_URL:http://localhost:11434} # chat: