Skip to content

Commit 1d81f41

Browse files
committed
Merge branch 'main' into update-openAI-models-and-test
2 parents c6a47dd + 0d54069 commit 1d81f41

File tree

89 files changed

+19367
-65
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+19367
-65
lines changed

.pipeline/checkstyle-suppressions.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
<suppress files="[/\\]core[/\\]model[/\\]" checks=".*"/>
1111
<suppress files="[/\\]openai[/\\]generated[/\\]model[/\\]" checks=".*"/>
1212
<suppress files="[/\\]orchestration[/\\]model[/\\]" checks=".*"/>
13+
<suppress files="[/\\]grounding[/\\]api[/\\]" checks=".*"/>
14+
<suppress files="[/\\]grounding[/\\]model[/\\]" checks=".*"/>
1315
<!-- Suppress TODOs -->
1416
<suppress files="OpenAiChatMessage.java" checks="TodoComment" lines="257,7" />
1517
<suppress files="ChatCompletionResponseMessage.java" checks="TodoComment" lines="53,34" />

.pipeline/spotbugs-exclusions.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
<Package name="com.sap.ai.sdk.core.client"/>
66
<Package name="com.sap.ai.sdk.core.model"/>
77
<Package name="com.sap.ai.sdk.orchestration.model"/>
8+
<Package name="com.sap.ai.sdk.grounding.client"/>
9+
<Package name="com.sap.ai.sdk.grounding.model"/>
810
</Or>
911
</Match>
1012
</FindBugsFilter>

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ For more detailed information and advanced usage, please refer to the following:
136136
- [<img src="sample-code/spring-app/src/main/resources/static/Open-AI-Logo.svg" width="16"/> OpenAI Chat Completion](docs/guides/OPENAI_CHAT_COMPLETION.md)
137137
- [<img src="https://spring.io/favicon-32x32.png" width="16"/> Spring AI Integration](docs/guides/SPRING_AI_INTEGRATION.md)
138138
- [🧰 AI Core Deployment](docs/guides/AI_CORE_DEPLOYMENT.md)
139+
- [<img src="sample-code/spring-app/src/main/resources/static/grounding.png" width="16"/> AI Core Grounding](docs/guides/GROUNDING.md)
139140

140141
For updating versions, please refer to the [**Release Notes**](docs/release-notes/release-notes-0-to-14.md).
141142

docs/guides/GROUNDING.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Grounding Services
2+
3+
## Table of Contents
4+
5+
- [Introduction](#introduction)
6+
- [Prerequisites](#prerequisites)
7+
- [Maven Dependencies](#maven-dependencies)
8+
- [Usage](#usage)
9+
- [Data Ingestion](#data-ingestion)
10+
- [Pipeline API](#pipeline-api)
11+
- [Vector API](#vector-api)
12+
- [Data Retrieval](#retrieval-api)
13+
- [Retrieval API](#create-a-deployment)
14+
- [Grounding via Orchestration](#grounding-via-orchestration)
15+
16+
## Introduction
17+
18+
This guide provides examples on how to manage data in SAP Document Grounding.
19+
It's divided into two main sections: Data Ingestion and Data Retrieval.
20+
21+
> [!WARNING]
22+
> The below examples rely on generated model classes.
23+
> Please be aware of the [implications described here](/README.md#general-requirements).
24+
25+
## Prerequisites
26+
27+
Before using the Grounding module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements).
28+
Additionally, include the necessary Maven dependency in your project.
29+
30+
### Maven Dependencies
31+
32+
Add the following dependency to your `pom.xml` file:
33+
34+
```xml
35+
<dependency>
36+
<groupId>com.sap.ai.sdk</groupId>
37+
<artifactId>grounding</artifactId>
38+
<version>${ai-sdk.version}</version>
39+
</dependency>
40+
```
41+
42+
See [an example pom in our Spring Boot application](../../sample-code/spring-app/pom.xml)
43+
44+
## Usage
45+
46+
In addition to the prerequisites above, we assume you have already set up the following to carry out the examples in this guide:
47+
48+
- A running instance of SAP AI Core with correctly setup credentials, including a resource group id.
49+
50+
## Data Ingestion
51+
52+
The following APIs are available for data ingestion: Pipeline and Vector.
53+
54+
### Pipeline API
55+
56+
Consider the following code sample to read pipelines, create a new one and get its status:
57+
58+
```java
59+
var api = new GroundingClient().pipelines();
60+
var resourceGroupId = "default";
61+
62+
// get all pipelines
63+
Pipelines pipelines = api.getAllPipelines(resourceGroupId);
64+
65+
// create new pipeline
66+
var type = "MSSharePoint"; // or "S3" or "SFTP"
67+
var pipelineSecret = "my-secret-name";
68+
var config = PipelinePostRequstConfiguration.create().destination(pipelineSecret);
69+
var request = PipelinePostRequst.create().type(type)._configuration(config);
70+
PipelineId pipeline = api.createPipeline(resourceGroupId, request);
71+
72+
// get pipeline status
73+
PipelineStatus status = api.getPipelineStatus(resourceGroupId, pipeline.getPipelineId());
74+
```
75+
76+
### Vector API
77+
78+
```java
79+
var api = new GroundingClient().vector();
80+
var resourceGroupId = "default";
81+
82+
// resolve collection id
83+
var collectionId = UUID.fromString("12345-123-123-123-0123456abcdef");
84+
85+
var request = DocumentCreateRequest.create()
86+
.documents(BaseDocument.create()
87+
.chunks(TextOnlyBaseChunk.create()
88+
.content("The dog makes _woof_")
89+
.metadata(KeyValueListPair.create()
90+
.key("animal").value("dog")))
91+
.metadata(DocumentKeyValueListPair.create()
92+
.key("topic").value("sound")));
93+
DocumentsListResponse response = api.createDocuments(resourceGroupId, collectionId, request);
94+
```
95+
96+
Refer to the [DeploymentController.java](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java) in our Spring Boot application for a complete example.
97+
98+
## Data Retrieval
99+
100+
The following APIs are available for data retrieval: Retrieval and Orchestration.
101+
102+
103+
### Retrieval API
104+
105+
Consider the following code sample to search for relevant grounding data based on a query:
106+
107+
```java
108+
var api = new GroundingClient().retrieval();
109+
var resourceGroupId = "default";
110+
111+
var filter =
112+
RetrievalSearchFilter.create()
113+
.id("question")
114+
.dataRepositoryType(DataRepositoryType.VECTOR)
115+
.dataRepositories(List.of("*"))
116+
.searchConfiguration(SearchConfiguration.create().maxChunkCount(10));
117+
var search = RetrievalSearchInput.create().query("What is SAP Cloud SDK for AI?").filters(filter);
118+
RetievalSearchResults results = api.search(resourceGroupId, search);
119+
```
120+
121+
### Grounding via Orchestration
122+
123+
You can use the grounding service via orchestration.
124+
Please find the [documentation on Orchestration client in the dedicated document](ORCHESTRATION_CHAT_COMPLETION.md).
125+
126+
```java
127+
OrchestrationClient client;
128+
129+
var databaseFilter =
130+
DocumentGroundingFilter.create()
131+
.dataRepositoryType(DataRepositoryType.VECTOR)
132+
.searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(3));
133+
var groundingConfigConfig =
134+
GroundingModuleConfigConfig.create()
135+
.inputParams(List.of("query"))
136+
.outputParam("results")
137+
.addFiltersItem(databaseFilter);
138+
var groundingConfig =
139+
GroundingModuleConfig.create()
140+
.type(GroundingModuleConfig.TypeEnum.DOCUMENT_GROUNDING_SERVICE)
141+
.config(groundingConfigConfig);
142+
var configWithGrounding =
143+
new OrchestrationModuleConfig()
144+
.withLlmConfig(GPT_4O)
145+
.withGroundingConfig(groundingConfig);
146+
147+
var inputParams = Map.of("query", "What is SAP Cloud SDK for AI?");
148+
149+
var prompt =
150+
new OrchestrationPrompt(
151+
inputParams,
152+
Message.system("Context message with embedded grounding results. {{?results}}"));
153+
154+
OrchestrationChatResponse response = client.chatCompletion(prompt, configWithGrounding);
155+
```

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiAssistantMessage.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.sap.ai.sdk.foundationmodels.openai;
22

3+
import static lombok.AccessLevel.PACKAGE;
4+
35
import com.google.common.annotations.Beta;
46
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionRequestAssistantMessage;
57
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionRequestAssistantMessageContent;
8+
import java.util.List;
69
import javax.annotation.Nonnull;
10+
import lombok.AllArgsConstructor;
11+
import lombok.Getter;
712
import lombok.Value;
813
import lombok.experimental.Accessors;
914

@@ -15,13 +20,25 @@
1520
@Beta
1621
@Value
1722
@Accessors(fluent = true)
23+
@AllArgsConstructor(access = PACKAGE)
1824
class OpenAiAssistantMessage implements OpenAiMessage {
1925

20-
/** The role of the message. */
26+
/** The role associated with this message. */
2127
@Nonnull String role = "assistant";
2228

2329
/** The content of the message. */
24-
@Nonnull String content;
30+
@Getter(onMethod_ = @Beta)
31+
@Nonnull
32+
OpenAiMessageContent content;
33+
34+
/**
35+
* Creates a new assistant message with the given single message.
36+
*
37+
* @param singleMessage the message.
38+
*/
39+
OpenAiAssistantMessage(@Nonnull final String singleMessage) {
40+
this(new OpenAiMessageContent(List.of(new OpenAiTextItem(singleMessage))));
41+
}
2542

2643
/**
2744
* Converts the message to a serializable object.
@@ -30,8 +47,9 @@ class OpenAiAssistantMessage implements OpenAiMessage {
3047
*/
3148
@Nonnull
3249
ChatCompletionRequestAssistantMessage createChatCompletionRequestMessage() {
50+
final var textItem = (OpenAiTextItem) this.content().items().get(0);
3351
return new ChatCompletionRequestAssistantMessage()
3452
.role(ChatCompletionRequestAssistantMessage.RoleEnum.fromValue(role()))
35-
.content(ChatCompletionRequestAssistantMessageContent.create(content));
53+
.content(ChatCompletionRequestAssistantMessageContent.create(textItem.text()));
3654
}
3755
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.sap.ai.sdk.foundationmodels.openai;
2+
3+
import com.google.common.annotations.Beta;
4+
5+
/**
6+
* Represents an item in a {@link OpenAiMessageContent} object.
7+
*
8+
* @since 1.4.0
9+
*/
10+
@Beta
11+
public sealed interface OpenAiContentItem permits OpenAiTextItem, OpenAiImageItem {}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package com.sap.ai.sdk.foundationmodels.openai;
2+
3+
import com.google.common.annotations.Beta;
4+
import java.util.Locale;
5+
import javax.annotation.Nonnull;
6+
7+
/**
8+
* Represents an image item in a {@link OpenAiMessageContent} object.
9+
*
10+
* @param imageUrl the URL of the image
11+
* @param detailLevel the detail level of the image (optional)
12+
* @since 1.4.0
13+
*/
14+
@Beta
15+
public record OpenAiImageItem(@Nonnull String imageUrl, @Nonnull DetailLevel detailLevel)
16+
implements OpenAiContentItem {
17+
18+
/**
19+
* Creates a new image item with the given image URL.
20+
*
21+
* @param imageUrl the URL of the image
22+
*/
23+
public OpenAiImageItem(@Nonnull final String imageUrl) {
24+
this(imageUrl, DetailLevel.AUTO);
25+
}
26+
27+
/** The detail level of the image. */
28+
public enum DetailLevel {
29+
/** Low detail level. */
30+
LOW("low"),
31+
/** High detail level. */
32+
HIGH("high"),
33+
/** Automatic detail level. */
34+
AUTO("auto");
35+
36+
private final String level;
37+
38+
/**
39+
* Converts a string to a detail level.
40+
*
41+
* @param str the string to convert
42+
* @return the detail level
43+
*/
44+
@Nonnull
45+
static DetailLevel fromString(@Nonnull final String str) {
46+
return DetailLevel.valueOf(str.toUpperCase(Locale.ENGLISH));
47+
}
48+
49+
/**
50+
* Get the string representation of the DetailLevel
51+
*
52+
* @return the DetailLevel as string
53+
*/
54+
@Nonnull
55+
public String toString() {
56+
return level;
57+
}
58+
59+
DetailLevel(@Nonnull final String level) {
60+
this.level = level;
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)