diff --git a/core-services/prompt-registry/pom.xml b/core-services/prompt-registry/pom.xml
index e7880ee9d..2738f5849 100644
--- a/core-services/prompt-registry/pom.xml
+++ b/core-services/prompt-registry/pom.xml
@@ -38,11 +38,11 @@
${project.basedir}/../../
- 91%
+ 88%
93%
94%
100%
- 83%
+ 80%
100%
@@ -73,10 +73,6 @@
com.fasterxml.jackson.core
jackson-core
-
- com.google.guava
- guava
-
com.fasterxml.jackson.core
jackson-annotations
diff --git a/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClient.java b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigMixin.java
similarity index 68%
rename from core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClient.java
rename to core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigMixin.java
index 5a9d1096b..ebbc56d65 100644
--- a/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClient.java
+++ b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigMixin.java
@@ -4,9 +4,7 @@
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.google.common.annotations.Beta;
import com.sap.ai.sdk.core.AiCoreService;
-import com.sap.ai.sdk.prompt.registry.client.OrchestrationConfigsApi;
import com.sap.ai.sdk.prompt.registry.model.AzureContentSafetyInputFilterConfig;
import com.sap.ai.sdk.prompt.registry.model.AzureContentSafetyOutputFilterConfig;
import com.sap.ai.sdk.prompt.registry.model.InputFilterConfig;
@@ -18,32 +16,10 @@
import lombok.NoArgsConstructor;
import lombok.val;
-/**
- * Client for managing Orchestration Configurations in the Prompt Registry service.
- *
- * @since 1.15.0
- */
-@Beta
-public class OrchestrationConfigClient extends OrchestrationConfigsApi {
-
- /**
- * Instantiates a client to manage Orchestration Configurations on the Prompt Registry service.
- */
- public OrchestrationConfigClient() {
- this(new AiCoreService());
- }
-
- /**
- * Instantiates a client to manage Orchestration Configurations on the Prompt Registry service.
- *
- * @param aiCoreService The configured connectivity instance to AI Core
- */
- public OrchestrationConfigClient(@Nonnull final AiCoreService aiCoreService) {
- super(addMixin(aiCoreService));
- }
+class OrchestrationConfigMixin {
@Nonnull
- private static ApiClient addMixin(@Nonnull final AiCoreService service) {
+ static ApiClient addMixin(@Nonnull final AiCoreService service) {
final var destination = service.getBaseDestination();
val objectMapper =
@@ -54,8 +30,8 @@ private static ApiClient addMixin(@Nonnull final AiCoreService service) {
return ApiClient.create(destination).withObjectMapper(objectMapper);
}
- @NoArgsConstructor(access = AccessLevel.PRIVATE)
- private static class JacksonMixin {
+ @NoArgsConstructor(access = AccessLevel.PACKAGE)
+ static class JacksonMixin {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
diff --git a/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClient.java b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClientMixin.java
similarity index 79%
rename from core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClient.java
rename to core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClientMixin.java
index ae252897a..6d2f8652e 100644
--- a/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClient.java
+++ b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptClientMixin.java
@@ -11,7 +11,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.sap.ai.sdk.core.AiCoreService;
-import com.sap.ai.sdk.prompt.registry.client.PromptTemplatesApi;
import com.sap.ai.sdk.prompt.registry.model.MultiChatContent;
import com.sap.ai.sdk.prompt.registry.model.MultiChatTemplate;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplate;
@@ -28,34 +27,10 @@
import lombok.NoArgsConstructor;
import lombok.val;
-/**
- * Client for the Prompt Registry service.
- *
- * @since 1.6.0
- */
-public class PromptClient extends PromptTemplatesApi {
-
- /**
- * Instantiates this a client to invoke operations on the Prompt Registry service.
- *
- * @since 1.6.0
- */
- public PromptClient() {
- this(new AiCoreService());
- }
-
- /**
- * Instantiates this a client to invoke operations on the Prompt Registry service.
- *
- * @param aiCoreService The configured connectivity instance to AI Core
- * @since 1.6.0
- */
- public PromptClient(@Nonnull final AiCoreService aiCoreService) {
- super(addMixin(aiCoreService));
- }
+class PromptClientMixin {
@Nonnull
- private static ApiClient addMixin(@Nonnull final AiCoreService service) {
+ static ApiClient addMixin(@Nonnull final AiCoreService service) {
final var destination = service.getBaseDestination();
val objectMapper =
@@ -66,8 +41,8 @@ private static ApiClient addMixin(@Nonnull final AiCoreService service) {
return ApiClient.create(destination).withObjectMapper(objectMapper);
}
- @NoArgsConstructor(access = AccessLevel.PRIVATE)
- private static class JacksonMixin {
+ @NoArgsConstructor(access = AccessLevel.PACKAGE)
+ static class JacksonMixin {
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
@JsonDeserialize(using = PromptTemplateDeserializer.class)
interface TemplateMixIn {}
@@ -85,7 +60,7 @@ interface TemplateMixIn {}
interface ResponseFormat {}
}
- private static class PromptTemplateDeserializer extends JsonDeserializer {
+ static class PromptTemplateDeserializer extends JsonDeserializer {
@Override
public PromptTemplate deserialize(
diff --git a/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClient.java b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClient.java
new file mode 100644
index 000000000..bbf58d0fe
--- /dev/null
+++ b/core-services/prompt-registry/src/main/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClient.java
@@ -0,0 +1,50 @@
+package com.sap.ai.sdk.prompt.registry;
+
+import com.sap.ai.sdk.core.AiCoreService;
+import com.sap.ai.sdk.prompt.registry.client.OrchestrationConfigsApi;
+import com.sap.ai.sdk.prompt.registry.client.PromptTemplatesApi;
+import javax.annotation.Nonnull;
+
+/**
+ * Unified client to use Prompt Registry API
+ *
+ * @since 2.0
+ */
+public class PromptRegistryClient {
+
+ private final AiCoreService aiCoreService;
+
+ /** Constructs default PromptRegistryClient */
+ public PromptRegistryClient() {
+ this(new AiCoreService());
+ }
+
+ /**
+ * Constructs PromptRegistryClient with customized AiCoreService
+ *
+ * @param service customized AiCoreService
+ */
+ public PromptRegistryClient(@Nonnull final AiCoreService service) {
+ aiCoreService = service;
+ }
+
+ /**
+ * Get the prompt templates client
+ *
+ * @return the client
+ */
+ @Nonnull
+ public PromptTemplatesApi prompt() {
+ return new PromptTemplatesApi(PromptClientMixin.addMixin(aiCoreService));
+ }
+
+ /**
+ * Get the orchestration configs client
+ *
+ * @return the client
+ */
+ @Nonnull
+ public OrchestrationConfigsApi orchestrationConfig() {
+ return new OrchestrationConfigsApi(OrchestrationConfigMixin.addMixin(aiCoreService));
+ }
+}
diff --git a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClientTest.java b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClientTest.java
index 2365d0bdc..f3bd2abbb 100644
--- a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClientTest.java
+++ b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/OrchestrationConfigClientTest.java
@@ -5,10 +5,11 @@
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.sap.ai.sdk.core.AiCoreService;
+import com.sap.ai.sdk.prompt.registry.client.OrchestrationConfigsApi;
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
import java.util.UUID;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -17,13 +18,14 @@ public class OrchestrationConfigClientTest {
private static final WireMockExtension WM =
WireMockExtension.newInstance().options(wireMockConfig().dynamicPort()).build();
- private static OrchestrationConfigClient client;
+ private static OrchestrationConfigsApi client;
- @BeforeEach
- void setup() {
+ @BeforeAll
+ static void setup() {
final HttpDestination destination = DefaultHttpDestination.builder(WM.baseUrl()).build();
final AiCoreService service = new AiCoreService().withBaseDestination(destination);
- client = new OrchestrationConfigClient(service);
+ final var promptRegistryClient = new PromptRegistryClient(service);
+ client = promptRegistryClient.orchestrationConfig();
}
@Test
diff --git a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClientTest.java b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClientTest.java
index b81131c0a..16eea6301 100644
--- a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClientTest.java
+++ b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/PromptRegistryClientTest.java
@@ -6,6 +6,7 @@
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.sap.ai.sdk.core.AiCoreService;
+import com.sap.ai.sdk.prompt.registry.client.PromptTemplatesApi;
import com.sap.ai.sdk.prompt.registry.model.MultiChatTemplate;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplateGetResponse;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplateSubstitutionRequest;
@@ -18,7 +19,7 @@
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
import java.util.Map;
import java.util.UUID;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -27,13 +28,14 @@ class PromptRegistryClientTest {
private static final WireMockExtension WM =
WireMockExtension.newInstance().options(wireMockConfig().dynamicPort()).build();
- private static PromptClient client;
+ private static PromptTemplatesApi client;
- @BeforeEach
- void setup() {
+ @BeforeAll
+ static void setup() {
final HttpDestination destination = DefaultHttpDestination.builder(WM.baseUrl()).build();
final AiCoreService service = new AiCoreService().withBaseDestination(destination);
- client = new PromptClient(service);
+ PromptRegistryClient promptRegistryClient = new PromptRegistryClient(service);
+ client = promptRegistryClient.prompt();
}
@Test
diff --git a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/spring/SpringAiConverterTest.java b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/spring/SpringAiConverterTest.java
index 7008efabe..bbf2d63ee 100644
--- a/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/spring/SpringAiConverterTest.java
+++ b/core-services/prompt-registry/src/test/java/com/sap/ai/sdk/prompt/registry/spring/SpringAiConverterTest.java
@@ -6,17 +6,18 @@
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.sap.ai.sdk.core.AiCoreService;
-import com.sap.ai.sdk.prompt.registry.PromptClient;
+import com.sap.ai.sdk.prompt.registry.PromptRegistryClient;
+import com.sap.ai.sdk.prompt.registry.client.PromptTemplatesApi;
import com.sap.ai.sdk.prompt.registry.model.MultiChatContent;
import com.sap.ai.sdk.prompt.registry.model.MultiChatTemplate;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplate;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplateSubstitutionRequest;
import com.sap.ai.sdk.prompt.registry.model.PromptTemplateSubstitutionResponse;
import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination;
-import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination;
import java.util.List;
import java.util.Map;
import lombok.val;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.ai.chat.messages.Message;
@@ -28,12 +29,17 @@ public class SpringAiConverterTest {
private static final WireMockExtension WM =
WireMockExtension.newInstance().options(wireMockConfig().dynamicPort()).build();
- private final HttpDestination DESTINATION = DefaultHttpDestination.builder(WM.baseUrl()).build();
- private final AiCoreService SERVICE = new AiCoreService().withBaseDestination(DESTINATION);
+ private static PromptTemplatesApi client;
+
+ @BeforeAll
+ static void setup() {
+ val destination = DefaultHttpDestination.builder(WM.baseUrl()).build();
+ val service = new AiCoreService().withBaseDestination(destination);
+ client = new PromptRegistryClient(service).prompt();
+ }
@Test
void testPromptRegistryToSpringAi() {
- var client = new PromptClient(SERVICE);
val promptResponse =
client.parsePromptTemplateByNameVersion(
"categorization",
@@ -56,7 +62,6 @@ void testPromptRegistryToSpringAi() {
@Test
void testInvalidRoleThrowsException() {
- var client = new PromptClient(SERVICE);
val errorPrompt =
client.parsePromptTemplateByNameVersion(
"categorization",
@@ -75,7 +80,6 @@ void testInvalidRoleThrowsException() {
@Test
void testMultiChatTemplateTextContentToSpringAi() {
- var client = new PromptClient(SERVICE);
val promptResponse =
client.parsePromptTemplateByNameVersion(
"categorization",
@@ -94,7 +98,6 @@ void testMultiChatTemplateTextContentToSpringAi() {
@Test
void testMultiChatTemplateImageContentThrowsException() {
- var client = new PromptClient(SERVICE);
val promptResponse =
client.parsePromptTemplateByNameVersion(
"categorization",
diff --git a/docs/release_notes.md b/docs/release_notes.md
index c8381b375..d4505038e 100644
--- a/docs/release_notes.md
+++ b/docs/release_notes.md
@@ -10,6 +10,30 @@
- [RPT] SAP-RPT was updated to the newer 1.6.0 API
- [Orchestration] Spring AI support was upgraded to version `2.0.1`
+- [Core] OrchestrationConfigClient and PromptClient were reworked into unified PromptRegistryClient,
+ see migration guide below for additional information
+
+#### Prompt registry client Migration Guide
+
+OrchestrationConfigClient and PromptClient were replaced with unified PromptRegistryClient,
+
+OrchestrationConfigClient:
+```diff
+-var orchestrationConfigsClient = new OrchestrationConfigClient();
+-var configs = orchestrationConfigsClient.listOrchestrationConfigs();
+
++var orchestractionConfigsClient = new PromptRegistryClient().orchestrationConfig();
++var configs = orchestractionConfigsClient.listOrchestrationConfigs();
+```
+
+PromptRegistryClient:
+```diff
+-var promptClient = new PromptClient();
+-var templates = promptClient.listPromptTemplates();
+
++var promptClient = new PromptRegistryClient().prompt();
++var templates = promptClient.listPromptTemplates();
+```
#### Spring AI 2.0.1 Migration Guide
diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/PromptRegistryController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/PromptRegistryController.java
index 097a7c193..a130d425d 100644
--- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/PromptRegistryController.java
+++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/PromptRegistryController.java
@@ -3,8 +3,9 @@
import com.sap.ai.sdk.foundationmodels.openai.OpenAiClient;
import com.sap.ai.sdk.foundationmodels.openai.OpenAiModel;
import com.sap.ai.sdk.foundationmodels.openai.spring.OpenAiChatModel;
-import com.sap.ai.sdk.prompt.registry.OrchestrationConfigClient;
-import com.sap.ai.sdk.prompt.registry.PromptClient;
+import com.sap.ai.sdk.prompt.registry.PromptRegistryClient;
+import com.sap.ai.sdk.prompt.registry.client.OrchestrationConfigsApi;
+import com.sap.ai.sdk.prompt.registry.client.PromptTemplatesApi;
import com.sap.ai.sdk.prompt.registry.model.LLMModelDetails;
import com.sap.ai.sdk.prompt.registry.model.OrchestrationConfigDeleteResponse;
import com.sap.ai.sdk.prompt.registry.model.OrchestrationConfigListResponse;
@@ -49,8 +50,9 @@
@RequestMapping("/prompt-registry")
class PromptRegistryController {
static final String NAME = "java-e2e-test";
- private static final PromptClient promptClient = new PromptClient();
- private static final OrchestrationConfigClient orchConfigClient = new OrchestrationConfigClient();
+ private static final OrchestrationConfigsApi orchConfigClient =
+ new PromptRegistryClient().orchestrationConfig();
+ private static final PromptTemplatesApi promptClient = new PromptRegistryClient().prompt();
@GetMapping("/listTemplates")
PromptTemplateListResponse listTemplates() {
@@ -135,16 +137,15 @@ Generation promptRegistryToSpringAi() {
val cl = ChatClient.builder(openAiClient).defaultAdvisors(advisor).build();
val promptResponse =
- new PromptClient()
- .parsePromptTemplateByNameVersion(
- "categorization",
- "0.0.1",
- "java-e2e-test",
- "default",
- null,
- false,
- PromptTemplateSubstitutionRequest.create()
- .inputParams(Map.of("inputExample", "I love football")));
+ promptClient.parsePromptTemplateByNameVersion(
+ "categorization",
+ "0.0.1",
+ "java-e2e-test",
+ "default",
+ null,
+ false,
+ PromptTemplateSubstitutionRequest.create()
+ .inputParams(Map.of("inputExample", "I love football")));
final List messages = SpringAiConverter.promptTemplateToMessages(promptResponse);
val prompt = new Prompt(messages);
diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
index 088cfab5f..3f7fbc952 100644
--- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
+++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java
@@ -46,7 +46,8 @@
import com.sap.ai.sdk.orchestration.model.SearchDocumentKeyValueListPair;
import com.sap.ai.sdk.orchestration.model.SearchSelectOptionEnum;
import com.sap.ai.sdk.orchestration.model.Template;
-import com.sap.ai.sdk.prompt.registry.OrchestrationConfigClient;
+import com.sap.ai.sdk.prompt.registry.PromptRegistryClient;
+import com.sap.ai.sdk.prompt.registry.client.OrchestrationConfigsApi;
import com.sap.ai.sdk.prompt.registry.model.LLMModelDetails;
import com.sap.ai.sdk.prompt.registry.model.OrchestrationConfigPostRequest;
import com.sap.ai.sdk.prompt.registry.model.PartialModuleConfigs;
@@ -888,7 +889,8 @@ public OrchestrationChatResponse executeConfigFromReference() {
}
private void ensureOrchestrationConfigExists(final String scenario, final String name) {
- final OrchestrationConfigClient orchConfigClient = new OrchestrationConfigClient();
+ final OrchestrationConfigsApi orchConfigClient =
+ new PromptRegistryClient().orchestrationConfig();
if (!orchConfigExists("test-config-for-OrchestrationTest", orchConfigClient)) {
final OrchestrationConfigPostRequest postRequest =
OrchestrationConfigPostRequest.create()
@@ -901,8 +903,8 @@ private void ensureOrchestrationConfigExists(final String scenario, final String
}
private boolean orchConfigExists(
- final String configName, final OrchestrationConfigClient orchConfigClient) {
- return orchConfigClient.listOrchestrationConfigs().getResources().stream()
+ final String configName, final OrchestrationConfigsApi orchestrationConfigsClient) {
+ return orchestrationConfigsClient.listOrchestrationConfigs().getResources().stream()
.anyMatch(resp -> resp.getName().equals(configName));
}
@@ -975,7 +977,7 @@ public Stream streamDeltasWithInlineConfig(
public Stream streamDeltasWithReferenceById() {
// get a valid id
ensureOrchestrationConfigExists("sdk-test-paraphrase", "create-3-paraphrases-of-sentence");
- val orchConfigClient = new OrchestrationConfigClient();
+ val orchConfigClient = new PromptRegistryClient().orchestrationConfig();
val id =
orchConfigClient.listOrchestrationConfigs().getResources().stream()
.filter(r -> r.getName().equals("test-config-for-OrchestrationTest"))