From d0301ae3e94f7c67ab9de4791013d2d055129e29 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Thu, 6 Mar 2025 16:03:29 +0100 Subject: [PATCH 1/4] Fix Grounding e2e test --- .../app/controllers/GroundingController.java | 10 +++++++-- .../ai/sdk/app/controllers/GroundingTest.java | 21 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java index c1a427c72..b90118521 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java @@ -9,6 +9,7 @@ import com.sap.ai.sdk.grounding.client.RetrievalApi; import com.sap.ai.sdk.grounding.client.VectorApi; import com.sap.ai.sdk.grounding.model.BaseDocument; +import com.sap.ai.sdk.grounding.model.Chunk; import com.sap.ai.sdk.grounding.model.Collection; import com.sap.ai.sdk.grounding.model.CollectionRequest; import com.sap.ai.sdk.grounding.model.DataRepository; @@ -19,7 +20,6 @@ import com.sap.ai.sdk.grounding.model.EmbeddingConfig; import com.sap.ai.sdk.grounding.model.KeyValueListPair; import com.sap.ai.sdk.grounding.model.Pipeline; -import com.sap.ai.sdk.grounding.model.ResultsInner1; import com.sap.ai.sdk.grounding.model.RetrievalSearchFilter; import com.sap.ai.sdk.grounding.model.RetrievalSearchInput; import com.sap.ai.sdk.grounding.model.SearchConfiguration; @@ -95,7 +95,13 @@ Object searchInDocuments( if ("json".equals(format)) { return results; } - final var messages = results.getResults().stream().map(ResultsInner1::getMessage).toList(); + final var messages = + results.getResults().stream() + .flatMap(resultsInner1 -> resultsInner1.getResults().stream()) + .flatMap(result -> result.getDataRepository().getDocuments().stream()) + .flatMap(dataRepositorySearchResult -> dataRepositorySearchResult.getChunks().stream()) + .map(Chunk::getContent) + .toList(); return "Found the following response(s): " + messages; } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java index 250cc1639..028bc7c3a 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java @@ -57,6 +57,9 @@ void testRepositoriesGetAll() { void testCreateDeleteCollection() { final var controller = new GroundingController(); + // (0) DELETE OLD DOCUMENTS + this.deleteOldDocuments(); + // (1) CREATE COLLECTION final var collectionId = controller.createCollection(JSON_FORMAT); final var collectionUuid = UUID.fromString(collectionId); @@ -65,7 +68,7 @@ void testCreateDeleteCollection() { // (1.1) TEST COLLECTION LOOKUP this.testCollectionsGetAll(); - // (2) SANITY CHECK: NO DOCUMENTS + // (2) SANITY CHECK: NO DOCUMENTS IN COLLECTION final var documentsEmpty = controller.getDocumentsByCollectionId(collectionUuid, JSON_FORMAT); assertThat(documentsEmpty).isInstanceOf(Documents.class); assertThat(((Documents) documentsEmpty).getCount()).isEqualTo(0); @@ -143,4 +146,20 @@ void testGetDocumentById(UUID collectionId, UUID documentId) { assertThat(chunk.getMetadata()).isNotNull().isNotEmpty(); } } + + void deleteOldDocuments() { + final var controller = new GroundingController(); + + final var result = controller.getAllCollections(JSON_FORMAT); + assertThat(result).isInstanceOf(CollectionsListResponse.class); + final var collectionsList = ((CollectionsListResponse) result).getResources(); + + for (final var collection : collectionsList) { + if ("e2e".equals(collection.getTitle())) { + final var deletion = controller.deleteDocuments(collection.getId(), JSON_FORMAT); + assertThat(deletion).isInstanceOf(OpenApiResponse.class); + assertThat(((OpenApiResponse) deletion).getStatusCode()).isEqualTo(202); + } + } + } } From b4999947d4034ca6031ff4c591cbea9d0bdc3c4a Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 10 Mar 2025 15:24:36 +0100 Subject: [PATCH 2/4] Requested changes --- .../app/controllers/GroundingController.java | 31 ++++++++++++++++++- .../ai/sdk/app/controllers/GroundingTest.java | 22 ++----------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java index b90118521..8d7b86720 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java @@ -12,6 +12,7 @@ import com.sap.ai.sdk.grounding.model.Chunk; import com.sap.ai.sdk.grounding.model.Collection; import com.sap.ai.sdk.grounding.model.CollectionRequest; +import com.sap.ai.sdk.grounding.model.CollectionsListResponse; import com.sap.ai.sdk.grounding.model.DataRepository; import com.sap.ai.sdk.grounding.model.DataRepositoryType; import com.sap.ai.sdk.grounding.model.DocumentCreateRequest; @@ -24,6 +25,7 @@ import com.sap.ai.sdk.grounding.model.RetrievalSearchInput; import com.sap.ai.sdk.grounding.model.SearchConfiguration; import com.sap.ai.sdk.grounding.model.TextOnlyBaseChunk; +import com.sap.cloud.sdk.services.openapi.core.OpenApiResponse; import java.time.format.TextStyle; import java.util.List; import java.util.Locale; @@ -49,6 +51,7 @@ class GroundingController { private static final RetrievalApi CLIENT_RETRIEVAL = new GroundingClient().retrieval(); private static final VectorApi CLIENT_VECTOR = new GroundingClient().vector(); private static final String RESOURCE_GROUP = "ai-sdk-java-e2e"; + private static final String COLLECTION_TITLE = "ai-sdk-java-e2e-test"; /** Retrieve (up to 10) grounding pipeline entities. */ @GetMapping("/pipelines/list") @@ -136,7 +139,8 @@ Object getDocumentsByCollectionId( String createCollection( @Nullable @RequestParam(value = "format", required = false) final String format) { final var embeddingConfig = EmbeddingConfig.create().modelName(TEXT_EMBEDDING_ADA_002.name()); - final var request = CollectionRequest.create().embeddingConfig(embeddingConfig).title("e2e"); + final var request = + CollectionRequest.create().embeddingConfig(embeddingConfig).title(COLLECTION_TITLE); final var documents = CLIENT_VECTOR.createCollection(RESOURCE_GROUP, request); final Map> headers = documents.getHeaders(); @@ -212,4 +216,29 @@ Object getDocumentChunksById( final var ids = document.getChunks().stream().map(TextOnlyBaseChunk::getContent).toList(); return "The following document ids are available: %s.".formatted(ids); } + + /** Delete all collections. */ + @GetMapping("/vector/collection/clear") + Object deleteCollections( + @Nullable @RequestParam(value = "format", required = false) final String format) { + final var collections = this.getAllCollections("json"); + final var collectionsList = ((CollectionsListResponse) collections).getResources(); + var statusCode = 0; + final var deletions = new java.util.ArrayList<>(List.of()); + + for (final var collection : collectionsList) { + if (COLLECTION_TITLE.equals(collection.getTitle())) { + final var deletion = this.deleteDocuments(collection.getId(), "json"); + if (deletion instanceof OpenApiResponse) { + final var status = ((OpenApiResponse) deletion).getStatusCode(); + deletions.add(deletion); + statusCode = Math.max(status, statusCode); + } + } + } + if ("json".equals(format)) { + return deletions; + } + return statusCode >= 400 ? "Failed to delete collections" : "Deletion successful"; + } } diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java index 028bc7c3a..4429597b5 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java @@ -57,8 +57,8 @@ void testRepositoriesGetAll() { void testCreateDeleteCollection() { final var controller = new GroundingController(); - // (0) DELETE OLD DOCUMENTS - this.deleteOldDocuments(); + // (0) DELETE OLD COLLECTIONS + controller.deleteCollections(JSON_FORMAT); // (1) CREATE COLLECTION final var collectionId = controller.createCollection(JSON_FORMAT); @@ -89,7 +89,7 @@ void testCreateDeleteCollection() { final var dayOfWeek = now().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH); this.assertDocumentSearchResult((RetievalSearchResults) search, dayOfWeek); - // (5) DELETE COLLECTION + // (5) CLEAN UP Object deletion = controller.deleteDocuments(collectionUuid, JSON_FORMAT); assertThat(deletion).isInstanceOf(OpenApiResponse.class); assertThat(((OpenApiResponse) deletion).getStatusCode()).isEqualTo(202); @@ -146,20 +146,4 @@ void testGetDocumentById(UUID collectionId, UUID documentId) { assertThat(chunk.getMetadata()).isNotNull().isNotEmpty(); } } - - void deleteOldDocuments() { - final var controller = new GroundingController(); - - final var result = controller.getAllCollections(JSON_FORMAT); - assertThat(result).isInstanceOf(CollectionsListResponse.class); - final var collectionsList = ((CollectionsListResponse) result).getResources(); - - for (final var collection : collectionsList) { - if ("e2e".equals(collection.getTitle())) { - final var deletion = controller.deleteDocuments(collection.getId(), JSON_FORMAT); - assertThat(deletion).isInstanceOf(OpenApiResponse.class); - assertThat(((OpenApiResponse) deletion).getStatusCode()).isEqualTo(202); - } - } - } } From 7e2e5845729135c7e2f887b5bd16b6a3afdba1c8 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 10 Mar 2025 16:13:25 +0100 Subject: [PATCH 3/4] Requested changes --- .../ai/sdk/app/controllers/GroundingController.java | 13 ++++--------- .../sap/ai/sdk/app/controllers/GroundingTest.java | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java index 8d7b86720..b9260e150 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java @@ -172,7 +172,7 @@ Object createDocument( /** Delete all items from a given grounding document collection. */ @GetMapping("/vector/collection/by-id/{id}/clear") - Object deleteDocuments( + Object deleteCollection( @Nonnull @PathVariable("id") final UUID collectionId, @Nullable @RequestParam(value = "format", required = false) final String format) { final var dayOfWeek = now().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH); @@ -192,7 +192,6 @@ Object deleteDocuments( if (del.getStatusCode() >= 400) { final var msg = "Document {} could not be deleted, status code [{}], headers: {}"; log.error(msg, documentId, del.getStatusCode(), del.getHeaders()); - throw new IllegalStateException("Document deletion failed for id " + documentId); } } final var response = CLIENT_VECTOR.deleteCollectionById(RESOURCE_GROUP, collectionId + ""); @@ -225,15 +224,11 @@ Object deleteCollections( final var collectionsList = ((CollectionsListResponse) collections).getResources(); var statusCode = 0; final var deletions = new java.util.ArrayList<>(List.of()); - for (final var collection : collectionsList) { if (COLLECTION_TITLE.equals(collection.getTitle())) { - final var deletion = this.deleteDocuments(collection.getId(), "json"); - if (deletion instanceof OpenApiResponse) { - final var status = ((OpenApiResponse) deletion).getStatusCode(); - deletions.add(deletion); - statusCode = Math.max(status, statusCode); - } + final var deletion = (OpenApiResponse) this.deleteCollection(collection.getId(), "json"); + deletions.add(deletion); + statusCode = Math.max(deletion.getStatusCode(), statusCode); } } if ("json".equals(format)) { diff --git a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java index 4429597b5..b796ddc7e 100644 --- a/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java +++ b/sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java @@ -90,7 +90,7 @@ void testCreateDeleteCollection() { this.assertDocumentSearchResult((RetievalSearchResults) search, dayOfWeek); // (5) CLEAN UP - Object deletion = controller.deleteDocuments(collectionUuid, JSON_FORMAT); + Object deletion = controller.deleteCollection(collectionUuid, JSON_FORMAT); assertThat(deletion).isInstanceOf(OpenApiResponse.class); assertThat(((OpenApiResponse) deletion).getStatusCode()).isEqualTo(202); From 0e1293fb01b6d492a915f7046ca794cefbc521a5 Mon Sep 17 00:00:00 2001 From: Jonas Israel Date: Mon, 10 Mar 2025 16:17:33 +0100 Subject: [PATCH 4/4] small fix --- .../com/sap/ai/sdk/app/controllers/GroundingController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java index b9260e150..0ad69a7f3 100644 --- a/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java +++ b/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java @@ -27,6 +27,7 @@ import com.sap.ai.sdk.grounding.model.TextOnlyBaseChunk; import com.sap.cloud.sdk.services.openapi.core.OpenApiResponse; import java.time.format.TextStyle; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -223,7 +224,7 @@ Object deleteCollections( final var collections = this.getAllCollections("json"); final var collectionsList = ((CollectionsListResponse) collections).getResources(); var statusCode = 0; - final var deletions = new java.util.ArrayList<>(List.of()); + final var deletions = new ArrayList<>(); for (final var collection : collectionsList) { if (COLLECTION_TITLE.equals(collection.getTitle())) { final var deletion = (OpenApiResponse) this.deleteCollection(collection.getId(), "json");