Skip to content

Commit dcad8a1

Browse files
committed
Add extended test case for documents
1 parent 2f4bcc7 commit dcad8a1

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
11
package com.sap.ai.sdk.app.controllers;
22

3+
import static com.sap.ai.sdk.foundationmodels.openai.OpenAiModel.TEXT_EMBEDDING_ADA_002;
4+
import static java.time.LocalDate.now;
35
import static java.util.stream.Collectors.joining;
46

57
import com.sap.ai.sdk.grounding.GroundingClient;
68
import com.sap.ai.sdk.grounding.api.PipelinesApi;
79
import com.sap.ai.sdk.grounding.api.RetrievalApi;
810
import com.sap.ai.sdk.grounding.api.VectorApi;
11+
import com.sap.ai.sdk.grounding.model.BaseDocument;
912
import com.sap.ai.sdk.grounding.model.Collection;
13+
import com.sap.ai.sdk.grounding.model.CollectionRequest;
1014
import com.sap.ai.sdk.grounding.model.DataRepository;
15+
import com.sap.ai.sdk.grounding.model.DataRepositoryType;
16+
import com.sap.ai.sdk.grounding.model.DocumentCreateRequest;
17+
import com.sap.ai.sdk.grounding.model.DocumentKeyValueListPair;
1118
import com.sap.ai.sdk.grounding.model.DocumentWithoutChunks;
19+
import com.sap.ai.sdk.grounding.model.EmbeddingConfig;
20+
import com.sap.ai.sdk.grounding.model.KeyValueListPair;
1221
import com.sap.ai.sdk.grounding.model.Pipeline;
22+
import com.sap.ai.sdk.grounding.model.ResultsInner1;
23+
import com.sap.ai.sdk.grounding.model.RetrievalSearchFilter;
24+
import com.sap.ai.sdk.grounding.model.RetrievalSearchInput;
25+
import com.sap.ai.sdk.grounding.model.SearchConfiguration;
1326
import com.sap.ai.sdk.grounding.model.TextOnlyBaseChunk;
27+
import java.time.format.TextStyle;
28+
import java.util.List;
29+
import java.util.Locale;
30+
import java.util.Map;
1431
import java.util.UUID;
1532
import javax.annotation.Nonnull;
1633
import javax.annotation.Nullable;
@@ -31,7 +48,7 @@ class GroundingController {
3148
private static final PipelinesApi CLIENT_PIPELINES = GroundingClient.create().pipelines();
3249
private static final RetrievalApi CLIENT_RETRIEVAL = GroundingClient.create().retrieval();
3350
private static final VectorApi CLIENT_VECTOR = GroundingClient.create().vector();
34-
private static final String RESOURCE_GROUP = "default";
51+
private static final String RESOURCE_GROUP = "ai-sdk-java-e2e";
3552

3653
/**
3754
* Stop all deployments with the Java specific configuration ID.
@@ -70,6 +87,30 @@ Object getAllRepositories(
7087
return "Found repositories with titles: " + titles;
7188
}
7289

90+
/**
91+
* Delete all deployments with the Java specific configuration ID.
92+
*
93+
* <p>Only UNKNOWN and STOPPED deployments can be DELETED
94+
*/
95+
@GetMapping("/retrieval/repositories")
96+
Object searchInDocuments(
97+
@Nullable @RequestParam(value = "format", required = false) final String format) {
98+
final var filter =
99+
RetrievalSearchFilter.create()
100+
.id("question")
101+
.dataRepositoryType(DataRepositoryType.VECTOR)
102+
.dataRepositories(List.of("*"))
103+
.searchConfiguration(SearchConfiguration.create().maxChunkCount(10));
104+
final var q = RetrievalSearchInput.create().query("When was the last upload?").filters(filter);
105+
final var results = CLIENT_RETRIEVAL.search(RESOURCE_GROUP, q);
106+
107+
if ("json".equals(format)) {
108+
return results;
109+
}
110+
final var messages = results.getResults().stream().map(ResultsInner1::getMessage).toList();
111+
return "Found the following response(s): " + messages;
112+
}
113+
73114
/** Get all deployments with the Java specific configuration ID. */
74115
@GetMapping("/vector/collections")
75116
Object getAllCollections(
@@ -96,6 +137,76 @@ Object getDocumentsByCollectionId(
96137
return "The following document ids are available: %s.".formatted(ids);
97138
}
98139

140+
/** Get all deployments, including non-Java specific deployments */
141+
@GetMapping("/vector/collection/create")
142+
String createCollection(
143+
@Nullable @RequestParam(value = "format", required = false) final String format) {
144+
final var embeddingConfig = EmbeddingConfig.create().modelName(TEXT_EMBEDDING_ADA_002.name());
145+
final var request = CollectionRequest.create().embeddingConfig(embeddingConfig).title("e2e");
146+
final var documents = CLIENT_VECTOR.createCollection(RESOURCE_GROUP, request);
147+
final Map<String, List<String>> headers = documents.getHeaders();
148+
149+
final var locationHeader = headers.get("Location").get(0);
150+
return locationHeader.replaceAll("^.*?/([a-f0-9-]+)/.*?$", "$1");
151+
}
152+
153+
/** Get all deployments, including non-Java specific deployments */
154+
@GetMapping("/vector/collection/by-id/{id}/day")
155+
Object createDocument(
156+
@Nonnull @PathVariable("id") final UUID collectionId,
157+
@Nullable @RequestParam(value = "format", required = false) final String format) {
158+
final var dayOfWeek = now().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH);
159+
;
160+
final var documentContent = "Last upload on " + dayOfWeek;
161+
162+
final var chunkMeta = KeyValueListPair.create().key("context").value("day-of-week");
163+
final var chunk = TextOnlyBaseChunk.create().content(documentContent).metadata(chunkMeta);
164+
final var docMeta = DocumentKeyValueListPair.create().key("purpose").value("testing");
165+
final var doc = BaseDocument.create().chunks(chunk).metadata(docMeta);
166+
final var request = DocumentCreateRequest.create().documents(doc);
167+
final var response = CLIENT_VECTOR.createDocuments(RESOURCE_GROUP, collectionId, request);
168+
169+
if ("json".equals(format)) {
170+
return response;
171+
}
172+
final var ids = response.getDocuments().stream().map(DocumentWithoutChunks::getId).toList();
173+
return "The following document ids are available: %s.".formatted(ids);
174+
}
175+
176+
/** Get all deployments, including non-Java specific deployments */
177+
@GetMapping("/vector/collection/by-id/{id}/clear")
178+
Object deleteDocuments(
179+
@Nonnull @PathVariable("id") final UUID collectionId,
180+
@Nullable @RequestParam(value = "format", required = false) final String format) {
181+
final var dayOfWeek = now().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH);
182+
;
183+
final var chunkMeta = KeyValueListPair.create().key("context").value("day-of-week");
184+
final var chunk =
185+
TextOnlyBaseChunk.create().content("Today is " + dayOfWeek).metadata(chunkMeta);
186+
final var docMeta = DocumentKeyValueListPair.create().key("purpose").value("testing");
187+
final var doc = BaseDocument.create().chunks(chunk).metadata(docMeta);
188+
final var request = DocumentCreateRequest.create().documents(doc);
189+
190+
final var documents = CLIENT_VECTOR.getAllDocuments(RESOURCE_GROUP, collectionId);
191+
final var ids = documents.getResources().stream().map(DocumentWithoutChunks::getId).toList();
192+
log.info("Deleting collection {} with {} documents: {}", collectionId, ids.size(), ids);
193+
194+
for (UUID documentId : ids) {
195+
final var del = CLIENT_VECTOR.deleteDocumentById(RESOURCE_GROUP, collectionId, documentId);
196+
if (del.getStatusCode() >= 400) {
197+
final var msg = "Document {} could not be deleted, status code [{}], headers: ";
198+
log.error(msg, documentId, del.getStatusCode(), del.getHeaders());
199+
throw new IllegalStateException("Document deletion failed for id " + documentId);
200+
}
201+
}
202+
final var response = CLIENT_VECTOR.deleteCollectionById(RESOURCE_GROUP, collectionId + "");
203+
204+
if ("json".equals(format)) {
205+
return response;
206+
}
207+
return response.getStatusCode() >= 400 ? "Failed to delete collection" : "Deletion successful";
208+
}
209+
99210
/** Get all deployments, including non-Java specific deployments */
100211
@GetMapping("/vector/collection/by-id/{collectionId}/document/by-id/{documentId}")
101212
Object getDocumentChunksById(

sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/GroundingTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package com.sap.ai.sdk.app.controllers;
22

3+
import static java.time.LocalDate.now;
34
import static org.assertj.core.api.Assertions.assertThat;
5+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
46

57
import com.sap.ai.sdk.grounding.model.CollectionsListResponse;
68
import com.sap.ai.sdk.grounding.model.DataRepositories;
79
import com.sap.ai.sdk.grounding.model.DocumentResponse;
810
import com.sap.ai.sdk.grounding.model.Documents;
11+
import com.sap.ai.sdk.grounding.model.DocumentsListResponse;
912
import com.sap.ai.sdk.grounding.model.Pipelines;
13+
import com.sap.ai.sdk.grounding.model.RetievalSearchResults;
14+
import com.sap.cloud.sdk.services.openapi.core.OpenApiResponse;
15+
import java.time.format.TextStyle;
16+
import java.util.Locale;
1017
import java.util.UUID;
1118
import org.junit.jupiter.api.Test;
1219

@@ -80,6 +87,65 @@ void testGetDocuments() {
8087
}
8188
}
8289

90+
@Test
91+
void testCreateDeleteCollection() {
92+
final var controller = new GroundingController();
93+
94+
// (1) CREATE COLLECTION
95+
final var collectionId = controller.createCollection(JSON_FORMAT);
96+
final var collectionUuid = UUID.fromString(collectionId);
97+
assertThat(collectionId).isNotNull();
98+
99+
// (2) SANITY CHECK: NO DOCUMENTS
100+
final var documentsEmpty = controller.getDocumentsByCollectionId(collectionUuid, JSON_FORMAT);
101+
assertThat(documentsEmpty).isInstanceOf(Documents.class);
102+
assertThat(((Documents) documentsEmpty).getCount()).isEqualTo(0);
103+
assertThat(((Documents) documentsEmpty).getResources()).isNotNull().isEmpty();
104+
105+
// (3) UPLOAD A DOCUMENT
106+
final var documentCreated = controller.createDocument(collectionUuid, JSON_FORMAT);
107+
assertThat(documentCreated).isInstanceOf(DocumentsListResponse.class);
108+
assertThat(((DocumentsListResponse) documentCreated).getDocuments()).isNotNull().hasSize(1);
109+
110+
// (4) SEARCH FOR DOCUMENTS
111+
Object search = controller.searchInDocuments(JSON_FORMAT);
112+
final var dayOfWeek = now().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH);
113+
114+
assertThat(search).isInstanceOf(RetievalSearchResults.class);
115+
assertThat(((RetievalSearchResults) search).getResults())
116+
.isNotNull()
117+
.isNotEmpty()
118+
.allSatisfy(
119+
r ->
120+
assertThat(r.getResults())
121+
.isNotNull()
122+
.isNotEmpty()
123+
.allSatisfy(
124+
doc ->
125+
assertThat(doc.getDataRepository().getDocuments())
126+
.isNotNull()
127+
.isNotEmpty()
128+
.allSatisfy(
129+
m ->
130+
assertThat(m.getChunks())
131+
.isNotNull()
132+
.isNotEmpty()
133+
.allSatisfy(
134+
chunk ->
135+
assertThat(chunk.getContent())
136+
.isNotNull()
137+
.contains(dayOfWeek)))));
138+
139+
// (5) DELETE COLLECTION
140+
Object deletion = controller.deleteDocuments(collectionUuid, JSON_FORMAT);
141+
assertThat(deletion).isInstanceOf(OpenApiResponse.class);
142+
assertThat(((OpenApiResponse) deletion).getStatusCode()).isEqualTo(202);
143+
144+
// (6) SANITY CHECK: NO COLLECTION
145+
assertThatThrownBy(() -> controller.getDocumentsByCollectionId(collectionUuid, JSON_FORMAT))
146+
.hasMessageContaining("404 Not Found");
147+
}
148+
83149
@Test
84150
void testGetDocumentById() {
85151
final var controller = new GroundingController();

0 commit comments

Comments
 (0)