Skip to content
8 changes: 2 additions & 6 deletions core-services/prompt-registry/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
</scm>
<properties>
<project.rootdir>${project.basedir}/../../</project.rootdir>
<coverage.complexity>91%</coverage.complexity>
<coverage.complexity>88%</coverage.complexity>
<coverage.line>93%</coverage.line>
<coverage.instruction>94%</coverage.instruction>
<coverage.branch>100%</coverage.branch>
<coverage.method>83%</coverage.method>
<coverage.method>80%</coverage.method>
<coverage.class>100%</coverage.class>
</properties>

Expand Down Expand Up @@ -73,10 +73,6 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 =
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 =
Expand All @@ -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 {}
Expand All @@ -85,7 +60,7 @@ interface TemplateMixIn {}
interface ResponseFormat {}
}

private static class PromptTemplateDeserializer extends JsonDeserializer<PromptTemplate> {
static class PromptTemplateDeserializer extends JsonDeserializer<PromptTemplate> {

@Override
public PromptTemplate deserialize(
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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",
Expand All @@ -56,7 +62,6 @@ void testPromptRegistryToSpringAi() {

@Test
void testInvalidRoleThrowsException() {
var client = new PromptClient(SERVICE);
val errorPrompt =
client.parsePromptTemplateByNameVersion(
"categorization",
Expand All @@ -75,7 +80,6 @@ void testInvalidRoleThrowsException() {

@Test
void testMultiChatTemplateTextContentToSpringAi() {
var client = new PromptClient(SERVICE);
val promptResponse =
client.parsePromptTemplateByNameVersion(
"categorization",
Expand All @@ -94,7 +98,6 @@ void testMultiChatTemplateTextContentToSpringAi() {

@Test
void testMultiChatTemplateImageContentThrowsException() {
var client = new PromptClient(SERVICE);
val promptResponse =
client.parsePromptTemplateByNameVersion(
"categorization",
Expand Down
24 changes: 24 additions & 0 deletions docs/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- [Core] OrchestrationConfigClient and PromptClient were reworked into unified PromptRegistryClient,
- [Prompt Registry] `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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OrchestrationConfigClient and PromptClient were replaced with unified PromptRegistryClient,
`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

Expand Down
Loading