-
Notifications
You must be signed in to change notification settings - Fork 16
feat: [DevOps] Poc RPT #732
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4a88b37
8363a6f
920963f
53d8fa8
3d4c979
faa656a
1931444
65ce38c
47b981c
70d0234
ff33f98
80c6167
b580486
640a57a
1d1e851
d8d56f6
5fd47b6
ee539a0
58a8bfb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <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"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>com.sap.ai.sdk</groupId> | ||
| <artifactId>sdk-parent</artifactId> | ||
| <version>1.16.0-SNAPSHOT</version> | ||
| <relativePath>../../pom.xml</relativePath> | ||
| </parent> | ||
| <groupId>com.sap.ai.sdk.foundationmodels</groupId> | ||
| <artifactId>sap-rpt</artifactId> | ||
| <name>SAP RPT Model Client</name> | ||
| <description>SAP Cloud SDK for AI is the official Software Development Kit (SDK) for SAP AI Core, SAP Generative AI Hub, and Orchestration Service. This is the client for consuming SAP RPT model for in-context learning predictions on tabular data.</description> | ||
| <url>https://github.com/SAP/ai-sdk-java?tab=readme-ov-file#documentation</url> | ||
| <organization> | ||
| <name>SAP SE</name> | ||
| <url>https://www.sap.com</url> | ||
| </organization> | ||
| <licenses> | ||
| <license> | ||
| <name>The Apache Software License, Version 2.0</name> | ||
| <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url> | ||
| </license> | ||
| </licenses> | ||
| <developers> | ||
| <developer> | ||
| <name>SAP</name> | ||
| <email>cloudsdk@sap.com</email> | ||
| <organization>SAP SE</organization> | ||
| <organizationUrl>https://www.sap.com</organizationUrl> | ||
| </developer> | ||
| </developers> | ||
| <scm> | ||
| <connection>scm:git:git://github.com/SAP/ai-sdk-java.git</connection> | ||
| <developerConnection>scm:git:ssh://github.com:SAP/ai-sdk-java.git</developerConnection> | ||
| <url>https://github.com/SAP/ai-sdk-java/tree/main</url> | ||
| </scm> | ||
| <properties> | ||
| <project.rootdir>${project.basedir}/../../</project.rootdir> | ||
| <coverage.complexity>85%</coverage.complexity> | ||
| <coverage.line>86%</coverage.line> | ||
| <coverage.instruction>88%</coverage.instruction> | ||
| <coverage.branch>100%</coverage.branch> | ||
| <coverage.method>85%</coverage.method> | ||
| </properties> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>com.sap.ai.sdk</groupId> | ||
| <artifactId>core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.sap.cloud.sdk.cloudplatform</groupId> | ||
| <artifactId>cloudplatform-connectivity</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.sap.cloud.sdk.datamodel</groupId> | ||
| <artifactId>openapi-core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.springframework</groupId> | ||
| <artifactId>spring-core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.springframework</groupId> | ||
| <artifactId>spring-web</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-annotations</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.google.code.findbugs</groupId> | ||
| <artifactId>jsr305</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.google.guava</groupId> | ||
| <artifactId>guava</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-databind</artifactId> | ||
| </dependency> | ||
| <!-- scope "provided" --> | ||
| <dependency> | ||
| <groupId>org.projectlombok</groupId> | ||
| <artifactId>lombok</artifactId> | ||
| <scope>provided</scope> | ||
| </dependency> | ||
| <!-- scope "test" --> | ||
| <dependency> | ||
| <groupId>org.junit.jupiter</groupId> | ||
| <artifactId>junit-jupiter-api</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.assertj</groupId> | ||
| <artifactId>assertj-core</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.wiremock</groupId> | ||
| <artifactId>wiremock</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.sap.cloud.sdk.cloudplatform</groupId> | ||
| <artifactId>connectivity-apache-httpclient5</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.httpcomponents.client5</groupId> | ||
| <artifactId>httpclient5</artifactId> | ||
| </dependency> | ||
| </dependencies> | ||
| <profiles> | ||
| <profile> | ||
| <id>generate</id> | ||
| <activation> | ||
| <activeByDefault>false</activeByDefault> | ||
| <property> | ||
| <name>generate</name> | ||
| </property> | ||
| </activation> | ||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>com.sap.cloud.sdk.datamodel</groupId> | ||
| <artifactId>openapi-generator-maven-plugin</artifactId> | ||
| <configuration> | ||
| <outputDirectory>${project.basedir}/src/main/java</outputDirectory> | ||
| <enableOneOfAnyOfGeneration>true</enableOneOfAnyOfGeneration> | ||
| <compileScope>COMPILE</compileScope> | ||
| <deleteOutputDirectory>true</deleteOutputDirectory> | ||
| </configuration> | ||
| <executions> | ||
| <execution> | ||
| <id>sap-rpt</id> | ||
| <goals> | ||
| <goal>generate</goal> | ||
| </goals> | ||
| <phase>generate-sources</phase> | ||
| <configuration> | ||
| <inputSpec>${project.basedir}/src/main/resources/spec/sap-rpt-1_openapi.json</inputSpec> | ||
| <modelPackage>com.sap.ai.sdk.foundationmodels.rpt.generated.model</modelPackage> | ||
| <apiPackage>com.sap.ai.sdk.foundationmodels.rpt.generated.client</apiPackage> | ||
| <generateApis>true</generateApis> | ||
| <additionalProperties> | ||
| <pojoBuilderMethodName>create</pojoBuilderMethodName> | ||
| <enumUnknownDefaultCase>true</enumUnknownDefaultCase> | ||
| <useOneOfInterfaces>true</useOneOfInterfaces> | ||
| <useOneOfCreators>true</useOneOfCreators> | ||
| <useFloatArrays>true</useFloatArrays> | ||
| <excludePaths>/predict_parquet</excludePaths> | ||
| </additionalProperties> | ||
| </configuration> | ||
| </execution> | ||
| </executions> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </profile> | ||
| </profiles> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| package com.sap.ai.sdk.foundationmodels.rpt; | ||
|
|
||
| import static com.sap.ai.sdk.core.JacksonConfiguration.getDefaultObjectMapper; | ||
|
|
||
| import com.google.common.collect.Iterables; | ||
| import com.sap.ai.sdk.core.AiCoreService; | ||
| import com.sap.ai.sdk.core.DeploymentResolutionException; | ||
| import com.sap.ai.sdk.foundationmodels.rpt.generated.client.DefaultApi; | ||
| import com.sap.ai.sdk.foundationmodels.rpt.generated.model.PredictRequestPayload; | ||
| import com.sap.ai.sdk.foundationmodels.rpt.generated.model.PredictResponsePayload; | ||
| import com.sap.cloud.sdk.cloudplatform.connectivity.ApacheHttpClient5Accessor; | ||
| import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; | ||
| import com.sap.cloud.sdk.services.openapi.apiclient.ApiClient; | ||
| import javax.annotation.Nonnull; | ||
| import lombok.AccessLevel; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.val; | ||
| import org.springframework.http.client.BufferingClientHttpRequestFactory; | ||
| import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; | ||
| import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | ||
| import org.springframework.web.client.RestTemplate; | ||
|
|
||
| /** | ||
| * Client for interacting with SAP RPT foundation models. | ||
| * | ||
| * @since 1.16.0 | ||
| */ | ||
| @RequiredArgsConstructor(access = AccessLevel.PRIVATE) | ||
| public class RptClient { | ||
| @Nonnull private final DefaultApi api; | ||
|
|
||
| /** | ||
| * Creates a new RptClient for the specified foundation model. | ||
| * | ||
| * @param foundationModel The foundation model to use. | ||
| * @return A new instance of RptClient. | ||
| * @throws DeploymentResolutionException If there is an error resolving the deployment. | ||
| */ | ||
| @Nonnull | ||
| public static RptClient forModel(@Nonnull final RptModel foundationModel) | ||
| throws DeploymentResolutionException { | ||
| final var destination = new AiCoreService().getInferenceDestination().forModel(foundationModel); | ||
| return forDestination(destination); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new RptClient for the specified destination. | ||
| * | ||
| * @param destination The destination to use. | ||
| * @return A new instance of RptClient. | ||
| */ | ||
| static RptClient forDestination(@Nonnull final Destination destination) { | ||
| // This is a workaround to override the object mapper to ignore null on serialization | ||
| val httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); | ||
| httpRequestFactory.setHttpClient(ApacheHttpClient5Accessor.getHttpClient(destination)); | ||
| final var rt = new RestTemplate(); | ||
| Iterables.filter(rt.getMessageConverters(), MappingJackson2HttpMessageConverter.class) | ||
| .forEach(converter -> converter.setObjectMapper(getDefaultObjectMapper())); | ||
| rt.setRequestFactory(new BufferingClientHttpRequestFactory(httpRequestFactory)); | ||
|
|
||
| final var apiClient = new ApiClient(rt).setBasePath(destination.asHttp().getUri().toString()); | ||
| return new RptClient(new DefaultApi(apiClient)); | ||
| } | ||
|
|
||
| /** | ||
| * Predict targets using SAP RPT model with structured data. * | ||
| * | ||
| * <p><b>200</b> - Successful response with predictive insights. | ||
| * | ||
| * <p><b>400</b> - Bad Request - Invalid input. | ||
| * | ||
| * <p><b>422</b> - Unprocessable Content - Invalid input. | ||
| * | ||
| * <p><b>500</b> - Internal Server Error. | ||
| * | ||
| * @param requestBody The prediction request | ||
| * @return prediction response from the RPT model | ||
| */ | ||
| @Nonnull | ||
| public PredictResponsePayload tabCompletion(@Nonnull final PredictRequestPayload requestBody) { | ||
| return api.predict(requestBody); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.sap.ai.sdk.foundationmodels.rpt; | ||
|
|
||
| import com.sap.ai.sdk.core.AiModel; | ||
| import javax.annotation.Nonnull; | ||
| import javax.annotation.Nullable; | ||
|
|
||
| /** | ||
| * Represents an SAP RPT foundation model. | ||
| * | ||
| * @param name The name of the model. | ||
| * @param version The version of the model (optional). | ||
| * @since 1.16.0 | ||
| */ | ||
| public record RptModel(@Nonnull String name, @Nullable String version) implements AiModel { | ||
|
|
||
| /** SAP RPT 1 Small model. */ | ||
| public static final RptModel SAP_RPT_1_SMALL = new RptModel("sap-rpt-1-small", null); | ||
|
|
||
| /** SAP RPT 1 Large model. */ | ||
| public static final RptModel SAP_RPT_1_LARGE = new RptModel("sap-rpt-1-large", null); | ||
|
|
||
| /** | ||
| * Create a new instance of RptModel with the provided version. | ||
| * | ||
| * @param version The version of the model. | ||
| * @return The new instance of RptModel. | ||
| */ | ||
| @Nonnull | ||
| public RptModel withVersion(@Nonnull final String version) { | ||
| return new RptModel(name, version); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| package com.sap.ai.sdk.foundationmodels.rpt.generated.client; | ||
|
|
||
| import com.google.common.annotations.Beta; | ||
| import com.sap.ai.sdk.foundationmodels.rpt.generated.model.PredictRequestPayload; | ||
| import com.sap.ai.sdk.foundationmodels.rpt.generated.model.PredictResponsePayload; | ||
| import com.sap.cloud.sdk.cloudplatform.connectivity.Destination; | ||
| import com.sap.cloud.sdk.services.openapi.apiclient.ApiClient; | ||
| import com.sap.cloud.sdk.services.openapi.core.AbstractOpenApiService; | ||
| import com.sap.cloud.sdk.services.openapi.core.OpenApiRequestException; | ||
| import java.util.List; | ||
| import javax.annotation.Nonnull; | ||
| import org.springframework.core.ParameterizedTypeReference; | ||
| import org.springframework.http.HttpHeaders; | ||
| import org.springframework.http.HttpMethod; | ||
| import org.springframework.http.MediaType; | ||
| import org.springframework.util.LinkedMultiValueMap; | ||
| import org.springframework.util.MultiValueMap; | ||
| import org.springframework.web.util.UriComponentsBuilder; | ||
|
|
||
| /** | ||
| * SAP-RPT-1 Tabular AI in version 0.1.0. | ||
| * | ||
| * <p>A REST API for in-context learning with the SAP-RPT-1 model. | ||
| */ | ||
| public class DefaultApi extends AbstractOpenApiService { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Minor/Question) This is a very non-descriptive class name (which does not come from the spec itself as far as I can see). Does it make sense to rename that when generating?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the spec is currently missing a |
||
| /** | ||
| * Instantiates this API class to invoke operations on the SAP-RPT-1 Tabular AI. | ||
| * | ||
| * @param httpDestination The destination that API should be used with | ||
| */ | ||
| public DefaultApi(@Nonnull final Destination httpDestination) { | ||
| super(httpDestination); | ||
| } | ||
|
|
||
| /** | ||
| * Instantiates this API class to invoke operations on the SAP-RPT-1 Tabular AI based on a given | ||
| * {@link ApiClient}. | ||
| * | ||
| * @param apiClient ApiClient to invoke the API on | ||
| */ | ||
| @Beta | ||
| public DefaultApi(@Nonnull final ApiClient apiClient) { | ||
| super(apiClient); | ||
| } | ||
|
|
||
| /** | ||
| * Make in-context predictions for specified target columns based on provided table data JSON | ||
| * (optionally gzip-compressed). | ||
| * | ||
| * <p>Make in-context predictions for specified target columns. Either \"rows\" or | ||
| * \"columns\" must be provided and must contain both context and query rows. You can | ||
| * optionally send gzip-compressed JSON payloads and set a \"Content-Encoding: gzip\" | ||
| * header. | ||
| * | ||
| * <p><b>200</b> - Successful Prediction | ||
| * | ||
| * <p><b>400</b> - Bad Request - Invalid input data | ||
| * | ||
| * <p><b>413</b> - Payload Too Large | ||
| * | ||
| * <p><b>422</b> - Validation Error | ||
| * | ||
| * <p><b>500</b> - Internal Server Error | ||
| * | ||
| * @param predictRequestPayload The value for the parameter predictRequestPayload | ||
| * @return PredictResponsePayload | ||
| * @throws OpenApiRequestException if an error occurs while attempting to invoke the API | ||
| */ | ||
| @Nonnull | ||
| public PredictResponsePayload predict(@Nonnull final PredictRequestPayload predictRequestPayload) | ||
| throws OpenApiRequestException { | ||
| final Object localVarPostBody = predictRequestPayload; | ||
|
|
||
| // verify the required parameter 'predictRequestPayload' is set | ||
| if (predictRequestPayload == null) { | ||
| throw new OpenApiRequestException( | ||
| "Missing the required parameter 'predictRequestPayload' when calling predict"); | ||
| } | ||
|
|
||
| final String localVarPath = UriComponentsBuilder.fromPath("/predict").build().toUriString(); | ||
|
|
||
| final MultiValueMap<String, String> localVarQueryParams = | ||
| new LinkedMultiValueMap<String, String>(); | ||
| final HttpHeaders localVarHeaderParams = new HttpHeaders(); | ||
| final MultiValueMap<String, Object> localVarFormParams = | ||
| new LinkedMultiValueMap<String, Object>(); | ||
|
|
||
| final String[] localVarAccepts = {"application/json"}; | ||
| final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); | ||
| final String[] localVarContentTypes = {"application/json"}; | ||
| final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); | ||
|
|
||
| final String[] localVarAuthNames = new String[] {}; | ||
|
|
||
| final ParameterizedTypeReference<PredictResponsePayload> localVarReturnType = | ||
| new ParameterizedTypeReference<PredictResponsePayload>() {}; | ||
| return apiClient.invokeAPI( | ||
| localVarPath, | ||
| HttpMethod.POST, | ||
| localVarQueryParams, | ||
| localVarPostBody, | ||
| localVarHeaderParams, | ||
| localVarFormParams, | ||
| localVarAccept, | ||
| localVarContentType, | ||
| localVarAuthNames, | ||
| localVarReturnType); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Question)
Can we use the new generator without spring dependencies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I am working on the related cloud sdk item to fix spring optionality first. Then, later make use of the same in the new module client