From d2aeb3ce2971b5c29dc2bf865d8ab104c1d04834 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 19 Nov 2025 11:06:54 +0100 Subject: [PATCH 1/4] convenience --- .../sap/ai/sdk/orchestration/Grounding.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) 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 8e78462f1..1829e1cca 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 @@ -31,6 +31,8 @@ public class Grounding implements GroundingProvider { private List filters = List.of(DocumentGroundingFilter.create().dataRepositoryType(DataRepositoryType.VECTOR)); + @Nonnull private List metadataParams = List.of(); + @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; @@ -60,6 +62,18 @@ public Grounding filters(@Nonnull final GroundingModuleConfigConfigFiltersInner. return this; } + /** + * Set which metadataParams are used in the grounding response. + * + * @param metadataParams List of metadataParams to set. + * @return The modified grounding configuration. + */ + @Nonnull + public Grounding metadataParams(@Nonnull final String... metadataParams) { + this.metadataParams = List.of(metadataParams); + return this; + } + /** * Create a prompt with grounding parameters included in the message. * @@ -86,8 +100,10 @@ public GroundingModuleConfig createConfig() { GroundingModuleConfigConfigPlaceholders.create() .input(List.of("userMessage")) .output("groundingContext")) - .filters(filters); + .filters(filters) + .metadataParams(metadataParams); + // metadata_params field is not allowed for data repository type: `help.sap.com` if (filters.contains( DocumentGroundingFilter.create().dataRepositoryType(DataRepositoryType.HELP_SAP_COM))) { groundingConfigConfig.setMetadataParams(null); From 77ccb3308303f41e4951b1093167018c49394bad Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 19 Nov 2025 11:07:06 +0100 Subject: [PATCH 2/4] tests --- .../orchestration/OrchestrationUnitTest.java | 22 ++++++++ .../resources/groundingRequestMetadata.json | 51 +++++++++++++++++++ .../app/services/OrchestrationService.java | 8 ++- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 orchestration/src/test/resources/groundingRequestMetadata.json diff --git a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java index ba389c4ba..8bf3a8257 100644 --- a/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java +++ b/orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java @@ -268,6 +268,28 @@ void testGrounding() throws IOException { postRequestedFor(urlPathEqualTo("/v2/completion")).withRequestBody(equalToJson(request))); } + @Test + void testGroundingWithConvenience() throws IOException { + stubFor( + post(urlPathEqualTo("/v2/completion")) + .willReturn( + aResponse() + .withBodyFile("groundingResponse.json") + .withHeader("Content-Type", "application/json"))); + + var dbFilters = DocumentGroundingFilter.create().dataRepositoryType(DataRepositoryType.VECTOR); + + var groundingConfig = Grounding.create().metadataParams("foo", "bar").filters(dbFilters); + var prompt = groundingConfig.createGroundingPrompt("Hello, what do you know?"); + var configWithGrounding = config.withGrounding(groundingConfig); + + final var response = client.chatCompletion(prompt, configWithGrounding); + + final String request = fileLoaderStr.apply("groundingRequestMetadata.json"); + verify( + postRequestedFor(urlPathEqualTo("/v2/completion")).withRequestBody(equalToJson(request))); + } + @Test void testGroundingWithHelpSapCom() throws IOException { stubFor( diff --git a/orchestration/src/test/resources/groundingRequestMetadata.json b/orchestration/src/test/resources/groundingRequestMetadata.json new file mode 100644 index 000000000..c0859eb2c --- /dev/null +++ b/orchestration/src/test/resources/groundingRequestMetadata.json @@ -0,0 +1,51 @@ +{ + "config" : { + "modules" : { + "prompt_templating" : { + "prompt" : { + "template" : [ { + "content" : "{{?userMessage}} Use the following information as additional context: {{?groundingContext}}", + "role" : "user" + } ], + "defaults" : { }, + "tools" : [ ] + }, + "model" : { + "name" : "gpt-4o", + "version" : "latest", + "params" : { + "max_tokens" : 50, + "temperature" : 0.1, + "frequency_penalty" : 0, + "presence_penalty" : 0, + "top_p" : 1, + "n" : 1 + }, + "timeout" : 600, + "max_retries" : 2 + } + }, + "grounding" : { + "type" : "document_grounding_service", + "config" : { + "filters" : [ { + "data_repositories" : [ "*" ], + "data_repository_type" : "vector", + "data_repository_metadata" : [ ], + "document_metadata" : [ ], + "chunk_metadata" : [ ] + } ], + "placeholders" : { + "input" : [ "userMessage" ], + "output" : "groundingContext" + }, + "metadata_params" : [ "foo", "bar" ] + } + } + } + }, + "placeholder_values" : { + "userMessage" : "Hello, what do you know?" + }, + "messages_history" : [ ] +} \ No newline at end of file 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 231647230..161a75255 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 @@ -380,8 +380,12 @@ public OrchestrationChatResponse grounding( .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(1)) .addDocumentMetadataItem(documentMetadata); - val groundingConfig = Grounding.create().filters(databaseFilter); - val prompt = groundingConfig.createGroundingPrompt(userMessage); + val groundingConfig = Grounding.create().filters(databaseFilter).metadataParams("*"); + val prompt = + groundingConfig + .createGroundingPrompt(userMessage) + .messageHistory( + List.of(Message.system("Add in the response all metadata from grounding."))); val maskingConfig = // optional masking configuration DpiMasking.anonymization() .withEntities(DPIEntities.SENSITIVE_DATA) From 1240394e9e3fba993cd74245e64aacf81f80727f Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Wed, 19 Nov 2025 11:07:13 +0100 Subject: [PATCH 3/4] release notes --- docs/release_notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release_notes.md b/docs/release_notes.md index 64f99b816..d162ff0dc 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -12,7 +12,8 @@ ### ✨ New Functionality --[Orchestration] Added new models for `OrchestrationAiModel`: `SONAR`,`SONAR_PRO`. +- [Orchestration] Added new models for `OrchestrationAiModel`: `SONAR`,`SONAR_PRO`. +- [Orchestration] Convenience for adding the `metadata_params` option to grounding calls. ### 📈 Improvements From 5090024084dc88edef84d164a7a20f6e10d7ba0c Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Thu, 20 Nov 2025 12:54:26 +0100 Subject: [PATCH 4/4] review --- .../src/main/java/com/sap/ai/sdk/orchestration/Grounding.java | 4 +++- .../com/sap/ai/sdk/app/controllers/OrchestrationTest.java | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) 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 1829e1cca..7e549eafb 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 @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import lombok.Setter; import lombok.experimental.Accessors; import lombok.val; @@ -31,7 +32,7 @@ public class Grounding implements GroundingProvider { private List filters = List.of(DocumentGroundingFilter.create().dataRepositoryType(DataRepositoryType.VECTOR)); - @Nonnull private List metadataParams = List.of(); + @Nullable private List metadataParams = null; @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; @@ -67,6 +68,7 @@ public Grounding filters(@Nonnull final GroundingModuleConfigConfigFiltersInner. * * @param metadataParams List of metadataParams to set. * @return The modified grounding configuration. + * @since 1.13.0 */ @Nonnull public Grounding metadataParams(@Nonnull final String... metadataParams) { diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java index ce613ba74..e3d60efa3 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java @@ -209,6 +209,9 @@ void testGrounding() { assertThat(result.getIntermediateResults().getGrounding().getData()).isNotNull(); assertThat(result.getIntermediateResults().getGrounding().getMessage()) .isEqualTo("grounding result"); + var groundingData = + (Map) result.getIntermediateResults().getGrounding().getData(); + assertThat(groundingData.get("grounding_result")).contains("metadata"); var maskingResult = result.getIntermediateResults().getInputMasking(); assertThat(maskingResult.getMessage()).isNotEmpty();