diff --git a/core/pom.xml b/core/pom.xml index 7df195f49..cebd81148 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -89,10 +89,6 @@ com.fasterxml.jackson.module jackson-module-parameter-names - - com.google.guava - guava - org.slf4j slf4j-api 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 d567ca1ef..471923a06 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 @@ -3,7 +3,6 @@ import static com.sap.ai.sdk.core.JacksonConfiguration.getDefaultObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; -import com.google.common.annotations.Beta; import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination; import com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException; @@ -139,7 +138,6 @@ protected String buildDeploymentPath(@Nonnull final String deploymentId) { * * @param resourceGroup the resource group of the deleted deployment, usually "default". */ - @Beta public void reloadCachedDeployments(@Nonnull final String resourceGroup) { deploymentResolver.reloadDeployments(resourceGroup); } diff --git a/core/src/main/java/com/sap/ai/sdk/core/common/ClientResponseHandler.java b/core/src/main/java/com/sap/ai/sdk/core/common/ClientResponseHandler.java index 1f0bef1b4..1026423df 100644 --- a/core/src/main/java/com/sap/ai/sdk/core/common/ClientResponseHandler.java +++ b/core/src/main/java/com/sap/ai/sdk/core/common/ClientResponseHandler.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.annotations.Beta; import io.vavr.control.Try; import java.nio.charset.StandardCharsets; import java.util.Optional; @@ -20,7 +19,7 @@ import org.apache.hc.core5.http.io.entity.EntityUtils; /** - * Parse incoming JSON responses and handles any errors. For internal use only. + * For internal SDK use only. Parse incoming JSON responses and handles any errors. * * @param The type of the successful response. * @param The type of the exception to throw. @@ -44,12 +43,11 @@ public class ClientResponseHandler objectMapper(@Nonnull final ObjectMapper jackson) { objectMapper = jackson; @@ -57,7 +55,8 @@ public ClientResponseHandler objectMapper(@Nonnull final ObjectMapper j } /** - * Processes a {@link ClassicHttpResponse} and returns some value corresponding to that response. + * Internal SDK usage only. Processes a {@link ClassicHttpResponse} and returns some value + * corresponding to that response. * * @param response The response to process * @return A model class instantiated from the response @@ -101,7 +100,7 @@ private Try tryGetContent(@Nonnull final HttpEntity entity) { } /** - * Process the error response and throw an exception. + * For internal SDK usage only. Process the error response and throw an exception. * * @param httpResponse The response to process * @throws ClientException if the response is an error (4xx/5xx) @@ -142,7 +141,8 @@ protected void buildAndThrowException(@Nonnull final ClassicHttpResponse httpRes } /** - * Parses the JSON content of an error response and throws a module specific exception. + * For internal SDK usage only. Parses the JSON content of an error response and throws a module + * specific exception. * * @param content The JSON content of the error response. * @param httpResponse The HTTP response that contains the error. diff --git a/core/src/main/java/com/sap/ai/sdk/core/common/ClientStreamingHandler.java b/core/src/main/java/com/sap/ai/sdk/core/common/ClientStreamingHandler.java index 79fde4402..e7680d555 100644 --- a/core/src/main/java/com/sap/ai/sdk/core/common/ClientStreamingHandler.java +++ b/core/src/main/java/com/sap/ai/sdk/core/common/ClientStreamingHandler.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.annotations.Beta; import java.io.IOException; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -11,7 +10,8 @@ import org.apache.hc.core5.http.ClassicHttpResponse; /** - * Parse incoming JSON responses and handles any errors. For internal use only. + * For internal SDK usage only. Parse incoming JSON responses and handles any errors. For internal + * use only. * * @param The type of the response. * @param The type of the exception to throw. @@ -24,20 +24,19 @@ public class ClientStreamingHandler< extends ClientResponseHandler { /** - * Set the {@link ObjectMapper} to use for parsing JSON responses. + * For internal SDK usage only. Set the {@link ObjectMapper} to use for parsing JSON responses. * * @param jackson The {@link ObjectMapper} to use * @return the current instance of {@link ClientStreamingHandler} with the changed object mapper */ @Nonnull - @Beta public ClientStreamingHandler objectMapper(@Nonnull final ObjectMapper jackson) { super.objectMapper(jackson); return this; } /** - * Creates a new instance of the {@link ClientStreamingHandler}. + * For internal SDK usage only. Creates a new instance of the {@link ClientStreamingHandler}. * * @param deltaType The type of the response. * @param errorType The type of the error. @@ -51,8 +50,8 @@ public ClientStreamingHandler( } /** - * Processes a {@link ClassicHttpResponse} and returns a {@link Stream} of deltas corresponding to - * that response. + * For internal SDK usage only. Processes a {@link ClassicHttpResponse} and returns a {@link + * Stream} of deltas corresponding to that response. * * @param response The response to process * @return A {@link Stream} of a model class instantiated from the response diff --git a/docs/release_notes.md b/docs/release_notes.md index 120f51b39..98cf2c714 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -12,6 +12,12 @@ - [Orchestration] Spring AI support was upgraded to version `2.0.1` - [Prompt Registry] `OrchestrationConfigClient` and `PromptClient` were reworked into unified `PromptRegistryClient`, see migration guide below for additional information +- [Orchestration] `OrchestrationClient.executeRequestFromJsonModuleConfig` method was removed from SDK without a replacement +- [OpenAi] `OpenAi.withApiVersion` was removed from public API and deprecated +- [Orchestration] Internal AI SDK methods `createInputFilterConfig` and `createOutputFilterConfig` were removed + from public API +- [Orchestration] Internal AI SDK methods `createConfig` were removed from `GroundingProvider` and `MaskingProvider` +- [Orchestration] Internal AI SDK method `createMessage` was removed from `Message` class. #### Prompt registry client Migration Guide diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/AiCoreOpenAiClient.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/AiCoreOpenAiClient.java index 826695f68..39ddc0c96 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/AiCoreOpenAiClient.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/AiCoreOpenAiClient.java @@ -1,6 +1,5 @@ package com.sap.ai.sdk.foundationmodels.openai; -import com.google.common.annotations.Beta; import com.openai.core.ClientOptions; import com.openai.services.async.ResponseServiceAsync; import com.openai.services.async.ResponseServiceAsyncImpl; @@ -24,7 +23,6 @@ */ @Slf4j @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -@Beta public class AiCoreOpenAiClient { private final HttpDestination destination; diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiBatchInput.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiBatchInput.java index c98c425bb..9bbc53909 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiBatchInput.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiBatchInput.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.foundationmodels.openai.generated.model.CreateChatCompletionRequest; import java.io.IOException; import java.util.ArrayList; @@ -37,7 +36,6 @@ public class OpenAiBatchInput { * * @param chatCompletionRequests the list of chat completion requests to include in the batch */ - @Beta public OpenAiBatchInput(@Nonnull final OpenAiChatCompletionRequest... chatCompletionRequests) { for (int i = 0; i < chatCompletionRequests.length; i++) { val request = chatCompletionRequests[i]; diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClient.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClient.java index bd3b4176a..056c8f6ed 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClient.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClient.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.core.AiCoreService; import com.sap.ai.sdk.core.DeploymentResolutionException; import com.sap.ai.sdk.core.common.ClientResponseHandler; @@ -82,7 +81,6 @@ public static OpenAiClient forModel(@Nonnull final OpenAiModel foundationModel) * * @return created client */ - @Beta @Nonnull public static OpenAiRealtimeClient realtimeClient() { final var withResolvedDestination = OpenAiClient.forModel(OpenAiModel.GPT_REALTIME); @@ -95,9 +93,9 @@ public static OpenAiRealtimeClient realtimeClient() { * @param apiVersion the API version to target. * @return a new client. */ - @Beta + @Deprecated // does not align with the target state of the SDK, is planned for removal @Nonnull - public OpenAiClient withApiVersion(@Nonnull final String apiVersion) { + private OpenAiClient withApiVersion(@Nonnull final String apiVersion) { final var newDestination = DefaultHttpDestination.fromDestination(this.destination) // set the API version as URL query parameter diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientException.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientException.java index 2042c18f9..d9fb196d1 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientException.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientException.java @@ -1,6 +1,5 @@ package com.sap.ai.sdk.foundationmodels.openai; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.core.common.ClientException; import com.sap.ai.sdk.core.common.ClientExceptionFactory; import com.sap.ai.sdk.foundationmodels.openai.generated.model.ErrorResponse; @@ -17,12 +16,8 @@ public class OpenAiClientException extends ClientException { /** * Retrieves the {@link ErrorResponse} from the OpenAI service, if available. * - *

Note: This method is marked as {@link Beta} because it uses generated API types in its - * public signature. - * * @return The {@link ErrorResponse} object, or {@code null} if not available. */ - @Beta @Nullable public ErrorResponse getErrorResponse() { final var clientError = super.getClientError(); diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/TextInputChannel.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/TextInputChannel.java index bbd78c40a..f1d2dadd2 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/TextInputChannel.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/TextInputChannel.java @@ -1,13 +1,11 @@ package com.sap.ai.sdk.foundationmodels.openai; -import com.google.common.annotations.Beta; import javax.annotation.Nonnull; /** * Allows to input (send) text to the open channel, must be closed when not needed anymore (e.g. * try-with-resources) */ -@Beta public interface TextInputChannel extends AutoCloseable { /** @@ -15,6 +13,5 @@ public interface TextInputChannel extends AutoCloseable { * * @param text text to send */ - @Beta void sendText(@Nonnull final String text); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioInputChannel.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioInputChannel.java index af37b6b43..2f017c041 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioInputChannel.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioInputChannel.java @@ -1,13 +1,10 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; - /** * Functional interface representing audio input channel (used by audio data producer) * *

Should be closed by application (try-with-resources) when not needed anymore */ -@Beta public interface AudioInputChannel extends AutoCloseable { /** @@ -17,6 +14,5 @@ public interface AudioInputChannel extends AutoCloseable { * * @param rawBytesChunk binary data in the depending on the use case format */ - @Beta void inputAudio(byte[] rawBytesChunk); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioOutputChannel.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioOutputChannel.java index 1d8733184..4271e3f1a 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioOutputChannel.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/AudioOutputChannel.java @@ -1,9 +1,6 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; - /** Functional interface representing audio output channel (audio data consumer) */ -@Beta public interface AudioOutputChannel { /** @@ -16,6 +13,5 @@ public interface AudioOutputChannel { * single logical entity (e.g. gets called at the end when all byte parts of a single message * get passed) */ - @Beta void outputAudio(byte[] rawBytesChunk, boolean isLast); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/OpenAiRealtimeClient.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/OpenAiRealtimeClient.java index 98ce597ac..116a52827 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/OpenAiRealtimeClient.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/OpenAiRealtimeClient.java @@ -1,6 +1,5 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.foundationmodels.openai.TextInputChannel; import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; import com.sap.cloud.sdk.cloudplatform.connectivity.Header; @@ -12,7 +11,6 @@ * OpenAI client implementation of Realtime API. Abstracts technical implementation, transport and * threading and exposes business-level operations (high level interface) */ -@Beta public class OpenAiRealtimeClient { static final int PATH_BUFFER_SIZE = @@ -25,7 +23,6 @@ public class OpenAiRealtimeClient { * * @param destination - destination to use */ - @Beta public OpenAiRealtimeClient(@Nonnull final Destination destination) { this.destination = destination; } @@ -58,7 +55,6 @@ public OpenAiRealtimeClient(@Nonnull final Destination destination) { * @return input channel, allowing for text input */ @Nonnull - @Beta public TextInputChannel textToSpeech( @Nonnull final AudioOutputChannel audioOutputConsumer, @Nonnull final RealtimeParam... params) { @@ -94,7 +90,6 @@ public TextInputChannel textToSpeech( * bit) */ @Nonnull - @Beta public AudioInputChannel speechToSpeech( @Nonnull final AudioOutputChannel audioOutputConsumer, @Nonnull final RealtimeParam... params) { diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParam.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParam.java index 26214db7b..f1ad5a6cd 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParam.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParam.java @@ -1,11 +1,9 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; import javax.annotation.Nonnull; -/** Represents possible configuration params of realtime client */ -@Beta -public interface RealtimeParam { +/** Represents possible configuration params of realtime client Internal sdk usage only */ +public abstract class RealtimeParam { /** Represents configurable options */ enum ParamName { /** Voice name to use to produce sound */ @@ -19,13 +17,16 @@ enum ParamName { SYSTEM_PROMPT, } + /** Internal use only. Can only be extended or constructed in the same package. */ + RealtimeParam() {} + /** * Returns param name * * @return name */ @Nonnull - ParamName getParamName(); + abstract ParamName getParamName(); /** * Returns string value representation of the param @@ -33,5 +34,5 @@ enum ParamName { * @return string value */ @Nonnull - String getValueAsString(); + abstract String getValueAsString(); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamSystemPrompt.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamSystemPrompt.java index 10ec75d3a..b505b6483 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamSystemPrompt.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamSystemPrompt.java @@ -1,13 +1,11 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** Allows to configure model system prompt */ -@Beta -public final class RealtimeParamSystemPrompt implements RealtimeParam { +public final class RealtimeParamSystemPrompt extends RealtimeParam { private final String systemPrompt; @@ -16,25 +14,23 @@ public final class RealtimeParamSystemPrompt implements RealtimeParam { * * @param systemPrompt system prompt to use */ - @Beta public RealtimeParamSystemPrompt(@Nonnull final String systemPrompt) { this.systemPrompt = systemPrompt; } @Override - @Beta - public @Nonnull ParamName getParamName() { + @Nonnull + ParamName getParamName() { return ParamName.SYSTEM_PROMPT; } @Override - @Beta - public @Nonnull String getValueAsString() { + @Nonnull + String getValueAsString() { return systemPrompt; } @Override - @Beta public boolean equals(@Nullable final Object o) { if (o == null || getClass() != o.getClass()) { return false; @@ -44,7 +40,6 @@ public boolean equals(@Nullable final Object o) { } @Override - @Beta public int hashCode() { return Objects.hashCode(systemPrompt); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamTurnDetection.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamTurnDetection.java index cb087bca2..f1c8433da 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamTurnDetection.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamTurnDetection.java @@ -1,16 +1,13 @@ package com.sap.ai.sdk.foundationmodels.openai.realtime; -import com.google.common.annotations.Beta; import java.util.Objects; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** Allows to configure turn detection (how model responds). */ -@Beta -public final class RealtimeParamTurnDetection implements RealtimeParam { +public final class RealtimeParamTurnDetection extends RealtimeParam { /** Model tries to recognize if/when it should respond automatically */ - @Beta public static final RealtimeParamTurnDetection BY_MODEL_AUTO = new RealtimeParamTurnDetection("BY_MODEL_AUTO"); @@ -19,7 +16,6 @@ public final class RealtimeParamTurnDetection implements RealtimeParam { * Less convenient than the automatic option but may give lower latency in some cases (model does * not need to perform additional turn detection analysis). */ - @Beta public static final RealtimeParamTurnDetection EACH_CALL_IS_A_TURN = new RealtimeParamTurnDetection("EACH_CALL_IS_A_TURN"); @@ -30,19 +26,18 @@ public final class RealtimeParamTurnDetection implements RealtimeParam { } @Override - @Beta - public @Nonnull ParamName getParamName() { + @Nonnull + ParamName getParamName() { return ParamName.TURN_DETECTION; } @Override - @Beta - public @Nonnull String getValueAsString() { + @Nonnull + String getValueAsString() { return turnDetectionKind; } @Override - @Beta public boolean equals(@Nullable final Object o) { if (o == null || getClass() != o.getClass()) { return false; @@ -52,7 +47,6 @@ public boolean equals(@Nullable final Object o) { } @Override - @Beta public int hashCode() { return Objects.hashCode(turnDetectionKind); } diff --git a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamVoice.java b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamVoice.java index e5ff23f0b..eb7464550 100644 --- a/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamVoice.java +++ b/foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/realtime/RealtimeParamVoice.java @@ -6,14 +6,13 @@ import javax.annotation.Nullable; /** Allows to configure model output voice */ -@Beta -public final class RealtimeParamVoice implements RealtimeParam { +public final class RealtimeParamVoice extends RealtimeParam { /** Standard voice 1 */ - @Beta public static final RealtimeParamVoice DEFAULT_1 = new RealtimeParamVoice("DEFAULT_1"); + public static final RealtimeParamVoice DEFAULT_1 = new RealtimeParamVoice("DEFAULT_1"); /** Standard voice 2 */ - @Beta public static final RealtimeParamVoice DEFAULT_2 = new RealtimeParamVoice("DEFAULT_2"); + public static final RealtimeParamVoice DEFAULT_2 = new RealtimeParamVoice("DEFAULT_2"); private final String voice; @@ -37,19 +36,18 @@ public static RealtimeParamVoice withExplicitVoice(@Nonnull final String voiceNa } @Override - @Beta - public @Nonnull ParamName getParamName() { + @Nonnull + ParamName getParamName() { return ParamName.OUTPUT_VOICE; } @Override - @Beta - public @Nonnull String getValueAsString() { + @Nonnull + String getValueAsString() { return voice; } @Override - @Beta public boolean equals(@Nullable final Object o) { if (o == null || getClass() != o.getClass()) { return false; @@ -59,7 +57,6 @@ public boolean equals(@Nullable final Object o) { } @Override - @Beta public int hashCode() { return Objects.hashCode(voice); } diff --git a/foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientGeneratedTest.java b/foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientGeneratedTest.java index 3a213116e..9a64ee972 100644 --- a/foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientGeneratedTest.java +++ b/foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiClientGeneratedTest.java @@ -88,14 +88,6 @@ void apiVersion() { exactly(1), postRequestedFor(anyUrl()).withQueryParam("api-version", equalTo("2024-02-01"))); - Try.of( - () -> client.withApiVersion("fooBar").chatCompletion(new OpenAiChatCompletionRequest(""))); - verify(exactly(1), postRequestedFor(anyUrl()).withQueryParam("api-version", equalTo("fooBar"))); - - assertThat(client) - .describedAs( - "withApiVersion should return a new object, the sut object should remain unchanged") - .isNotSameAs(client.withApiVersion("fooBar")); Try.of(() -> client.chatCompletion(new OpenAiChatCompletionRequest(""))); verify( exactly(2), diff --git a/foundation-models/sap-rpt/pom.xml b/foundation-models/sap-rpt/pom.xml index 920e16877..215b91a1b 100644 --- a/foundation-models/sap-rpt/pom.xml +++ b/foundation-models/sap-rpt/pom.xml @@ -76,10 +76,6 @@ com.google.code.findbugs jsr305 - - com.google.guava - guava - org.projectlombok diff --git a/foundation-models/sap-rpt/src/main/java/com/sap/ai/sdk/foundationmodels/rpt/RptClient.java b/foundation-models/sap-rpt/src/main/java/com/sap/ai/sdk/foundationmodels/rpt/RptClient.java index 7a1fca93f..66e2e6e2a 100644 --- a/foundation-models/sap-rpt/src/main/java/com/sap/ai/sdk/foundationmodels/rpt/RptClient.java +++ b/foundation-models/sap-rpt/src/main/java/com/sap/ai/sdk/foundationmodels/rpt/RptClient.java @@ -4,7 +4,6 @@ import static com.sap.ai.sdk.foundationmodels.rpt.RptModel.SAP_RPT_1_6_LARGE; import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.core.AiCoreService; import com.sap.ai.sdk.core.DeploymentResolutionException; import com.sap.ai.sdk.core.JacksonConfiguration; @@ -68,9 +67,6 @@ static RptClient forDestination( /** * Predict targets using SAP RPT model with structured data. * - *

Note: This method is marked as {@link Beta} because it uses generated API types in its - * public signature. - * *

200 - Successful Prediction * *

400 - Bad Request - Invalid input data @@ -87,8 +83,8 @@ static RptClient forDestination( * embedded {@link com.sap.ai.sdk.foundationmodels.rpt.generated.model.PredictionConfig} is * set to {@code null} on the passed-in object as a side effect. */ - @Beta @Nonnull + @SuppressWarnings("PMD.PublicApiExposesModelType") // we consider model class stable public PredictResponsePayload tableCompletion(@Nonnull final PredictRequestPayload requestBody) { if (!contextModePossible) { configFrom(requestBody).setContextMode(null); @@ -111,9 +107,6 @@ private static PredictionConfig configFrom(@Nonnull final PredictRequestPayload * Make in-context predictions for specified target columns based on provided table data Parquet * file. * - *

Note: This method is marked as {@link Beta} because it uses generated API types in its - * public signature. - * *

200 - Successful Prediction * *

400 - Bad Request - Invalid input data @@ -132,7 +125,7 @@ private static PredictionConfig configFrom(@Nonnull final PredictRequestPayload * set to {@code null} as a side effect. * @since 1.16.0 */ - @Beta + @SuppressWarnings("PMD.PublicApiExposesModelType") // we consider model class stable @Nonnull public PredictResponsePayload tableCompletion( @Nonnull final File parquetFile, @Nonnull final PredictionConfig predictionConfig) { diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AssistantMessage.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AssistantMessage.java index 29e83c5bb..120ef2ce3 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AssistantMessage.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AssistantMessage.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import lombok.AccessLevel; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Value; @@ -21,9 +22,10 @@ /** Represents a chat message as 'assistant' to the orchestration service. */ @Value +@EqualsAndHashCode(callSuper = true) @Accessors(fluent = true) @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class AssistantMessage implements Message { +public class AssistantMessage extends Message { /** The role of the assistant. */ @Nonnull String role = "assistant"; @@ -39,6 +41,19 @@ public class AssistantMessage implements Message { @Nullable List reasoningContent; + /** + * Creates a new assistant message with the given tool calls. + * + * @param toolCalls list of tool call objects + * @deprecated Please use {@link #withToolCalls(List)} instead. + */ + @Deprecated + public AssistantMessage(@Nonnull final List toolCalls) { + content = new MessageContent(List.of()); + this.toolCalls = toolCalls; + reasoningContent = null; + } + /** * Creates a new assistant message with the given single message. * @@ -61,19 +76,6 @@ public AssistantMessage(@Nonnull final String singleMessage) { reasoningContent = null; } - /** - * Creates a new assistant message with the given tool calls. - * - * @param toolCalls list of tool call objects - * @deprecated Please use {@link #withToolCalls(List)} instead. - */ - @Deprecated - public AssistantMessage(@Nonnull final List toolCalls) { - content = new MessageContent(List.of()); - this.toolCalls = toolCalls; - reasoningContent = null; - } - /** * Returns a new AssistantMessage instance with the provided tool calls added to the existing * ones. diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AzureContentFilter.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AzureContentFilter.java index 93792bbc1..e54be8c08 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AzureContentFilter.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/AzureContentFilter.java @@ -33,7 +33,7 @@ @Setter @NoArgsConstructor @Accessors(fluent = true) -public class AzureContentFilter implements ContentFilter { +public class AzureContentFilter extends ContentFilter { /** The filter category for hate content. */ @Nullable AzureFilterThreshold hate; @@ -66,7 +66,7 @@ public class AzureContentFilter implements ContentFilter { */ @Override @Nonnull - public AzureContentSafetyInputFilterConfig createInputFilterConfig() { + AzureContentSafetyInputFilterConfig createInputFilterConfig() { if (hate == null && selfHarm == null && sexual == null && violence == null) { throw new IllegalArgumentException("At least one filter category must be set"); } @@ -91,7 +91,7 @@ public AzureContentSafetyInputFilterConfig createInputFilterConfig() { */ @Override @Nonnull - public AzureContentSafetyOutputFilterConfig createOutputFilterConfig() { + AzureContentSafetyOutputFilterConfig createOutputFilterConfig() { if (hate == null && selfHarm == null && sexual == null diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ContentFilter.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ContentFilter.java index 4e63cbcd2..817dfdc35 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ContentFilter.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ContentFilter.java @@ -1,13 +1,12 @@ package com.sap.ai.sdk.orchestration; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.orchestration.model.InputFilterConfig; import com.sap.ai.sdk.orchestration.model.OutputFilterConfig; import javax.annotation.Nonnull; /** - * Interface representing convenience wrappers of serializable content filter that defines - * thresholds for different content categories. + * For internal SDK usage only. Class representing convenience wrappers of serializable content + * filter that defines thresholds for different content categories. * *

SAP * AI Core: Orchestration - Input Filtering @@ -15,25 +14,23 @@ *

SAP * AI Core: Orchestration - Output Filtering */ -public interface ContentFilter { +public abstract class ContentFilter { /** - * A method that produces the serializable equivalent {@link InputFilterConfig} object from data - * encapsulated in the {@link ContentFilter} object. + * For internal SDK usage only. A method that produces the serializable equivalent {@link + * InputFilterConfig} object from data encapsulated in the {@link ContentFilter} object. * * @return the corresponding {@link InputFilterConfig} object. */ - @Beta @Nonnull - InputFilterConfig createInputFilterConfig(); + abstract InputFilterConfig createInputFilterConfig(); /** - * A method that produces the serializable equivalent {@link OutputFilterConfig} object from data - * encapsulated in the {@link ContentFilter} object. + * For internal SDK usage only. A method that produces the serializable equivalent {@link + * OutputFilterConfig} object from data encapsulated in the {@link ContentFilter} object. * * @return the corresponding {@link OutputFilterConfig} object. */ - @Beta @Nonnull - OutputFilterConfig createOutputFilterConfig(); + abstract OutputFilterConfig createOutputFilterConfig(); } diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/DpiMasking.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/DpiMasking.java index 181a6c335..d6b72eded 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/DpiMasking.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/DpiMasking.java @@ -16,6 +16,7 @@ import java.util.stream.Stream; import javax.annotation.Nonnull; import lombok.AccessLevel; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Value; @@ -30,9 +31,10 @@ * Core: Orchestration - Data Masking */ @Value +@EqualsAndHashCode(callSuper = true) @Getter(AccessLevel.PACKAGE) @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class DpiMasking implements MaskingProvider { +public class DpiMasking extends MaskingProvider { @Nonnull DPIConfig.MethodEnum maskingMethod; @Nonnull List entitiesConfig; @With boolean maskGroundingInput; @@ -140,7 +142,7 @@ public DpiMasking withAllowList(@Nonnull final List allowList) { @Nonnull @Override - public DPIConfig createConfig() { + DPIConfig createConfig() { return DPIConfig.create() .type(SAP_DATA_PRIVACY_INTEGRATION) .method(maskingMethod) diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/EmbeddingDeserializer.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/EmbeddingDeserializer.java index 452f04e6b..8b7d472b5 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/EmbeddingDeserializer.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/EmbeddingDeserializer.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.orchestration.model.Embedding; import com.sap.ai.sdk.orchestration.model.EmbeddingMultiFormat; import java.io.IOException; @@ -15,7 +14,6 @@ * {@code @JsonCreator} annotations by intelligently detecting the JSON structure and choosing the * appropriate implementation. */ -@Beta class EmbeddingDeserializer extends JsonDeserializer { /** diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java index a03d22cd0..04aea5d8c 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -1,6 +1,5 @@ package com.sap.ai.sdk.orchestration; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.orchestration.model.DataRepositoryType; import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig; @@ -25,7 +24,7 @@ * Core: Orchestration - Grounding */ @Accessors(fluent = true) -public class Grounding implements GroundingProvider { +public class Grounding extends GroundingProvider { @Nonnull private List filters = @@ -33,7 +32,7 @@ public class Grounding implements GroundingProvider { @Nullable private List metadataParams = null; - @Setter(onMethod_ = {@Nonnull, @Beta}) + @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; /** @@ -95,7 +94,7 @@ public OrchestrationPrompt createGroundingPrompt(@Nonnull final String message) @Nonnull @Override - public GroundingModuleConfig createConfig() { + GroundingModuleConfig createConfig() { val groundingConfigConfig = GroundingModuleConfigConfig.create() .placeholders( diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java index 31df0e818..cf0b45d7b 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java @@ -4,13 +4,18 @@ import javax.annotation.Nonnull; /** - * Interface for grounding configurations. + * API Contract for grounding configurations. * *

SAP AI * Core: Orchestration - Grounding */ -@FunctionalInterface -public interface GroundingProvider { +public abstract class GroundingProvider { + + /** + * Internal class. Package-local inheritance only. Not supposed to be implemented outside of AI + * SDK. + */ + GroundingProvider() {} /** * Create a grounding configuration. @@ -18,5 +23,5 @@ public interface GroundingProvider { * @return the grounding configuration */ @Nonnull - GroundingModuleConfig createConfig(); + abstract GroundingModuleConfig createConfig(); } diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/LlamaGuardFilter.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/LlamaGuardFilter.java index b312d882c..89e941a6b 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/LlamaGuardFilter.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/LlamaGuardFilter.java @@ -33,20 +33,20 @@ */ @Accessors(fluent = true) @Setter -public class LlamaGuardFilter implements ContentFilter { +public class LlamaGuardFilter extends ContentFilter { @SuppressWarnings("PMD.LombokGetterSetterExposesModelType") private LlamaGuard38b config = LlamaGuard38b.create(); @Nonnull @Override - public LlamaGuard38bFilterConfig createInputFilterConfig() { + LlamaGuard38bFilterConfig createInputFilterConfig() { return LlamaGuard38bFilterConfig.create().type(LLAMA_GUARD_3_8B).config(config); } @Nonnull @Override - public LlamaGuard38bFilterConfig createOutputFilterConfig() { + LlamaGuard38bFilterConfig createOutputFilterConfig() { return createInputFilterConfig(); } } diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java index 804aff91d..10e5d52aa 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java @@ -9,7 +9,13 @@ *

SAP AI * Core: Orchestration - Data Masking */ -public interface MaskingProvider { +public abstract class MaskingProvider { + + /** + * Internal class. Package-local inheritance only. Not supposed to be implemented outside of AI + * SDK. + */ + MaskingProvider() {} /** * Create a masking configuration. @@ -17,5 +23,5 @@ public interface MaskingProvider { * @return the masking configuration */ @Nonnull - DPIConfig createConfig(); + abstract DPIConfig createConfig(); } diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Message.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Message.java index 89e667c6c..ae3f37548 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Message.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Message.java @@ -5,9 +5,18 @@ import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import lombok.EqualsAndHashCode; -/** Interface representing convenience wrappers of chat message to the orchestration service. */ -public sealed interface Message permits AssistantMessage, SystemMessage, ToolMessage, UserMessage { +/** + * Contract-representing class for convenience wrappers of chat message to the orchestration + * service. + */ +@EqualsAndHashCode +public abstract class Message { + + /** Internal SDK usage only. Limit inheritance visibility to package-local scope */ + Message() {} + ; /** * A convenience method to create a user message from a string. @@ -16,7 +25,7 @@ public sealed interface Message permits AssistantMessage, SystemMessage, ToolMes * @return the user message. */ @Nonnull - static UserMessage user(@Nonnull final String message) { + public static UserMessage user(@Nonnull final String message) { return user(message, null); } @@ -29,7 +38,7 @@ static UserMessage user(@Nonnull final String message) { * @return the user message. */ @Nonnull - static UserMessage user( + public static UserMessage user( @Nonnull final String message, @Nullable final CacheControl cacheControl) { return new UserMessage(message, cacheControl); } @@ -42,7 +51,7 @@ static UserMessage user( * @since 1.3.0 */ @Nonnull - static UserMessage user(@Nonnull final ImageItem imageItem) { + public static UserMessage user(@Nonnull final ImageItem imageItem) { return new UserMessage(new MessageContent(List.of(imageItem))); } @@ -54,7 +63,7 @@ static UserMessage user(@Nonnull final ImageItem imageItem) { * @since 1.18.0 */ @Nonnull - static UserMessage user(@Nonnull final Path filePath) { + public static UserMessage user(@Nonnull final Path filePath) { return new UserMessage(new MessageContent(List.of())).withFile(filePath); } @@ -65,7 +74,7 @@ static UserMessage user(@Nonnull final Path filePath) { * @return the assistant message. */ @Nonnull - static AssistantMessage assistant(@Nonnull final String message) { + public static AssistantMessage assistant(@Nonnull final String message) { return new AssistantMessage(message); } @@ -76,7 +85,7 @@ static AssistantMessage assistant(@Nonnull final String message) { * @return the system message. */ @Nonnull - static SystemMessage system(@Nonnull final String message) { + public static SystemMessage system(@Nonnull final String message) { return system(message, null); } @@ -90,7 +99,7 @@ static SystemMessage system(@Nonnull final String message) { * @return the system message */ @Nonnull - static SystemMessage system( + public static SystemMessage system( @Nonnull final String message, @Nullable final CacheControl cacheControl) { return new SystemMessage(message, cacheControl); } @@ -101,7 +110,7 @@ static SystemMessage system( * @return the corresponding {@code ChatMessage} object. */ @Nonnull - ChatMessage createChatMessage(); + abstract ChatMessage createChatMessage(); /** * Returns the role of the assistant. @@ -109,7 +118,7 @@ static SystemMessage system( * @return the role. */ @Nonnull - String role(); + public abstract String role(); /** * Returns the content of the message. @@ -117,5 +126,5 @@ static SystemMessage system( * @return the content. */ @Nonnull - MessageContent content(); + public abstract MessageContent content(); } diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClient.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClient.java index 955a04def..a450a092f 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClient.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClient.java @@ -2,11 +2,7 @@ import static com.sap.ai.sdk.orchestration.OrchestrationJacksonConfiguration.getOrchestrationObjectMapper; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.core.AiCoreService; import com.sap.ai.sdk.orchestration.model.CompletionPostRequest; import com.sap.ai.sdk.orchestration.model.CompletionPostResponse; @@ -192,49 +188,6 @@ public OrchestrationChatResponse chatCompletionUsingReference( return new OrchestrationChatResponse(response); } - /** - * Perform a request to the orchestration service using a module configuration provided as JSON - * string. This can be useful when building a configuration in the AI Launchpad UI and exporting - * it as JSON. Furthermore, this allows for using features that are not yet supported natively by - * the API. - * - *

NOTE: This method does not support streaming. - * - * @param prompt The input parameters and optionally message history to use for prompt execution. - * @param moduleConfig The module configuration in JSON format. - * @return The completion response. - * @throws OrchestrationClientException If the request fails. - */ - @Beta - @Nonnull - public OrchestrationChatResponse executeRequestFromJsonModuleConfig( - @Nonnull final OrchestrationPrompt prompt, @Nonnull final String moduleConfig) - throws OrchestrationClientException { - if (!prompt.getMessages().isEmpty()) { - throw new IllegalArgumentException( - "Prompt must not contain any messages when using a JSON module configuration, as the template is already defined in the JSON."); - } - - final ObjectNode requestJson = JACKSON.createObjectNode(); - final var chatMessageHistory = - prompt.getMessagesHistory().stream().map(Message::createChatMessage).toList(); - requestJson.set("messages_history", JACKSON.valueToTree(chatMessageHistory)); - requestJson.set("input_params", JACKSON.valueToTree(prompt.getTemplateParameters())); - - final JsonNode moduleConfigJson; - try { - moduleConfigJson = JACKSON.readTree(moduleConfig); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException( - "The provided module configuration is not valid JSON: " + moduleConfig, e); - } - requestJson.set("orchestration_config", moduleConfigJson); - - return new OrchestrationChatResponse( - executor.execute( - COMPLETION_ENDPOINT, requestJson, CompletionPostResponse.class, customHeaders)); - } - /** * Generate a completion for the given request object. * diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClientException.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClientException.java index 5c136bea6..0c16152c6 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClientException.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationClientException.java @@ -2,7 +2,6 @@ import static java.util.Locale.ROOT; -import com.google.common.annotations.Beta; import com.sap.ai.sdk.core.common.ClientException; import com.sap.ai.sdk.core.common.ClientExceptionFactory; import com.sap.ai.sdk.orchestration.OrchestrationFilterException.Input; @@ -119,13 +118,9 @@ public OrchestrationError getClientError() { /** * Retrieves the {@link ErrorResponse} from the orchestration service, if available. * - *

Note: This method is marked as {@link Beta} because it uses generated API types in its - * public signature. - * * @return The {@link ErrorResponse} object, or {@code null} if not available. * @since 1.10.0 */ - @Beta @Nullable public ErrorResponse getErrorResponse() { if (getClientError() instanceof OrchestrationError.Synchronous orchestrationError) { @@ -137,13 +132,9 @@ public ErrorResponse getErrorResponse() { /** * Retrieves the {@link ErrorResponseStreaming} from the orchestration service, if available. * - *

Note: This method is marked as {@link Beta} because it uses generated API types in its - * public signature. - * * @return The {@link ErrorResponseStreaming} object, or {@code null} if not available. * @since 1.10.0 */ - @Beta @Nullable public ErrorResponseStreaming getErrorResponseStreaming() { if (getClientError() instanceof OrchestrationError.Streaming orchestrationError) { diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/PolymorphicFallbackDeserializer.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/PolymorphicFallbackDeserializer.java index 4279995b8..5d948d3be 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/PolymorphicFallbackDeserializer.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/PolymorphicFallbackDeserializer.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonMappingException; -import com.google.common.annotations.Beta; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -24,7 +23,6 @@ * @since 1.2.0 * @param The base type for deserialization. */ -@Beta @AllArgsConstructor(access = AccessLevel.PROTECTED) class PolymorphicFallbackDeserializer extends JsonDeserializer { diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/SystemMessage.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/SystemMessage.java index ab0a8c190..e2cbc8f0f 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/SystemMessage.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/SystemMessage.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import lombok.AccessLevel; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Value; @@ -21,10 +22,11 @@ import lombok.val; /** Represents a chat message as 'system' to the orchestration service. */ +@EqualsAndHashCode(callSuper = true) @Value @Accessors(fluent = true) @RequiredArgsConstructor(access = AccessLevel.PACKAGE) -public class SystemMessage implements Message { +public class SystemMessage extends Message { /** The role of the assistant. */ @Nonnull String role = "system"; diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ToolMessage.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ToolMessage.java index eba89f6e9..385244892 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ToolMessage.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/ToolMessage.java @@ -21,7 +21,7 @@ @AllArgsConstructor @Getter @Accessors(fluent = true) -public final class ToolMessage implements Message { +public final class ToolMessage extends Message { /** The role of the assistant. */ @Nonnull final String role = "tool"; diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/UserMessage.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/UserMessage.java index 33e4077f8..ec9a8b0c3 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/UserMessage.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/UserMessage.java @@ -23,6 +23,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import lombok.AccessLevel; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Value; @@ -31,11 +32,12 @@ import lombok.extern.slf4j.Slf4j; /** Represents a chat message as 'user' to the orchestration service. */ +@EqualsAndHashCode(callSuper = true) @Slf4j @Value @Accessors(fluent = true) @RequiredArgsConstructor(access = AccessLevel.PACKAGE) -public class UserMessage implements Message { +public class UserMessage extends Message { private static final String PDF_DATA_URI_PREFIX = "data:application/pdf;base64,"; /** The role of the assistant. */ diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java index 1ee70d47b..cc7c2055d 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java @@ -8,7 +8,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; import static com.github.tomakehurst.wiremock.client.WireMock.jsonResponse; import static com.github.tomakehurst.wiremock.client.WireMock.noContent; -import static com.github.tomakehurst.wiremock.client.WireMock.okJson; import static com.github.tomakehurst.wiremock.client.WireMock.okXml; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; @@ -829,64 +828,6 @@ void testErrorHandling(@Nonnull final Runnable request) { softly.assertAll(); } - @Test - void testExecuteRequestFromJson() { - stubFor(post(anyUrl()).willReturn(okJson("{}"))); - - prompt = - new OrchestrationPrompt(Map.of("foo", "bar")) - .messageHistory(List.of(new UserMessage("Hello World!"))); - final var configJson = - """ - { - "module_configurations": { - "llm_module_config": { - "model_name": "mistralai--mistral-large-instruct", - "model_params": {} - } - } - } - """; - - final var expectedJson = - """ - { - "messages_history": [{ - "role" : "user", - "content" : "Hello World!" - }], - "input_params": { - "foo" : "bar" - }, - "orchestration_config": { - "module_configurations": { - "llm_module_config": { - "model_name": "mistralai--mistral-large-instruct", - "model_params": {} - } - } - } - } - """; - - var result = client.executeRequestFromJsonModuleConfig(prompt, configJson); - assertThat(result).isNotNull(); - - verify(postRequestedFor(anyUrl()).withRequestBody(equalToJson(expectedJson))); - } - - @Test - void testExecuteRequestFromJsonThrows() { - assertThatThrownBy(() -> client.executeRequestFromJsonModuleConfig(prompt, "{}")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("messages"); - - prompt = new OrchestrationPrompt(Map.of()); - assertThatThrownBy(() -> client.executeRequestFromJsonModuleConfig(prompt, "{ foo")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("not valid JSON"); - } - @Test void testThrowsOnContentFilter() { var mock = mock(OrchestrationClient.class);