Skip to main content

Cluster Schema Service

The ClusterSchemaService groups a set of custom document schemas into semantically similar clusters. It sends the schemas to the watsonx.ai clustering API and returns each cluster as a list of ClusterSchemas objects, letting you discover which document types are semantically related.

Quick Start

ClusterSchemaService service = ClusterSchemaService.builder()
.apiKey(WATSONX_API_KEY)
.projectId(WATSONX_PROJECT_ID)
.baseUrl(CloudRegion.DALLAS)
.build();

ClusterSchemas passport = new ClusterSchemas("Passport",
Schema.builder()
.documentType("Passport")
.documentDescription("A government-issued travel document")
.fields(KvpFields.builder()
.add("surname", KvpField.of("The holder's last name", "SMITH"))
.add("given_names", KvpField.of("The holder's first names", "ALICE MARIE"))
.build())
.build());

ClusterSchemas nationalId = new ClusterSchemas("National_ID",
Schema.builder()
.documentType("National ID Card")
.documentDescription("A government-issued national identity document")
.fields(KvpFields.builder()
.add("surname", KvpField.of("The holder's family name", "DOE"))
.add("given_names", KvpField.of("The holder's first names", "JOHN JAMES"))
.build())
.build());

List<List<ClusterSchemas>> groups = service.clusterSchemaAndFetch(passport, nationalId);

for (List<ClusterSchemas> cluster : groups) {
System.out.println("Cluster:");
cluster.forEach(s -> System.out.println(" - " + s.documentName()));
}
// → Cluster:
// → - Passport
// → - National_ID

Overview

The ClusterSchemaService enables you to:

  • Group semantically similar document schemas into clusters automatically.
  • Identify which document types share common fields and structure.
  • Prepare input for schema consolidation workflows before merging.
  • Optionally override the default foundation model used for clustering.

Service Configuration

Basic Setup

ClusterSchemaService service = ClusterSchemaService.builder()
.apiKey(WATSONX_API_KEY)
.projectId(WATSONX_PROJECT_ID)
.baseUrl(CloudRegion.DALLAS)
.build();

Builder Parameters

ParameterTypeRequiredDescription
apiKeyStringConditionalAPI key for IBM Cloud authentication
authenticatorAuthenticatorConditionalCustom authentication (alternative to apiKey)
projectIdStringConditionalProject ID where clustering will be performed
spaceIdStringConditionalSpace ID (alternative to projectId)
baseUrlString/CloudRegionYeswatsonx.ai service base URL
timeoutDurationNoRequest timeout (default: 60 seconds)
logRequestsBooleanNoEnable request logging (default: false)
logResponsesBooleanNoEnable response logging (default: false)
httpClientHttpClientNoCustom HTTP client
verifySslBooleanNoSSL certificate verification (default: true)
versionStringNoAPI version override

Either apiKey or authenticator must be provided. Either projectId or spaceId must be specified.


Examples

Cluster and Fetch in One Call

clusterSchemaAndFetch submits the request, polls until completion, and returns the grouped result directly:

List<List<ClusterSchemas>> groups = service.clusterSchemaAndFetch(passport, nationalId, invoice);

for (List<ClusterSchemas> cluster : groups) {
System.out.println("Cluster: " +
cluster.stream().map(ClusterSchemas::documentName).collect(Collectors.joining(", ")));
}
// → Cluster: Passport, National_ID
// → Cluster: Invoice

With a List of Schemas

Pass a List instead of varargs when the schemas are already collected:

List<ClusterSchemas> schemas = buildSchemas(); // your own list
List<List<ClusterSchemas>> groups = service.clusterSchemaAndFetch(schemas);

With Custom Parameters

Override project/space context or specify a custom semantic model:

ClusterSchemaParameters parameters = ClusterSchemaParameters.builder()
.projectId("other-project-id")
.semanticConfig(
ClusterSchemaSemanticConfig.builder()
.defaultModelName("mistralai/mistral-medium-2505")
.build()
)
.build();

List<List<ClusterSchemas>> groups =
service.clusterSchemaAndFetch(parameters, passport, nationalId);

Async: Start Then Poll

Use startClusterSchema to submit the job without waiting, then retrieve results later:

// Submit the job
ClusterSchemaResponse response = service.startClusterSchema(passport, nationalId);
String jobId = response.metadata().id();

// … do other work …

// Retrieve the result
ClusterSchemaResponse result = service.fetchRequest(jobId);
System.out.println("Status: " + result.entity().results().status());

if (Status.COMPLETED.value().equals(result.entity().results().status())) {
result.entity().results().schemas()
.forEach(cluster -> System.out.println("Cluster: " +
cluster.stream().map(ClusterSchemas::documentName)
.collect(Collectors.joining(", "))));
}

Managing Requests

Cancel or remove a cluster schema job:

ClusterSchemaResponse response = service.startClusterSchema(passport, nationalId);

boolean deleted = service.deleteRequest(
response.metadata().id(),
ClusterSchemaDeleteParameters.builder()
.hardDelete(true)
.build()
);

System.out.println("Deleted: " + deleted);
// → Deleted: true

Deleting a non-existent ID returns false.


Cluster Schema Parameters

ClusterSchemaParameters controls optional per-request overrides.

Builder Reference

ParameterTypeDescription
schemasList<ClusterSchemas>Override the list of schemas to cluster for this request
semanticConfigClusterSchemaSemanticConfigSemantic model configuration
projectIdStringOverride the default Project ID
spaceIdStringOverride the default Space ID
transactionIdStringRequest tracking ID

Using a Custom Foundation Model

Override the default clustering model with defaultModelName:

ClusterSchemaSemanticConfig semanticConfig = ClusterSchemaSemanticConfig.builder()
.defaultModelName("ibm/granite-4-h-small")
.build();

ClusterSchemaParameters parameters = ClusterSchemaParameters.builder()
.semanticConfig(semanticConfig)
.build();

List<List<ClusterSchemas>> groups =
service.clusterSchemaAndFetch(parameters, passport, nationalId);

ClusterSchemaResponse

Returned by startClusterSchema and fetchRequest.

FieldTypeDescription
metadata().id()StringUnique identifier for the cluster schema request
metadata().createdAt()StringTimestamp when the request was created
metadata().projectId()StringProject ID associated with the request
entity().parameters()ParametersParameters used for this clustering
entity().results()ClusterSchemaResultThe current clustering result

ClusterSchemaResult

FieldTypeDescription
status()StringCurrent status: Status.SUBMITTED, Status.RUNNING, Status.COMPLETED, or Status.FAILED (use Status.COMPLETED.value() to compare)
runningAt()StringTimestamp when processing started
completedAt()StringTimestamp when processing completed or failed
schemas()List<List<ClusterSchemas>>The clusters - each inner list contains the schemas grouped together
error()ErrorError details if status is failed

ClusterSchemas

Each entry in a cluster:

FieldTypeDescription
documentName()StringThe name identifying this schema entry
schema()SchemaThe full schema definition