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 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..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,6 +32,8 @@ public class Grounding implements GroundingProvider { private List filters = List.of(DocumentGroundingFilter.create().dataRepositoryType(DataRepositoryType.VECTOR)); + @Nullable private List metadataParams = null; + @Setter(onMethod_ = {@Nonnull}) private TypeEnum documentGroundingService = TypeEnum.DOCUMENT_GROUNDING_SERVICE; @@ -60,6 +63,19 @@ 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. + * @since 1.13.0 + */ + @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 +102,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); 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) 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();