Skip to content

Commit db1815c

Browse files
rpanackalCharlesDuboisSAPbot-sdk-jsa-d
authored
feat: PoC 📚 Prompt Registry client (#343)
* Initial (error prone) model gen - pmd checks NOT disabled/suppresed * fix pr title lint * Generated client * Added sample code endpoint * Added e2e test * Formatting * Working * Formatting * Do not re-generate client * spec-update.yaml * Fix generation * Cloud SDK 5.17.0 * Set property correctly * Revert "Set property correctly" This reverts commit 3394f13. * Initial * Doc * PMD * Better solution --------- Co-authored-by: Roshin Rajan Panackal <[email protected]> Co-authored-by: I538344 <[email protected]> Co-authored-by: SAP Cloud SDK Bot <[email protected]> Co-authored-by: Alexander Dümont <[email protected]>
1 parent 8a7b914 commit db1815c

40 files changed

+8680
-1
lines changed

.github/workflows/pr-lint.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323
OpenAI
2424
Orchestration
2525
DevOps
26+
PromptRegistry
2627
headerPattern: '^(\w.+): (?:\[(\w.+)\] )?(.+)$'
2728
headerPatternCorrespondence: type, scope, subject
2829
# for available types, check:

.github/workflows/spec-update.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
- core
1212
- grounding
1313
- orchestration
14+
- prompt-registry
1415
default: orchestration
1516
file-ref:
1617
description: "Branch or tag to checkout the spec file from"
@@ -78,6 +79,10 @@ jobs:
7879
API_URL="$API_BASE_URL/AI/llm-orchestration/contents/src/spec/api.yaml?ref=$REF"
7980
FILE_PATH='orchestration/src/main/resources/spec/orchestration.yaml'
8081
;;
82+
prompt-registry)
83+
API_URL="$API_BASE_URL/AI/prompt-registry/contents/src/spec/prompt-registry.yaml?ref=$REF"
84+
FILE_PATH='prompt-registry/src/main/resources/spec/prompt-registry.yaml'
85+
;;
8186
esac
8287
8388
echo "Downloading $CHOICE specification file from $API_URL ..."
@@ -187,4 +192,4 @@ jobs:
187192
echo "| Client Testing | ${{ steps.compile.outputs.test_result == 'success' && '✅' || steps.compile.outputs.test_result == 'skipped' && '⏩' || '❌' }} ${{ steps.compile.outputs.test_result }}" >> $GITHUB_STEP_SUMMARY
188193
echo "| Branch Creation | ${{ steps.push.outcome == 'success' && '✅ [Branch Link]($DIFF_URL)' || '❌ failure' }}" >> $GITHUB_STEP_SUMMARY
189194
echo "| Pull Request Creation | ${{ env.CREATE_PR == 'false' && '⏩ skipped' || '' }}${{ env.CREATE_PR == 'true' && steps.push.outcome == 'success' && '✅ [PR Link]($PR_URL)' || '' }}" >> $GITHUB_STEP_SUMMARY
190-
fi
195+
fi

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<module>orchestration</module>
3434
<module>document-grounding</module>
3535
<module>foundation-models/openai</module>
36+
<module>prompt-registry</module>
3637
</modules>
3738
<scm>
3839
<connection/>
@@ -209,6 +210,11 @@
209210
<artifactId>document-grounding</artifactId>
210211
<version>${project.version}</version>
211212
</dependency>
213+
<dependency>
214+
<groupId>com.sap.ai.sdk</groupId>
215+
<artifactId>prompt-registry</artifactId>
216+
<version>${project.version}</version>
217+
</dependency>
212218
<dependency>
213219
<groupId>com.sap.ai.sdk.foundationmodels</groupId>
214220
<artifactId>openai</artifactId>
@@ -628,6 +634,8 @@ https://gitbox.apache.org/repos/asf?p=maven-pmd-plugin.git;a=blob_plain;f=src/ma
628634
<exclude>com/sap/ai/sdk/orchestration/model/*</exclude>
629635
<exclude>com/sap/ai/sdk/grounding/client/*</exclude>
630636
<exclude>com/sap/ai/sdk/grounding/model/*</exclude>
637+
<exclude>com/sap/ai/sdk/prompt/registry/client/*</exclude>
638+
<exclude>com/sap/ai/sdk/prompt/registry/model/*</exclude>
631639
</excludes>
632640
</configuration>
633641
<executions>
@@ -652,6 +660,8 @@ https://gitbox.apache.org/repos/asf?p=maven-pmd-plugin.git;a=blob_plain;f=src/ma
652660
<exclude>com/sap/ai/sdk/foundationmodels/openai/generated/model/*</exclude>
653661
<exclude>com/sap/ai/sdk/grounding/client/*</exclude>
654662
<exclude>com/sap/ai/sdk/grounding/model/*</exclude>
663+
<exclude>com/sap/ai/sdk/prompt/registry/model/*</exclude>
664+
<exclude>com/sap/ai/sdk/prompt/registry/client/*</exclude>
655665
<exclude>com/sap/ai/sdk/app/**/*</exclude>
656666
</excludes>
657667
</configuration>
@@ -766,6 +776,7 @@ https://gitbox.apache.org/repos/asf?p=maven-pmd-plugin.git;a=blob_plain;f=src/ma
766776
</activation>
767777
<modules>
768778
<module>sample-code/spring-app</module>
779+
<module>prompt-registry</module>
769780
</modules>
770781
</profile>
771782
<profile>

prompt-registry/pom.xml

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>com.sap.ai.sdk</groupId>
6+
<artifactId>sdk-parent</artifactId>
7+
<version>1.4.0-SNAPSHOT</version>
8+
</parent>
9+
<artifactId>prompt-registry</artifactId>
10+
<name>Prompt Registry client</name>
11+
<description>SAP Cloud SDK for AI is the official Software Development Kit (SDK) for SAP AI Core, SAP Generative AI
12+
Hub, and Orchestration Service. This is the client for life cycle management of your prompts without
13+
Orchestration Service.</description>
14+
<url>https://github.com/SAP/ai-sdk-java?tab=readme-ov-file#documentation</url>
15+
<organization>
16+
<name>SAP SE</name>
17+
<url>https://www.sap.com</url>
18+
</organization>
19+
<licenses>
20+
<license>
21+
<name>The Apache Software License, Version 2.0</name>
22+
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
23+
</license>
24+
</licenses>
25+
<developers>
26+
<developer>
27+
<name>SAP</name>
28+
<email>[email protected]</email>
29+
<organization>SAP SE</organization>
30+
<organizationUrl>https://www.sap.com</organizationUrl>
31+
</developer>
32+
</developers>
33+
<properties>
34+
<project.rootdir>${project.basedir}/../</project.rootdir>
35+
<coverage.complexity>75%</coverage.complexity>
36+
<coverage.line>87%</coverage.line>
37+
<coverage.instruction>89%</coverage.instruction>
38+
<coverage.branch>100%</coverage.branch>
39+
<coverage.method>75%</coverage.method>
40+
<coverage.class>100%</coverage.class>
41+
</properties>
42+
43+
<dependencies>
44+
<!-- scope "compile" -->
45+
<dependency>
46+
<groupId>com.sap.ai.sdk</groupId>
47+
<artifactId>core</artifactId>
48+
</dependency>
49+
<dependency>
50+
<groupId>com.sap.cloud.sdk.datamodel</groupId>
51+
<artifactId>openapi-core</artifactId>
52+
</dependency>
53+
<dependency>
54+
<groupId>org.springframework</groupId>
55+
<artifactId>spring-core</artifactId>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.springframework</groupId>
59+
<artifactId>spring-web</artifactId>
60+
</dependency>
61+
<dependency>
62+
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
63+
<artifactId>cloudplatform-connectivity</artifactId>
64+
</dependency>
65+
<dependency>
66+
<groupId>com.sap.cloud.sdk.cloudplatform</groupId>
67+
<artifactId>connectivity-apache-httpclient5</artifactId>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.apache.httpcomponents.client5</groupId>
71+
<artifactId>httpclient5</artifactId>
72+
</dependency>
73+
<dependency>
74+
<groupId>com.fasterxml.jackson.core</groupId>
75+
<artifactId>jackson-databind</artifactId>
76+
</dependency>
77+
<dependency>
78+
<groupId>com.google.guava</groupId>
79+
<artifactId>guava</artifactId>
80+
</dependency>
81+
<dependency>
82+
<groupId>com.fasterxml.jackson.core</groupId>
83+
<artifactId>jackson-annotations</artifactId>
84+
</dependency>
85+
<dependency>
86+
<groupId>com.google.code.findbugs</groupId>
87+
<artifactId>jsr305</artifactId>
88+
</dependency>
89+
<!-- scope "provided" -->
90+
<dependency>
91+
<groupId>org.projectlombok</groupId>
92+
<artifactId>lombok</artifactId>
93+
<scope>provided</scope>
94+
</dependency>
95+
<!-- scope "test" -->
96+
<dependency>
97+
<groupId>org.junit.jupiter</groupId>
98+
<artifactId>junit-jupiter-api</artifactId>
99+
<scope>test</scope>
100+
</dependency>
101+
<dependency>
102+
<groupId>org.wiremock</groupId>
103+
<artifactId>wiremock</artifactId>
104+
<scope>test</scope>
105+
</dependency>
106+
<dependency>
107+
<groupId>org.assertj</groupId>
108+
<artifactId>assertj-core</artifactId>
109+
<scope>test</scope>
110+
</dependency>
111+
</dependencies>
112+
113+
<profiles>
114+
<profile>
115+
<id>generate</id>
116+
<activation>
117+
<activeByDefault>false</activeByDefault>
118+
<property>
119+
<name>generate</name>
120+
</property>
121+
</activation>
122+
<build>
123+
<plugins>
124+
<plugin>
125+
<groupId>com.sap.cloud.sdk.datamodel</groupId>
126+
<artifactId>openapi-generator-maven-plugin</artifactId>
127+
<configuration>
128+
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
129+
<apiMaturity>beta</apiMaturity>
130+
<enableOneOfAnyOfGeneration>true</enableOneOfAnyOfGeneration>
131+
<compileScope>COMPILE</compileScope>
132+
<deleteOutputDirectory>true</deleteOutputDirectory>
133+
</configuration>
134+
<executions>
135+
<execution>
136+
<id>prompt-registry</id>
137+
<goals>
138+
<goal>generate</goal>
139+
</goals>
140+
<phase>generate-sources</phase>
141+
<configuration>
142+
<inputSpec>${project.basedir}/src/main/resources/spec/prompt-registry.yaml</inputSpec>
143+
<apiPackage>com.sap.ai.sdk.prompt.registry.client</apiPackage>
144+
<modelPackage>com.sap.ai.sdk.prompt.registry.model</modelPackage>
145+
<additionalProperties>
146+
<pojoBuilderMethodName>create</pojoBuilderMethodName>
147+
<pojoBuildMethodName/>
148+
<pojoConstructorVisibility>protected</pojoConstructorVisibility>
149+
<enumUnknownDefaultCase>true</enumUnknownDefaultCase>
150+
<removeOperationIdPrefix>true</removeOperationIdPrefix>
151+
<removeOperationIdPrefixDelimiter>\.</removeOperationIdPrefixDelimiter>
152+
<removeOperationIdPrefixCount>3</removeOperationIdPrefixCount>
153+
<useOneOfInterfaces>true</useOneOfInterfaces>
154+
</additionalProperties>
155+
</configuration>
156+
</execution>
157+
</executions>
158+
</plugin>
159+
</plugins>
160+
</build>
161+
</profile>
162+
</profiles>
163+
</project>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.sap.ai.sdk.prompt.registry;
2+
3+
import static com.sap.ai.sdk.core.JacksonConfiguration.getDefaultObjectMapper;
4+
5+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
6+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
7+
import com.google.common.collect.Iterables;
8+
import com.sap.ai.sdk.core.AiCoreService;
9+
import com.sap.ai.sdk.prompt.registry.client.DefaultApi;
10+
import com.sap.ai.sdk.prompt.registry.model.PromptTemplateSpecResponseFormat;
11+
import com.sap.ai.sdk.prompt.registry.model.ResponseFormatText;
12+
import com.sap.ai.sdk.prompt.registry.model.SingleChatTemplate;
13+
import com.sap.ai.sdk.prompt.registry.model.Template;
14+
import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor;
15+
import com.sap.cloud.sdk.services.openapi.apiclient.ApiClient;
16+
import javax.annotation.Nonnull;
17+
import lombok.AccessLevel;
18+
import lombok.NoArgsConstructor;
19+
import org.springframework.http.client.BufferingClientHttpRequestFactory;
20+
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
21+
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
22+
import org.springframework.web.client.RestTemplate;
23+
24+
/** Client for the Prompt Registry service. */
25+
public class PromptClient extends DefaultApi {
26+
27+
/** Instantiates this a client to invoke operations on the Prompt Registry service. */
28+
public PromptClient() {
29+
this(new AiCoreService());
30+
}
31+
32+
/**
33+
* Instantiates this a client to invoke operations on the Prompt Registry service.
34+
*
35+
* @param aiCoreService The configured connectivity instance to AI Core
36+
*/
37+
public PromptClient(@Nonnull final AiCoreService aiCoreService) {
38+
super(addMixin(aiCoreService));
39+
}
40+
41+
@Nonnull
42+
private static ApiClient addMixin(@Nonnull final AiCoreService service) {
43+
final var destination = service.getBaseDestination();
44+
final var httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
45+
httpRequestFactory.setHttpClient(ApacheHttpClient5Accessor.getHttpClient(destination));
46+
47+
final var rt = new RestTemplate();
48+
Iterables.filter(rt.getMessageConverters(), MappingJackson2HttpMessageConverter.class)
49+
.forEach(
50+
converter ->
51+
converter.setObjectMapper(
52+
getDefaultObjectMapper()
53+
.addMixIn(Template.class, JacksonMixin.TemplateMixIn.class)
54+
.addMixIn(
55+
PromptTemplateSpecResponseFormat.class,
56+
JacksonMixin.ResponseFormat.class)));
57+
58+
rt.setRequestFactory(new BufferingClientHttpRequestFactory(httpRequestFactory));
59+
60+
return new ApiClient(rt).setBasePath(destination.asHttp().getUri().toString());
61+
}
62+
63+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
64+
private static class JacksonMixin {
65+
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
66+
@JsonDeserialize(as = SingleChatTemplate.class)
67+
interface TemplateMixIn {}
68+
69+
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
70+
@JsonDeserialize(as = ResponseFormatText.class)
71+
interface ResponseFormat {}
72+
}
73+
}

0 commit comments

Comments
 (0)