diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/action/voyageai/VoyageAIActionCreator.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/action/voyageai/VoyageAIActionCreator.java index 111af588f3ce5..641d6aa942405 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/action/voyageai/VoyageAIActionCreator.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/action/voyageai/VoyageAIActionCreator.java @@ -10,9 +10,16 @@ import org.elasticsearch.inference.InputType; import org.elasticsearch.xpack.inference.external.action.ExecutableAction; import org.elasticsearch.xpack.inference.external.action.SenderExecutableAction; +import org.elasticsearch.xpack.inference.external.http.retry.ResponseHandler; +import org.elasticsearch.xpack.inference.external.http.sender.DocumentsOnlyInput; +import org.elasticsearch.xpack.inference.external.http.sender.GenericRequestManager; +import org.elasticsearch.xpack.inference.external.http.sender.QueryAndDocsInputs; import org.elasticsearch.xpack.inference.external.http.sender.Sender; -import org.elasticsearch.xpack.inference.external.http.sender.VoyageAIEmbeddingsRequestManager; -import org.elasticsearch.xpack.inference.external.http.sender.VoyageAIRerankRequestManager; +import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIEmbeddingsRequest; +import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIRerankRequest; +import org.elasticsearch.xpack.inference.external.response.voyageai.VoyageAIEmbeddingsResponseEntity; +import org.elasticsearch.xpack.inference.external.response.voyageai.VoyageAIRerankResponseEntity; +import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIResponseHandler; import org.elasticsearch.xpack.inference.services.ServiceComponents; import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsModel; import org.elasticsearch.xpack.inference.services.voyageai.rerank.VoyageAIRerankModel; @@ -26,6 +33,15 @@ * Provides a way to construct an {@link ExecutableAction} using the visitor pattern based on the voyageai model type. */ public class VoyageAIActionCreator implements VoyageAIActionVisitor { + public static final ResponseHandler EMBEDDINGS_HANDLER = new VoyageAIResponseHandler( + "voyageai text embedding", + VoyageAIEmbeddingsResponseEntity::fromResponse + ); + static final ResponseHandler RERANK_HANDLER = new VoyageAIResponseHandler( + "voyageai rerank", + (request, response) -> VoyageAIRerankResponseEntity.fromResponse(response) + ); + private final Sender sender; private final ServiceComponents serviceComponents; @@ -37,16 +53,30 @@ public VoyageAIActionCreator(Sender sender, ServiceComponents serviceComponents) @Override public ExecutableAction create(VoyageAIEmbeddingsModel model, Map taskSettings, InputType inputType) { var overriddenModel = VoyageAIEmbeddingsModel.of(model, taskSettings, inputType); + var manager = new GenericRequestManager<>( + serviceComponents.threadPool(), + overriddenModel, + EMBEDDINGS_HANDLER, + (documentsOnlyInput) -> new VoyageAIEmbeddingsRequest(documentsOnlyInput.getInputs(), overriddenModel), + DocumentsOnlyInput.class + ); + var failedToSendRequestErrorMessage = constructFailedToSendRequestMessage("VoyageAI embeddings"); - var requestCreator = VoyageAIEmbeddingsRequestManager.of(overriddenModel, serviceComponents.threadPool()); - return new SenderExecutableAction(sender, requestCreator, failedToSendRequestErrorMessage); + return new SenderExecutableAction(sender, manager, failedToSendRequestErrorMessage); } @Override public ExecutableAction create(VoyageAIRerankModel model, Map taskSettings) { var overriddenModel = VoyageAIRerankModel.of(model, taskSettings); + var manager = new GenericRequestManager<>( + serviceComponents.threadPool(), + overriddenModel, + RERANK_HANDLER, + (rerankInput) -> new VoyageAIRerankRequest(rerankInput.getQuery(), rerankInput.getChunks(), model), + QueryAndDocsInputs.class + ); + var failedToSendRequestErrorMessage = constructFailedToSendRequestMessage("VoyageAI rerank"); - var requestCreator = VoyageAIRerankRequestManager.of(overriddenModel, serviceComponents.threadPool()); - return new SenderExecutableAction(sender, requestCreator, failedToSendRequestErrorMessage); + return new SenderExecutableAction(sender, manager, failedToSendRequestErrorMessage); } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIEmbeddingsRequestManager.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIEmbeddingsRequestManager.java deleted file mode 100644 index be186dc54f8f2..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIEmbeddingsRequestManager.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.external.http.sender; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.inference.InferenceServiceResults; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.xpack.inference.external.http.retry.RequestSender; -import org.elasticsearch.xpack.inference.external.http.retry.ResponseHandler; -import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIEmbeddingsRequest; -import org.elasticsearch.xpack.inference.external.response.voyageai.VoyageAIEmbeddingsResponseEntity; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIResponseHandler; -import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsModel; - -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; - -public class VoyageAIEmbeddingsRequestManager extends VoyageAIRequestManager { - private static final Logger logger = LogManager.getLogger(VoyageAIEmbeddingsRequestManager.class); - private static final ResponseHandler HANDLER = createEmbeddingsHandler(); - - private static ResponseHandler createEmbeddingsHandler() { - return new VoyageAIResponseHandler("voyageai text embedding", VoyageAIEmbeddingsResponseEntity::fromResponse); - } - - public static VoyageAIEmbeddingsRequestManager of(VoyageAIEmbeddingsModel model, ThreadPool threadPool) { - return new VoyageAIEmbeddingsRequestManager(Objects.requireNonNull(model), Objects.requireNonNull(threadPool)); - } - - private final VoyageAIEmbeddingsModel model; - - private VoyageAIEmbeddingsRequestManager(VoyageAIEmbeddingsModel model, ThreadPool threadPool) { - super(threadPool, model); - this.model = Objects.requireNonNull(model); - } - - @Override - public void execute( - InferenceInputs inferenceInputs, - RequestSender requestSender, - Supplier hasRequestCompletedFunction, - ActionListener listener - ) { - List docsInput = DocumentsOnlyInput.of(inferenceInputs).getInputs(); - VoyageAIEmbeddingsRequest request = new VoyageAIEmbeddingsRequest(docsInput, model); - - execute(new ExecutableInferenceRequest(requestSender, logger, request, HANDLER, hasRequestCompletedFunction, listener)); - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRequestManager.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRequestManager.java deleted file mode 100644 index 99a0617ff510a..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRequestManager.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.external.http.sender; - -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIModel; - -import java.util.Map; -import java.util.Objects; - -abstract class VoyageAIRequestManager extends BaseRequestManager { - private static final String DEFAULT_MODEL_FAMILY = "default_model_family"; - private static final Map MODEL_TO_MODEL_FAMILY = Map.of( - "voyage-multimodal-3", - "embed_multimodal", - "voyage-3-large", - "embed_large", - "voyage-code-3", - "embed_large", - "voyage-3", - "embed_medium", - "voyage-3-lite", - "embed_small", - "voyage-finance-2", - "embed_large", - "voyage-law-2", - "embed_large", - "voyage-code-2", - "embed_large", - "rerank-2", - "rerank_large", - "rerank-2-lite", - "rerank_small" - ); - - protected VoyageAIRequestManager(ThreadPool threadPool, VoyageAIModel model) { - super(threadPool, model.getInferenceEntityId(), RateLimitGrouping.of(model), model.rateLimitServiceSettings().rateLimitSettings()); - } - - record RateLimitGrouping(int apiKeyHash) { - public static RateLimitGrouping of(VoyageAIModel model) { - Objects.requireNonNull(model); - String modelId = model.getServiceSettings().modelId(); - String modelFamily = MODEL_TO_MODEL_FAMILY.getOrDefault(modelId, DEFAULT_MODEL_FAMILY); - - return new RateLimitGrouping(modelFamily.hashCode()); - } - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRerankRequestManager.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRerankRequestManager.java deleted file mode 100644 index ca91ad4dda276..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/sender/VoyageAIRerankRequestManager.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.external.http.sender; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.inference.InferenceServiceResults; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.xpack.inference.external.http.retry.RequestSender; -import org.elasticsearch.xpack.inference.external.http.retry.ResponseHandler; -import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIRerankRequest; -import org.elasticsearch.xpack.inference.external.response.voyageai.VoyageAIRerankResponseEntity; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIResponseHandler; -import org.elasticsearch.xpack.inference.services.voyageai.rerank.VoyageAIRerankModel; - -import java.util.Objects; -import java.util.function.Supplier; - -public class VoyageAIRerankRequestManager extends VoyageAIRequestManager { - private static final Logger logger = LogManager.getLogger(VoyageAIRerankRequestManager.class); - private static final ResponseHandler HANDLER = createVoyageAIResponseHandler(); - - private static ResponseHandler createVoyageAIResponseHandler() { - return new VoyageAIResponseHandler("voyageai rerank", (request, response) -> VoyageAIRerankResponseEntity.fromResponse(response)); - } - - public static VoyageAIRerankRequestManager of(VoyageAIRerankModel model, ThreadPool threadPool) { - return new VoyageAIRerankRequestManager(Objects.requireNonNull(model), Objects.requireNonNull(threadPool)); - } - - private final VoyageAIRerankModel model; - - private VoyageAIRerankRequestManager(VoyageAIRerankModel model, ThreadPool threadPool) { - super(threadPool, model); - this.model = model; - } - - @Override - public void execute( - InferenceInputs inferenceInputs, - RequestSender requestSender, - Supplier hasRequestCompletedFunction, - ActionListener listener - ) { - var rerankInput = QueryAndDocsInputs.of(inferenceInputs); - VoyageAIRerankRequest request = new VoyageAIRerankRequest(rerankInput.getQuery(), rerankInput.getChunks(), model); - - execute(new ExecutableInferenceRequest(requestSender, logger, request, HANDLER, hasRequestCompletedFunction, listener)); - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/RequestUtils.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/RequestUtils.java index 6116b1cc234c6..b2f073c1eb69c 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/RequestUtils.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/RequestUtils.java @@ -34,5 +34,9 @@ public static URI buildUri(URI accountUri, String service, CheckedSupplier uriBuilder) { + return buildUri(null, service, uriBuilder); + } + private RequestUtils() {} } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIEmbeddingsRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIEmbeddingsRequest.java index a24f5dc8e14ea..a5dfb69529ae9 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIEmbeddingsRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIEmbeddingsRequest.java @@ -12,10 +12,8 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.inference.external.request.HttpRequest; import org.elasticsearch.xpack.inference.external.request.Request; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIAccount; import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsModel; import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsServiceSettings; -import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsTaskSettings; import java.net.URI; import java.nio.charset.StandardCharsets; @@ -24,47 +22,43 @@ public class VoyageAIEmbeddingsRequest extends VoyageAIRequest { - private final VoyageAIAccount account; private final List input; - private final VoyageAIEmbeddingsServiceSettings serviceSettings; - private final VoyageAIEmbeddingsTaskSettings taskSettings; - private final String model; - private final String inferenceEntityId; + private final VoyageAIEmbeddingsModel embeddingsModel; public VoyageAIEmbeddingsRequest(List input, VoyageAIEmbeddingsModel embeddingsModel) { - Objects.requireNonNull(embeddingsModel); - - account = VoyageAIAccount.of(embeddingsModel); + this.embeddingsModel = Objects.requireNonNull(embeddingsModel); this.input = Objects.requireNonNull(input); - serviceSettings = embeddingsModel.getServiceSettings(); - taskSettings = embeddingsModel.getTaskSettings(); - model = embeddingsModel.getServiceSettings().getCommonSettings().modelId(); - inferenceEntityId = embeddingsModel.getInferenceEntityId(); } @Override public HttpRequest createHttpRequest() { - HttpPost httpPost = new HttpPost(account.uri()); + HttpPost httpPost = new HttpPost(embeddingsModel.uri()); ByteArrayEntity byteEntity = new ByteArrayEntity( - Strings.toString(new VoyageAIEmbeddingsRequestEntity(input, serviceSettings, taskSettings, model)) - .getBytes(StandardCharsets.UTF_8) + Strings.toString( + new VoyageAIEmbeddingsRequestEntity( + input, + embeddingsModel.getServiceSettings(), + embeddingsModel.getTaskSettings(), + embeddingsModel.getServiceSettings().modelId() + ) + ).getBytes(StandardCharsets.UTF_8) ); httpPost.setEntity(byteEntity); - decorateWithHeaders(httpPost, account); + decorateWithHeaders(httpPost, embeddingsModel); return new HttpRequest(httpPost, getInferenceEntityId()); } @Override public String getInferenceEntityId() { - return inferenceEntityId; + return embeddingsModel.getInferenceEntityId(); } @Override public URI getURI() { - return account.uri(); + return embeddingsModel.uri(); } @Override @@ -77,11 +71,7 @@ public boolean[] getTruncationInfo() { return null; } - public VoyageAIEmbeddingsTaskSettings getTaskSettings() { - return taskSettings; - } - public VoyageAIEmbeddingsServiceSettings getServiceSettings() { - return serviceSettings; + return embeddingsModel.getServiceSettings(); } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequest.java index 5455a2f0301f2..36e0581929591 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequest.java @@ -11,15 +11,15 @@ import org.apache.http.client.methods.HttpPost; import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xpack.inference.external.request.Request; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIAccount; +import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIModel; import static org.elasticsearch.xpack.inference.external.request.RequestUtils.createAuthBearerHeader; public abstract class VoyageAIRequest implements Request { - public static void decorateWithHeaders(HttpPost request, VoyageAIAccount account) { + public static void decorateWithHeaders(HttpPost request, VoyageAIModel model) { request.setHeader(HttpHeaders.CONTENT_TYPE, XContentType.JSON.mediaType()); - request.setHeader(createAuthBearerHeader(account.apiKey())); + request.setHeader(createAuthBearerHeader(model.apiKey())); request.setHeader(VoyageAIUtils.createRequestSourceHeader()); } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRerankRequest.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRerankRequest.java index 37d15fe1fe2c5..9fb50720e4d55 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRerankRequest.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRerankRequest.java @@ -12,9 +12,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.inference.external.request.HttpRequest; import org.elasticsearch.xpack.inference.external.request.Request; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIAccount; import org.elasticsearch.xpack.inference.services.voyageai.rerank.VoyageAIRerankModel; -import org.elasticsearch.xpack.inference.services.voyageai.rerank.VoyageAIRerankTaskSettings; import java.net.URI; import java.nio.charset.StandardCharsets; @@ -23,46 +21,40 @@ public class VoyageAIRerankRequest extends VoyageAIRequest { - private final VoyageAIAccount account; private final String query; private final List input; - private final VoyageAIRerankTaskSettings taskSettings; - private final String model; - private final String inferenceEntityId; + private final VoyageAIRerankModel model; public VoyageAIRerankRequest(String query, List input, VoyageAIRerankModel model) { - Objects.requireNonNull(model); + this.model = Objects.requireNonNull(model); - this.account = VoyageAIAccount.of(model); this.input = Objects.requireNonNull(input); this.query = Objects.requireNonNull(query); - taskSettings = model.getTaskSettings(); - this.model = model.getServiceSettings().modelId(); - inferenceEntityId = model.getInferenceEntityId(); } @Override public HttpRequest createHttpRequest() { - HttpPost httpPost = new HttpPost(account.uri()); + HttpPost httpPost = new HttpPost(model.uri()); ByteArrayEntity byteEntity = new ByteArrayEntity( - Strings.toString(new VoyageAIRerankRequestEntity(query, input, taskSettings, model)).getBytes(StandardCharsets.UTF_8) + Strings.toString(new VoyageAIRerankRequestEntity(query, input, model.getTaskSettings(), model.getServiceSettings().modelId())) + .getBytes(StandardCharsets.UTF_8) ); httpPost.setEntity(byteEntity); - decorateWithHeaders(httpPost, account); + decorateWithHeaders(httpPost, model); return new HttpRequest(httpPost, getInferenceEntityId()); } @Override public String getInferenceEntityId() { - return inferenceEntityId; + return model.getInferenceEntityId(); } @Override public URI getURI() { - return account.uri(); + return model.uri(); } @Override diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/voyageai/VoyageAIAccount.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/voyageai/VoyageAIAccount.java deleted file mode 100644 index bb7de2fc8ad0c..0000000000000 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/voyageai/VoyageAIAccount.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.inference.external.voyageai; - -import org.elasticsearch.ElasticsearchStatusException; -import org.elasticsearch.common.settings.SecureString; -import org.elasticsearch.rest.RestStatus; -import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIModel; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Objects; - -public record VoyageAIAccount(URI uri, SecureString apiKey) { - - public static VoyageAIAccount of(VoyageAIModel model) { - try { - var uri = model.buildUri(); - return new VoyageAIAccount(uri, model.apiKey()); - } catch (URISyntaxException e) { - // using bad request here so that potentially sensitive URL information does not get logged - throw new ElasticsearchStatusException("Failed to construct VoyageAI URL", RestStatus.BAD_REQUEST, e); - } - } - - public VoyageAIAccount { - Objects.requireNonNull(uri); - Objects.requireNonNull(apiKey); - } -} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIModel.java index e63a716b96617..7f9b9fc405d26 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIModel.java @@ -10,53 +10,68 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.core.Nullable; import org.elasticsearch.inference.InputType; -import org.elasticsearch.inference.Model; import org.elasticsearch.inference.ModelConfigurations; import org.elasticsearch.inference.ModelSecrets; import org.elasticsearch.inference.ServiceSettings; import org.elasticsearch.inference.TaskSettings; import org.elasticsearch.xpack.inference.external.action.ExecutableAction; import org.elasticsearch.xpack.inference.external.action.voyageai.VoyageAIActionVisitor; +import org.elasticsearch.xpack.inference.services.RateLimitGroupingModel; import org.elasticsearch.xpack.inference.services.ServiceUtils; import org.elasticsearch.xpack.inference.services.settings.ApiKeySecrets; +import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; import java.net.URI; -import java.net.URISyntaxException; import java.util.Map; import java.util.Objects; -public abstract class VoyageAIModel extends Model { +public abstract class VoyageAIModel extends RateLimitGroupingModel { + private static final String DEFAULT_MODEL_FAMILY = "default_model_family"; + private static final Map MODEL_TO_MODEL_FAMILY = Map.of( + "voyage-multimodal-3", + "embed_multimodal", + "voyage-3-large", + "embed_large", + "voyage-code-3", + "embed_large", + "voyage-3", + "embed_medium", + "voyage-3-lite", + "embed_small", + "voyage-finance-2", + "embed_large", + "voyage-law-2", + "embed_large", + "voyage-code-2", + "embed_large", + "rerank-2", + "rerank_large", + "rerank-2-lite", + "rerank_small" + ); + private final SecureString apiKey; private final VoyageAIRateLimitServiceSettings rateLimitServiceSettings; - protected final URI uri; - - public VoyageAIModel( - ModelConfigurations configurations, - ModelSecrets secrets, - @Nullable ApiKeySecrets apiKeySecrets, - VoyageAIRateLimitServiceSettings rateLimitServiceSettings - ) { - this(configurations, secrets, apiKeySecrets, rateLimitServiceSettings, null); - } + private final URI uri; public VoyageAIModel( ModelConfigurations configurations, ModelSecrets secrets, @Nullable ApiKeySecrets apiKeySecrets, VoyageAIRateLimitServiceSettings rateLimitServiceSettings, - String url + URI uri ) { super(configurations, secrets); this.rateLimitServiceSettings = Objects.requireNonNull(rateLimitServiceSettings); this.apiKey = ServiceUtils.apiKey(apiKeySecrets); - this.uri = url == null ? null : URI.create(url); + this.uri = Objects.requireNonNull(uri); } protected VoyageAIModel(VoyageAIModel model, TaskSettings taskSettings) { super(model, taskSettings); - this.rateLimitServiceSettings = model.rateLimitServiceSettings(); + this.rateLimitServiceSettings = model.rateLimitServiceSettings; this.apiKey = model.apiKey(); this.uri = model.uri; } @@ -64,7 +79,7 @@ protected VoyageAIModel(VoyageAIModel model, TaskSettings taskSettings) { protected VoyageAIModel(VoyageAIModel model, ServiceSettings serviceSettings) { super(model, serviceSettings); - this.rateLimitServiceSettings = model.rateLimitServiceSettings(); + this.rateLimitServiceSettings = model.rateLimitServiceSettings; this.apiKey = model.apiKey(); this.uri = model.uri; } @@ -73,22 +88,20 @@ public SecureString apiKey() { return apiKey; } - public VoyageAIRateLimitServiceSettings rateLimitServiceSettings() { - return rateLimitServiceSettings; - } + public int rateLimitGroupingHash() { + String modelId = getServiceSettings().modelId(); + String modelFamily = MODEL_TO_MODEL_FAMILY.getOrDefault(modelId, DEFAULT_MODEL_FAMILY); - public abstract ExecutableAction accept(VoyageAIActionVisitor creator, Map taskSettings, InputType inputType); + return Objects.hash(modelFamily, apiKey); + } - public URI uri() { - return uri; + public RateLimitSettings rateLimitSettings() { + return rateLimitServiceSettings.rateLimitSettings(); } - public URI buildUri() throws URISyntaxException { - if (uri == null) { - return buildRequestUri(); - } + public URI uri() { return uri; } - protected abstract URI buildRequestUri() throws URISyntaxException; + public abstract ExecutableAction accept(VoyageAIActionVisitor creator, Map taskSettings, InputType inputType); } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/embeddings/VoyageAIEmbeddingsModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/embeddings/VoyageAIEmbeddingsModel.java index 41194f6862a44..bb476cf024415 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/embeddings/VoyageAIEmbeddingsModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/embeddings/VoyageAIEmbeddingsModel.java @@ -18,13 +18,16 @@ import org.elasticsearch.xpack.inference.external.action.voyageai.VoyageAIActionVisitor; import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIUtils; import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.ServiceUtils; import org.elasticsearch.xpack.inference.services.settings.DefaultSecretSettings; import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIModel; +import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIService; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; +import static org.elasticsearch.xpack.inference.external.request.RequestUtils.buildUri; import static org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIUtils.HOST; public class VoyageAIEmbeddingsModel extends VoyageAIModel { @@ -51,42 +54,46 @@ public VoyageAIEmbeddingsModel( VoyageAIEmbeddingsServiceSettings.fromMap(serviceSettings, context), VoyageAIEmbeddingsTaskSettings.fromMap(taskSettings), chunkingSettings, - DefaultSecretSettings.fromMap(secrets) + DefaultSecretSettings.fromMap(secrets), + buildUri(VoyageAIService.NAME, VoyageAIEmbeddingsModel::buildRequestUri) ); } + public static URI buildRequestUri() throws URISyntaxException { + return new URIBuilder().setScheme("https") + .setHost(HOST) + .setPathSegments(VoyageAIUtils.VERSION_1, VoyageAIUtils.EMBEDDINGS_PATH) + .build(); + } + // should only be used for testing VoyageAIEmbeddingsModel( - String modelId, + String inferenceId, String service, + String url, VoyageAIEmbeddingsServiceSettings serviceSettings, VoyageAIEmbeddingsTaskSettings taskSettings, ChunkingSettings chunkingSettings, @Nullable DefaultSecretSettings secretSettings ) { - super( - new ModelConfigurations(modelId, TaskType.TEXT_EMBEDDING, service, serviceSettings, taskSettings, chunkingSettings), - new ModelSecrets(secretSettings), - secretSettings, - serviceSettings.getCommonSettings() - ); + this(inferenceId, service, serviceSettings, taskSettings, chunkingSettings, secretSettings, ServiceUtils.createUri(url)); } - VoyageAIEmbeddingsModel( - String modelId, + private VoyageAIEmbeddingsModel( + String inferenceId, String service, - String url, VoyageAIEmbeddingsServiceSettings serviceSettings, VoyageAIEmbeddingsTaskSettings taskSettings, ChunkingSettings chunkingSettings, - @Nullable DefaultSecretSettings secretSettings + @Nullable DefaultSecretSettings secretSettings, + URI uri ) { super( - new ModelConfigurations(modelId, TaskType.TEXT_EMBEDDING, service, serviceSettings, taskSettings, chunkingSettings), + new ModelConfigurations(inferenceId, TaskType.TEXT_EMBEDDING, service, serviceSettings, taskSettings, chunkingSettings), new ModelSecrets(secretSettings), secretSettings, serviceSettings.getCommonSettings(), - url + uri ); } @@ -117,11 +124,4 @@ public DefaultSecretSettings getSecretSettings() { public ExecutableAction accept(VoyageAIActionVisitor visitor, Map taskSettings, InputType inputType) { return visitor.create(this, taskSettings, inputType); } - - protected URI buildRequestUri() throws URISyntaxException { - return new URIBuilder().setScheme("https") - .setHost(HOST) - .setPathSegments(VoyageAIUtils.VERSION_1, VoyageAIUtils.EMBEDDINGS_PATH) - .build(); - } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/rerank/VoyageAIRerankModel.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/rerank/VoyageAIRerankModel.java index 57c478962b5f2..479791a442191 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/rerank/VoyageAIRerankModel.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/voyageai/rerank/VoyageAIRerankModel.java @@ -17,13 +17,16 @@ import org.elasticsearch.xpack.inference.external.action.voyageai.VoyageAIActionVisitor; import org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIUtils; import org.elasticsearch.xpack.inference.services.ConfigurationParseContext; +import org.elasticsearch.xpack.inference.services.ServiceUtils; import org.elasticsearch.xpack.inference.services.settings.DefaultSecretSettings; import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIModel; +import org.elasticsearch.xpack.inference.services.voyageai.VoyageAIService; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; +import static org.elasticsearch.xpack.inference.external.request.RequestUtils.buildUri; import static org.elasticsearch.xpack.inference.external.request.voyageai.VoyageAIUtils.HOST; public class VoyageAIRerankModel extends VoyageAIModel { @@ -45,35 +48,44 @@ public VoyageAIRerankModel( service, VoyageAIRerankServiceSettings.fromMap(serviceSettings, context), VoyageAIRerankTaskSettings.fromMap(taskSettings), - DefaultSecretSettings.fromMap(secrets) + DefaultSecretSettings.fromMap(secrets), + buildUri(VoyageAIService.NAME, VoyageAIRerankModel::buildRequestUri) ); } + public static URI buildRequestUri() throws URISyntaxException { + return new URIBuilder().setScheme("https") + .setHost(HOST) + .setPathSegments(VoyageAIUtils.VERSION_1, VoyageAIUtils.RERANK_PATH) + .build(); + } + // should only be used for testing VoyageAIRerankModel( - String modelId, + String inferenceId, String service, + String url, VoyageAIRerankServiceSettings serviceSettings, VoyageAIRerankTaskSettings taskSettings, @Nullable DefaultSecretSettings secretSettings ) { - this(modelId, service, null, serviceSettings, taskSettings, secretSettings); + this(inferenceId, service, serviceSettings, taskSettings, secretSettings, ServiceUtils.createUri(url)); } - VoyageAIRerankModel( - String modelId, + private VoyageAIRerankModel( + String inferenceId, String service, - String url, VoyageAIRerankServiceSettings serviceSettings, VoyageAIRerankTaskSettings taskSettings, - @Nullable DefaultSecretSettings secretSettings + @Nullable DefaultSecretSettings secretSettings, + URI uri ) { super( - new ModelConfigurations(modelId, TaskType.RERANK, service, serviceSettings, taskSettings), + new ModelConfigurations(inferenceId, TaskType.RERANK, service, serviceSettings, taskSettings), new ModelSecrets(secretSettings), secretSettings, serviceSettings.getCommonSettings(), - url + uri ); } @@ -81,10 +93,6 @@ private VoyageAIRerankModel(VoyageAIRerankModel model, VoyageAIRerankTaskSetting super(model, taskSettings); } - public VoyageAIRerankModel(VoyageAIRerankModel model, VoyageAIRerankServiceSettings serviceSettings) { - super(model, serviceSettings); - } - @Override public VoyageAIRerankServiceSettings getServiceSettings() { return (VoyageAIRerankServiceSettings) super.getServiceSettings(); @@ -112,11 +120,4 @@ public ExecutableAction accept(VoyageAIActionVisitor visitor, Map { - ActionListener listener = invocation.getArgument(3); - listener.onFailure(new IllegalStateException("failed")); - - return Void.TYPE; - }).when(sender).send(any(), any(), any(), any()); - - var action = createAction(null, "secret", VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS, "model", null, sender); - - PlainActionFuture listener = new PlainActionFuture<>(); - action.execute(new DocumentsOnlyInput(List.of("abc")), InferenceAction.Request.DEFAULT_TIMEOUT, listener); - - var thrownException = expectThrows(ElasticsearchException.class, () -> listener.actionGet(TIMEOUT)); - - MatcherAssert.assertThat(thrownException.getMessage(), is("Failed to send VoyageAI embeddings request. Cause: failed")); - } - public void testExecute_ThrowsException() { var sender = mock(Sender.class); doThrow(new IllegalArgumentException("failed")).when(sender).send(any(), any(), any(), any()); @@ -373,20 +355,6 @@ public void testExecute_ThrowsException() { MatcherAssert.assertThat(thrownException.getMessage(), is("Failed to send VoyageAI embeddings request. Cause: failed")); } - public void testExecute_ThrowsExceptionWithNullUrl() { - var sender = mock(Sender.class); - doThrow(new IllegalArgumentException("failed")).when(sender).send(any(), any(), any(), any()); - - var action = createAction(null, "secret", VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS, "model", null, sender); - - PlainActionFuture listener = new PlainActionFuture<>(); - action.execute(new DocumentsOnlyInput(List.of("abc")), InferenceAction.Request.DEFAULT_TIMEOUT, listener); - - var thrownException = expectThrows(ElasticsearchException.class, () -> listener.actionGet(TIMEOUT)); - - MatcherAssert.assertThat(thrownException.getMessage(), is("Failed to send VoyageAI embeddings request. Cause: failed")); - } - private ExecutableAction createAction( String url, String apiKey, @@ -396,9 +364,16 @@ private ExecutableAction createAction( Sender sender ) { var model = VoyageAIEmbeddingsModelTests.createModel(url, apiKey, taskSettings, 1024, 1024, modelName, embeddingType); + var manager = new GenericRequestManager<>( + threadPool, + model, + EMBEDDINGS_HANDLER, + (documentsOnlyInput) -> new VoyageAIEmbeddingsRequest(documentsOnlyInput.getInputs(), model), + DocumentsOnlyInput.class + ); + var failedToSendRequestErrorMessage = constructFailedToSendRequestMessage("VoyageAI embeddings"); - var requestCreator = VoyageAIEmbeddingsRequestManager.of(model, threadPool); - return new SenderExecutableAction(sender, requestCreator, failedToSendRequestErrorMessage); + return new SenderExecutableAction(sender, manager, failedToSendRequestErrorMessage); } } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequestTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequestTests.java index 5244ef83a7c7b..44206edcc0345 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequestTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/external/request/voyageai/VoyageAIRequestTests.java @@ -9,12 +9,9 @@ import org.apache.http.HttpHeaders; import org.apache.http.client.methods.HttpPost; -import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xcontent.XContentType; -import org.elasticsearch.xpack.inference.external.voyageai.VoyageAIAccount; - -import java.net.URI; +import org.elasticsearch.xpack.inference.services.voyageai.embeddings.VoyageAIEmbeddingsModelTests; import static org.hamcrest.Matchers.is; @@ -22,14 +19,12 @@ public class VoyageAIRequestTests extends ESTestCase { public void testDecorateWithHeaders() { var request = new HttpPost("http://www.abc.com"); + var model = VoyageAIEmbeddingsModelTests.createModel("abc", "key", null, "model_id"); - VoyageAIRequest.decorateWithHeaders( - request, - new VoyageAIAccount(URI.create("http://www.abc.com"), new SecureString(new char[] { 'a', 'b', 'c' })) - ); + VoyageAIRequest.decorateWithHeaders(request, model); assertThat(request.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue(), is(XContentType.JSON.mediaType())); - assertThat(request.getFirstHeader(HttpHeaders.AUTHORIZATION).getValue(), is("Bearer abc")); + assertThat(request.getFirstHeader(HttpHeaders.AUTHORIZATION).getValue(), is("Bearer key")); assertThat(request.getFirstHeader(VoyageAIUtils.REQUEST_SOURCE_HEADER).getValue(), is(VoyageAIUtils.ELASTIC_REQUEST_SOURCE)); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIServiceTests.java index 3a5fce350046e..0481f7a6482be 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/voyageai/VoyageAIServiceTests.java @@ -53,7 +53,6 @@ import org.junit.Before; import java.io.IOException; -import java.net.URISyntaxException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -109,8 +108,7 @@ public void testParseRequestConfig_CreatesAVoyageAIEmbeddingsModel() throws IOEx MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.INGEST, null))); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); @@ -126,7 +124,6 @@ public void testParseRequestConfig_CreatesAVoyageAIEmbeddingsModel() throws IOEx ), modelListener ); - } } @@ -136,8 +133,7 @@ public void testParseRequestConfig_CreatesAVoyageAIEmbeddingsModelWhenChunkingSe MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.INGEST, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); @@ -166,8 +162,7 @@ public void testParseRequestConfig_CreatesAVoyageAIEmbeddingsModelWhenChunkingSe MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.INGEST, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); @@ -196,8 +191,7 @@ public void testParseRequestConfig_OptionalTaskSettings() throws IOException { MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), equalTo(VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS)); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); @@ -333,13 +327,10 @@ public void testParsePersistedConfigWithSecrets_CreatesAVoyageAIEmbeddingsModel( MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -362,14 +353,11 @@ public void testParsePersistedConfigWithSecrets_CreatesAVoyageAIEmbeddingsModelW MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -391,14 +379,11 @@ public void testParsePersistedConfigWithSecrets_CreatesAVoyageAIEmbeddingsModelW MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -446,13 +431,10 @@ public void testParsePersistedConfigWithSecrets_DoesNotThrowWhenAnExtraKeyExists MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.SEARCH, null))); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -477,13 +459,10 @@ public void testParsePersistedConfigWithSecrets_DoesNotThrowWhenAnExtraKeyExists MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS)); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -506,13 +485,10 @@ public void testParsePersistedConfigWithSecrets_NotThrowWhenAnExtraKeyExistsInSe MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -537,13 +513,10 @@ public void testParsePersistedConfigWithSecrets_NotThrowWhenAnExtraKeyExistsInSe MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS)); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -568,13 +541,10 @@ public void testParsePersistedConfigWithSecrets_NotThrowWhenAnExtraKeyExistsInTa MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.SEARCH, null))); MatcherAssert.assertThat(embeddingsModel.getSecretSettings().apiKey().toString(), is("secret")); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -590,13 +560,10 @@ public void testParsePersistedConfig_CreatesAVoyageAIEmbeddingsModel() throws IO MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -613,14 +580,11 @@ public void testParsePersistedConfig_CreatesAVoyageAIEmbeddingsModelWhenChunking MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -636,14 +600,11 @@ public void testParsePersistedConfig_CreatesAVoyageAIEmbeddingsModelWhenChunking MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); MatcherAssert.assertThat(embeddingsModel.getConfigurations().getChunkingSettings(), instanceOf(ChunkingSettings.class)); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -678,7 +639,6 @@ public void testParsePersistedConfig_CreatesAVoyageAIEmbeddingsModelWithoutUrl() MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings((InputType) null, null))); assertNull(embeddingsModel.getSecretSettings()); @@ -698,13 +658,10 @@ public void testParsePersistedConfig_DoesNotThrowWhenAnExtraKeyExistsInConfig() MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(VoyageAIEmbeddingsTaskSettings.EMPTY_SETTINGS)); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -723,13 +680,10 @@ public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInServiceSettin MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.SEARCH, null))); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } } @@ -747,13 +701,10 @@ public void testParsePersistedConfig_NotThrowWhenAnExtraKeyExistsInTaskSettings( MatcherAssert.assertThat(model, instanceOf(VoyageAIEmbeddingsModel.class)); var embeddingsModel = (VoyageAIEmbeddingsModel) model; - assertNull(embeddingsModel.uri()); - MatcherAssert.assertThat(embeddingsModel.buildUri().toString(), is("https://api.voyageai.com/v1/embeddings")); + MatcherAssert.assertThat(embeddingsModel.uri().toString(), is("https://api.voyageai.com/v1/embeddings")); MatcherAssert.assertThat(embeddingsModel.getServiceSettings().getCommonSettings().modelId(), is("model")); MatcherAssert.assertThat(embeddingsModel.getTaskSettings(), is(new VoyageAIEmbeddingsTaskSettings(InputType.INGEST, null))); assertNull(embeddingsModel.getSecretSettings()); - } catch (URISyntaxException e) { - throw new RuntimeException(e); } }