From 986924ebb9c5211adc7cde229eea67e4b74c3320 Mon Sep 17 00:00:00 2001 From: I538344 Date: Thu, 23 Jan 2025 10:53:59 +0100 Subject: [PATCH 01/13] Orchestration Grounding convenience --- .../sap/ai/sdk/orchestration/Grounding.java | 76 +++++++++++++++++++ .../sdk/orchestration/GroundingProvider.java | 21 +++++ .../ai/sdk/orchestration/MaskingProvider.java | 4 +- .../OrchestrationModuleConfig.java | 14 ++++ .../OrchestrationModuleConfigTest.java | 37 +++++++++ .../app/services/OrchestrationService.java | 26 ++----- 6 files changed, 155 insertions(+), 23 deletions(-) create mode 100644 orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java create mode 100644 orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java new file mode 100644 index 000000000..e96e68ae3 --- /dev/null +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -0,0 +1,76 @@ +package com.sap.ai.sdk.orchestration; + +import com.google.common.annotations.Beta; +import com.sap.ai.sdk.orchestration.model.DataRepositoryType; +import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig.TypeEnum; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfig; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; +import lombok.Setter; +import lombok.experimental.Accessors; +import lombok.val; + +/** + * Grounding integrates external, contextually relevant, domain-specific, or real-time data into AI + * processes. This data supplements the natural language processing capabilities of pre-trained + * models, which are trained on general material. + * + * @link SAP AI + * Core: Orchestration - Grounding + */ +@Beta +@Setter(onMethod_ = {@Nonnull}) +@Accessors(fluent = true) +public class Grounding implements GroundingProvider { + + private String id = "someID"; + private DataRepositoryType dataRepositoryType = DataRepositoryType.VECTOR; + private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; + + /** + * Create a new default grounding provider. + * + *

It is by default a document grounding service with a vector data repository and id "someID". + * + * @return The grounding provider. + */ + @Nonnull + public static Grounding create() { + return new Grounding(); + } + + /** + * Create a prompt with grounding parameters included in the message. + * + *

It uses the inputParams {@code groundingInput} for the user message and {@code + * groundingOutput} for the grounding context. + * + * @param message The user message. + * @return The prompt with grounding. + */ + @Nonnull + public OrchestrationPrompt createGroundingPrompt(@Nonnull final String message) { + return new OrchestrationPrompt( + Map.of("groundingInput", message), + Message.user( + "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}")); + } + + @Nonnull + @Override + public GroundingModuleConfig createConfig() { + val filterInner = + DocumentGroundingFilter.create().id(id).dataRepositoryType(dataRepositoryType); + val groundingConfigConfig = + GroundingModuleConfigConfig.create() + .inputParams(List.of("groundingInput")) + .outputParam("groundingOutput") + .addFiltersItem(filterInner); + return GroundingModuleConfig.create() + .type(documentGroundingService) + .config(groundingConfigConfig); + } +} diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java new file mode 100644 index 000000000..b323a4324 --- /dev/null +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java @@ -0,0 +1,21 @@ +package com.sap.ai.sdk.orchestration; + +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig; +import javax.annotation.Nonnull; + +/** + * Interface for grounding configurations. + * + * @link SAP AI + * Core: Orchestration - Grounding + */ +public interface GroundingProvider { + + /** + * Create a grounding configuration. + * + * @return the grounding configuration + */ + @Nonnull + GroundingModuleConfig createConfig(); +} diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java index 001db2e26..96f932ce9 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/MaskingProvider.java @@ -12,9 +12,9 @@ public interface MaskingProvider { /** - * Create a masking provider for the configuration. + * Create a masking configuration. * - * @return the masking provider + * @return the masking configuration */ @Nonnull MaskingProviderConfig createConfig(); diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfig.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfig.java index 2d603678f..ff6a52f31 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfig.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfig.java @@ -197,4 +197,18 @@ public OrchestrationModuleConfig withOutputFiltering( return this.withFilteringConfig(newFilteringConfig); } + + /** + * Creates a new configuration with the given grounding configuration. + * + * @link SAP + * AI Core: Orchestration - Grounding + * @param groundingProvider The grounding configuration to use. + * @return A new configuration with the given grounding configuration. + */ + @Nonnull + public OrchestrationModuleConfig withGrounding( + @Nonnull final GroundingProvider groundingProvider) { + return this.withGroundingConfig(groundingProvider.createConfig()); + } } diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java index 8e2f25298..66aa40097 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java @@ -3,11 +3,17 @@ import static com.sap.ai.sdk.orchestration.AzureFilterThreshold.ALLOW_SAFE_LOW_MEDIUM; import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.GPT_4O; import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.Parameter.MAX_TOKENS; +import static com.sap.ai.sdk.orchestration.model.DataRepositoryType.VECTOR; +import static com.sap.ai.sdk.orchestration.model.GroundingModuleConfig.TypeEnum.DOCUMENT_GROUNDING_SERVICE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.sap.ai.sdk.orchestration.model.DPIConfig; import com.sap.ai.sdk.orchestration.model.DPIEntities; +import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfig; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfigFiltersInner; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.Test; @@ -121,4 +127,35 @@ void testLLMConfig() { .withFailMessage("Static models should be unchanged") .isEqualTo("latest"); } + + @Test + void testGroundingConfig() { + var groundingConfig = Grounding.create(); + var config = + new OrchestrationModuleConfig().withLlmConfig(GPT_4O).withGrounding(groundingConfig); + + assertThat(config.getGroundingConfig()).isNotNull(); + assertThat(config.getGroundingConfig().getType()).isEqualTo(DOCUMENT_GROUNDING_SERVICE); + + GroundingModuleConfigConfig configConfig = config.getGroundingConfig().getConfig(); + assertThat(configConfig).isNotNull(); + assertThat(configConfig.getInputParams()).containsExactly("groundingInput"); + assertThat(configConfig.getOutputParam()).isEqualTo("groundingOutput"); + + List filters = configConfig.getFilters(); + assertThat(filters).hasSize(1); + DocumentGroundingFilter filter = (DocumentGroundingFilter) filters.get(0); + assertThat(filter.getId()).isEqualTo("someID"); + assertThat(filter.getDataRepositoryType()).isEqualTo(VECTOR); + } + + @Test + void testGroundingPrompt() { + var prompt = Grounding.create().createGroundingPrompt("Hello, World!"); + assertThat(prompt.getMessages()).hasSize(1); + var message = prompt.getMessages().get(0); + assertThat(message.content()) + .isEqualTo( + "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}"); + } } diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java index d8746f9ce..18a1dfa43 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java @@ -7,6 +7,7 @@ import com.sap.ai.sdk.orchestration.AzureContentFilter; import com.sap.ai.sdk.orchestration.AzureFilterThreshold; import com.sap.ai.sdk.orchestration.DpiMasking; +import com.sap.ai.sdk.orchestration.Grounding; import com.sap.ai.sdk.orchestration.Message; import com.sap.ai.sdk.orchestration.OrchestrationChatResponse; import com.sap.ai.sdk.orchestration.OrchestrationClient; @@ -14,10 +15,6 @@ import com.sap.ai.sdk.orchestration.OrchestrationModuleConfig; import com.sap.ai.sdk.orchestration.OrchestrationPrompt; import com.sap.ai.sdk.orchestration.model.DPIEntities; -import com.sap.ai.sdk.orchestration.model.DataRepositoryType; -import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; -import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig; -import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfig; import com.sap.ai.sdk.orchestration.model.Template; import java.util.List; import java.util.Map; @@ -25,6 +22,7 @@ import javax.annotation.Nonnull; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.springframework.stereotype.Service; /** Service class for the Orchestration service */ @@ -238,23 +236,9 @@ public OrchestrationChatResponse maskingPseudonymization(@Nonnull final DPIEntit */ @Nonnull public OrchestrationChatResponse grounding(@Nonnull final String groundingInput) { - final var message = - Message.user( - "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}"); - final var prompt = new OrchestrationPrompt(Map.of("groundingInput", groundingInput), message); - - final var filterInner = - DocumentGroundingFilter.create().id("someID").dataRepositoryType(DataRepositoryType.VECTOR); - final var groundingConfigConfig = - GroundingModuleConfigConfig.create() - .inputParams(List.of("groundingInput")) - .outputParam("groundingOutput") - .addFiltersItem(filterInner); - final var groundingConfig = - GroundingModuleConfig.create() - .type(GroundingModuleConfig.TypeEnum.DOCUMENT_GROUNDING_SERVICE) - .config(groundingConfigConfig); - final var configWithGrounding = config.withGroundingConfig(groundingConfig); + val groundingConfig = Grounding.create(); + val prompt = groundingConfig.createGroundingPrompt(groundingInput); + val configWithGrounding = config.withGrounding(groundingConfig); return client.chatCompletion(prompt, configWithGrounding); } From 50f0f45bd66413144b731849c82497136743005f Mon Sep 17 00:00:00 2001 From: I538344 Date: Thu, 23 Jan 2025 11:01:59 +0100 Subject: [PATCH 02/13] Added docs and release notes --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 31 +++++--------------- docs/release-notes/release_notes.md | 1 + 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 635de0512..c514a37c1 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -206,31 +206,16 @@ In this example, the input will be masked before the call to the LLM and will re Use the grounding module to provide additional context to the AI model. ```java - var message = - Message.user( - "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}"); - var prompt = - new OrchestrationPrompt(Map.of("groundingInput", "What does Joule do?"), message); - - var filterInner = - DocumentGroundingFilter.create().id("someID").dataRepositoryType(DataRepositoryType.VECTOR); - var groundingConfigConfig = - GroundingModuleConfigConfig.create() - .inputParams(List.of("groundingInput")) - .outputParam("groundingOutput") - .addFiltersItem(filterInner); - - var groundingConfig = - GroundingModuleConfig.create() - .type(GroundingModuleConfig.TypeEnum.DOCUMENT_GROUNDING_SERVICE) - .config(groundingConfigConfig); - var configWithGrounding = config.withGroundingConfig(groundingConfig); - - var result = - new OrchestrationClient().chatCompletion(prompt, configWithGrounding); +var groundingConfig = Grounding.create(); +var prompt = groundingConfig.createGroundingPrompt("What does Joule do?"); +var configWithGrounding = config.withGrounding(groundingConfig); + +var result = client.chatCompletion(prompt, configWithGrounding); ``` -In this example, the AI model is provided with additional context in the form of grounding information. Note, that it is necessary to provide the grounding input via one or more input variables. +In this example, the AI model is provided with additional context in the form of grounding information. + +`Grounding.create()` is by default a document grounding service with a vector data repository and id `"someID"`. ## Stream chat completion diff --git a/docs/release-notes/release_notes.md b/docs/release-notes/release_notes.md index ef8313847..1275365d8 100644 --- a/docs/release-notes/release_notes.md +++ b/docs/release-notes/release_notes.md @@ -16,6 +16,7 @@ - New Orchestration features: - [Spring AI integration](../guides/ORCHESTRATION_CHAT_COMPLETION.md#spring-ai-integration) + - [Add Grounding configuration convenience](../guides/ORCHESTRATION_CHAT_COMPLETION.md#grounding) - Images are now supported as input in newly introduced `MultiChatMessage`. - `MultiChatMessage` also allows for multiple content items (text or image) in one object. - Grounding input can be masked with `DPIConfig`. From ec28d01f908642e0ffb8075b0a0f3d5488f8e255 Mon Sep 17 00:00:00 2001 From: I538344 Date: Thu, 23 Jan 2025 13:15:30 +0100 Subject: [PATCH 03/13] Removed someId --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 2 +- .../src/main/java/com/sap/ai/sdk/orchestration/Grounding.java | 4 ++-- .../ai/sdk/orchestration/OrchestrationModuleConfigTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index c514a37c1..7beed60d4 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -215,7 +215,7 @@ var result = client.chatCompletion(prompt, configWithGrounding); In this example, the AI model is provided with additional context in the form of grounding information. -`Grounding.create()` is by default a document grounding service with a vector data repository and id `"someID"`. +`Grounding.create()` is by default a document grounding service with a vector data repository. ## Stream chat completion diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java index e96e68ae3..b34d43a26 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -26,14 +26,14 @@ @Accessors(fluent = true) public class Grounding implements GroundingProvider { - private String id = "someID"; + private String id = ""; private DataRepositoryType dataRepositoryType = DataRepositoryType.VECTOR; private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; /** * Create a new default grounding provider. * - *

It is by default a document grounding service with a vector data repository and id "someID". + *

It is by default a document grounding service with a vector data repository. * * @return The grounding provider. */ diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java index 66aa40097..e8c420239 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java @@ -145,7 +145,7 @@ void testGroundingConfig() { List filters = configConfig.getFilters(); assertThat(filters).hasSize(1); DocumentGroundingFilter filter = (DocumentGroundingFilter) filters.get(0); - assertThat(filter.getId()).isEqualTo("someID"); + assertThat(filter.getId()).isEqualTo(""); assertThat(filter.getDataRepositoryType()).isEqualTo(VECTOR); } From e0cd77754b378f0e4f8f9e4a629f4b70d2e33e98 Mon Sep 17 00:00:00 2001 From: I538344 Date: Thu, 23 Jan 2025 13:35:36 +0100 Subject: [PATCH 04/13] Alex likes functional interfaces --- .../java/com/sap/ai/sdk/orchestration/GroundingProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java index b323a4324..b19b4c018 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/GroundingProvider.java @@ -9,6 +9,7 @@ * @link SAP AI * Core: Orchestration - Grounding */ +@FunctionalInterface public interface GroundingProvider { /** From 078df19bd58788800e3da52705d0ac6bb144fce6 Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 12:53:37 +0100 Subject: [PATCH 05/13] final --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 17 +++- .../sap/ai/sdk/orchestration/Grounding.java | 20 ++--- .../app/services/OrchestrationService.java | 89 ++++++++++++------- 3 files changed, 80 insertions(+), 46 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 7beed60d4..2179dfa18 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -206,7 +206,22 @@ In this example, the input will be masked before the call to the LLM and will re Use the grounding module to provide additional context to the AI model. ```java -var groundingConfig = Grounding.create(); +// optional filter for collections +var documentMetadata = + SearchDocumentKeyValueListPair.create() + .key("document metadata") + .value("2") + .selectMode(List.of(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT)); +// optional filter for document chunks +var databaseFilter = + DocumentGroundingFilter.create() + .id("") + .dataRepositoryType(DataRepositoryType.VECTOR) + .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) + .documentMetadata(List.of(documentMetadata)) + .chunkMetadata(List.of(KeyValueListPair.create().key("index").value("1"))); + +var groundingConfig = Grounding.create().filter(databaseFilter); var prompt = groundingConfig.createGroundingPrompt("What does Joule do?"); var configWithGrounding = config.withGrounding(groundingConfig); diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java index b34d43a26..d0ccce27c 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -26,8 +26,8 @@ @Accessors(fluent = true) public class Grounding implements GroundingProvider { - private String id = ""; - private DataRepositoryType dataRepositoryType = DataRepositoryType.VECTOR; + private DocumentGroundingFilter filter = + DocumentGroundingFilter.create().id("").dataRepositoryType(DataRepositoryType.VECTOR); private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; /** @@ -45,8 +45,8 @@ public static Grounding create() { /** * Create a prompt with grounding parameters included in the message. * - *

It uses the inputParams {@code groundingInput} for the user message and {@code - * groundingOutput} for the grounding context. + *

It uses the inputParams {@code userMessage} for the user message and {@code + * groundingContext} for the grounding context. * * @param message The user message. * @return The prompt with grounding. @@ -54,21 +54,19 @@ public static Grounding create() { @Nonnull public OrchestrationPrompt createGroundingPrompt(@Nonnull final String message) { return new OrchestrationPrompt( - Map.of("groundingInput", message), + Map.of("userMessage", message), Message.user( - "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}")); + "{{?userMessage}} Use the following information as additional context: {{?groundingContext}}")); } @Nonnull @Override public GroundingModuleConfig createConfig() { - val filterInner = - DocumentGroundingFilter.create().id(id).dataRepositoryType(dataRepositoryType); val groundingConfigConfig = GroundingModuleConfigConfig.create() - .inputParams(List.of("groundingInput")) - .outputParam("groundingOutput") - .addFiltersItem(filterInner); + .inputParams(List.of("userMessage")) + .outputParam("groundingContext") + .addFiltersItem(filter); return GroundingModuleConfig.create() .type(documentGroundingService) .config(groundingConfigConfig); diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java index 18a1dfa43..0eaee7fdb 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java @@ -15,6 +15,12 @@ import com.sap.ai.sdk.orchestration.OrchestrationModuleConfig; import com.sap.ai.sdk.orchestration.OrchestrationPrompt; import com.sap.ai.sdk.orchestration.model.DPIEntities; +import com.sap.ai.sdk.orchestration.model.DataRepositoryType; +import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; +import com.sap.ai.sdk.orchestration.model.GroundingFilterSearchConfiguration; +import com.sap.ai.sdk.orchestration.model.KeyValueListPair; +import com.sap.ai.sdk.orchestration.model.SearchDocumentKeyValueListPair; +import com.sap.ai.sdk.orchestration.model.SearchSelectOptionEnum; import com.sap.ai.sdk.orchestration.model.Template; import java.util.List; import java.util.Map; @@ -42,7 +48,7 @@ public class OrchestrationService { */ @Nonnull public OrchestrationChatResponse completion(@Nonnull final String famousPhrase) { - final var prompt = new OrchestrationPrompt(famousPhrase + " Why is this phrase so famous?"); + val prompt = new OrchestrationPrompt(famousPhrase + " Why is this phrase so famous?"); return client.chatCompletion(prompt, config); } @@ -53,7 +59,7 @@ public OrchestrationChatResponse completion(@Nonnull final String famousPhrase) */ @Nonnull public Stream streamChatCompletion(@Nonnull final String topic) { - final var prompt = + val prompt = new OrchestrationPrompt( "Please create a small story about " + topic + " with around 700 words."); return client.streamChatCompletion(prompt, config); @@ -68,13 +74,12 @@ public Stream streamChatCompletion(@Nonnull final String topic) { */ @Nonnull public OrchestrationChatResponse template(@Nonnull final String language) { - final var template = - Message.user("Reply with 'Orchestration Service is working!' in {{?language}}"); - final var templatingConfig = Template.create().template(List.of(template.createChatMessage())); - final var configWithTemplate = config.withTemplateConfig(templatingConfig); + val template = Message.user("Reply with 'Orchestration Service is working!' in {{?language}}"); + val templatingConfig = Template.create().template(List.of(template.createChatMessage())); + val configWithTemplate = config.withTemplateConfig(templatingConfig); - final var inputParams = Map.of("language", language); - final var prompt = new OrchestrationPrompt(inputParams); + val inputParams = Map.of("language", language); + val prompt = new OrchestrationPrompt(inputParams); return client.chatCompletion(prompt, configWithTemplate); } @@ -86,12 +91,12 @@ public OrchestrationChatResponse template(@Nonnull final String language) { */ @Nonnull public OrchestrationChatResponse messagesHistory(@Nonnull final String prevMessage) { - final var prompt = new OrchestrationPrompt(Message.user(prevMessage)); + val prompt = new OrchestrationPrompt(Message.user(prevMessage)); - final var result = client.chatCompletion(prompt, config); + val result = client.chatCompletion(prompt, config); // Let's presume a user asks the following follow-up question - final var nextPrompt = + val nextPrompt = new OrchestrationPrompt(Message.user("What is the typical food there?")) .messageHistory(result.getAllMessages()); @@ -111,12 +116,12 @@ public OrchestrationChatResponse messagesHistory(@Nonnull final String prevMessa @Nonnull public OrchestrationChatResponse inputFiltering(@Nonnull final AzureFilterThreshold policy) throws OrchestrationClientException { - final var prompt = + val prompt = new OrchestrationPrompt("'We shall spill blood tonight', said the operation in-charge."); - final var filterConfig = + val filterConfig = new AzureContentFilter().hate(policy).selfHarm(policy).sexual(policy).violence(policy); - final var configWithFilter = config.withInputFiltering(filterConfig); + val configWithFilter = config.withInputFiltering(filterConfig); return client.chatCompletion(prompt, configWithFilter); } @@ -133,16 +138,16 @@ public OrchestrationChatResponse inputFiltering(@Nonnull final AzureFilterThresh @Nonnull public OrchestrationChatResponse outputFiltering(@Nonnull final AzureFilterThreshold policy) { - final var systemMessage = Message.system("Give three paraphrases for the following sentence"); + val systemMessage = Message.system("Give three paraphrases for the following sentence"); // Reliably triggering the content filter of models fine-tuned for ethical compliance // is difficult. The prompt below may be rendered ineffective in the future. - final var prompt = + val prompt = new OrchestrationPrompt("'We shall spill blood tonight', said the operation in-charge.") .messageHistory(List.of(systemMessage)); - final var filterConfig = + val filterConfig = new AzureContentFilter().hate(policy).selfHarm(policy).sexual(policy).violence(policy); - final var configWithFilter = config.withOutputFiltering(filterConfig); + val configWithFilter = config.withOutputFiltering(filterConfig); return client.chatCompletion(prompt, configWithFilter); } @@ -158,19 +163,19 @@ public OrchestrationChatResponse outputFiltering(@Nonnull final AzureFilterThres */ @Nonnull public OrchestrationChatResponse maskingAnonymization(@Nonnull final DPIEntities entity) { - final var systemMessage = + val systemMessage = Message.system( "Please evaluate the following user feedback and judge if the sentiment is positive or negative."); - final var userMessage = + val userMessage = Message.user( """ I think the SDK is good, but could use some further enhancements. My architect Alice and manager Bob pointed out that we need the grounding capabilities, which aren't supported yet. """); - final var prompt = new OrchestrationPrompt(systemMessage, userMessage); - final var maskingConfig = DpiMasking.anonymization().withEntities(entity); - final var configWithMasking = config.withMaskingConfig(maskingConfig); + val prompt = new OrchestrationPrompt(systemMessage, userMessage); + val maskingConfig = DpiMasking.anonymization().withEntities(entity); + val configWithMasking = config.withMaskingConfig(maskingConfig); return client.chatCompletion(prompt, configWithMasking); } @@ -183,11 +188,11 @@ public OrchestrationChatResponse maskingAnonymization(@Nonnull final DPIEntities @Nonnull public OrchestrationChatResponse completionWithResourceGroup( @Nonnull final String resourceGroup, @Nonnull final String famousPhrase) { - final var destination = + val destination = new AiCoreService().getInferenceDestination(resourceGroup).forScenario("orchestration"); - final var clientWithResourceGroup = new OrchestrationClient(destination); + val clientWithResourceGroup = new OrchestrationClient(destination); - final var prompt = new OrchestrationPrompt(famousPhrase + " Why is this phrase so famous?"); + val prompt = new OrchestrationPrompt(famousPhrase + " Why is this phrase so famous?"); return clientWithResourceGroup.chatCompletion(prompt, config); } @@ -203,13 +208,13 @@ public OrchestrationChatResponse completionWithResourceGroup( */ @Nonnull public OrchestrationChatResponse maskingPseudonymization(@Nonnull final DPIEntities entity) { - final var systemMessage = + val systemMessage = Message.system( """ Please write an initial response to the below user feedback, stating that we are working on the feedback and will get back to them soon. Please make sure to address the user in person and end with "Best regards, the AI SDK team". """); - final var userMessage = + val userMessage = Message.user( """ Username: Mallory @@ -220,9 +225,9 @@ public OrchestrationChatResponse maskingPseudonymization(@Nonnull final DPIEntit My architect Alice and manager Bob pointed out that we need the grounding capabilities, which aren't supported yet. """); - final var prompt = new OrchestrationPrompt(systemMessage, userMessage); - final var maskingConfig = DpiMasking.pseudonymization().withEntities(entity, DPIEntities.EMAIL); - final var configWithMasking = config.withMaskingConfig(maskingConfig); + val prompt = new OrchestrationPrompt(systemMessage, userMessage); + val maskingConfig = DpiMasking.pseudonymization().withEntities(entity, DPIEntities.EMAIL); + val configWithMasking = config.withMaskingConfig(maskingConfig); return client.chatCompletion(prompt, configWithMasking); } @@ -232,12 +237,28 @@ public OrchestrationChatResponse maskingPseudonymization(@Nonnull final DPIEntit * * @link SAP * AI Core: Orchestration - Grounding + * @param userMessage the user message to provide grounding for * @return the assistant response object */ @Nonnull - public OrchestrationChatResponse grounding(@Nonnull final String groundingInput) { - val groundingConfig = Grounding.create(); - val prompt = groundingConfig.createGroundingPrompt(groundingInput); + public OrchestrationChatResponse grounding(@Nonnull final String userMessage) { + // optional filter for collections + val documentMetadata = + SearchDocumentKeyValueListPair.create() + .key("document metadata") + .value("2") + .selectMode(List.of(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT)); + // optional filter for document chunks + val databaseFilter = + DocumentGroundingFilter.create() + .id("") + .dataRepositoryType(DataRepositoryType.VECTOR) + .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) + .documentMetadata(List.of(documentMetadata)) + .chunkMetadata(List.of(KeyValueListPair.create().key("index").value("1"))); + + val groundingConfig = Grounding.create().filter(databaseFilter); + val prompt = groundingConfig.createGroundingPrompt(userMessage); val configWithGrounding = config.withGrounding(groundingConfig); return client.chatCompletion(prompt, configWithGrounding); From 2b090de1fc9b46ab12c406c74f42f0c9bd4efa59 Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 12:58:53 +0100 Subject: [PATCH 06/13] final --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 2179dfa18..51c72d968 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -209,8 +209,8 @@ Use the grounding module to provide additional context to the AI model. // optional filter for collections var documentMetadata = SearchDocumentKeyValueListPair.create() - .key("document metadata") - .value("2") + .key("my-collection") + .value("value") .selectMode(List.of(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT)); // optional filter for document chunks var databaseFilter = From d594557d28766a4e3aece0bf5dfd103160364dba Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 13:00:44 +0100 Subject: [PATCH 07/13] less params --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 4 +--- .../com/sap/ai/sdk/app/services/OrchestrationService.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 51c72d968..7c996321f 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -217,9 +217,7 @@ var databaseFilter = DocumentGroundingFilter.create() .id("") .dataRepositoryType(DataRepositoryType.VECTOR) - .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) - .documentMetadata(List.of(documentMetadata)) - .chunkMetadata(List.of(KeyValueListPair.create().key("index").value("1"))); + .documentMetadata(List.of(documentMetadata)); var groundingConfig = Grounding.create().filter(databaseFilter); var prompt = groundingConfig.createGroundingPrompt("What does Joule do?"); diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java index 0eaee7fdb..b3ff9aa05 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java @@ -18,7 +18,6 @@ import com.sap.ai.sdk.orchestration.model.DataRepositoryType; import com.sap.ai.sdk.orchestration.model.DocumentGroundingFilter; import com.sap.ai.sdk.orchestration.model.GroundingFilterSearchConfiguration; -import com.sap.ai.sdk.orchestration.model.KeyValueListPair; import com.sap.ai.sdk.orchestration.model.SearchDocumentKeyValueListPair; import com.sap.ai.sdk.orchestration.model.SearchSelectOptionEnum; import com.sap.ai.sdk.orchestration.model.Template; @@ -254,8 +253,7 @@ public OrchestrationChatResponse grounding(@Nonnull final String userMessage) { .id("") .dataRepositoryType(DataRepositoryType.VECTOR) .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) - .documentMetadata(List.of(documentMetadata)) - .chunkMetadata(List.of(KeyValueListPair.create().key("index").value("1"))); + .documentMetadata(List.of(documentMetadata)); val groundingConfig = Grounding.create().filter(databaseFilter); val prompt = groundingConfig.createGroundingPrompt(userMessage); From beaeeff98d192f79fbb4cc3e375d0ae8a3d2e3de Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 13:01:32 +0100 Subject: [PATCH 08/13] link --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 7c996321f..92b1c0321 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -230,6 +230,8 @@ In this example, the AI model is provided with additional context in the form of `Grounding.create()` is by default a document grounding service with a vector data repository. +Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java). + ## 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. From ecfb112882c9eaf3ff9b8e28d6624790be11f2e6 Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 13:41:00 +0100 Subject: [PATCH 09/13] fix tests --- .../ai/sdk/orchestration/OrchestrationModuleConfigTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java index e8c420239..ab30ad9e4 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java @@ -139,8 +139,8 @@ void testGroundingConfig() { GroundingModuleConfigConfig configConfig = config.getGroundingConfig().getConfig(); assertThat(configConfig).isNotNull(); - assertThat(configConfig.getInputParams()).containsExactly("groundingInput"); - assertThat(configConfig.getOutputParam()).isEqualTo("groundingOutput"); + assertThat(configConfig.getInputParams()).containsExactly("userMessage"); + assertThat(configConfig.getOutputParam()).isEqualTo("groundingContext"); List filters = configConfig.getFilters(); assertThat(filters).hasSize(1); @@ -156,6 +156,6 @@ void testGroundingPrompt() { var message = prompt.getMessages().get(0); assertThat(message.content()) .isEqualTo( - "{{?groundingInput}} Use the following information as additional context: {{?groundingOutput}}"); + "{{?userMessage}} Use the following information as additional context: {{?groundingContext}}"); } } From d27b9e0a67f64dcbd51f601a7f9a1be2da82bd76 Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 16:14:39 +0100 Subject: [PATCH 10/13] Added better filters API --- .../sap/ai/sdk/orchestration/Grounding.java | 29 ++++++++++++++++--- .../OrchestrationModuleConfigTest.java | 15 ++++++++++ .../app/services/OrchestrationService.java | 2 +- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java index d0ccce27c..aa5a99227 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -6,8 +6,10 @@ import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig; import com.sap.ai.sdk.orchestration.model.GroundingModuleConfig.TypeEnum; import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfig; +import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfigFiltersInner; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.annotation.Nonnull; import lombok.Setter; import lombok.experimental.Accessors; @@ -22,12 +24,15 @@ * Core: Orchestration - Grounding */ @Beta -@Setter(onMethod_ = {@Nonnull}) @Accessors(fluent = true) public class Grounding implements GroundingProvider { - private DocumentGroundingFilter filter = + private static final GroundingModuleConfigConfigFiltersInner DEFAULT_FILTER = DocumentGroundingFilter.create().id("").dataRepositoryType(DataRepositoryType.VECTOR); + + private List filters; + + @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; /** @@ -42,6 +47,20 @@ public static Grounding create() { return new Grounding(); } + /** + * Set filters for grounding. + * + * @param filters List of filters to set. + * @return The modified grounding configuration. + */ + @Nonnull + public Grounding filters(@Nonnull final GroundingModuleConfigConfigFiltersInner... filters) { + if (filters.length != 0) { + this.filters = List.of(filters); + } + return this; + } + /** * Create a prompt with grounding parameters included in the message. * @@ -65,8 +84,10 @@ public GroundingModuleConfig createConfig() { val groundingConfigConfig = GroundingModuleConfigConfig.create() .inputParams(List.of("userMessage")) - .outputParam("groundingContext") - .addFiltersItem(filter); + .outputParam("groundingContext"); + groundingConfigConfig.setFilters( + Objects.requireNonNullElseGet(filters, () -> List.of(DEFAULT_FILTER))); + return GroundingModuleConfig.create() .type(documentGroundingService) .config(groundingConfigConfig); diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java index ab30ad9e4..bdfa1f02b 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationModuleConfigTest.java @@ -149,6 +149,21 @@ void testGroundingConfig() { assertThat(filter.getDataRepositoryType()).isEqualTo(VECTOR); } + @Test + void testGroundingConfigWithFilters() { + var filter1 = DocumentGroundingFilter.create().id("123").dataRepositoryType(VECTOR); + var filter2 = DocumentGroundingFilter.create().id("234").dataRepositoryType(VECTOR); + var groundingConfig = Grounding.create().filters(filter1, filter2); + var config = + new OrchestrationModuleConfig().withLlmConfig(GPT_4O).withGrounding(groundingConfig); + + assertThat(config.getGroundingConfig()).isNotNull(); + var configConfig = config.getGroundingConfig().getConfig(); + assertThat(configConfig).isNotNull(); + + assertThat(config.getGroundingConfig().getConfig().getFilters()).hasSize(2); + } + @Test void testGroundingPrompt() { var prompt = Grounding.create().createGroundingPrompt("Hello, World!"); diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java index b3ff9aa05..440eb72a5 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java @@ -255,7 +255,7 @@ public OrchestrationChatResponse grounding(@Nonnull final String userMessage) { .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) .documentMetadata(List.of(documentMetadata)); - val groundingConfig = Grounding.create().filter(databaseFilter); + val groundingConfig = Grounding.create().filters(databaseFilter); val prompt = groundingConfig.createGroundingPrompt(userMessage); val configWithGrounding = config.withGrounding(groundingConfig); From 8ab0ddd0a63e4b166a74340a3c88cc931ee08eec Mon Sep 17 00:00:00 2001 From: Charles Dubois <103174266+CharlesDuboisSAP@users.noreply.github.com> Date: Fri, 24 Jan 2025 16:15:22 +0100 Subject: [PATCH 11/13] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexander Dümont <22489773+newtork@users.noreply.github.com> --- docs/guides/ORCHESTRATION_CHAT_COMPLETION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md index 92b1c0321..771922e99 100644 --- a/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md +++ b/docs/guides/ORCHESTRATION_CHAT_COMPLETION.md @@ -211,13 +211,13 @@ var documentMetadata = SearchDocumentKeyValueListPair.create() .key("my-collection") .value("value") - .selectMode(List.of(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT)); + .addSelectModeItem(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT); // optional filter for document chunks var databaseFilter = DocumentGroundingFilter.create() .id("") .dataRepositoryType(DataRepositoryType.VECTOR) - .documentMetadata(List.of(documentMetadata)); + .addDocumentMetadataItem(documentMetadata); var groundingConfig = Grounding.create().filter(databaseFilter); var prompt = groundingConfig.createGroundingPrompt("What does Joule do?"); From d0724520b7510c3eb8d513b94bf1e086386e83a0 Mon Sep 17 00:00:00 2001 From: I538344 Date: Fri, 24 Jan 2025 16:15:35 +0100 Subject: [PATCH 12/13] Better api usage in service --- .../com/sap/ai/sdk/app/services/OrchestrationService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java index 440eb72a5..882714180 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java @@ -246,14 +246,14 @@ public OrchestrationChatResponse grounding(@Nonnull final String userMessage) { SearchDocumentKeyValueListPair.create() .key("document metadata") .value("2") - .selectMode(List.of(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT)); + .addSelectModeItem(SearchSelectOptionEnum.IGNORE_IF_KEY_ABSENT); // optional filter for document chunks val databaseFilter = DocumentGroundingFilter.create() .id("") .dataRepositoryType(DataRepositoryType.VECTOR) .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) - .documentMetadata(List.of(documentMetadata)); + .addDocumentMetadataItem(documentMetadata); val groundingConfig = Grounding.create().filters(databaseFilter); val prompt = groundingConfig.createGroundingPrompt(userMessage); From 8ca2f666f11b9a59f338df27b7f6a92b1b3dfd06 Mon Sep 17 00:00:00 2001 From: I538344 Date: Mon, 27 Jan 2025 11:37:08 +0100 Subject: [PATCH 13/13] Alex's comment --- .../com/sap/ai/sdk/orchestration/Grounding.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java index aa5a99227..d60874366 100644 --- a/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java +++ b/orchestration/src/main/java/com/sap/ai/sdk/orchestration/Grounding.java @@ -9,7 +9,6 @@ import com.sap.ai.sdk.orchestration.model.GroundingModuleConfigConfigFiltersInner; import java.util.List; import java.util.Map; -import java.util.Objects; import javax.annotation.Nonnull; import lombok.Setter; import lombok.experimental.Accessors; @@ -27,10 +26,10 @@ @Accessors(fluent = true) public class Grounding implements GroundingProvider { - private static final GroundingModuleConfigConfigFiltersInner DEFAULT_FILTER = - DocumentGroundingFilter.create().id("").dataRepositoryType(DataRepositoryType.VECTOR); - - private List filters; + @Nonnull + private List filters = + List.of( + DocumentGroundingFilter.create().id("").dataRepositoryType(DataRepositoryType.VECTOR)); @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; @@ -84,9 +83,8 @@ public GroundingModuleConfig createConfig() { val groundingConfigConfig = GroundingModuleConfigConfig.create() .inputParams(List.of("userMessage")) - .outputParam("groundingContext"); - groundingConfigConfig.setFilters( - Objects.requireNonNullElseGet(filters, () -> List.of(DEFAULT_FILTER))); + .outputParam("groundingContext") + .filters(filters); return GroundingModuleConfig.create() .type(documentGroundingService)