diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d704d2f7..39fb37ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,9 +2,11 @@ ## Code of Conduct -All members of the project community must abide by the [SAP Open Source Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md). +All members of the project community must abide by +the [SAP Open Source Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md). Only by respecting each other we can develop a productive, collaborative community. -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting [a project maintainer](.reuse/dep5). +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by +contacting [a project maintainer](.reuse/dep5). ## Engaging in Our Project @@ -12,19 +14,27 @@ We use GitHub to manage reviews of pull requests. * If you are a new contributor, see: [Steps to Contribute](#steps-to-contribute) -* Before implementing your change, create an issue that describes the problem you would like to solve or the code that should be enhanced. Please note that you are willing to work on that issue. +* Before implementing your change, create an issue that describes the problem you would like to solve or the code that + should be enhanced. Please note that you are willing to work on that issue. -* The team will review the issue and decide whether it should be implemented as a pull request. In that case, they will assign the issue to you. If the team decides against picking up the issue, the team will post a comment with an explanation. +* The team will review the issue and decide whether it should be implemented as a pull request. In that case, they will + assign the issue to you. If the team decides against picking up the issue, the team will post a comment with an + explanation. ## Contributing with AI-generated code -As artificial intelligence evolves, AI-generated code is becoming valuable for many software projects, including open-source initiatives. While we recognize the potential benefits of incorporating AI-generated content into our open-source projects there a certain requirements that need to be reflected and adhered to when making contributions. +As artificial intelligence evolves, AI-generated code is becoming valuable for many software projects, including +open-source initiatives. While we recognize the potential benefits of incorporating AI-generated content into our +open-source projects there a certain requirements that need to be reflected and adhered to when making contributions. -Please see our [guideline for AI-generated code contributions to SAP Open Source Software Projects](https://github.com/SAP/.github/blob/main/CONTRIBUTING_USING_GENAI.md) for these requirements. +Please see +our [guideline for AI-generated code contributions to SAP Open Source Software Projects](https://github.com/SAP/.github/blob/main/CONTRIBUTING_USING_GENAI.md) +for these requirements. ## Steps to Contribute -Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on. This is to prevent duplicated efforts from other contributors on the same issue. +Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on. +This is to prevent duplicated efforts from other contributors on the same issue. If you have questions about one of the issues, please comment on them, and one of the maintainers will clarify. @@ -35,10 +45,20 @@ You are welcome to contribute code in order to fix a bug or to implement a new f The following rule governs code contributions: * Contributions must be licensed under the [Apache 2.0 License](./LICENSE) -* Due to legal reasons, contributors will be asked to accept a Developer Certificate of Origin (DCO) when they create the first pull request to this project. This happens in an automated fashion during the submission process. SAP uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). +* Due to legal reasons, contributors will be asked to accept a Developer Certificate of Origin (DCO) when they create + the first pull request to this project. This happens in an automated fashion during the submission process. SAP + uses [the standard DCO text of the Linux Foundation](https://developercertificate.org/). + +### Set-up Formatting + +- It's recommended to install + the [Google Java Format plugin for IntelliJ](https://plugins.jetbrains.com/plugin/8527-google-java-format), while + following + these [instructions](https://github.com/google/google-java-format?tab=readme-ov-file#intellij-android-studio-and-other-jetbrains-ides). ## Issues and Planning * We use GitHub issues to track bugs and enhancement requests. -* Please provide as much context as possible when you open an issue. The information you provide must be comprehensive enough to reproduce that issue for the assignee. +* Please provide as much context as possible when you open an issue. The information you provide must be comprehensive + enough to reproduce that issue for the assignee. diff --git a/README.md b/README.md index 882b34b0..00d77177 100644 --- a/README.md +++ b/README.md @@ -5,520 +5,239 @@ # SAP Cloud SDK for AI (for Java) -# ⚠️ This is a pre-alpha version of the AI SDK for Java. The APIs are subject to change ⚠️ +> ⚠️ **This is a pre-alpha version of the AI SDK for Java. The APIs are subject to change.** ⚠️ -## About this project +## Table of Contents -Integrate chat completion into your business applications with SAP Cloud SDK for GenAI Hub. Leverage the Generative AI Hub of SAP AI Core to make use of templating, grounding, data masking, content filtering and more. Set up your SAP AI Core instance with SAP Cloud SDK for AI Core. +- [Introduction](#introduction) +- [General Requirements](#general-requirements) +- [Connecting to SAP AI Core](#connecting-to-sap-ai-core) + - [Option 1: Set Credentials as Environment Variable](#option-1-set-credentials-as-environment-variable) + - [Option 2: Regular Service Binding in SAP BTP Cloud Foundry](#option-2-regular-service-binding-in-sap-btp-cloud-foundry) + - [Option 3: Define and Use a Destination](#option-3-define-and-use-a-destination) +- [Getting Started](#getting-started) + - [What You'll Build](#what-youll-build) + - [Prerequisites](#prerequisites) + - [Write the Code](#write-the-code) + - [Run and Test the Application Locally](#run-and-test-the-application-locally) + - [Deploying to Cloud Foundry (Optional)](#deploying-to-cloud-foundry-optional) +- [Documentation](#documentation) +- [FAQs](#faqs) +- [Contribute, Support and Feedback](#contribute-support-and-feedback) +- [Security / Disclosure](#security--disclosure) +- [Code of Conduct](#code-of-conduct) +- [Licensing](#licensing) -## List of available and tested APIs +## Introduction -We maintain [a list of currently available and tested AI Core APIs](docs/list-of-tested-APIs.md) +Welcome to the **SAP Cloud SDK for AI (for Java)**. +This SDK enables developers to seamlessly integrate AI capabilities, such as chat completion, into their Java-based business applications using SAP's Generative AI Hub. +Leverage powerful features like templating, grounding, data masking, and content filtering to build intelligent applications. +The SDK simplifies the setup and interaction with SAP AI Core, allowing you to focus on delivering value through AI integration. -# Documentation +## General Requirements -## AI Core Deployment +To use the SAP AI SDK for Java, the following general prerequisites must be met: -### Prerequisites +- **Java Development Kit (JDK) 17** or higher installed. +- **Apache Maven 3.9** or higher installed. +- **SAP AI Core Service** enabled in your SAP BTP account. + - [How to enable the AI Core service](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/initial-setup) +- **SAP AI Core Credentials** to access the AI Core service. + - [Connecting to SAP AI Core](#connecting-to-sap-ai-core) +- **(Optional) Spring Boot** version 3 or higher if you are using Spring Boot. -- The AI Core service in BTP - - [How to enable the AI Core service](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/initial-setup) -- Created a configuration in AI Core - -
- An example configuration from the AI Core /configuration endpoint -
-    {
-      "createdAt": "2024-07-03T12:44:08Z",
-      "executableId": "azure-openai",
-      "id": "12345-123-123-123-123456abcdefg",
-      "inputArtifactBindings": [],
-      "name": "gpt-35-turbo",
-      "parameterBindings": [
-        {
-          "key": "modelName",
-          "value": "gpt-35-turbo"
-        },
-        {
-          "key": "modelVersion",
-          "value": "latest"
-        }
-      ],
-      "scenarioId": "foundation-models"
-    }
-    
-
-- A Java project with a Maven `pom.xml` - - Java 17 or higher - - Maven 3.9 or higher - - if Spring Boot is used, then minimum version 3 -- [Set the AI Core credentials as an environment variable for local testing](#set-credentials-as-dedicated-environment-variable) - -### Maven dependencies - -Add the following dependencies to your `pom.xml` file: - -```xml - - - com.sap.ai.sdk - core - ${ai-sdk.version} - - -``` +See [an example `pom.xml` in our Spring Boot application](sample-code/spring-app/pom.xml). -See [an example pom in our Spring Boot application](sample-code/spring-app/pom.xml) +## Connecting to SAP AI Core -### Create a Deployment +To interact with SAP AI Core services, the SAP AI SDK requires credentials available at application runtime. +By default, the SDK automatically extracts these credentials from a service instance of type `aicore` bound to your application. -```java -public AiDeploymentCreationResponse createDeployment() { +If running the application locally without this service binding, you may encounter an exception: - final AiDeploymentCreationResponse deployment = - new DeploymentApi(getClient()) - .create( - "default", - AiDeploymentCreationRequest.create() - .configurationId("12345-123-123-123-123456abcdefg")); +``` +Could not find any matching service bindings for service identifier 'aicore' +``` - String id = deployment.getId(); - AiExecutionStatus status = deployment.getStatus(); +There are multiple ways to provide these credentials: - return deployment; -} -``` +| Option | Description | +|--------|----------------------------------------------------------------------------------------------------------| +| **1** | Set an environment variable explicitly: `AICORE_SERVICE_KEY` | +| **2** | Regular service binding in SAP BTP Cloud Foundry (results in `VCAP_SERVICES` environment variable entry) | +| **3** | Define and use a _Destination_ in the SAP BTP Destination Service | -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java) +Additional methods (not recommended for production): -### Delete a Deployment +- Use the [hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry) approach for + CAP applications (e.g., `cds bind --to aicore --exec mvn spring-boot:run`) +- Leverage a "user-provided" service binding +- Define and use a custom `ServiceBinding` or `ServiceBindingAccessor` in your application -```java -public AiDeploymentDeletionResponse deleteDeployment(AiDeploymentCreationResponse deployment) { - - DeploymentApi client = new DeploymentApi(getClient()); - - if (deployment.getStatus() == AiExecutionStatus.RUNNING) { - // Only RUNNING deployments can be STOPPED - client.modify( - "default", - deployment.getId(), - AiDeploymentModificationRequest.create().targetStatus(AiDeploymentTargetStatus.STOPPED)); - } - // Wait a few seconds for the deployment to stop - // Only UNKNOWN and STOPPED deployments can be DELETED - return client.delete("default", deployment.getId()); -} -``` +### Option 1: Set Credentials as Environment Variable -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java) +
+Click to view detailed steps -## OpenAI chat completion -### Prerequisites +**1. Obtain Service Credentials:** -- A deployed OpenAI model in AI Core. - - [How to deploy a model to AI Core](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-generative-ai-model-in-sap-ai-core) - -
- An example deployed model from the AI Core /deployments endpoint -
-    {
-      "id": "d123456abcdefg",
-      "deploymentUrl": "https://api.ai.region.aws.ml.hana.ondemand.com/v2/inference/deployments/d123456abcdefg",
-      "configurationId": "12345-123-123-123-123456abcdefg",
-      "configurationName": "gpt-35-turbo",
-      "scenarioId": "foundation-models",
-      "status": "RUNNING",
-      "statusMessage": null,
-      "targetStatus": "RUNNING",
-      "lastOperation": "CREATE",
-      "latestRunningConfigurationId": "12345-123-123-123-123456abcdefg",
-      "ttl": null,
-      "details": {
-        "scaling": {
-          "backendDetails": null,
-          "backend_details": {
-          }
-        },
-        "resources": {
-          "backendDetails": null,
-          "backend_details": {
-            "model": {
-              "name": "gpt-35-turbo",
-              "version": "latest"
-            }
-          }
-        }
-      },
-      "createdAt": "2024-07-03T12:44:22Z",
-      "modifiedAt": "2024-07-16T12:44:19Z",
-      "submissionTime": "2024-07-03T12:44:51Z",
-      "startTime": "2024-07-03T12:45:56Z",
-      "completionTime": null
-    }
-    
-
-- A Java project with a Maven `pom.xml` - - Java 17 or higher - - Maven 3.9 or higher - - if Spring Boot is used, then minimum version 3 -- [Set the AI Core credentials as an environment variable for local testing](#set-credentials-as-dedicated-environment-variable) - -### Maven dependencies - -Add the following dependencies to your `pom.xml` file: - -```xml - - - com.sap.ai.sdk.foundationmodels - openai - ${ai-sdk.version} - - -``` +- Log into the **SAP BTP Cockpit** +- Navigate to **Instances and Subscriptions** -> **Instances** -> **AI Core** +- Click **View Credentials** and copy the JSON content -See [an example pom in our Spring Boot application](sample-code/spring-app/pom.xml) +**2. Set Environment Variable:** -### Simple chat completion +- In your IDE or terminal, set the environment variable `AICORE_SERVICE_KEY` with the copied JSON content -```java -final OpenAiChatCompletionOutput result = - OpenAiClient.forModel(GPT_35_TURBO) - .withSystemPrompt("You are a helpful AI") - .chatCompletion("Hello World! Why is this phrase so famous?"); +Example: -final String resultMessage = result.getContent(); +```shell +export AICORE_SERVICE_KEY='{ "clientid": "...", "clientsecret": "...", "url": "...", "serviceurls": { "AI_API_URL": "..." } }' ``` -### Message history - -```java -final var systemMessage = - new OpenAiChatSystemMessage().setContent("You are a helpful assistant"); -final var userMessage = - new OpenAiChatUserMessage().addText("Hello World! Why is this phrase so famous?"); -final var request = - new OpenAiChatCompletionParameters().addMessages(systemMessage, userMessage); +
-final OpenAiChatCompletionOutput result = - OpenAiClient.forModel(GPT_35_TURBO).chatCompletion(request); +### Option 2: Regular Service Binding in SAP BTP Cloud Foundry -final String resultMessage = result.getContent(); -``` - -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java) +
+Click to view detailed steps -### Chat completion with a model not defined in `OpenAiModel` -```java -final OpenAiChatCompletionOutput result = - OpenAiClient.forModel(new OpenAiModel("model")).chatCompletion(request); -``` +**1. Bind an existing `aicore` service instance to your application** -### Stream chat completion +SAP BTP provides multiple ways to do this: -It's possible to pass a stream of chat completion delta elements, e.g. from the application backend to the frontend in real-time. +- Using the web interface +- Using the CLI +- Using MTA or manifest files -#### Stream the chat completion asynchronously -This is a blocking example for streaming and printing directly to the console: -```java -String msg = "Can you give me the first 100 numbers of the Fibonacci sequence?"; +[Learn more about binding service instances to applications](https://help.sap.com/docs/btp/sap-business-technology-platform/binding-service-instances-to-applications) -OpenAiClient client = OpenAiClient.forModel(GPT_35_TURBO); +After restarting your application, you should see an "aicore" entry in the `VCAP_SERVICES` environment variable: -// try-with-resources on stream ensures the connection will be closed -try( Stream stream = client.streamChatCompletion(msg)) { - stream.forEach(deltaString -> { - System.out.print(deltaString); - System.out.flush(); - }); +```json +{ + "aicore": [ + { + "clientid": "...", + "clientsecret": "...", + "url": "...", + "serviceurls": { + "AI_API_URL": "..." + } + } + ] } ``` -
-It's also possible to aggregate the total output. +
-The following example is non-blocking. -Any asynchronous library can be used, e.g. classic Thread API. +### Option 3: Define and Use a Destination -```java -String msg = "Can you give me the first 100 numbers of the Fibonacci sequence?"; +
+Click to view detailed steps -OpenAiChatCompletionParameters request = - new OpenAiChatCompletionParameters() - .addMessages(new OpenAiChatUserMessage().addText(msg)); +**1. Obtain Service Credentials:** (Same as in Option 1) -OpenAiChatCompletionOutput totalOutput = new OpenAiChatCompletionOutput(); -OpenAiClient client = OpenAiClient.forModel(GPT_35_TURBO); +**2. Create a Destination:** -// Do the request before the thread starts to handle exceptions during request initialization -Stream stream = client.streamChatCompletionDeltas(request); +- In the **SAP BTP Cockpit**, go to **Connectivity** -> **Destinations** +- Click **New Destination** and configure: -Thread thread = new Thread(() -> { - // try-with-resources ensures the stream is closed - try (stream) { - stream.peek(totalOutput::addDelta).forEach(delta -> System.out.println(delta)); - } -}); -thread.start(); // non-blocking + - **Name**: `my-aicore` + - **Type**: `HTTP` + - **URL**: `[serviceurls.AI_API_URL]/v2` (append `/v2` to the URL) + - **Proxy Type**: `Internet` + - **Authentication**: `OAuth2ClientCredentials` + - **Client ID**: `[clientid]` + - **Client Secret**: `[clientsecret]` + - **Token Service URL Type**: `Dedicated` + - **Token Service URL**: `[url]` -thread.join(); // blocking +**3. Use the Destination in Your Application:** -// access aggregated information from total output, e.g. -Integer tokens = totalOutput.getUsage().getCompletionTokens(); -System.out.println("Tokens: " + tokens); +```java +Destination destination = DestinationAccessor.getDestination("my-aicore"); +ApiClient client = Core.getClient(destination); ```
-#### Spring Boot example +## Getting Started -Please find [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java). -It shows the usage of Spring Boot's `ResponseBodyEmitter` to stream the chat completion delta messages to the frontend in real-time. +### What You'll Build -## Orchestration chat completion +In this quickstart, you'll build a simple Spring Boot application that uses the OpenAI GPT-3.5 Turbo model for chat completion. +The application will send a prompt to the AI model and display the generated response. ### Prerequisites -- A deployed Orchestration service in AI Core. - - [Orchestration documentation](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/orchestration) - -
- An example orchestration deployment from the AI Core /deployments endpoint -
-    {
-      "id": "d123456abcdefg",
-      "deploymentUrl": "https://api.ai.intprod-eu12.eu-central-1.aws.ml.hana.ondemand.com/v2/inference/deployments/d123456abcdefg",
-      "configurationId": "12345-123-123-123-123456abcdefg",
-      "configurationName": "orchestration",
-      "scenarioId": "orchestration",
-      "status": "RUNNING",
-      "statusMessage": null,
-      "targetStatus": "RUNNING",
-      "lastOperation": "CREATE",
-      "latestRunningConfigurationId": "12345-123-123-123-123456abcdefg",
-      "ttl": null,
-      "createdAt": "2024-08-05T16:17:29Z",
-      "modifiedAt": "2024-08-06T06:32:50Z",
-      "submissionTime": "2024-08-05T16:17:40Z",
-      "startTime": "2024-08-05T16:18:41Z",
-      "completionTime": null
-    }
-    
-
-- A Java project with a Maven `pom.xml` - - Java 17 or higher - - Maven 3.9 or higher - - if Spring Boot is used, then minimum version 3 -- [Set the AI Core credentials as an environment variable for local testing](#set-credentials-as-dedicated-environment-variable) - -### Maven dependencies - -Add the following dependencies to your `pom.xml` file: - -```xml - - - com.sap.ai.sdk - orchestration - ${ai-sdk.version} - - -``` +Before you begin, ensure you have: -See [an example pom in our Spring Boot application](sample-code/spring-app/pom.xml) +- Met the [General Requirements](#general-requirements). +- Met the OpenAI Chat Completion module specific requirements + - Refer to [Prerequisites for OpenAI Chat Completion](docs/guides/OPENAI_CHAT_COMPLETION.md#prerequisites) +- Set up the AI Core credentials + using [(1) Environment Variable](#option-1-set-credentials-as-environment-variable) + or [(2) Regular Service Binding](#option-2-regular-service-binding-in-sap-btp-cloud-foundry). +- Deployed the OpenAI GPT-3.5 Turbo model in SAP AI Core. + - Refer to [Deploying the OpenAI GPT-3.5 Turbo Model](docs/guides/OPENAI_CHAT_COMPLETION.md#usage) -### Chat completion template - -```java -final var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); - -final var inputParams = - Map.of("input", "Reply with 'Orchestration Service is working!' in German"); -final var template = ChatMessage.create().role("user").content("{{?input}}"); -final var templatingConfig = TemplatingModuleConfig.create().template(template); - -final var config = - CompletionPostRequest.create() - .orchestrationConfig( - OrchestrationConfig.create() - .moduleConfigurations( - ModuleConfigs.create() - .llmModuleConfig(llmConfig) - .templatingModuleConfig(templatingConfig))) - .inputParams(inputParams); - -final CompletionPostResponse result = - new OrchestrationCompletionApi(getOrchestrationClient("default")) - .orchestrationV1EndpointsCreate(config); - -final String messageResult = - result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); -``` +### Write the Code -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) - -### Messages history +Add the following code to the controller or service class in your Spring Boot application: ```java -final var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); - -List messagesHistory = - List.of( - ChatMessage.create().role("user").content("What is the capital of France?"), - ChatMessage.create().role("assistant").content("The capital of France is Paris.")); - -final var message = - ChatMessage.create().role("user").content("What is the typical food there?"); -final var templatingConfig = TemplatingModuleConfig.create().template(message); - -final var config = - CompletionPostRequest.create() - .orchestrationConfig( - OrchestrationConfig.create() - .moduleConfigurations( - ModuleConfigs.create() - .llmModuleConfig(llmConfig) - .templatingModuleConfig(templatingConfig))) - .inputParams(Map.of()) - .messagesHistory(messagesHistory); - -final CompletionPostResponse result = - new OrchestrationCompletionApi(getOrchestrationClient("default")) - .orchestrationV1EndpointsCreate(config); - -final String messageResult = - result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); +// Initialize the client for GPT-3.5 Turbo model +OpenAiClient client = OpenAiClient.forModel(OpenAiModel.GPT_35_TURBO); + +// Perform chat completion +OpenAiChatCompletionOutput result = + client + .withSystemPrompt("You are a helpful assistant.") + .chatCompletion("Hello World! Why is this phrase so famous?"); ``` -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) +### Run and Test the Application Locally -### Chat completion filter +Then, compile and run your application: -```java -final var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); - -final var inputParams = - Map.of( - "disclaimer", - "```DISCLAIMER: The area surrounding the apartment is known for prostitutes and gang violence including armed conflicts, gun violence is frequent."); -final var template = - ChatMessage.create() - .role("user") - .content( - "Create a rental posting for subletting my apartment in the downtown area. Keep it short. Make sure to add the following disclaimer to the end. Do not change it! {{?disclaimer}}"); -final var templatingConfig = TemplatingModuleConfig.create().template(template); - -final var filterStrict = - FilterConfig.create() - .type(FilterConfig.TypeEnum.AZURE_CONTENT_SAFETY) - .config( - AzureContentSafety.create() - .hate(NUMBER_0) - .selfHarm(NUMBER_0) - .sexual(NUMBER_0) - .violence(NUMBER_0)); - -final var filterLoose = - FilterConfig.create() - .type(FilterConfig.TypeEnum.AZURE_CONTENT_SAFETY) - .config( - AzureContentSafety.create() - .hate(NUMBER_4) - .selfHarm(NUMBER_4) - .sexual(NUMBER_4) - .violence(NUMBER_4)); - -final var filteringConfig = - FilteringModuleConfig.create() - // changing the input to filterLoose will allow the message to pass - .input(FilteringConfig.create().filters(filterStrict)) - .output(FilteringConfig.create().filters(filterStrict)); - -final var config = - CompletionPostRequest.create() - .orchestrationConfig( - OrchestrationConfig.create() - .moduleConfigurations( - ModuleConfigs.create() - .llmModuleConfig(llmConfig) - .templatingModuleConfig(templatingConfig) - .filteringModuleConfig(filteringConfig))) - .inputParams(inputParams); - -final CompletionPostResponse result = - new OrchestrationCompletionApi(getOrchestrationClient("default")) - // this fails with Bad Request because the strict filter prohibits the input message - .orchestrationV1EndpointsCreate(config); - -final String messageResult = - result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); -``` +```shell +cd your-spring-app/ -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) +mvn compile +mvn spring-boot:run +``` -### Data masking +### Deploying to Cloud Foundry (Optional) -In the following example we use the data masking module to anonymize persons and phone numbers in the input. +When deploying your productive application to Cloud Foundry, it is recommended to use **service binding** to provide the AI Core credentials as per [Option 2](#option-2-regular-service-binding-in-sap-btp-cloud-foundry). -In this case, the input will be masked before the call to the LLM. However, data can not be unmasked in the LLM output. +Build your application using Maven and deploy it to Cloud Foundry: -```java -final var inputParams = Map.of("privateInfo", "Patrick Morgan +49 (970) 333-3833"); -final var template = - ChatMessage.create().role("user").content("What is the nationality of {{?privateInfo}}"); -final var templatingConfig = TemplatingModuleConfig.create().template(template); - -final var maskingProvider = - MaskingProviderConfig.create() - .type(MaskingProviderConfig.TypeEnum.SAP_DATA_PRIVACY_INTEGRATION) - .method(MaskingProviderConfig.MethodEnum.ANONYMIZATION) - .entities( - DPIEntityConfig.create().type(DPIEntities.PHONE), - DPIEntityConfig.create().type(DPIEntities.PERSON)); -final var maskingConfig = MaskingModuleConfig.create().maskingProviders(maskingProvider); - -final CompletionPostRequest config = - CompletionPostRequest.create() - .orchestrationConfig( - OrchestrationConfig.create() - .moduleConfigurations( - ModuleConfigs.create() - .llmModuleConfig(LLM_CONFIG) - .templatingModuleConfig(templatingConfig) - .maskingModuleConfig(maskingConfig))) - .inputParams(inputParams); - -final CompletionPostResponse result = - new OrchestrationCompletionApi(getOrchestrationClient("default")) - .orchestrationV1EndpointsCreate(config); - -final String messageResult = - result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); -``` + ```shell + cf push + ``` -See [an example in our Spring Boot application](sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) +That's it! +Your application should now be running on Cloud Foundry, and the AI Core credentials are provided securely via service binding. -### Set model parameters +## Documentation -Change your LLM module configuration to add model parameters: +For more detailed information and advanced usage, please refer to the following: -```java -var llmConfig = - LLMModuleConfig.create() - .modelName("gpt-35-turbo") - .modelParams( - Map.of( - "max_tokens", 50, - "temperature", 0.1, - "frequency_penalty", 0, - "presence_penalty", 0)); -``` +- [OpenAI Chat Completion](docs/guides/OPENAI_CHAT_COMPLETION.md) +- [Orchestration Chat Completion](docs/guides/ORCHESTRATION_CHAT_COMPLETION.md) +- [AI Core Deployment](docs/guides/AI_CORE_DEPLOYMENT.md) -See [an example in our unit test](orchestration/src/test/java/com/sap/ai/sdk/orchestration/client/OrchestrationUnitTest.java) +## FAQs -## Add a header to every request +### How to add a custom header to AI Core requests? To add a header to AI Core requests, use the following code: + ```java ApiClient client = Core.getClient().addDefaultHeader("header-key", "header-value"); DeploymentApi api = new DeploymentApi(client); @@ -526,120 +245,29 @@ DeploymentApi api = new DeploymentApi(client); For more customization, creating a [HeaderProvider](https://sap.github.io/cloud-sdk/docs/java/features/connectivity/http-destinations#about-headerproviders) is also possible. -## Requirements and Setup for AI Core - -For any AI Core service interaction, the SAP AI SDK requires credentials to be available at application runtime. -By default, the credentials are extracted automatically from a service instance of type "aicore" bound to the application. -Running the application locally without this service binding will throw an exception: - -``` -Could not find any matching service bindings for service identifier 'aicore' -``` - -There are multiple options to register the service binding: -* Regular service binding in SAP BTP Cloud Foundry (resulting in `VCAP_SERVICES` env var entry). -* Set an environment variable explicitly: `AICORE_SERVICE_KEY` -* Define and use a _Destination_ in _BTP Destination Service_. -* (For CAP applications) use the [hybrid testing](https://cap.cloud.sap/docs/advanced/hybrid-testing#services-on-cloud-foundry) approach _(not recommended for production)_. - * For example: `cds bind --to aicore --exec mvn spring-boot:run` -* Leveraging `"user-provided"` service binding _(not recommended for production)_. -* Define and use a custom `ServiceBinding` or `ServiceBindingAccessor` declaration in application _(not recommended for production)_. - -### Regular service binding in SAP BTP Cloud Foundry - -* Bind an existing service instance of type `aicore` to your application. - [With SAP BTP multiple options are available](https://help.sap.com/docs/btp/sap-business-technology-platform/binding-service-instances-to-applications): using the web interface, the CLI, MTA or manifest. - -
After application restart, there should be an "aicore" entry in environment variable VCAP_SERVICES. - -```json -{ - "aicore": [ - { - "clientid": "...", - "clientsecret": "...", - "url": "...", - "identityzone": "...", - "identityzoneid": "...", - "appname": "...", - "serviceurls": { - "AI_API_URL": "..." - } - } - ] -} -``` - -
- -### Set credentials as dedicated environment variable - -- Go into the SAP BTP Cockpit -- Instances and Subscriptions -> Instances -> AI Core -> View Credentials -> Copy JSON -- Set it as an environment variable `AICORE_SERVICE_KEY` in your IDE - - Or in your terminal: -```shell -export AICORE_SERVICE_KEY='{ "serviceurls": { "AI_API_URL": ...' -``` - -### Define and use a Destination - -* Lookup service-key credentials as explained in the previous step for `AICORE_SERVICE_KEY`. - -*
Define a new destination in the SAP BTP Destination Service using the service-key credentials - - * (Destinations can be added on subaccount level and on service instance level.) - * (The URL field requires an additional path segment: `/v2`) - * **Name**: _my-aicore_ - * **Type**: HTTP - * **URL**: _[serviceurls.AI_API_URL]/v2_ - * **Proxy-Type**: Internet - * **Authentication**: _Oauth2ClientCredentials_ - * **Client ID**: _[clientid]_ - * **Client Secret**: _[clientsecret]_ - * **Token Service URL Type**: Dedicated - * **Token Service URL**: _[url]_ - -
- -* At application runtime the following can be executed: - ```java - Destination destination = DestinationAccessor.getDestination("my-aicore"); - ApiClient client = Core.getClient(destination); - ``` - -### Run the Spring Boot test application - -```shell -cd sample-code/spring-app -mvn spring-boot:run -``` - -### Deploy to Cloud Foundry - -```shell -mvn clean package -cf push -``` - -# Contribute +### More Examples -### Set-up Formatting +Explore example applications and code snippets: -- Install the Google Java Format plugin on Intellij and follow these [instructions](https://github.com/google/google-java-format?tab=readme-ov-file#intellij-android-studio-and-other-jetbrains-ides). +- [Spring Boot Application Example](sample-code/spring-app) -## Support, Feedback, Contributing +## Contribute, Support and Feedback -This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/ai-sdk-java/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md). +This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/ai-sdk-java/issues). +Contribution and feedback are encouraged and always welcome. +For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md). ## Security / Disclosure -If you find any bug that may be a security problem, please follow our instructions at [in our security policy](https://github.com/SAP/ai-sdk-java/security/policy) on how to report it. Please do not create GitHub issues for security-related doubts or problems. + +If you find any bug that may be a security problem, please follow our instructions at [in our security policy](https://github.com/SAP/ai-sdk-java/security/policy) on how to report it. +Please do not create GitHub issues for security-related doubts or problems. ## Code of Conduct -We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md) at all times. +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. +By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/SAP/.github/blob/main/CODE_OF_CONDUCT.md) at all times. ## Licensing -Copyright 2024 SAP SE or an SAP affiliate company and ai-sdk-java contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/ai-sdk-java). +Copyright 2024 SAP SE or an SAP affiliate company and ai-sdk-java contributors. Please see our [LICENSE](LICENSE) for copyright and license information. +Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/ai-sdk-java). diff --git a/docs/guides/AI_CORE_DEPLOYMENT.md b/docs/guides/AI_CORE_DEPLOYMENT.md new file mode 100644 index 00000000..cf891ab4 --- /dev/null +++ b/docs/guides/AI_CORE_DEPLOYMENT.md @@ -0,0 +1,104 @@ +# AI Core Deployment + +## Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) + - [Maven Dependencies](#maven-dependencies) +- [Usage](#usage) + - [Create a Deployment](#create-a-deployment) + - [Delete a Deployment](#delete-a-deployment) + +## Introduction + +This guide provides examples on how to create and manage deployments in SAP AI Core using the SAP AI SDK for Java. + +## Prerequisites + +Before using the AI Core module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements). +Additionally, include the necessary Maven dependency in your project. + +### Maven Dependencies + +Add the following dependency to your `pom.xml` file: + +```xml + + com.sap.ai.sdk + core + ${ai-sdk.version} + +``` + +See [an example pom in our Spring Boot application](../../sample-code/spring-app/pom.xml) + +## Usage + +In addition to the prerequisites above, we assume you have already set up the following to carry out the examples in this guide: + +- **An AI Core Configuration** created in SAP AI Core. + -
+ Example configuration from the AI Core /configuration endpoint + + ```json + { + "createdAt": "2024-07-03T12:44:08Z", + "executableId": "azure-openai", + "id": "12345-123-123-123-123456abcdefg", + "inputArtifactBindings": [], + "name": "gpt-35-turbo", + "parameterBindings": [ + { + "key": "modelName", + "value": "gpt-35-turbo" + }, + { + "key": "modelVersion", + "value": "latest" + } + ], + "scenarioId": "foundation-models" + } + ``` +
+ +### Create a Deployment + +Use the following code snippet to create a deployment in SAP AI Core: + +```java +var api = new DeploymentApi(getClient()); +var resourceGroupId = "default"; + +AiDeploymentCreationRequest request = + AiDeploymentCreationRequest.create().configurationId("12345-123-123-123-123456abcdefg"); +AiDeploymentCreationResponse deployment = api.create(resourceGroupId, request); + +var id = deployment.getId(); +AiExecutionStatus status = deployment.getStatus(); +``` + +Refer to the [DeploymentController.java](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java) in our Spring Boot application for a complete example. + +### Delete a Deployment + +```java +AiDeploymentCreationResponse deployment; // provided +String deploymentId = deployment.getId(); + +var api = new DeploymentApi(getClient()); +var resourceGroupId = "default"; + +if (deployment.getStatus() == AiExecutionStatus.RUNNING) { + // Only RUNNING deployments can be STOPPED + api.modify( + resourceGroupId, + deploymentId, + AiDeploymentModificationRequest.create().targetStatus(AiDeploymentTargetStatus.STOPPED)); +} +// Wait a few seconds for the deployment to stop +// Only UNKNOWN and STOPPED deployments can be DELETED +api.delete(resourceGroupId, deployment.getId()); +``` + +Refer to the [DeploymentController.java](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java) in our Spring Boot application for a complete example. diff --git a/docs/guides/OPENAI_CHAT_COMPLETION.md b/docs/guides/OPENAI_CHAT_COMPLETION.md new file mode 100644 index 00000000..f6ce8604 --- /dev/null +++ b/docs/guides/OPENAI_CHAT_COMPLETION.md @@ -0,0 +1,190 @@ +# OpenAI Chat Completion + +## Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) +- [Maven Dependencies](#maven-dependencies) +- [Usage](#usage) + - [Simple Chat Completion](#simple-chat-completion) + - [Message History](#message-history) + - [Chat Completion with Custom Model](#chat-completion-with-custom-model) + - [Stream Chat Completion](#stream-chat-completion) + - [Asynchronous Streaming](#asynchronous-streaming) + - [Aggregating Total Output](#aggregating-total-output) + - [Spring Boot Example](#spring-boot-example) + +## Introduction + +This guide demonstrates how to use the SAP AI SDK for Java to perform chat completion tasks using OpenAI models deployed on SAP AI Core. + +## Prerequisites + +Before using the AI Core module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements). +Additionally, include the necessary Maven dependency in your project. + +### Maven Dependencies + +Add the following dependency to your `pom.xml` file: + +```xml + + + com.sap.ai.sdk.foundationmodels + openai + ${ai-sdk.version} + + +``` + +See [an example pom in our Spring Boot application](../../sample-code/spring-app/pom.xml) + +## Usage + +In addition to the prerequisites above, we assume you have already set up the following to carry out the examples in this guide: + +- **A Deployed OpenAI Model in SAP AI Core** + - Refer + to [How to deploy a model to AI Core](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-generative-ai-model-in-sap-ai-core) + for setup instructions. + -
+ Example deployed model from the AI Core /deployments endpoint + + ```json + { + "id": "d123456abcdefg", + "deploymentUrl": "https://api.ai.region.aws.ml.hana.ondemand.com/v2/inference/deployments/d123456abcdefg", + "configurationId": "12345-123-123-123-123456abcdefg", + "configurationName": "gpt-35-turbo", + "scenarioId": "foundation-models", + "status": "RUNNING", + "statusMessage": null, + "targetStatus": "RUNNING", + "lastOperation": "CREATE", + "latestRunningConfigurationId": "12345-123-123-123-123456abcdefg", + "ttl": null, + "details": { + "scaling": { + "backendDetails": null, + "backend_details": {} + }, + "resources": { + "backendDetails": null, + "backend_details": { + "model": { + "name": "gpt-35-turbo", + "version": "latest" + } + } + } + }, + "createdAt": "2024-07-03T12:44:22Z", + "modifiedAt": "2024-07-16T12:44:19Z", + "submissionTime": "2024-07-03T12:44:51Z", + "startTime": "2024-07-03T12:45:56Z", + "completionTime": null + } + ``` + +
+ +### Simple chat completion + +```java +OpenAiChatCompletionOutput result = + OpenAiClient.forModel(GPT_35_TURBO) + .withSystemPrompt("You are a helpful AI") + .chatCompletion("Hello World! Why is this phrase so famous?"); + +String resultMessage = result.getContent(); +``` + +### Message history + +```java +var systemMessage = + new OpenAiChatSystemMessage().setContent("You are a helpful assistant"); +var userMessage = + new OpenAiChatUserMessage().addText("Hello World! Why is this phrase so famous?"); +var request = + new OpenAiChatCompletionParameters().addMessages(systemMessage, userMessage); + +OpenAiChatCompletionOutput result = + OpenAiClient.forModel(GPT_35_TURBO).chatCompletion(request); + +String resultMessage = result.getContent(); +``` + +See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java) + +### Chat Completion with Custom Model + +```java +OpenAiChatCompletionOutput result = + OpenAiClient.forModel(new OpenAiModel("model")).chatCompletion(request); +``` + +### Stream chat completion + +It's possible to pass a stream of chat completion delta elements, e.g. from the application backend to the frontend in real-time. + +#### Asynchronous Streaming + +This is a blocking example for streaming and printing directly to the console: + +```java +String msg = "Can you give me the first 100 numbers of the Fibonacci sequence?"; + +OpenAiClient client = OpenAiClient.forModel(GPT_35_TURBO); + +// try-with-resources on stream ensures the connection will be closed +try (Stream stream = client.streamChatCompletion(msg)) { + stream.forEach( + deltaString -> { + System.out.print(deltaString); + System.out.flush(); + }); +} +``` + +#### Aggregating Total Output + +The following example is non-blocking and demonstrates how to aggregate the complete response. +Any asynchronous library can be used, such as the classic Thread API. + +```java +var message = "Can you give me the first 100 numbers of the Fibonacci sequence?"; + +OpenAiChatMessage.OpenAiChatUserMessage userMessage = + new OpenAiChatMessage.OpenAiChatUserMessage().addText(message); +OpenAiChatCompletionParameters requestParameters = + new OpenAiChatCompletionParameters().addMessages(userMessage); + +OpenAiClient client = OpenAiClient.forModel(GPT_35_TURBO); +var totalOutput = new OpenAiChatCompletionOutput(); + +// Prepare the stream before starting the thread to handle any initialization exceptions +Stream stream = + client.streamChatCompletionDeltas(requestParameters); + +var streamProcessor = + new Thread( + () -> { + // try-with-resources ensures the stream is closed after processing + try (stream) { + stream.peek(totalOutput::addDelta).forEach(System.out::println); + } + }); + +streamProcessor.start(); // Start processing in a separate thread (non-blocking) +streamProcessor.join(); // Wait for the thread to finish (blocking) + +// Access aggregated information from total output +Integer tokensUsed = totalOutput.getUsage().getCompletionTokens(); +System.out.println("Tokens used: " + tokensUsed); +``` + +#### Spring Boot example + +Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java). It shows the usage of Spring +Boot's `ResponseBodyEmitter` to stream the chat completion delta messages to the frontend in real-time. diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md new file mode 100644 index 00000000..43b883e1 --- /dev/null +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -0,0 +1,267 @@ +# Orchestration Chat Completion + +## Table of Contents + +- [Introduction](#introduction) +- [Prerequisites](#prerequisites) + - [Maven Dependencies](#maven-dependencies) +- [Usage](#usage) + - [Chat completion with Templates](#chat-completion-with-templates) + - [Message history](#message-history) + - [Chat Completion Filter](#chat-completion-filter) + - [Data Masking](#data-masking) + - [Set Model Parameters](#set-model-parameters) + +## Introduction + +This guide provides examples of how to use the Orchestration service in SAP AI Core for chat completion tasks using the SAP AI SDK for Java. + +## Prerequisites + +Before using the AI Core module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements). +Additionally, include the necessary Maven dependency in your project. + +### Maven Dependencies + +Add the following dependency to your `pom.xml` file: + +```xml + + + com.sap.ai.sdk + orchestration + ${ai-sdk.version} + + +``` + +See [an example `pom.xml` in our Spring Boot application](../../sample-code/spring-app/pom.xml). + +## Usage + +In addition to the prerequisites above, we assume you have already set up the following to carry out the examples in this guide: + +- **A Deployed Orchestration Service in SAP AI Core** + - Refer to the [Orchestration Documentation](https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/orchestration) for setup instructions. + -
+ Example orchestration deployment from the AI Core /deployments endpoint + + ```json + { + "id": "d123456abcdefg", + "deploymentUrl": "https://api.ai.intprod-eu12.eu-central-1.aws.ml.hana.ondemand.com/v2/inference/deployments/d123456abcdefg", + "configurationId": "12345-123-123-123-123456abcdefg", + "configurationName": "orchestration", + "scenarioId": "orchestration", + "status": "RUNNING", + "statusMessage": null, + "targetStatus": "RUNNING", + "lastOperation": "CREATE", + "latestRunningConfigurationId": "12345-123-123-123-123456abcdefg", + "ttl": null, + "createdAt": "2024-08-05T16:17:29Z", + "modifiedAt": "2024-08-06T06:32:50Z", + "submissionTime": "2024-08-05T16:17:40Z", + "startTime": "2024-08-05T16:18:41Z", + "completionTime": null + } + ``` + +
+ +### Chat completion with Templates + +Use a chat completion template to generate a response in German: + +```java +var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); + +var inputParams = + Map.of("input", "Reply with 'Orchestration Service is working!' in German"); +var template = ChatMessage.create().role("user").content("{{?input}}"); +var templatingConfig = TemplatingModuleConfig.create().template(template); + +var config = + CompletionPostRequest.create() + .orchestrationConfig( + OrchestrationConfig.create() + .moduleConfigurations( + ModuleConfigs.create() + .llmModuleConfig(llmConfig) + .templatingModuleConfig(templatingConfig))) + .inputParams(inputParams); + +var resourceGroupId = "default"; +CompletionPostResponse result = + new OrchestrationCompletionApi(getOrchestrationClient(resourceGroupId)) + .orchestrationV1EndpointsCreate(config); + +String messageResult = + result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); +``` + +See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) + +### Message history + +Include a message history to maintain context in the conversation: + +```java +var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); + +List messagesHistory = + List.of( + ChatMessage.create().role("user").content("What is the capital of France?"), + ChatMessage.create().role("assistant").content("The capital of France is Paris.")); + +var message = + ChatMessage.create().role("user").content("What is the typical food there?"); +var templatingConfig = TemplatingModuleConfig.create().template(message); + +var config = + CompletionPostRequest.create() + .orchestrationConfig( + OrchestrationConfig.create() + .moduleConfigurations( + ModuleConfigs.create() + .llmModuleConfig(llmConfig) + .templatingModuleConfig(templatingConfig))) + .inputParams(Map.of()) + .messagesHistory(messagesHistory); + +var resourceGroupId = "default"; +CompletionPostResponse result = + new OrchestrationCompletionApi(getOrchestrationClient(resourceGroupId)) + .orchestrationV1EndpointsCreate(config); + +String messageResult = + result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); +``` + +See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) + +### Chat completion filter + +Apply content filtering to the chat completion: + +```java +var llmConfig = LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()); + +var inputParams = + Map.of( + "disclaimer", + "```DISCLAIMER: The area surrounding the apartment is known for prostitutes and gang violence including armed conflicts, gun violence is frequent."); +var template = + ChatMessage.create() + .role("user") + .content( + "Create a rental posting for subletting my apartment in the downtown area. Keep it short. Make sure to add the following disclaimer to the end. Do not change it! {{?disclaimer}}"); +var templatingConfig = TemplatingModuleConfig.create().template(template); + +var filterStrict = + FilterConfig.create() + .type(FilterConfig.TypeEnum.AZURE_CONTENT_SAFETY) + .config( + AzureContentSafety.create() + .hate(NUMBER_0) + .selfHarm(NUMBER_0) + .sexual(NUMBER_0) + .violence(NUMBER_0)); + +var filterLoose = + FilterConfig.create() + .type(FilterConfig.TypeEnum.AZURE_CONTENT_SAFETY) + .config( + AzureContentSafety.create() + .hate(NUMBER_4) + .selfHarm(NUMBER_4) + .sexual(NUMBER_4) + .violence(NUMBER_4)); + +var filteringConfig = + FilteringModuleConfig.create() + // changing the input to filterLoose will allow the message to pass + .input(FilteringConfig.create().filters(filterStrict)) + .output(FilteringConfig.create().filters(filterStrict)); + +var config = + CompletionPostRequest.create() + .orchestrationConfig( + OrchestrationConfig.create() + .moduleConfigurations( + ModuleConfigs.create() + .llmModuleConfig(llmConfig) + .templatingModuleConfig(templatingConfig) + .filteringModuleConfig(filteringConfig))) + .inputParams(inputParams); + +var resourceGroupId = "default"; +CompletionPostResponse result = + new OrchestrationCompletionApi(getOrchestrationClient(resourceGroupId)) + // this fails with Bad Request because the strict filter prohibits the input message + .orchestrationV1EndpointsCreate(config); + +String messageResult = + result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); +``` + +See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) + +### Data masking + +Use the data masking module to anonymize personal information in the input: + +```java +var inputParams = Map.of("privateInfo", "Patrick Morgan +49 (970) 333-3833"); +var template = + ChatMessage.create().role("user").content("What is the nationality of {{?privateInfo}}"); +var templatingConfig = TemplatingModuleConfig.create().template(template); + +var maskingProvider = + MaskingProviderConfig.create() + .type(MaskingProviderConfig.TypeEnum.SAP_DATA_PRIVACY_INTEGRATION) + .method(MaskingProviderConfig.MethodEnum.ANONYMIZATION) + .entities( + DPIEntityConfig.create().type(DPIEntities.PHONE), + DPIEntityConfig.create().type(DPIEntities.PERSON)); +var maskingConfig = MaskingModuleConfig.create().maskingProviders(maskingProvider); + +CompletionPostRequest config = + CompletionPostRequest.create() + .orchestrationConfig( + OrchestrationConfig.create() + .moduleConfigurations( + ModuleConfigs.create() + .llmModuleConfig(LLM_CONFIG) + .templatingModuleConfig(templatingConfig) + .maskingModuleConfig(maskingConfig))) + .inputParams(inputParams); + +var resourceGroupId = "default"; +CompletionPostResponse result = + new OrchestrationCompletionApi(getOrchestrationClient(resourceGroupId)) + .orchestrationV1EndpointsCreate(config); + +String messageResult = + result.getOrchestrationResult().getChoices().get(0).getMessage().getContent(); +``` + +In this example, the input will be masked before the call to the LLM. Note that data cannot be unmasked in the LLM output. + +See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) + +### Set model parameters + +Change your LLM module configuration to add model parameters: + +```java +var llmConfig = + LLMModuleConfig.create() + .modelName("gpt-35-turbo") + .modelParams( + Map.of( + "max_tokens", 50, + "temperature", 0.1, + "frequency_penalty", 0, + "presence_penalty", 0)); +```