---
id: document-grounding
title: Document Grounding
hide_title: false
hide_table_of_contents: false
description: How to manage data in SAP Document Grounding using the SAP AI SDK for Java.
keywords:
  - sap
  - cloud
  - sdk
  - ai
---

## Introduction

This guide provides examples on how to manage data in [SAP Document Grounding](https://help.sap.com/docs/sap-ai-core/generative-ai/data-management-apis-6348a01a930d414ab7ac7ab522d81eb5).
It's divided into two main sections: Data Ingestion and Data Retrieval.

:::warning
All classes in the `...model` and `...client` packages are generated from an OpenAPI specification.
These classes can be used, but no API stability guarantees are provided, even for minor releases.
Maintenance and support are limited to ensuring consistency with the service specification.
No additional convenience API layer is provided.
:::

## Prerequisites

Before using the Document Grounding module, ensure that you have met all the general requirements outlined in the [overview](../overview-cloud-sdk-for-ai-java#general-requirements).

Additionally, make sure your [resource group has the Document Grounding service enabled](https://help.sap.com/docs/sap-ai-core/generative-ai/create-resource-group-for-grounding-e32efa5402154101b4cc05c03ef5be09).

Finally, include the necessary Maven dependency in your project.

### Maven Dependencies

Add the following dependency to your `pom.xml` file:

```xml
<dependency>
    <groupId>com.sap.ai.sdk</groupId>
    <artifactId>document-grounding</artifactId>
    <version>${ai-sdk.version}</version>
</dependency>
```

See [an example pom in our Spring Boot application](https://github.com/SAP/ai-sdk-java/tree/main/sample-code/spring-app/pom.xml)

## Usage

In addition to the prerequisites above, we assume you have already set up the following to carry out the examples in this guide:

- A running instance of SAP AI Core with correctly setup credentials, including a resource group id.

## Data Ingestion

The following APIs are available for data ingestion: Pipeline and Vector.

### Pipeline API

Consider the following code sample to read pipelines, create a new one and get its status:

```java
var api = new GroundingClient().pipelines();
var resourceGroupId = "default";

// get all pipelines
GetPipelines pipelines = api.getAllPipelines(resourceGroupId);

// create new pipeline (MSSharePoint example)
var pipelineSecret = "my-secret-name";
var sharePointSite = SharePointSite.create().name("my-site");
var sharePointConfig = SharePointConfig.create().site(sharePointSite);
var config =
    MSSharePointConfiguration.create().destination(pipelineSecret).sharePoint(sharePointConfig);
var request =
    MSSharePointPipelineCreateRequest.create()
        .type(MS_SHARE_POINT)
        ._configuration(config);
PipelineId pipeline = api.createPipeline(resourceGroupId, request);

// get pipeline by id, returns a GetPipeline (MSSharePointPipelineGetResponse, S3PipelineGetResponse, or SFTPPipelineGetResponse)
var status = (MSSharePointPipelineGetResponse) = api.getPipelineById(resourceGroupId, pipeline.getPipelineId());
```

### Vector API

#### Collection creation

```java
String resourceGroupId;
CollectionRequest collectionRequest;

var api = new GroundingClient().vector();

OpenApiResponse documents = api.createCollection(resourceGroupId, collectionRequest);
Map<String, List<String>> headers = documents.getHeaders();

String locationHeader = headers.get("Location").get(0);
String collectionId = locationHeader.replaceAll("^.*?/([a-f0-9-]+)/.*?$", "$1");
```

#### Document creation

```java
var api = new GroundingClient().vector();
var resourceGroupId = "default";

// resolve collection id
var collectionId = UUID.fromString("12345-123-123-123-0123456abcdef");

var request =
    DocumentCreateRequest.create()
        .documents(BaseDocument.create()
            .chunks(TextOnlyBaseChunkCreate.create()
               .content("The dog makes _woof_")
               .addMetadataItem(VectorKeyValueListPair.create().key("animal").value("dog")))
            .addMetadataItem(VectorDocumentKeyValueListPair.create().key("topic").value("sound")
                .matchMode(FilterMatchModeEnum.ANY)));
DocumentsListResponse response = api.createDocuments(resourceGroupId, collectionId, request);
```

Note that it is currently required to add the `.matchMode()` parameter to the `VectorDocumentKeyValueListPair`.
Otherwise, the grounding service will return a `500 Internal Server Error`.

#### Document search

```java
String resourceGroup;
TextSearchRequest textSearch;

var api = new GroundingClient().vector();
VectorSearchResults result = api.search(resourceGroup, textSearch);

String joinedContent = result.getResults().stream()
  .flatMap(r -> r.getResults().stream())
  .flatMap(r -> r.getDocuments().stream())
  .flatMap(d -> d.getChunks().stream())
  .map(VectorChunk::getContent)
  .collect(Collectors.joining());
```

Refer to the [GroundingController](https://github.com/SAP/ai-sdk-java/tree/main/sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/GroundingController.java) in our Spring Boot application for a complete example.

## Data Retrieval

The following APIs are available for data retrieval: Retrieval and Orchestration.

### Retrieval API

Consider the following code sample to search for relevant document grounding data based on a query:

```java
var api = new GroundingClient().retrieval();
var resourceGroupId = "default";

var filter =
    FiltersInner.create()
        .id("question")
        .dataRepositoryType(DataRepositoryType.VECTOR)
        .dataRepositories(List.of("*"))
        .searchConfiguration(RetrievalSearchConfiguration.create().maxChunkCount(10));
var search = RetrievalSearchInput.create().query("What is SAP Cloud SDK for AI?").filters(filter);
RetrievalSearchResults results = api.search(resourceGroupId, search);
```

### Grounding via Orchestration

You can use the grounding service via orchestration.
Please find the [Orchestration documentation on grounding](../orchestration/chat-completion#grounding).

```java
OrchestrationClient client;

var databaseFilter =
    DocumentGroundingFilter.create()
        .dataRepositoryType(VECTOR)
        .searchConfig(GroundingFilterSearchConfiguration.create().maxChunkCount(3));
var groundingConfigConfig =
    GroundingModuleConfigConfig.create()
        .placeholders(
            GroundingModuleConfigConfigPlaceholders.create().input("query").output("results"))
        .addFiltersItem(databaseFilter);
var groundingConfig =
    GroundingModuleConfig.create()
        .type(DOCUMENT_GROUNDING_SERVICE)
        .config(groundingConfigConfig);
var configWithGrounding =
    new OrchestrationModuleConfig().withLlmConfig(GPT_4O).withGroundingConfig(groundingConfig);

var inputParams = Map.of("query", "What is SAP Cloud SDK for AI?");

var prompt =
    new OrchestrationPrompt(
        inputParams,
        Message.system("Context message with embedded grounding results. {{?results}}"));

OrchestrationChatResponse response = client.chatCompletion(prompt, configWithGrounding);
```

## Custom Headers

To add custom headers to single or groups of your grounding calls, you can use the `.withHeader` method of the `GroundingClient`.

```java
var client = new GroundingClient();

var result = client.withHeader("foo", "bar").pipelines().getAllPipelines("default");
```
