diff --git a/core/src/main/java/com/sap/ai/sdk/core/AiCoreDeployment.java b/core/src/main/java/com/sap/ai/sdk/core/AiCoreDeployment.java index b0620591..465b58d5 100644 --- a/core/src/main/java/com/sap/ai/sdk/core/AiCoreDeployment.java +++ b/core/src/main/java/com/sap/ai/sdk/core/AiCoreDeployment.java @@ -1,103 +1,44 @@ package com.sap.ai.sdk.core; -import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; -import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationProperty; +import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException; +import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationNotFoundException; import com.sap.cloud.sdk.services.openapi.apiclient.ApiClient; -import java.util.function.Function; +import java.util.function.Supplier; import javax.annotation.Nonnull; import lombok.AccessLevel; -import lombok.Getter; import lombok.RequiredArgsConstructor; /** Connectivity convenience methods for AI Core with deployment. */ -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) public class AiCoreDeployment implements AiCoreDestination { + private final AiCoreService aiCoreService; - private static final String AI_RESOURCE_GROUP = "URL.headers.AI-Resource-Group"; - - // the delegating AI Core Service instance - @Nonnull private final AiCoreService service; - - // the deployment id handler to be used, based on instance - @Nonnull private final Function deploymentId; - - // the resource group, "default" if null - @Getter(AccessLevel.PROTECTED) - @Nonnull - private final String resourceGroup; + @Nonnull private final Supplier deploymentId; /** - * Default constructor with "default" resource group. + * Set the resource group. * - * @param service The AI Core service. - * @param deploymentId The deployment id handler. + * @param resourceGroup The resource group, default value "default". + * @return A new instance of the AI Core service. */ - public AiCoreDeployment( - @Nonnull final AiCoreService service, - @Nonnull final Function deploymentId) { - this(service, deploymentId, "default"); + @Nonnull + public AiCoreDeployment withResourceGroup(@Nonnull final String resourceGroup) { + aiCoreService.resourceGroup = resourceGroup; + return this; } @Nonnull @Override - public Destination destination() { - final var dest = service.baseDestinationHandler.apply(service); - final var builder = service.builderHandler.apply(service, dest); - destinationSetUrl(builder, dest); - destinationSetHeaders(builder); - return builder.build(); + public Destination destination() throws DestinationAccessException, DestinationNotFoundException { + aiCoreService.deploymentId = deploymentId.get(); + return aiCoreService.destination(); } @Nonnull @Override public ApiClient client() { - final var destination = destination(); - return service.clientHandler.apply(service, destination); - } - - /** - * Update and set the URL for the destination. - * - * @param builder The destination builder. - * @param dest The original destination reference. - */ - protected void destinationSetUrl( - @Nonnull final DefaultHttpDestination.Builder builder, @Nonnull final Destination dest) { - String uri = dest.get(DestinationProperty.URI).get(); - if (!uri.endsWith("/")) { - uri = uri + "/"; - } - builder.uri(uri + "v2/inference/deployments/%s/".formatted(getDeploymentId())); - } - - /** - * Update and set the default request headers for the destination. - * - * @param builder The destination builder. - */ - protected void destinationSetHeaders(@Nonnull final DefaultHttpDestination.Builder builder) { - builder.property(AI_RESOURCE_GROUP, getResourceGroup()); - } - - /** - * Set the resource group. - * - * @param resourceGroup The resource group. - * @return A new instance of the AI Core service. - */ - @Nonnull - public AiCoreDeployment withResourceGroup(@Nonnull final String resourceGroup) { - return new AiCoreDeployment(service, deploymentId, resourceGroup); - } - - /** - * Get the deployment id. - * - * @return The deployment id. - */ - @Nonnull - protected String getDeploymentId() { - return deploymentId.apply(this); + aiCoreService.deploymentId = deploymentId.get(); + return aiCoreService.client(); } } diff --git a/core/src/main/java/com/sap/ai/sdk/core/AiCoreService.java b/core/src/main/java/com/sap/ai/sdk/core/AiCoreService.java index c063b3c7..1d966f1c 100644 --- a/core/src/main/java/com/sap/ai/sdk/core/AiCoreService.java +++ b/core/src/main/java/com/sap/ai/sdk/core/AiCoreService.java @@ -32,18 +32,24 @@ @RequiredArgsConstructor public class AiCoreService implements AiCoreDestination { - final Function baseDestinationHandler; + Function baseDestinationHandler; final BiFunction clientHandler; final BiFunction builderHandler; private static final DeploymentCache DEPLOYMENT_CACHE = new DeploymentCache(); + private static final String AI_RESOURCE_GROUP = "URL.headers.AI-Resource-Group"; + + /** The resource group is defined by AiCoreDeployment.withResourceGroup(). */ + @Nonnull String resourceGroup; + + /** The deployment id is set by AiCoreDeployment.destination() or AiCoreDeployment.client(). */ + @Nonnull String deploymentId; + /** The default constructor. */ public AiCoreService() { - this( - AiCoreService::getBaseDestination, - AiCoreService::getApiClient, - AiCoreService::getDestinationBuilder); + this(AiCoreService::getApiClient, AiCoreService::getDestinationBuilder, "default", ""); + baseDestinationHandler = AiCoreService::getBaseDestination; } @Nonnull @@ -57,18 +63,48 @@ public ApiClient client() { @Override public Destination destination() { final var dest = baseDestinationHandler.apply(this); - return builderHandler.apply(this, dest).build(); + final var builder = builderHandler.apply(this, dest); + if (!deploymentId.isEmpty()) { + destinationSetUrl(builder, dest); + destinationSetHeaders(builder); + } + return builder.build(); + } + + /** + * Update and set the URL for the destination. + * + * @param builder The destination builder. + * @param dest The original destination reference. + */ + protected void destinationSetUrl( + @Nonnull final DefaultHttpDestination.Builder builder, @Nonnull final Destination dest) { + String uri = dest.get(DestinationProperty.URI).get(); + if (!uri.endsWith("/")) { + uri = uri + "/"; + } + builder.uri(uri + "v2/inference/deployments/%s/".formatted(deploymentId)); + } + + /** + * Update and set the default request headers for the destination. + * + * @param builder The destination builder. + */ + protected void destinationSetHeaders(@Nonnull final DefaultHttpDestination.Builder builder) { + builder.property(AI_RESOURCE_GROUP, resourceGroup); } /** * Set a specific base destination. * * @param destination The destination to be used for AI Core service calls. - * @return A new instance of the AI Core Service based on the provided destination. + * @return The AI Core Service based on the provided destination. */ @Nonnull public AiCoreService withDestination(@Nonnull final Destination destination) { - return new AiCoreService((service) -> destination, clientHandler, builderHandler); + baseDestinationHandler = (service) -> destination; + return this; } /** @@ -79,7 +115,7 @@ public AiCoreService withDestination(@Nonnull final Destination destination) { */ @Nonnull public AiCoreDeployment forDeployment(@Nonnull final String deploymentId) { - return new AiCoreDeployment(this, obj -> deploymentId); + return new AiCoreDeployment(this, () -> deploymentId); } /** @@ -95,9 +131,7 @@ public AiCoreDeployment forDeploymentByModel(@Nonnull final String modelName) throws NoSuchElementException { return new AiCoreDeployment( this, - obj -> - DEPLOYMENT_CACHE.getDeploymentIdByModel( - this.client(), obj.getResourceGroup(), modelName)); + () -> DEPLOYMENT_CACHE.getDeploymentIdByModel(this.client(), resourceGroup, modelName)); } /** @@ -113,9 +147,7 @@ public AiCoreDeployment forDeploymentByScenario(@Nonnull final String scenarioId throws NoSuchElementException { return new AiCoreDeployment( this, - obj -> - DEPLOYMENT_CACHE.getDeploymentIdByScenario( - this.client(), obj.getResourceGroup(), scenarioId)); + () -> DEPLOYMENT_CACHE.getDeploymentIdByScenario(client(), resourceGroup, scenarioId)); } /** diff --git a/core/src/test/java/com/sap/ai/sdk/core/AiCoreServiceTest.java b/core/src/test/java/com/sap/ai/sdk/core/AiCoreServiceTest.java index 7a275818..cdfd5874 100644 --- a/core/src/test/java/com/sap/ai/sdk/core/AiCoreServiceTest.java +++ b/core/src/test/java/com/sap/ai/sdk/core/AiCoreServiceTest.java @@ -121,7 +121,7 @@ protected ApiClient getApiClient(@Nonnull Destination destination) { final var destination = customServiceForDeployment.destination().asHttp(); assertThat(destination.getUri()).hasToString("https://ai/v2/inference/deployments/deployment/"); - final var resourceGroup = customServiceForDeployment.getResourceGroup(); + final var resourceGroup = customService.resourceGroup; assertThat(resourceGroup).isEqualTo("group"); } }