diff --git a/models/spring-ai-vertex-ai-palm2/README.md b/models/spring-ai-vertex-ai-palm2/README.md deleted file mode 100644 index 94668ffd7ee..00000000000 --- a/models/spring-ai-vertex-ai-palm2/README.md +++ /dev/null @@ -1,4 +0,0 @@ -[VertexAI PaLM2 Chat Documentation](https://docs.spring.io/spring-ai/reference/api/chat/vertexai-palm2-chat.html) - -[VertexAI PaLM2 Embedding Documentation](https://docs.spring.io/spring-ai/reference/api/embeddings/vertexai-embeddings-palm2.html) - diff --git a/models/spring-ai-vertex-ai-palm2/pom.xml b/models/spring-ai-vertex-ai-palm2/pom.xml deleted file mode 100644 index 2bf40081458..00000000000 --- a/models/spring-ai-vertex-ai-palm2/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - 4.0.0 - - org.springframework.ai - spring-ai - 1.0.0-SNAPSHOT - ../../pom.xml - - spring-ai-vertex-ai-palm2 - jar - Spring AI Model - Vertex AI PaLM2 - Vertex AI PaLM2 models support - https://github.com/spring-projects/spring-ai - - - https://github.com/spring-projects/spring-ai - git://github.com/spring-projects/spring-ai.git - git@github.com:spring-projects/spring-ai.git - - - - true - - - - - - - org.springframework.ai - spring-ai-core - ${project.parent.version} - - - - org.springframework - spring-web - - - - - - org.springframework - spring-context-support - - - - org.springframework.boot - spring-boot-starter-logging - - - - - org.springframework.ai - spring-ai-test - ${project.version} - test - - - - - diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatModel.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatModel.java deleted file mode 100644 index b68e054a47c..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatModel.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import java.util.List; -import java.util.stream.Collectors; - -import org.springframework.ai.chat.messages.MessageType; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.model.Generation; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.model.ModelOptionsUtils; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageRequest; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageResponse; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.MessagePrompt; -import org.springframework.util.Assert; -import org.springframework.util.CollectionUtils; - -/** - * @author Christian Tzolov - */ -public class VertexAiPaLm2ChatModel implements ChatModel { - - private final VertexAiPaLm2Api vertexAiApi; - - private final VertexAiPaLm2ChatOptions defaultOptions; - - public VertexAiPaLm2ChatModel(VertexAiPaLm2Api vertexAiApi) { - this(vertexAiApi, - VertexAiPaLm2ChatOptions.builder().withTemperature(0.7).withCandidateCount(1).withTopK(20).build()); - } - - public VertexAiPaLm2ChatModel(VertexAiPaLm2Api vertexAiApi, VertexAiPaLm2ChatOptions defaultOptions) { - Assert.notNull(defaultOptions, "Default options must not be null!"); - Assert.notNull(vertexAiApi, "VertexAiPaLm2Api must not be null!"); - - this.vertexAiApi = vertexAiApi; - this.defaultOptions = defaultOptions; - } - - @Override - public ChatResponse call(Prompt prompt) { - - GenerateMessageRequest request = createRequest(prompt); - - GenerateMessageResponse response = this.vertexAiApi.generateMessage(request); - - List generations = response.candidates() - .stream() - .map(vmsg -> new Generation(vmsg.content())) - .toList(); - - return new ChatResponse(generations); - } - - /** - * Accessible for testing. - */ - GenerateMessageRequest createRequest(Prompt prompt) { - - String vertexContext = prompt.getInstructions() - .stream() - .filter(m -> m.getMessageType() == MessageType.SYSTEM) - .map(m -> m.getContent()) - .collect(Collectors.joining(System.lineSeparator())); - - List vertexMessages = prompt.getInstructions() - .stream() - .filter(m -> m.getMessageType() == MessageType.USER || m.getMessageType() == MessageType.ASSISTANT) - .map(m -> new VertexAiPaLm2Api.Message(m.getMessageType().getValue(), m.getContent())) - .toList(); - - Assert.isTrue(!CollectionUtils.isEmpty(vertexMessages), "No user or assistant messages found in the prompt!"); - - var vertexPrompt = new MessagePrompt(vertexContext, vertexMessages); - - GenerateMessageRequest request = new GenerateMessageRequest(vertexPrompt); - - if (this.defaultOptions != null) { - request = ModelOptionsUtils.merge(request, this.defaultOptions, GenerateMessageRequest.class); - } - - if (prompt.getOptions() != null) { - VertexAiPaLm2ChatOptions updatedRuntimeOptions = ModelOptionsUtils.copyToTarget(prompt.getOptions(), - ChatOptions.class, VertexAiPaLm2ChatOptions.class); - request = ModelOptionsUtils.merge(updatedRuntimeOptions, request, GenerateMessageRequest.class); - } - - return request; - } - - @Override - public ChatOptions getDefaultOptions() { - return VertexAiPaLm2ChatOptions.fromOptions(this.defaultOptions); - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatOptions.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatOptions.java deleted file mode 100644 index 34a63ccb7b3..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatOptions.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; - -import org.springframework.ai.chat.prompt.ChatOptions; - -/** - * @author Christian Tzolov - * @author Thomas Vitale - */ -@JsonInclude(Include.NON_NULL) -public class VertexAiPaLm2ChatOptions implements ChatOptions { - - // @formatter:off - /** - * Controls the randomness of the output. Values can range over [0.0,1.0], inclusive. - * A value closer to 1.0 will produce responses that are more varied, while a value - * closer to 0.0 will typically result in less surprising responses from the - * generative. This value specifies default to be used by the backend while making the - * call to the generative. - */ - private @JsonProperty("temperature") Double temperature; - - /** - * The number of generated response messages to return. This value must be between [1, - * 8], inclusive. Defaults to 1. - */ - private @JsonProperty("candidateCount") Integer candidateCount; - - /** - * The maximum cumulative probability of tokens to consider when sampling. The - * generative uses combined Top-k and nucleus sampling. Nucleus sampling considers the - * smallest set of tokens whose probability sum is at least topP. - */ - private @JsonProperty("topP") Double topP; - - /** - * The maximum number of tokens to consider when sampling. The generative uses - * combined Top-k and nucleus sampling. Top-k sampling considers the set of topK most - * probable tokens. - */ - private @JsonProperty("topK") Integer topK; - // @formatter:on - - public static Builder builder() { - return new Builder(); - } - - public static VertexAiPaLm2ChatOptions fromOptions(VertexAiPaLm2ChatOptions fromOptions) { - return VertexAiPaLm2ChatOptions.builder() - .withTemperature(fromOptions.getTemperature()) - .withCandidateCount(fromOptions.getCandidateCount()) - .withTopP(fromOptions.getTopP()) - .withTopK(fromOptions.getTopK()) - .build(); - } - - @Override - public Double getTemperature() { - return this.temperature; - } - - public void setTemperature(Double temperature) { - this.temperature = temperature; - } - - public Integer getCandidateCount() { - return this.candidateCount; - } - - public void setCandidateCount(Integer candidateCount) { - this.candidateCount = candidateCount; - } - - @Override - public Double getTopP() { - return this.topP; - } - - public void setTopP(Double topP) { - this.topP = topP; - } - - @Override - public Integer getTopK() { - return this.topK; - } - - public void setTopK(Integer topK) { - this.topK = topK; - } - - @Override - @JsonIgnore - public String getModel() { - return null; - } - - @Override - @JsonIgnore - public Integer getMaxTokens() { - return null; - } - - @Override - @JsonIgnore - public List getStopSequences() { - return null; - } - - @Override - @JsonIgnore - public Double getFrequencyPenalty() { - return null; - } - - @Override - @JsonIgnore - public Double getPresencePenalty() { - return null; - } - - @Override - public VertexAiPaLm2ChatOptions copy() { - return fromOptions(this); - } - - public static class Builder { - - private VertexAiPaLm2ChatOptions options = new VertexAiPaLm2ChatOptions(); - - public Builder withTemperature(Double temperature) { - this.options.temperature = temperature; - return this; - } - - public Builder withCandidateCount(Integer candidateCount) { - this.options.candidateCount = candidateCount; - return this; - } - - public Builder withTopP(Double topP) { - this.options.topP = topP; - return this; - } - - public Builder withTopK(Integer topK) { - this.options.topK = topK; - return this; - } - - public VertexAiPaLm2ChatOptions build() { - return this.options; - } - - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModel.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModel.java deleted file mode 100644 index 3ece4c0bc33..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModel.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -import org.springframework.ai.document.Document; -import org.springframework.ai.embedding.AbstractEmbeddingModel; -import org.springframework.ai.embedding.Embedding; -import org.springframework.ai.embedding.EmbeddingRequest; -import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; - -/** - * @author Christian Tzolov - */ -public class VertexAiPaLm2EmbeddingModel extends AbstractEmbeddingModel { - - private final VertexAiPaLm2Api vertexAiApi; - - public VertexAiPaLm2EmbeddingModel(VertexAiPaLm2Api vertexAiApi) { - this.vertexAiApi = vertexAiApi; - } - - @Override - public float[] embed(Document document) { - return embed(document.getContent()); - } - - @Override - public EmbeddingResponse call(EmbeddingRequest request) { - List vertexEmbeddings = this.vertexAiApi.batchEmbedText(request.getInstructions()); - AtomicInteger indexCounter = new AtomicInteger(0); - List embeddings = vertexEmbeddings.stream() - .map(vm -> new Embedding(vm.value(), indexCounter.getAndIncrement())) - .toList(); - return new EmbeddingResponse(embeddings); - - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHints.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHints.java deleted file mode 100644 index 8e9ea670788..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHints.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2.aot; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.aot.hint.MemberCategory; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.RuntimeHintsRegistrar; - -import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClassesInPackage; - -/** - * The VertexRuntimeHints class is responsible for registering runtime hints for Vertex AI - * API classes. - * - * @author Josh Long - * @author Christian Tzolov - * @author Mark Pollack - */ -public class VertexRuntimeHints implements RuntimeHintsRegistrar { - - @Override - public void registerHints(RuntimeHints hints, ClassLoader classLoader) { - var mcs = MemberCategory.values(); - for (var tr : findJsonAnnotatedClassesInPackage(VertexAiPaLm2Api.class)) - hints.reflection().registerType(tr, mcs); - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2Api.java b/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2Api.java deleted file mode 100644 index e1e46326dcd..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2Api.java +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2.api; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; - -import org.springframework.ai.util.JacksonUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.Assert; -import org.springframework.web.client.ResponseErrorHandler; -import org.springframework.web.client.RestClient; - -// @formatter:off -/** - * Vertex AI API client for the Generative Language model. - * https://developers.generativeai.google/api/rest/generativelanguage - * https://cloud.google.com/vertex-ai/docs/generative-ai/learn/streaming - * - * Provides methods to generate a response from the model given an input - * https://developers.generativeai.google/api/rest/generativelanguage/models/generateMessage - * - * as well as to generate embeddings for the input text: - * https://developers.generativeai.google/api/rest/generativelanguage/models/embedText - * - * - * Supported models: - * - *
- * 		name=models/chat-bison-001,
- * 		version=001,
- * 		displayName=Chat Bison,
- * 		description=Chat-optimized generative language model.,
- * 		inputTokenLimit=4096,
- * 		outputTokenLimit=1024,
- * 		supportedGenerationMethods=[generateMessage, countMessageTokens],
- * 		temperature=0.25,
- * 		topP=0.95,
- *		topK=40
- *
- * 		name=models/text-bison-001,
- *		version=001,
- *		displayName=Text Bison,
- *		description=Model targeted for text generation.,
- * 		inputTokenLimit=8196,
- *		outputTokenLimit=1024,
- *		supportedGenerationMethods=[generateText, countTextTokens, createTunedTextModel],
- *		temperature=0.7,
- *		topP=0.95,
- *		topK=40
- *
- * 		name=models/embedding-gecko-001,
- * 		version=001,
- * 		displayName=Embedding Gecko, description=Obtain a distributed representation of a text.,
- * 		inputTokenLimit=1024,
- * 		outputTokenLimit=1,
- * 		supportedGenerationMethods=[embedText, countTextTokens],
- * 		temperature=null,
- * 		topP=null,
- * 		topK=null
- * 
- * - * https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models - * - * https://ai.google.dev/api/rest#rest-resource:-v1.models - * - * @author Christian Tzolov - * @author Thomas Vitale - */ -public class VertexAiPaLm2Api { - - /** - * The default generation model. This model is used to generate responses for the - * input text. - */ - public static final String DEFAULT_GENERATE_MODEL = "chat-bison-001"; - - /** - * The default embedding model. This model is used to generate embeddings for the - * input text. - */ - public static final String DEFAULT_EMBEDDING_MODEL = "embedding-gecko-001"; - - /** - * The default base URL for accessing the Vertex AI API. - */ - public static final String DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta3"; - - private final RestClient restClient; - - private final String apiKey; - - private final String chatModel; - - private final String embeddingModel; - - private final ObjectMapper objectMapper; - - /** - * Create a new chat completion api. - * @param apiKey vertex apiKey. - */ - public VertexAiPaLm2Api(String apiKey) { - this(DEFAULT_BASE_URL, apiKey, DEFAULT_GENERATE_MODEL, DEFAULT_EMBEDDING_MODEL, RestClient.builder()); - } - - /** - * Create a new chat completion api. - * @param baseUrl api base URL. - * @param apiKey vertex apiKey. - * @param model vertex model. - * @param embeddingModel vertex embedding model. - * @param restClientBuilder RestClient builder. - */ - public VertexAiPaLm2Api(String baseUrl, String apiKey, String model, String embeddingModel, - RestClient.Builder restClientBuilder) { - - this.chatModel = model; - this.embeddingModel = embeddingModel; - this.apiKey = apiKey; - this.objectMapper = JsonMapper.builder().addModules(JacksonUtils.instantiateAvailableModules()).build(); - - Consumer jsonContentHeaders = headers -> { - headers.setAccept(List.of(MediaType.APPLICATION_JSON)); - headers.setContentType(MediaType.APPLICATION_JSON); - }; - - ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() { - @Override - public boolean hasError(ClientHttpResponse response) throws IOException { - return response.getStatusCode().isError(); - } - - @Override - public void handleError(ClientHttpResponse response) throws IOException { - if (response.getStatusCode().isError()) { - throw new RuntimeException(String.format("%s - %s", response.getStatusCode().value(), - objectMapper.readValue(response.getBody(), ResponseError.class))); - } - } - }; - - this.restClient = restClientBuilder.baseUrl(baseUrl) - .defaultHeaders(jsonContentHeaders) - .defaultStatusHandler(responseErrorHandler) - .build(); - } - - /** - * Generates a response from the model given an input. - * @param request Request body. - * @return Response body. - */ - @SuppressWarnings("null") - public GenerateMessageResponse generateMessage(GenerateMessageRequest request) { - Assert.notNull(request, "The request body can not be null."); - - return this.restClient.post() - .uri("/models/{model}:generateMessage?key={apiKey}", this.chatModel, this.apiKey) - .body(request) - .retrieve() - .body(GenerateMessageResponse.class); - } - - /** - * Generates a response from the model given an input. - * @param text Text to embed. - * @return Embedding response. - */ - public Embedding embedText(String text) { - Assert.hasText(text, "The text can not be null or empty."); - - @JsonInclude(Include.NON_NULL) - record EmbeddingResponse(Embedding embedding) { - } - - EmbeddingResponse response = this.restClient.post() - .uri("/models/{model}:embedText?key={apiKey}", this.embeddingModel, this.apiKey) - .body(Map.of("text", text)) - .retrieve() - .body(EmbeddingResponse.class); - - return response != null ? response.embedding() : null; - } - - /** - * Generates a response from the model given an input. - * @param texts List of texts to embed. - * @return Embedding response containing a list of embeddings. - */ - public List batchEmbedText(List texts) { - Assert.notNull(texts, "The texts can not be null."); - - - BatchEmbeddingResponse response = this.restClient.post() - .uri("/models/{model}:batchEmbedText?key={apiKey}", this.embeddingModel, this.apiKey) - // https://developers.generativeai.google/api/rest/generativelanguage/models/batchEmbedText#request-body - .body(Map.of("texts", texts)) - .retrieve() - .body(BatchEmbeddingResponse.class); - - return response != null ? response.embeddings() : null; - } - - /** - * Returns the number of tokens in the message prompt. - * @param prompt Message prompt to count tokens for. - * @return Number of tokens in the message prompt. - */ - public Integer countMessageTokens(MessagePrompt prompt) { - - Assert.notNull(prompt, "The message prompt can not be null."); - - record TokenCount(@JsonProperty("tokenCount") Integer tokenCount) { - } - - TokenCount tokenCountResponse = this.restClient.post() - .uri("/models/{model}:countMessageTokens?key={apiKey}", this.chatModel, this.apiKey) - .body(Map.of("prompt", prompt)) - .retrieve() - .body(TokenCount.class); - - return tokenCountResponse != null ? tokenCountResponse.tokenCount() : null; - } - - /** - * Returns the list of models available for use. - * @return List of models available for use. - */ - public List listModels() { - - @JsonInclude(Include.NON_NULL) - record ModelList(@JsonProperty("models") List models) { - record ModelName(String name) { - } - } - - - ModelList modelList = this.restClient.get() - .uri("/models?key={apiKey}", this.apiKey) - .retrieve() - .body(ModelList.class); - - return modelList == null ? List.of() : - modelList.models().stream() - .map(ModelList.ModelName::name) - .toList(); - } - - /** - * Returns the model details. - * @param modelName Name of the model to get details for. - * @return Model details. - */ - public Model getModel(String modelName) { - - Assert.hasText(modelName, "The model name can not be null or empty."); - - if (modelName.startsWith("models/")) { - modelName = modelName.substring("models/".length()); - } - - return this.restClient.get() - .uri("/models/{model}?key={apiKey}", modelName, this.apiKey) - .retrieve() - .body(Model.class); - } - - @JsonInclude(Include.NON_NULL) - record BatchEmbeddingResponse(List embeddings) { - } - - /** - * API error response. - * - * @param error Error details. - */ - @JsonInclude(Include.NON_NULL) - public record ResponseError( - @JsonProperty("error") Error error) { - - /** - * Error details. - * - * @param message Error message. - * @param code Error code. - * @param status Error status. - */ - @JsonInclude(Include.NON_NULL) - public record Error( - @JsonProperty("message") String message, - @JsonProperty("code") String code, - @JsonProperty("status") String status) { - } - } - - /** - * Information about a Generative Language Model. - * - * @param name The resource name of the Model. Format: `models/{model} with a {model} - * naming convention of:` - * - *
-	 * {baseModelId}-{version}
-	 * 
- * @param baseModelId The name of the base model, pass this to the generation request. - * @param version The version of the model. This represents the major version. - * @param displayName The human-readable name of the model. E.g. "Chat Bison". The - * name can be up to 128 characters long and can consist of any UTF-8 characters. - * @param description A short description of the model. - * @param inputTokenLimit Maximum number of input tokens allowed for this model. - * @param outputTokenLimit Maximum number of output tokens allowed for this model. - * @param supportedGenerationMethods List of supported generation methods for this - * model. The method names are defined as Pascal case strings, such as generateMessage - * which correspond to API methods. - * @param temperature Controls the randomness of the output. Values can range over - * [0.0,1.0], inclusive. A value closer to 1.0 will produce responses that are more - * varied, while a value closer to 0.0 will typically result in less surprising - * responses from the model. This value specifies default to be used by the backend - * while making the call to the model. - * @param topP For Nucleus sampling. Nucleus sampling considers the smallest set of - * tokens whose probability sum is at least topP. This value specifies default to be - * used by the backend while making the call to the model. - * @param topK For Top-k sampling. Top-k sampling considers the set of topK most - * probable tokens. This value specifies default to be used by the backend while - * making the call to the model. - */ - @JsonInclude(Include.NON_NULL) - public record Model( - @JsonProperty("name") String name, - @JsonProperty("baseModelId") String baseModelId, - @JsonProperty("version") String version, - @JsonProperty("displayName") String displayName, - @JsonProperty("description") String description, - @JsonProperty("inputTokenLimit") Integer inputTokenLimit, - @JsonProperty("outputTokenLimit") Integer outputTokenLimit, - @JsonProperty("supportedGenerationMethods") List supportedGenerationMethods, - @JsonProperty("temperature") Double temperature, - @JsonProperty("topP") Double topP, - @JsonProperty("topK") Integer topK) { - } - - /** - * A list of floats representing the embedding. - * - * @param value The embedding values. - */ - @JsonInclude(Include.NON_NULL) - public record Embedding( - @JsonProperty("value") float[] value) { - - @Override - public final int hashCode() { - return Arrays.hashCode(this.value); - } - - @Override - public final boolean equals(Object arg0) { - return Arrays.equals(this.value,((Embedding) arg0).value); - } - } - - /** - * The base unit of structured text. A Message includes an author and the content of - * the Message. The author is used to tag messages when they are fed to the model as - * text. - * - * @param author (optional) Author of the message. This serves as a key for tagging - * the content of this Message when it is fed to the model as text.The author can be - * any alphanumeric string. - * @param content The text content of the structured Message. - * @param citationMetadata (output only) Citation information for model-generated - * content in this Message. If this Message was generated as output from the model, - * this field may be populated with attribution information for any text included in - * the content. This field is used only on output. - */ - @JsonInclude(Include.NON_NULL) - public record Message( - @JsonProperty("author") String author, - @JsonProperty("content") String content, - @JsonProperty("citationMetadata") CitationMetadata citationMetadata) { - - /** - * Short-hand constructor for a message without citation metadata. - * @param author (optional) Author of the message. - * @param content The text content of the structured Message. - */ - public Message(String author, String content) { - this(author, content, null); - } - - /** - * A collection of source attributions for a piece of content. - * - * Citations to sources for a specific response. - */ - @JsonInclude(Include.NON_NULL) - public record CitationMetadata( - @JsonProperty("citationSources") List citationSources) { - } - - /** - * A citation to a source for a portion of a specific response. - * - * @param startIndex (optional) Start of segment of the response that is - * attributed to this source. Index indicates the start of the segment, measured - * in bytes. - * @param endIndex (optional) End of the attributed segment, exclusive. - * @param uri (optional) URI that is attributed as a source for a portion of the - * text. - * @param license (optional) License for the GitHub project that is attributed as - * a source for segment.License info is required for code citations. - */ - @JsonInclude(Include.NON_NULL) - public record CitationSource( - @JsonProperty("startIndex") Integer startIndex, - @JsonProperty("endIndex") Integer endIndex, - @JsonProperty("uri") String uri, - @JsonProperty("license") String license) { - } - } - - /** - * All of the structured input text passed to the model as a prompt. - * - * A MessagePrompt contains a structured set of fields that provide context for the - * conversation, examples of user input/model output message pairs that prime the - * model to respond in different ways, and the conversation history or list of - * messages representing the alternating turns of the conversation between the user - * and the model. - * - * @param context (optional) Text that should be provided to the model first to ground - * the response. If not empty, this context will be given to the model first before - * the examples and messages. When using a context be sure to provide it with every - * request to maintain continuity. This field can be a description of your prompt to - * the model to help provide context and guide the responses. Examples: "Translate the - * phrase from English to French." or "Given a statement, classify the sentiment as - * happy, sad or neutral." Anything included in this field will take precedence over - * message history if the total input size exceeds the model's inputTokenLimit and the - * input request is truncated. - * @param examples (optional) Examples of what the model should generate. This - * includes both user input and the response that the model should emulate. These - * examples are treated identically to conversation messages except that they take - * precedence over the history in messages: If the total input size exceeds the - * model's inputTokenLimit the input will be truncated. Items will be dropped from - * messages before examples. - * @param messages (optional) A snapshot of the recent conversation history sorted - * chronologically. Turns alternate between two authors. If the total input size - * exceeds the model's inputTokenLimit the input will be truncated: The oldest items - * will be dropped from messages. - */ - @JsonInclude(Include.NON_NULL) - public record MessagePrompt( - @JsonProperty("context") String context, - @JsonProperty("examples") List examples, - @JsonProperty("messages") List messages) { - - /** - * Shortcut constructor for a message prompt without context. - * @param messages The conversation history used by the model. - */ - public MessagePrompt(List messages) { - this(null, null, messages); - } - - /** - * Shortcut constructor for a message prompt without context. - * @param context An input/output example used to instruct the Model. It - * demonstrates how the model should respond or format its response. - * @param messages The conversation history used by the model. - */ - public MessagePrompt(String context, List messages) { - this(context, null, messages); - } - - /** - * An input/output example used to instruct the Model. It demonstrates how the - * model should respond or format its response. - * - * @param input An example of an input Message from the user. - * @param output An example of an output Message from the model. - */ - @JsonInclude(Include.NON_NULL) - public record Example( - @JsonProperty("input") Message input, - @JsonProperty("output") Message output) { - } - } - - /** - * Message generation request body. - * - * @param prompt The structured textual input given to the model as a prompt. Given a - * prompt, the model will return what it predicts is the next message in the - * discussion. - * @param temperature (optional) Controls the randomness of the output. Values can - * range over [0.0,1.0], inclusive. A value closer to 1.0 will produce responses that - * are more varied, while a value closer to 0.0 will typically result in less - * surprising responses from the model. - * @param candidateCount (optional) The number of generated response messages to - * return. This value must be between [1, 8], inclusive. If unset, this will default - * to 1. - * @param topP (optional) The maximum cumulative probability of tokens to consider - * when sampling. The model uses combined Top-k and nucleus sampling. Nucleus sampling - * considers the smallest set of tokens whose probability sum is at least topP. - * @param topK (optional) The maximum number of tokens to consider when sampling. The - * model uses combined Top-k and nucleus sampling. Top-k sampling considers the set of - * topK most probable tokens. - */ - @JsonInclude(Include.NON_NULL) - public record GenerateMessageRequest( - @JsonProperty("prompt") MessagePrompt prompt, - @JsonProperty("temperature") Double temperature, - @JsonProperty("candidateCount") Integer candidateCount, - @JsonProperty("topP") Double topP, - @JsonProperty("topK") Integer topK) { - - /** - * Shortcut constructor to create a GenerateMessageRequest with only the prompt - * parameter. - * @param prompt The structured textual input given to the model as a prompt. - */ - public GenerateMessageRequest(MessagePrompt prompt) { - this(prompt, null, null, null, null); - } - - /** - * Shortcut constructor to create a GenerateMessageRequest with only the prompt - * and temperature parameters. - * @param prompt The structured textual input given to the model as a prompt. - * @param temperature (optional) Controls the randomness of the output. - * @param topK (optional) The maximum number of tokens to consider when sampling. - */ - public GenerateMessageRequest(MessagePrompt prompt, Double temperature, Integer topK) { - this(prompt, temperature, null, null, topK); - } - } - - /** - * The response from the model. This includes candidate messages and conversation - * history in the form of chronologically-ordered messages. - * - * @param candidates Candidate response messages from the model. - * @param messages The conversation history used by the model. - * @param filters A set of content filtering metadata for the prompt and response - * text. This indicates which SafetyCategory(s) blocked a candidate from this - * response, the lowest HarmProbability that triggered a block, and the HarmThreshold - * setting for that category. - */ - @JsonInclude(Include.NON_NULL) - public record GenerateMessageResponse( - @JsonProperty("candidates") List candidates, - @JsonProperty("messages") List messages, - @JsonProperty("filters") List filters) { - - /** - * Content filtering metadata associated with processing a single request. It - * contains a reason and an optional supporting string. The reason may be - * unspecified. - * - * @param reason The reason content was blocked during request processing. - * @param message A string that describes the filtering behavior in more detail. - */ - @JsonInclude(Include.NON_NULL) - public record ContentFilter( - @JsonProperty("reason") BlockedReason reason, - @JsonProperty("message") String message) { - - /** - * Reasons why content may have been blocked. - */ - public enum BlockedReason { - - /** - * A blocked reason was not specified. - */ - BLOCKED_REASON_UNSPECIFIED, - /** - * Content was blocked by safety settings. - */ - SAFETY, - /** - * Content was blocked, but the reason is uncategorized. - */ - OTHER - - } - } - } -} -// @formatter:on \ No newline at end of file diff --git a/models/spring-ai-vertex-ai-palm2/src/main/resources/META-INF/spring/aot.factories b/models/spring-ai-vertex-ai-palm2/src/main/resources/META-INF/spring/aot.factories deleted file mode 100644 index b5d460db1f3..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/main/resources/META-INF/spring/aot.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.aot.hint.RuntimeHintsRegistrar=\ - org.springframework.ai.vertexai.palm2.aot.VertexRuntimeHints \ No newline at end of file diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java deleted file mode 100644 index 21d07a608a2..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatGenerationClientIT.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; - -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.model.Generation; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.chat.prompt.PromptTemplate; -import org.springframework.ai.chat.prompt.SystemPromptTemplate; -import org.springframework.ai.converter.BeanOutputConverter; -import org.springframework.ai.converter.ListOutputConverter; -import org.springframework.ai.converter.MapOutputConverter; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.core.convert.support.DefaultConversionService; -import org.springframework.core.io.Resource; - -import static org.assertj.core.api.Assertions.assertThat; - -@SpringBootTest -@EnabledIfEnvironmentVariable(named = "PALM_API_KEY", matches = ".*") -class VertexAiPaLm2ChatGenerationClientIT { - - @Autowired - private VertexAiPaLm2ChatModel chatModel; - - @Value("classpath:/prompts/system-message.st") - private Resource systemResource; - - @Test - void roleTest() { - String request = "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."; - String name = "Bob"; - String voice = "pirate"; - UserMessage userMessage = new UserMessage(request); - SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(this.systemResource); - Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice)); - Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); - ChatResponse response = this.chatModel.call(prompt); - assertThat(response.getResult().getOutput().getContent()).contains("Bartholomew"); - } - - // @Test - void listOutputConverter() { - DefaultConversionService conversionService = new DefaultConversionService(); - ListOutputConverter outputConverter = new ListOutputConverter(conversionService); - - String format = outputConverter.getFormat(); - String template = """ - List five {subject} - {format} - """; - PromptTemplate promptTemplate = new PromptTemplate(template, - Map.of("subject", "ice cream flavors.", "format", format)); - Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatModel.call(prompt).getResult(); - - List list = outputConverter.convert(generation.getOutput().getContent()); - assertThat(list).hasSize(5); - - } - - // @Test - void mapOutputConverter() { - MapOutputConverter outputConverter = new MapOutputConverter(); - - String format = outputConverter.getFormat(); - String template = """ - Provide me a List of {subject} - {format} - """; - PromptTemplate promptTemplate = new PromptTemplate(template, - Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); - Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatModel.call(prompt).getResult(); - - Map result = outputConverter.convert(generation.getOutput().getContent()); - assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); - - } - - // @Test - void beanOutputConverterRecords() { - - BeanOutputConverter outputConverter = new BeanOutputConverter<>(ActorsFilmsRecord.class); - - String format = outputConverter.getFormat(); - String template = """ - Generate the filmography of 5 movies for Tom Hanks. - {format} - """; - PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); - Prompt prompt = new Prompt(promptTemplate.createMessage()); - Generation generation = this.chatModel.call(prompt).getResult(); - - ActorsFilmsRecord actorsFilms = outputConverter.convert(generation.getOutput().getContent()); - assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); - assertThat(actorsFilms.movies()).hasSize(5); - } - - record ActorsFilmsRecord(String actor, List movies) { - - } - - @SpringBootConfiguration - public static class TestConfiguration { - - @Bean - public VertexAiPaLm2Api vertexAiApi() { - return new VertexAiPaLm2Api(System.getenv("PALM_API_KEY")); - } - - @Bean - public VertexAiPaLm2ChatModel vertexAiEmbedding(VertexAiPaLm2Api vertexAiApi) { - return new VertexAiPaLm2ChatModel(vertexAiApi); - } - - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java deleted file mode 100644 index d2dc2802459..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatRequestTests.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import org.junit.jupiter.api.Test; - -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Christian Tzolov - */ -public class VertexAiPaLm2ChatRequestTests { - - VertexAiPaLm2ChatModel chatModel = new VertexAiPaLm2ChatModel(new VertexAiPaLm2Api("bla")); - - @Test - public void createRequestWithDefaultOptions() { - - var request = this.chatModel.createRequest(new Prompt("Test message content")); - - assertThat(request.prompt().messages()).hasSize(1); - - assertThat(request.candidateCount()).isEqualTo(1); - assertThat(request.temperature()).isEqualTo(0.7); - assertThat(request.topK()).isEqualTo(20); - assertThat(request.topP()).isNull(); - } - - @Test - public void createRequestWithPromptVertexAiOptions() { - - // Runtime options should override the default options. - VertexAiPaLm2ChatOptions promptOptions = VertexAiPaLm2ChatOptions.builder() - .withTemperature(0.8) - .withTopP(0.5) - .withTopK(99) - // .withCandidateCount(2) - .build(); - - var request = this.chatModel.createRequest(new Prompt("Test message content", promptOptions)); - - assertThat(request.prompt().messages()).hasSize(1); - - assertThat(request.candidateCount()).isEqualTo(1); - assertThat(request.temperature()).isEqualTo(0.8); - assertThat(request.topK()).isEqualTo(99); - assertThat(request.topP()).isEqualTo(0.5); - } - - @Test - public void createRequestWithPromptPortableChatOptions() { - - // runtime options. - ChatOptions portablePromptOptions = ChatOptionsBuilder.builder() - .withTemperature(0.9) - .withTopK(100) - .withTopP(0.6) - .build(); - - var request = this.chatModel.createRequest(new Prompt("Test message content", portablePromptOptions)); - - assertThat(request.prompt().messages()).hasSize(1); - - assertThat(request.candidateCount()).isEqualTo(1); - assertThat(request.temperature()).isEqualTo(0.9); - assertThat(request.topK()).isEqualTo(100); - assertThat(request.topP()).isEqualTo(0.6); - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModelIT.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModelIT.java deleted file mode 100644 index 221964fd12f..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModelIT.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2; - -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; - -import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; - -import static org.assertj.core.api.Assertions.assertThat; - -@SpringBootTest -@EnabledIfEnvironmentVariable(named = "PALM_API_KEY", matches = ".*") -class VertexAiPaLm2EmbeddingModelIT { - - @Autowired - private VertexAiPaLm2EmbeddingModel embeddingModel; - - @Test - void simpleEmbedding() { - assertThat(this.embeddingModel).isNotNull(); - EmbeddingResponse embeddingResponse = this.embeddingModel.embedForResponse(List.of("Hello World")); - assertThat(embeddingResponse.getResults()).hasSize(1); - assertThat(embeddingResponse.getResults().get(0).getOutput()).isNotEmpty(); - assertThat(this.embeddingModel.dimensions()).isEqualTo(768); - } - - @Test - void batchEmbedding() { - assertThat(this.embeddingModel).isNotNull(); - EmbeddingResponse embeddingResponse = this.embeddingModel - .embedForResponse(List.of("Hello World", "World is big and salvation is near")); - assertThat(embeddingResponse.getResults()).hasSize(2); - assertThat(embeddingResponse.getResults().get(0).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(0).getIndex()).isEqualTo(0); - assertThat(embeddingResponse.getResults().get(1).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(1).getIndex()).isEqualTo(1); - - assertThat(this.embeddingModel.dimensions()).isEqualTo(768); - } - - @SpringBootConfiguration - public static class TestConfiguration { - - @Bean - public VertexAiPaLm2Api vertexAiApi() { - return new VertexAiPaLm2Api(System.getenv("PALM_API_KEY")); - } - - @Bean - public VertexAiPaLm2EmbeddingModel vertexAiEmbedding(VertexAiPaLm2Api vertexAiApi) { - return new VertexAiPaLm2EmbeddingModel(vertexAiApi); - } - - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHintsTests.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHintsTests.java deleted file mode 100644 index ae57c09a3a4..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/aot/VertexRuntimeHintsTests.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2.aot; - -import java.util.Set; - -import org.junit.jupiter.api.Test; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.aot.hint.RuntimeHints; -import org.springframework.aot.hint.TypeReference; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.springframework.ai.aot.AiRuntimeHints.findJsonAnnotatedClassesInPackage; -import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection; - -class VertexRuntimeHintsTests { - - @Test - void registerHints() { - RuntimeHints runtimeHints = new RuntimeHints(); - VertexRuntimeHints vertexRuntimeHints = new VertexRuntimeHints(); - vertexRuntimeHints.registerHints(runtimeHints, null); - Set jsonAnnotatedClasses = findJsonAnnotatedClassesInPackage(VertexAiPaLm2Api.class); - for (TypeReference jsonAnnotatedClass : jsonAnnotatedClasses) { - assertThat(runtimeHints).matches(reflection().onType(jsonAnnotatedClass)); - } - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiIT.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiIT.java deleted file mode 100644 index 40f854df0f0..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiIT.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2.api; - -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.Embedding; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageRequest; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageResponse; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.MessagePrompt; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Integration tests for {@link VertexAiPaLm2Api}. Requires a valid API key to be set via - * the {@code PALM_API_KEY} environment and at the moment Google enables is it only in the - * US region (so use VPN for testing). - * - * @author Christian Tzolov - */ -@EnabledIfEnvironmentVariable(named = "PALM_API_KEY", matches = ".*") -public class VertexAiPaLm2ApiIT { - - VertexAiPaLm2Api vertexAiPaLm2Api = new VertexAiPaLm2Api(System.getenv("PALM_API_KEY")); - - @Test - public void generateMessage() { - - var prompt = new MessagePrompt(List.of(new VertexAiPaLm2Api.Message("0", "Hello, how are you?"))); - - GenerateMessageRequest request = new GenerateMessageRequest(prompt); - - GenerateMessageResponse response = this.vertexAiPaLm2Api.generateMessage(request); - - assertThat(response).isNotNull(); - - // Vertex returns the prompt messages in the response's messages list. - assertThat(response.messages()).hasSize(1); - assertThat(response.messages().get(0)).isEqualTo(prompt.messages().get(0)); - - // Vertex returns the answer in the response's candidates list. - assertThat(response.candidates()).hasSize(1); - assertThat(response.candidates().get(0).author()).isNotBlank(); - assertThat(response.candidates().get(0).content()).isNotBlank(); - } - - @Test - public void embedText() { - - var text = "Hello, how are you?"; - - Embedding response = this.vertexAiPaLm2Api.embedText(text); - - assertThat(response).isNotNull(); - assertThat(response.value()).hasSize(768); - } - - @Test - public void batchEmbedText() { - - var text = List.of("Hello, how are you?", "I am fine, thank you!"); - - List response = this.vertexAiPaLm2Api.batchEmbedText(text); - - assertThat(response).isNotNull(); - assertThat(response).hasSize(2); - assertThat(response.get(0).value()).hasSize(768); - assertThat(response.get(1).value()).hasSize(768); - } - - @Test - public void countMessageTokens() { - - var text = "Hello, how are you?"; - - var prompt = new MessagePrompt(List.of(new VertexAiPaLm2Api.Message("0", text))); - int response = this.vertexAiPaLm2Api.countMessageTokens(prompt); - - assertThat(response).isEqualTo(17); - } - - @Test - public void listModels() { - - List response = this.vertexAiPaLm2Api.listModels(); - - assertThat(response).isNotNull(); - assertThat(response).hasSizeGreaterThan(0); - assertThat(response).contains("models/chat-bison-001", "models/text-bison-001", "models/embedding-gecko-001"); - - System.out.println(" - " + response.stream() - .map(this.vertexAiPaLm2Api::getModel) - .map(VertexAiPaLm2Api.Model::toString) - .collect(Collectors.joining("\n - "))); - } - - @Test - public void getModel() { - - VertexAiPaLm2Api.Model model = this.vertexAiPaLm2Api.getModel("models/chat-bison-001"); - - System.out.println(model); - assertThat(model).isNotNull(); - assertThat(model.displayName()).isEqualTo("PaLM 2 Chat (Legacy)"); - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiTests.java b/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiTests.java deleted file mode 100644 index 77bfe39a490..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2ApiTests.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.vertexai.palm2.api; - -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.Embedding; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageRequest; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageResponse; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.GenerateMessageResponse.ContentFilter.BlockedReason; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api.MessagePrompt; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.web.client.RestClient; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.content; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestToUriTemplate; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - -/** - * @author Christian Tzolov - */ -@RestClientTest(VertexAiPaLm2ApiTests.Config.class) -public class VertexAiPaLm2ApiTests { - - private final static String TEST_API_KEY = "test-api-key"; - - @Autowired - private VertexAiPaLm2Api client; - - @Autowired - private MockRestServiceServer server; - - @Autowired - private ObjectMapper objectMapper; - - @AfterEach - void resetMockServer() { - this.server.reset(); - } - - @Test - public void generateMessage() throws JsonProcessingException { - - GenerateMessageRequest request = new GenerateMessageRequest( - new MessagePrompt(List.of(new VertexAiPaLm2Api.Message("0", "Hello, how are you?")))); - - GenerateMessageResponse expectedResponse = new GenerateMessageResponse( - List.of(new VertexAiPaLm2Api.Message("1", "Hello, how are you?")), - List.of(new VertexAiPaLm2Api.Message("0", "I'm fine, thank you.")), - List.of(new VertexAiPaLm2Api.GenerateMessageResponse.ContentFilter(BlockedReason.SAFETY, "reason"))); - - this.server - .expect(requestToUriTemplate("/models/{generative}:generateMessage?key={apiKey}", - VertexAiPaLm2Api.DEFAULT_GENERATE_MODEL, TEST_API_KEY)) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().json(this.objectMapper.writeValueAsString(request))) - .andRespond( - withSuccess(this.objectMapper.writeValueAsString(expectedResponse), MediaType.APPLICATION_JSON)); - - GenerateMessageResponse response = this.client.generateMessage(request); - - assertThat(response).isEqualTo(expectedResponse); - - this.server.verify(); - } - - @Test - public void embedText() throws JsonProcessingException { - - String text = "Hello, how are you?"; - - Embedding expectedEmbedding = new Embedding(new float[] { 0.1f, 0.2f, 0.3f }); - - this.server - .expect(requestToUriTemplate("/models/{generative}:embedText?key={apiKey}", - VertexAiPaLm2Api.DEFAULT_EMBEDDING_MODEL, TEST_API_KEY)) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().json(this.objectMapper.writeValueAsString(Map.of("text", text)))) - .andRespond(withSuccess(this.objectMapper.writeValueAsString(Map.of("embedding", expectedEmbedding)), - MediaType.APPLICATION_JSON)); - - Embedding embedding = this.client.embedText(text); - - assertThat(embedding).isEqualTo(expectedEmbedding); - - this.server.verify(); - } - - @Test - public void batchEmbedText() throws JsonProcessingException { - - List texts = List.of("Hello, how are you?", "I'm fine, thank you."); - - List expectedEmbeddings = List.of(new Embedding(new float[] { 0.1f, 0.2f, 0.3f }), - new Embedding(new float[] { 0.4f, 0.5f, 0.6f })); - - this.server - .expect(requestToUriTemplate("/models/{generative}:batchEmbedText?key={apiKey}", - VertexAiPaLm2Api.DEFAULT_EMBEDDING_MODEL, TEST_API_KEY)) - .andExpect(method(HttpMethod.POST)) - .andExpect(content().json(this.objectMapper.writeValueAsString(Map.of("texts", texts)))) - .andRespond(withSuccess(this.objectMapper.writeValueAsString(Map.of("embeddings", expectedEmbeddings)), - MediaType.APPLICATION_JSON)); - - List embeddings = this.client.batchEmbedText(texts); - - assertThat(embeddings).isEqualTo(expectedEmbeddings); - - this.server.verify(); - } - - @SpringBootConfiguration - static class Config { - - @Bean - public VertexAiPaLm2Api audioApi(RestClient.Builder builder) { - return new VertexAiPaLm2Api("", TEST_API_KEY, VertexAiPaLm2Api.DEFAULT_GENERATE_MODEL, - VertexAiPaLm2Api.DEFAULT_EMBEDDING_MODEL, builder); - } - - } - -} diff --git a/models/spring-ai-vertex-ai-palm2/src/test/resources/Google Generative AI - PaLM2 REST API.jpg b/models/spring-ai-vertex-ai-palm2/src/test/resources/Google Generative AI - PaLM2 REST API.jpg deleted file mode 100644 index dba271cf423..00000000000 Binary files a/models/spring-ai-vertex-ai-palm2/src/test/resources/Google Generative AI - PaLM2 REST API.jpg and /dev/null differ diff --git a/models/spring-ai-vertex-ai-palm2/src/test/resources/prompts/system-message.st b/models/spring-ai-vertex-ai-palm2/src/test/resources/prompts/system-message.st deleted file mode 100644 index dc2cf2dcd84..00000000000 --- a/models/spring-ai-vertex-ai-palm2/src/test/resources/prompts/system-message.st +++ /dev/null @@ -1,4 +0,0 @@ -"You are a helpful AI assistant. Your name is {name}. -You are an AI assistant that helps people find information. -Your name is {name} -You should reply to the user's request with your name and also in the style of a {voice}. \ No newline at end of file diff --git a/pom.xml b/pom.xml index aeaae887c06..244b4af46af 100644 --- a/pom.xml +++ b/pom.xml @@ -95,7 +95,6 @@ models/spring-ai-transformers models/spring-ai-vertex-ai-gemini models/spring-ai-vertex-ai-embedding - models/spring-ai-vertex-ai-palm2 models/spring-ai-watsonx-ai models/spring-ai-zhipuai models/spring-ai-moonshot @@ -116,7 +115,6 @@ spring-ai-spring-boot-starters/spring-ai-starter-transformers spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-embedding spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-gemini - spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-palm2 spring-ai-spring-boot-starters/spring-ai-starter-watsonx-ai spring-ai-spring-boot-starters/spring-ai-starter-zhipuai spring-ai-spring-boot-starters/spring-ai-starter-moonshot diff --git a/spring-ai-bom/pom.xml b/spring-ai-bom/pom.xml index 25296cbc7a2..f58271d94d5 100644 --- a/spring-ai-bom/pom.xml +++ b/spring-ai-bom/pom.xml @@ -134,12 +134,6 @@ ${project.version} - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ${project.version} - - org.springframework.ai spring-ai-vertex-ai-embedding @@ -461,12 +455,6 @@ ${project.version} - - org.springframework.ai - spring-ai-vertex-ai-palm2-spring-boot-starter - ${project.version} - - org.springframework.ai spring-ai-vertex-ai-embedding-spring-boot-starter diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc index 03c68dff20d..60cdd51297c 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/nav.adoc @@ -19,7 +19,6 @@ *** xref:api/chat/azure-openai-chat.adoc[Azure OpenAI] **** xref:api/chat/functions/azure-open-ai-chat-functions.adoc[Function Calling] *** xref:api/chat/google-vertexai.adoc[Google VertexAI] -**** xref:api/chat/vertexai-palm2-chat.adoc[VertexAI PaLM2 ] **** xref:api/chat/vertexai-gemini-chat.adoc[VertexAI Gemini] ***** xref:api/chat/functions/vertexai-gemini-chat-functions.adoc[Function Calling] *** xref:api/chat/groq-chat.adoc[Groq] @@ -55,7 +54,6 @@ *** VertexAI **** xref:api/embeddings/vertexai-embeddings-text.adoc[Text Embedding] **** xref:api/embeddings/vertexai-embeddings-multimodal.adoc[Multimodal Embedding] -**** xref:api/embeddings/vertexai-embeddings-palm2.adoc[PaLM2 Embedding] *** xref:api/embeddings/watsonx-ai-embeddings.adoc[watsonx.AI] *** xref:api/embeddings/zhipuai-embeddings.adoc[ZhiPu AI] ** xref:api/imageclient.adoc[Image Models] diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/comparison.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/comparison.adoc index df9cb03d53d..ae96a2c0687 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/comparison.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/comparison.adoc @@ -22,8 +22,7 @@ This table compares various Chat Models supported by Spring AI, detailing their | xref::api/chat/anthropic-chat.adoc[Anthropic Claude] | text, image ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] | xref::api/chat/azure-openai-chat.adoc[Azure OpenAI] | text, image ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::yes.svg[width=16] | xref::api/chat/vertexai-gemini-chat.adoc[Google VertexAI Gemini] | text, image, audio, video ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::yes.svg[width=16] -| xref::api/chat/vertexai-palm2-chat.adoc[Google VertexAI PaML2] | text ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] -| xref::api/chat/groq-chat.adoc[Groq (OpenAI-proxy)] | text, image ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::yes.svg[width=16] +| xref::api/chat/groq-chat.adoc[Groq (OpenAI-proxy)] | text, image ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::yes.svg[width=16] | xref::api/chat/huggingface.adoc[HuggingFace] | text ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] | xref::api/chat/mistralai-chat.adoc[Mistral AI] | text ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::yes.svg[width=16] | xref::api/chat/minimax-chat.adoc[MiniMax] | text ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::yes.svg[width=16] ^a| image::no.svg[width=12] ^a| image::no.svg[width=12] ^a| diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/google-vertexai.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/google-vertexai.adoc index 55d20942970..b2519eb4db9 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/google-vertexai.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/google-vertexai.adoc @@ -3,7 +3,6 @@ link:https://cloud.google.com/vertex-ai/docs/reference[VertexAI API] provides high-quality custom machine learning models with minimal machine learning expertise and effort. -Spring AI provides integration with VertexAI API through the following clients: +Spring AI provides integration with VertexAI API through the following client(s): -* xref:api/chat/vertexai-palm2-chat.adoc[] * xref:api/chat/vertexai-gemini-chat.adoc[] \ No newline at end of file diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc deleted file mode 100644 index 017f4be42a9..00000000000 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chat/vertexai-palm2-chat.adoc +++ /dev/null @@ -1,222 +0,0 @@ -= VertexAI PaLM2 Chat - -WARNING: - -> https://ai.google.dev/palm_docs/deprecation[As of February 15, 2024, the PaLM2 API for use with Google AI services and tooling is deprecated]. -In 6 months, the PaLM API will be decommissioned, meaning that users won't be able to use a PaLM model in a prompt, tune a new PaLM model, or run inference on PaLM-tuned models. - -The link:https://developers.generativeai.google/api/rest/generativelanguage[Generative Language] PaLM API allows developers to build generative AI applications using the PaLM model. Large Language Models (LLMs) are a powerful, versatile type of machine learning model that enables computers to comprehend and generate natural language through a series of prompts. The PaLM API is based on Google's next generation LLM, PaLM. It excels at a variety of different tasks like code generation, reasoning, and writing. You can use the PaLM API to build generative AI applications for use cases like content generation, dialogue agents, summarization and classification systems, and more. - -Based on the link:https://developers.generativeai.google/api/rest/generativelanguage/models[Models REST API]. - -== Prerequisites - -To access the PaLM2 REST API you need to obtain an access API KEY form link:https://makersuite.google.com/app/apikey[makersuite]. - -NOTE: Currently the PaLM API it is not available outside US, but you can use VPN for testing. - -The Spring AI project defines a configuration property named `spring.ai.vertex.ai.api-key` that you should set to the value of the `API Key` obtained. -Exporting an environment variable is one way to set that configuration property: - -[source,shell] ----- -export SPRING_AI_VERTEX_AI_API_KEY= ----- - -=== Add Repositories and BOM - -Spring AI artifacts are published in Spring Milestone and Snapshot repositories. Refer to the xref:getting-started.adoc#repositories[Repositories] section to add these repositories to your build system. - -To help with dependency management, Spring AI provides a BOM (bill of materials) to ensure that a consistent version of Spring AI is used throughout the entire project. Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build system. - - -== Auto-configuration - -Spring AI provides Spring Boot auto-configuration for the VertexAI Chat Client. -To enable it add the following dependency to your project's Maven `pom.xml` file: - -[source, xml] ----- - - org.springframework.ai - spring-ai-vertex-ai-palm2-spring-boot-starter - ----- - -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-vertex-ai-palm2-spring-boot-starter' -} ----- - -TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. - -=== Chat Properties - -The prefix `spring.ai.vertex.ai` is used as the property prefix that lets you connect to VertexAI. - -[cols="3,5,1", stripes=even] -|==== -| Property | Description | Default - -| spring.ai.vertex.ai.ai.base-url | The URL to connect to | https://generativelanguage.googleapis.com/v1beta3 -| spring.ai.vertex.ai.api-key | The API Key | - -|==== - -The prefix `spring.ai.vertex.ai.chat` is the property prefix that lets you configure the chat model implementation for VertexAI Chat. - -[cols="3,5,1", stripes=even] -|==== -| Property | Description | Default - -| spring.ai.vertex.ai.chat.enabled | Enable Vertex AI PaLM API chat model. | true -| spring.ai.vertex.ai.chat.model | This is the https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-chat[Vertex Chat model] to use | chat-bison-001 -| spring.ai.vertex.ai.chat.options.temperature | Controls the randomness of the output. Values can range over [0.0,1.0], inclusive. A value closer to 1.0 will produce responses that are more varied, while a value closer to 0.0 will typically result in less surprising responses from the generative. This value specifies default to be used by the backend while making the call to the generative. | 0.7 -| spring.ai.vertex.ai.chat.options.topK | The maximum number of tokens to consider when sampling. The generative uses combined Top-k and nucleus sampling. Top-k sampling considers the set of topK most probable tokens. | 20 -| spring.ai.vertex.ai.chat.options.topP | The maximum cumulative probability of tokens to consider when sampling. The generative uses combined Top-k and nucleus sampling. Nucleus sampling considers the smallest set of tokens whose probability sum is at least topP. | - -| spring.ai.vertex.ai.chat.options.candidateCount | The number of generated response messages to return. This value must be between [1, 8], inclusive. Defaults to 1. | 1 -|==== - -TIP: All properties prefixed with `spring.ai.vertex.ai.chat.options` can be overridden at runtime by adding a request specific <> to the `Prompt` call. - -== Runtime Options [[chat-options]] - -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2ChatOptions.java[VertexAiPaLm2ChatOptions.java] provides model configurations, such as the temperature, the topK, etc. - -On start-up, the default options can be configured with the `VertexAiPaLm2ChatModel(api, options)` constructor or the `spring.ai.vertex.ai.chat.options.*` properties. - -At run-time you can override the default options by adding new, request specific, options to the `Prompt` call. -For example to override the default temperature for a specific request: - -[source,java] ----- -ChatResponse response = chatModel.call( - new Prompt( - "Generate the names of 5 famous pirates.", - VertexAiPaLm2ChatOptions.builder() - .withTemperature(0.4) - .build() - )); ----- - -TIP: In addition to the model specific `VertexAiPaLm2ChatOptions` you can use a portable https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/ChatOptions.java[ChatOptions] instance, created with the https://github.com/spring-projects/spring-ai/blob/main/spring-ai-core/src/main/java/org/springframework/ai/chat/prompt/ChatOptionsBuilder.java[ChatOptionsBuilder#builder()]. - -== Sample Controller - -https://start.spring.io/[Create] a new Spring Boot project and add the `spring-ai-vertex-ai-palm2-spring-boot-starter` to your pom (or gradle) dependencies. - -Add a `application.properties` file, under the `src/main/resources` directory, to enable and configure the VertexAi chat model: - -[source,application.properties] ----- -spring.ai.vertex.ai.api-key=YOUR_API_KEY -spring.ai.vertex.ai.chat.model=chat-bison-001 -spring.ai.vertex.ai.chat.options.temperature=0.5 ----- - -TIP: replace the `api-key` with your VertexAI credentials. - -This will create a `VertexAiPaLm2ChatModel` implementation that you can inject into your class. -Here is an example of a simple `@Controller` class that uses the chat model for text generations. - -[source,java] ----- -@RestController -public class ChatController { - - private final VertexAiPaLm2ChatModel chatModel; - - @Autowired - public ChatController(VertexAiPaLm2ChatModel chatModel) { - this.chatModel = chatModel; - } - - @GetMapping("/ai/generate") - public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { - return Map.of("generation", this.chatModel.call(message)); - } - - @GetMapping("/ai/generateStream") - public Flux generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { - Prompt prompt = new Prompt(new UserMessage(message)); - return this.chatModel.stream(prompt); - } -} ----- - -== Manual Configuration - -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-openai/src/main/java/org/springframework/ai/vertexai/paml2/VertexAiPaLm2ChatModel.java[VertexAiPaLm2ChatModel] implements the `ChatModel` and uses the <> to connect to the VertexAI service. - -Add the `spring-ai-vertex-ai-palm2` dependency to your project's Maven `pom.xml` file: - -[source, xml] ----- - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ----- - -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-vertex-ai-palm' -} ----- - -TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. - -Next, create a `VertexAiPaLm2ChatModel` and use it for text generations: - -[source,java] ----- -VertexAiPaLm2Api vertexAiApi = new VertexAiPaLm2Api(< YOUR PALM_API_KEY>); - -var chatModel = new VertexAiPaLm2ChatModel(this.vertexAiApi, - VertexAiPaLm2ChatOptions.builder() - .withTemperature(0.4) - .build()); - -ChatResponse response = this.chatModel.call( - new Prompt("Generate the names of 5 famous pirates.")); ----- - -The `VertexAiPaLm2ChatOptions` provides the configuration information for the chat requests. -The `VertexAiPaLm2ChatOptions.Builder` is fluent options builder. - -=== Low-level VertexAiPaLm2Api Client [[low-level-api]] - -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-aipalm2/src/main/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2Api.java[VertexAiPaLm2Api] provides is lightweight Java client for VertexAiPaLm2Api Chat API. - -Following class diagram illustrates the `VertexAiPaLm2Api` chat interfaces and building blocks: - -image::vertex-ai-chat-low-level-api.jpg[w=800,align="center"] - -Here is a simple snippet how to use the api programmatically: - -[source,java] ----- -VertexAiPaLm2Api vertexAiApi = new VertexAiPaLm2Api(< YOUR PALM_API_KEY>); - -// Generate -var prompt = new MessagePrompt(List.of(new Message("0", "Hello, how are you?"))); - -GenerateMessageRequest request = new GenerateMessageRequest(this.prompt); - -GenerateMessageResponse response = this.vertexAiApi.generateMessage(this.request); - -// Embed text -Embedding embedding = this.vertexAiApi.embedText("Hello, how are you?"); - -// Batch embedding -List embeddings = this.vertexAiApi.batchEmbedText(List.of("Hello, how are you?", "I am fine, thank you!")); ----- - - - diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatmodel.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatmodel.adoc index 15da38a2115..a52b1c8c676 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatmodel.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatmodel.adoc @@ -221,7 +221,6 @@ image::spring-ai-chat-completions-clients.jpg[align="center", width="1000px"] * xref:api/chat/azure-openai-chat.adoc[Microsoft Azure Open AI Chat Completion] (streaming & function-calling support) * xref:api/chat/ollama-chat.adoc[Ollama Chat Completion] (streaming, multi-modality & function-calling support) * xref:api/chat/huggingface.adoc[Hugging Face Chat Completion] (no streaming support) -* xref:api/chat/vertexai-palm2-chat.adoc[Google Vertex AI PaLM2 Chat Completion] (no streaming support) * xref:api/chat/vertexai-gemini-chat.adoc[Google Vertex AI Gemini Chat Completion] (streaming, multi-modality & function-calling support) * xref:api/bedrock.adoc[Amazon Bedrock] ** xref:api/chat/bedrock/bedrock-cohere.adoc[Cohere Chat Completion] diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc index f99c5442c60..5ee70ffd7ef 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings.adoc @@ -166,6 +166,5 @@ Internally the various `EmbeddingModel` implementations use different low-level * xref:api/embeddings/bedrock-cohere-embedding.adoc[Spring AI Bedrock Cohere Embeddings] * xref:api/embeddings/bedrock-titan-embedding.adoc[Spring AI Bedrock Titan Embeddings] * xref:api/embeddings/vertexai-embeddings-text.adoc[Spring AI VertexAI Embeddings] -* xref:api/embeddings/vertexai-embeddings-palm2.adoc[Spring AI VertexAI PaLM2 Embeddings] * xref:api/embeddings/mistralai-embeddings.adoc[Spring AI Mistral AI Embeddings] * xref:api/embeddings/oci-genai-embeddings.adoc[Spring AI Oracle Cloud Infrastructure GenAI Embeddings] diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/vertexai-embeddings-palm2.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/vertexai-embeddings-palm2.adoc deleted file mode 100644 index 63365196f2e..00000000000 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/embeddings/vertexai-embeddings-palm2.adoc +++ /dev/null @@ -1,184 +0,0 @@ -= Google VertexAI PaLM2 Embeddings - -NOTE: For text-only embedding use cases, we recommend using the xref:api/embeddings/vertexai-embeddings-text.adoc[Vertex AI text-embeddings model] instead. - -The link:https://developers.generativeai.google/api/rest/generativelanguage[Generative Language] PaLM API allows developers to build generative AI applications using the PaLM model. -Large Language Models (LLMs) are a powerful, versatile type of machine learning model that enables computers to comprehend and generate natural language through a series of prompts. -The PaLM API is based on Google's next generation LLM, PaLM. -It excels at a variety of different tasks like code generation, reasoning, and writing. -You can use the PaLM API to build generative AI applications for use cases like content generation, dialogue agents, summarization and classification systems, and more. - -Based on the link:https://developers.generativeai.google/api/rest/generativelanguage/models[Models REST API]. - -== Prerequisites - -To access the PaLM2 REST API you need to obtain an access API KEY form link:https://makersuite.google.com/app/apikey[makersuite]. - -NOTE: Currently the PaLM API it is not available outside US, but you can use VPN for testing. - -The Spring AI project defines a configuration property named `spring.ai.vertex.ai.api-key` that you should set to the value of the `API Key` obtained. -Exporting an environment variable is one way to set that configuration property: - -[source,shell] ----- -export SPRING_AI_VERTEX_AI_API_KEY= ----- - -=== Add Repositories and BOM - -Spring AI artifacts are published in Spring Milestone and Snapshot repositories. Refer to the xref:getting-started.adoc#repositories[Repositories] section to add these repositories to your build system. - -To help with dependency management, Spring AI provides a BOM (bill of materials) to ensure that a consistent version of Spring AI is used throughout the entire project. Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build system. - - -== Auto-configuration - -Spring AI provides Spring Boot auto-configuration for the VertexAI Embedding Model. -To enable it add the following dependency to your project's Maven `pom.xml` file: - -[source, xml] ----- - - org.springframework.ai - spring-ai-vertex-ai-palm2-spring-boot-starter - ----- - -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-vertex-ai-palm2-spring-boot-starter' -} ----- - -TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. - -=== Embedding Properties - -The prefix `spring.ai.vertex.ai` is used as the property prefix that lets you connect to VertexAI. - -[cols="3,5,1"] -|==== -| Property | Description | Default - -| spring.ai.vertex.ai.ai.base-url | The URL to connect to | https://generativelanguage.googleapis.com/v1beta3 -| spring.ai.vertex.ai.api-key | The API Key | - -|==== - -The prefix `spring.ai.vertex.ai.embedding` is the property prefix that lets you configure the embedding model implementation for VertexAI Chat. - -[cols="3,5,1", stripes=even] -|==== -| Property | Description | Default - -| spring.ai.vertex.ai.embedding.enabled | Enable Vertex AI PaLM API Embedding model. | true -| spring.ai.vertex.ai.embedding.model | This is the https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-embeddings[Vertex Embedding model] to use | embedding-gecko-001 -|==== - - -== Sample Controller - -https://start.spring.io/[Create] a new Spring Boot project and add the `spring-ai-vertex-ai-palm2-spring-boot-starter` to your pom (or gradle) dependencies. - -Add a `application.properties` file, under the `src/main/resources` directory, to enable and configure the VertexAi chat model: - -[source,application.properties] ----- -spring.ai.vertex.ai.api-key=YOUR_API_KEY -spring.ai.vertex.ai.embedding.model=embedding-gecko-001 ----- - -TIP: replace the `api-key` with your VertexAI credentials. - -This will create a `VertexAiPaLm2EmbeddingModel` implementation that you can inject into your class. -Here is an example of a simple `@Controller` class that uses the embedding model for text generations. - -[source,java] ----- -@RestController -public class EmbeddingController { - - private final EmbeddingModel embeddingModel; - - @Autowired - public EmbeddingController(EmbeddingModel embeddingModel) { - this.embeddingModel = embeddingModel; - } - - @GetMapping("/ai/embedding") - public Map embed(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) { - EmbeddingResponse embeddingResponse = this.embeddingModel.embedForResponse(List.of(message)); - return Map.of("embedding", embeddingResponse); - } -} ----- - -== Manual Configuration - -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/VertexAiPaLm2EmbeddingModel.java[VertexAiPaLm2EmbeddingModel] implements the `EmbeddingModel` and uses the <> to connect to the VertexAI service. - -Add the `spring-ai-vertex-ai` dependency to your project's Maven `pom.xml` file: - -[source, xml] ----- - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ----- - -or to your Gradle `build.gradle` build file. - -[source,groovy] ----- -dependencies { - implementation 'org.springframework.ai:spring-ai-vertex-ai-palm2' -} ----- - -TIP: Refer to the xref:getting-started.adoc#dependency-management[Dependency Management] section to add the Spring AI BOM to your build file. - -Next, create a `VertexAiPaLm2EmbeddingModel` and use it for text generations: - -[source,java] ----- -VertexAiPaLm2Api vertexAiApi = new VertexAiPaLm2Api(< YOUR PALM_API_KEY>); - -var embeddingModel = new VertexAiPaLm2EmbeddingModel(this.vertexAiApi); - -EmbeddingResponse embeddingResponse = this.embeddingModel - .embedForResponse(List.of("Hello World", "World is big and salvation is near")); ----- - -== Low-level VertexAiPaLm2Api Client [[low-level-api]] - -The https://github.com/spring-projects/spring-ai/blob/main/models/spring-ai-vertex-ai-palm2/src/main/java/org/springframework/ai/vertexai/palm2/api/VertexAiPaLm2Api.java[VertexAiPaLm2Api] provides is lightweight Java client for VertexAiPaLm2Api Chat API. - -Following class diagram illustrates the `VertexAiPaLm2Api` embedding interfaces and building blocks: - -image::vertex-ai-chat-low-level-api.jpg[w=800,align="center"] - -Here is a simple snippet how to use the api programmatically: - -[source,java] ----- -VertexAiPaLm2Api vertexAiApi = new VertexAiPaLm2Api(< YOUR PALM_API_KEY>); - -// Generate -var prompt = new MessagePrompt(List.of(new Message("0", "Hello, how are you?"))); - -GenerateMessageRequest request = new GenerateMessageRequest(this.prompt); - -GenerateMessageResponse response = this.vertexAiApi.generateMessage(this.request); - -// Embed text -Embedding embedding = this.vertexAiApi.embedText("Hello, how are you?"); - -// Batch embedding -List embeddings = this.vertexAiApi.batchEmbedText(List.of("Hello, how are you?", "I am fine, thank you!")); ----- - - - diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc index ea7f72f7546..970b4d62dff 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/upgrade-notes.adoc @@ -301,3 +301,9 @@ You can access `0.7.1-SNAPSHOT` artifacts as before and still access https://mar ---- +== Upgrading to 1.0.0.M4 + +* PaLM API support removal + +As a follow up to the announcement to https://ai.google.dev/palm_docs/deprecation[deprecate PaLM API], the PaLM API support is removed. + diff --git a/spring-ai-spring-boot-autoconfigure/pom.xml b/spring-ai-spring-boot-autoconfigure/pom.xml index 1c7679fc8bc..2f6179bee67 100644 --- a/spring-ai-spring-boot-autoconfigure/pom.xml +++ b/spring-ai-spring-boot-autoconfigure/pom.xml @@ -233,14 +233,6 @@ true - - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ${project.parent.version} - true - - org.springframework.ai diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java deleted file mode 100644 index e782503895b..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2AutoConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.vertexai.palm2; - -import org.springframework.ai.autoconfigure.retry.SpringAiRetryAutoConfiguration; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatModel; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2EmbeddingModel; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration; -import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.web.client.RestClient; - -@AutoConfiguration(after = RestClientAutoConfiguration.class) -@ConditionalOnClass(VertexAiPaLm2Api.class) -@EnableConfigurationProperties({ VertexAiPalm2ConnectionProperties.class, VertexAiPlam2ChatProperties.class, - VertexAiPalm2EmbeddingProperties.class }) -@ImportAutoConfiguration(classes = { SpringAiRetryAutoConfiguration.class, RestClientAutoConfiguration.class, - WebClientAutoConfiguration.class }) -public class VertexAiPalm2AutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public VertexAiPaLm2Api vertexAiApi(VertexAiPalm2ConnectionProperties connectionProperties, - VertexAiPalm2EmbeddingProperties embeddingAiProperties, VertexAiPlam2ChatProperties chatProperties, - ObjectProvider restClientBuilderProvider) { - - return new VertexAiPaLm2Api(connectionProperties.getBaseUrl(), connectionProperties.getApiKey(), - chatProperties.getModel(), embeddingAiProperties.getModel(), - restClientBuilderProvider.getIfAvailable(RestClient::builder)); - } - - @Bean - @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = VertexAiPlam2ChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", - matchIfMissing = true) - public VertexAiPaLm2ChatModel vertexAiChatModel(VertexAiPaLm2Api vertexAiApi, - VertexAiPlam2ChatProperties chatProperties) { - return new VertexAiPaLm2ChatModel(vertexAiApi, chatProperties.getOptions()); - } - - @Bean - @ConditionalOnMissingBean - @ConditionalOnProperty(prefix = VertexAiPalm2EmbeddingProperties.CONFIG_PREFIX, name = "enabled", - havingValue = "true", matchIfMissing = true) - public VertexAiPaLm2EmbeddingModel vertexAiEmbeddingModel(VertexAiPaLm2Api vertexAiApi) { - return new VertexAiPaLm2EmbeddingModel(vertexAiApi); - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2ConnectionProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2ConnectionProperties.java deleted file mode 100644 index 49e93b8dcb4..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2ConnectionProperties.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.vertexai.palm2; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties(VertexAiPalm2ConnectionProperties.CONFIG_PREFIX) -public class VertexAiPalm2ConnectionProperties { - - public static final String CONFIG_PREFIX = "spring.ai.vertex.ai"; - - /** - * Vertex AI PaLM API access key. - */ - private String apiKey; - - /** - * Vertex AI PaLM API base URL. Defaults to - * https://generativelanguage.googleapis.com/v1beta3 - */ - private String baseUrl = VertexAiPaLm2Api.DEFAULT_BASE_URL; - - public String getApiKey() { - return this.apiKey; - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public String getBaseUrl() { - return this.baseUrl; - } - - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2EmbeddingProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2EmbeddingProperties.java deleted file mode 100644 index 531c8d4fb5f..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPalm2EmbeddingProperties.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.vertexai.palm2; - -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties(VertexAiPalm2EmbeddingProperties.CONFIG_PREFIX) -public class VertexAiPalm2EmbeddingProperties { - - public static final String CONFIG_PREFIX = "spring.ai.vertex.ai.embedding"; - - /** - * Enable Vertex AI PaLM API embedding model. - */ - private boolean enabled = true; - - /** - * Vertex AI PaLM API embedding generative name. Defaults to embedding-gecko-001. - */ - private String model = VertexAiPaLm2Api.DEFAULT_EMBEDDING_MODEL; - - public String getModel() { - return this.model; - } - - public void setModel(String model) { - this.model = model; - } - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPlam2ChatProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPlam2ChatProperties.java deleted file mode 100644 index 5627defd6d4..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPlam2ChatProperties.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.vertexai.palm2; - -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatOptions; -import org.springframework.ai.vertexai.palm2.api.VertexAiPaLm2Api; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties(VertexAiPlam2ChatProperties.CONFIG_PREFIX) -public class VertexAiPlam2ChatProperties { - - public static final String CONFIG_PREFIX = "spring.ai.vertex.ai.chat"; - - /** - * Enable Vertex AI PaLM API chat model - */ - private boolean enabled = true; - - /** - * Vertex AI PaLM API generative name. Defaults to chat-bison-001 - */ - private String model = VertexAiPaLm2Api.DEFAULT_GENERATE_MODEL; - - /** - * Vertex AI PaLM API generative options. - */ - private VertexAiPaLm2ChatOptions options = VertexAiPaLm2ChatOptions.builder() - .withTemperature(0.7) - .withTopP(null) - .withCandidateCount(1) - .withTopK(20) - .build(); - - public String getModel() { - return this.model; - } - - public void setModel(String model) { - this.model = model; - } - - public VertexAiPaLm2ChatOptions getOptions() { - return this.options; - } - - public void setOptions(VertexAiPaLm2ChatOptions options) { - this.options = options; - } - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 3697a809941..ab3f980b7fe 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -20,7 +20,6 @@ org.springframework.ai.autoconfigure.oci.genai.OCIGenAiAutoConfiguration org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration org.springframework.ai.autoconfigure.transformers.TransformersEmbeddingModelAutoConfiguration org.springframework.ai.autoconfigure.huggingface.HuggingfaceChatAutoConfiguration -org.springframework.ai.autoconfigure.vertexai.palm2.VertexAiPalm2AutoConfiguration org.springframework.ai.autoconfigure.vertexai.gemini.VertexAiGeminiAutoConfiguration org.springframework.ai.autoconfigure.bedrock.jurrasic2.BedrockAi21Jurassic2ChatAutoConfiguration org.springframework.ai.autoconfigure.bedrock.llama.BedrockLlamaChatAutoConfiguration diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java deleted file mode 100644 index 50790e79b8a..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vertexai/palm2/VertexAiPaLm2AutoConfigurationIT.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2023-2024 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.vertexai.palm2; - -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; - -import org.springframework.ai.embedding.EmbeddingResponse; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2ChatModel; -import org.springframework.ai.vertexai.palm2.VertexAiPaLm2EmbeddingModel; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -// NOTE: works only with US location. Use VPN if you are outside US. -@EnabledIfEnvironmentVariable(named = "PALM_API_KEY", matches = ".*") -@Disabled("Disabled due to the PALM API being decommissioned by Google.") -public class VertexAiPaLm2AutoConfigurationIT { - - private static final Log logger = LogFactory.getLog(VertexAiPaLm2AutoConfigurationIT.class); - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.vertex.ai.baseUrl=https://generativelanguage.googleapis.com/v1beta3", - "spring.ai.vertex.ai.apiKey=" + System.getenv("PALM_API_KEY"), - "spring.ai.vertex.ai.chat.model=chat-bison-001", "spring.ai.vertex.ai.chat.options.temperature=0.8", - "spring.ai.vertex.ai.embedding.model=embedding-gecko-001") - .withConfiguration(AutoConfigurations.of(VertexAiPalm2AutoConfiguration.class)); - - @Test - void generate() { - this.contextRunner.run(context -> { - VertexAiPaLm2ChatModel chatModel = context.getBean(VertexAiPaLm2ChatModel.class); - - String response = chatModel.call("Hello"); - - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); - }); - } - - @Test - void embedding() { - this.contextRunner.run(context -> { - VertexAiPaLm2EmbeddingModel embeddingModel = context.getBean(VertexAiPaLm2EmbeddingModel.class); - - EmbeddingResponse embeddingResponse = embeddingModel - .embedForResponse(List.of("Hello World", "World is big and salvation is near")); - assertThat(embeddingResponse.getResults()).hasSize(2); - assertThat(embeddingResponse.getResults().get(0).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(0).getIndex()).isEqualTo(0); - assertThat(embeddingResponse.getResults().get(1).getOutput()).isNotEmpty(); - assertThat(embeddingResponse.getResults().get(1).getIndex()).isEqualTo(1); - - assertThat(embeddingModel.dimensions()).isEqualTo(768); - }); - } - - @Test - public void embeddingActivation() { - - // Disable the embedding auto-configuration. - this.contextRunner.withPropertyValues("spring.ai.vertex.ai.embedding.enabled=false").run(context -> { - assertThat(context.getBeansOfType(VertexAiPalm2EmbeddingProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2EmbeddingModel.class)).isEmpty(); - }); - - // The embedding auto-configuration is enabled by default. - this.contextRunner.run(context -> { - assertThat(context.getBeansOfType(VertexAiPalm2EmbeddingProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2EmbeddingModel.class)).isNotEmpty(); - }); - - // Explicitly enable the embedding auto-configuration. - this.contextRunner.withPropertyValues("spring.ai.vertex.ai.embedding.enabled=true").run(context -> { - assertThat(context.getBeansOfType(VertexAiPalm2EmbeddingProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2EmbeddingModel.class)).isNotEmpty(); - }); - } - - @Test - public void chatActivation() { - - // Disable the chat auto-configuration. - this.contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=false").run(context -> { - assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatModel.class)).isEmpty(); - }); - - // The chat auto-configuration is enabled by default. - this.contextRunner.run(context -> { - assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatModel.class)).isNotEmpty(); - }); - - // Explicitly enable the chat auto-configuration. - this.contextRunner.withPropertyValues("spring.ai.vertex.ai.chat.enabled=true").run(context -> { - assertThat(context.getBeansOfType(VertexAiPlam2ChatProperties.class)).isNotEmpty(); - assertThat(context.getBeansOfType(VertexAiPaLm2ChatModel.class)).isNotEmpty(); - }); - } - -} diff --git a/spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-palm2/pom.xml b/spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-palm2/pom.xml deleted file mode 100644 index 97d0f1077c7..00000000000 --- a/spring-ai-spring-boot-starters/spring-ai-starter-vertex-ai-palm2/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - 4.0.0 - - org.springframework.ai - spring-ai - 1.0.0-SNAPSHOT - ../../pom.xml - - spring-ai-vertex-ai-palm2-spring-boot-starter - jar - Spring AI Starter - VertexAI PaLM2 - Spring AI VertexAI PaLM2 Auto Configuration - https://github.com/spring-projects/spring-ai - - - https://github.com/spring-projects/spring-ai - git://github.com/spring-projects/spring-ai.git - git@github.com:spring-projects/spring-ai.git - - - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.ai - spring-ai-spring-boot-autoconfigure - ${project.parent.version} - - - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ${project.parent.version} - - - - diff --git a/vector-stores/spring-ai-milvus-store/pom.xml b/vector-stores/spring-ai-milvus-store/pom.xml index 1a0029d032e..c671083d436 100644 --- a/vector-stores/spring-ai-milvus-store/pom.xml +++ b/vector-stores/spring-ai-milvus-store/pom.xml @@ -56,12 +56,6 @@ - - org.springframework.ai - spring-ai-vertex-ai-palm2 - ${parent.version} - test - org.springframework.ai