IBM watsonx.ai - Examples
Examples
Simple Chat
Chat with a simple string message (automatically converted to a user message):
-
Java
-
XML
-
YAML
from("direct:simpleChat")
.setBody(constant("What is the capital of France?"))
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat")
.log("Response: ${body}"); <route>
<from uri="direct:simpleChat"/>
<setBody>
<constant>What is the capital of France?</constant>
</setBody>
<to uri="ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat"/>
<log message="Response: ${body}"/>
</route> - route:
from:
uri: direct:simpleChat
steps:
- setBody:
constant: "What is the capital of France?"
- to:
uri: ibm-watsonx-ai:chat
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/granite-4-h-small
operation: chat
- log:
message: "Response: ${body}" Chat with System Message
Use a system message to control the assistant’s behavior:
-
Java
-
XML
-
YAML
from("direct:chatWithSystem")
.setHeader("CamelIBMWatsonxAiSystemMessage",
constant("You are a helpful assistant. Keep your answers brief."))
.setBody(constant("What is the capital of Italy?"))
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat")
.log("Response: ${body}"); <route>
<from uri="direct:chatWithSystem"/>
<setHeader name="CamelIBMWatsonxAiSystemMessage">
<constant>You are a helpful assistant. Keep your answers brief.</constant>
</setHeader>
<setBody>
<constant>What is the capital of Italy?</constant>
</setBody>
<to uri="ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat"/>
<log message="Response: ${body}"/>
</route> - route:
from:
uri: direct:chatWithSystem
steps:
- setHeader:
name: CamelIBMWatsonxAiSystemMessage
constant: "You are a helpful assistant. Keep your answers brief."
- setBody:
constant: "What is the capital of Italy?"
- to:
uri: ibm-watsonx-ai:chat
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/granite-4-h-small
operation: chat
- log:
message: "Response: ${body}" Streaming Chat
Stream chat responses with a callback consumer:
Consumer<String> callback and UserMessage SDK typeimport com.ibm.watsonx.ai.chat.model.UserMessage;
from("direct:streamChat")
.process(exchange -> {
// Set up a consumer to handle streamed chunks
Consumer<String> streamHandler = chunk -> {
System.out.print(chunk);
};
exchange.getIn().setHeader("CamelIBMWatsonxAiStreamConsumer", streamHandler);
exchange.getIn().setHeader("CamelIBMWatsonxAiMessages", List.of(
UserMessage.text("Tell me a joke about programming")
));
})
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/granite-4-h-small" +
"&operation=chatStreaming")
.log("Full response: ${body}"); Streaming Chat with WebSocket
Stream chat responses to WebSocket clients in real-time, similar to ChatGPT’s streaming UI. This example uses the camel-vertx-websocket component to receive messages from clients and stream responses back token-by-token:
-
Java
from("vertx-websocket:localhost:8080/chat")
// Store connection key for sending responses back to this specific client
.setProperty("connectionKey", header(VertxWebsocketConstants.CONNECTION_KEY))
.process(exchange -> {
String connectionKey = exchange.getProperty("connectionKey", String.class);
ProducerTemplate producer = exchange.getContext().createProducerTemplate();
// Stream consumer that sends each token as a WebSocket message
Consumer<String> streamHandler = chunk -> {
producer.sendBodyAndHeader(
"vertx-websocket:localhost:8080/chat",
chunk,
VertxWebsocketConstants.CONNECTION_KEY, connectionKey
);
};
exchange.getIn().setHeader(WatsonxAiConstants.STREAM_CONSUMER, streamHandler);
})
.setHeader(WatsonxAiConstants.SYSTEM_MESSAGE, constant("You are a helpful assistant."))
// The WebSocket message body becomes the user question
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/granite-4-h-small" +
"&operation=chatStreaming")
// Send completion marker to client
.process(exchange -> {
String connectionKey = exchange.getProperty("connectionKey", String.class);
exchange.getContext().createProducerTemplate().sendBodyAndHeader(
"vertx-websocket:localhost:8080/chat",
"[DONE]",
VertxWebsocketConstants.CONNECTION_KEY, connectionKey
);
}); This pattern enables building real-time chat applications where:
-
WebSocket clients connect and send messages
-
Each token from the LLM is streamed back immediately
-
Clients receive a
[DONE]marker when the response is complete
Requires the camel-vertx-websocket dependency. See the Vert.x WebSocket component documentation for more details. |
Chat with Tool Calling
Enable the LLM to call external tools (like Wikipedia search) and incorporate results into the conversation. This example shows a fully declarative route with no processors required:
-
Java
-
YAML
import com.ibm.watsonx.ai.chat.ToolRegistry;
import com.ibm.watsonx.ai.chat.model.Tool;
import com.ibm.watsonx.ai.tool.ToolService;
import com.ibm.watsonx.ai.tool.builtin.WikipediaTool;
// Create ToolService for utility tools (requires wxUrl)
ToolService toolService = ToolService.builder()
.apiKey(apiKey)
.baseUrl("https://api.dataplatform.cloud.ibm.com/wx")
.build();
// Create ToolRegistry with Wikipedia tool
ToolRegistry toolRegistry = ToolRegistry.builder()
.register(new WikipediaTool(toolService))
.build();
// Get tool schemas for chat
List<Tool> tools = toolRegistry.tools();
from("direct:chatWithTools")
// Set system message, tools, and registry via headers (body is the user question)
.setHeader("CamelIBMWatsonxAiSystemMessage",
constant("You are a helpful assistant. Use available tools when needed."))
.setHeader("CamelIBMWatsonxAiTools", constant(tools))
.setHeader("CamelIBMWatsonxAiToolRegistry", constant(toolRegistry))
// Send to chat
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/granite-3-8b-instruct" +
"&operation=chat")
// Loop while LLM requests tool calls
.loopDoWhile(simple("${header.CamelIBMWatsonxAiHasToolCalls} == true"))
.log("Executing tool calls...")
// Process tool calls using the dedicated operation
.to("ibm-watsonx-ai:tools?operation=processToolCalls")
// Continue conversation with tool results
.to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/granite-3-8b-instruct" +
"&operation=chat")
.end()
.log("Final response: ${body}"); - route:
from:
uri: direct:chatWithTools
steps:
- setHeader:
name: CamelIBMWatsonxAiSystemMessage
constant: "You are a helpful assistant. Use available tools when needed."
- setHeader:
name: CamelIBMWatsonxAiTools
constant: "{{tools}}"
- setHeader:
name: CamelIBMWatsonxAiToolRegistry
constant: "{{toolRegistry}}"
- to:
uri: ibm-watsonx-ai:chat
parameters:
apiKey: "RAW({{ibm.watsonx.api-key}})"
baseUrl: "{{ibm.watsonx.base-url}}"
projectId: "{{ibm.watsonx.project-id}}"
modelId: ibm/granite-3-8b-instruct
operation: chat
- loop:
id: loop-4459
doWhile: true
expression:
simple:
expression: ${header.CamelIBMWatsonxAiHasToolCalls} == true
steps:
- log:
message: Executing tool calls...
- to:
uri: ibm-watsonx-ai:tools
parameters:
operation: processToolCalls
- to:
uri: ibm-watsonx-ai:chat
parameters:
apiKey: RAW({{ibm.watsonx.api-key}})
baseUrl: "{{ibm.watsonx.base-url}}"
modelId: ibm/granite-3-8b-instruct
operation: chat
projectId: "{{ibm.watsonx.project-id}}"
- log:
message: "Final response: ${body}" The above route:
-
Sets the system message via
CamelIBMWatsonxAiSystemMessageheader -
The message body becomes the user question automatically
-
Sets tools and registry via headers for function calling
-
Uses
processToolCallsoperation to execute tools and update the conversation -
Loops until the LLM provides a final answer without tool calls
Tool operations require the wxUrl configuration (e.g., https://api.dataplatform.cloud.ibm.com/wx), which is different from the ML baseUrl. |
Text Embeddings
Generate embeddings for semantic search and similarity:
List.of() for batch input and process lambda for typed result handlingfrom("direct:embed")
.setBody(constant(List.of(
"Apache Camel is an integration framework",
"Quarkus is a Java framework"
)))
.to("ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/slate-125m-english-rtrvr" +
"&operation=embedding")
.process(exchange -> {
List<List<Float>> embeddings = exchange.getMessage().getBody(List.class);
System.out.println("Generated " + embeddings.size() + " embeddings");
System.out.println("Embedding dimensions: " + embeddings.get(0).size());
}); Single Text Embedding
Generate embedding for a single text input:
-
Java
-
XML
-
YAML
from("direct:embedSingle")
.setBody(constant("Apache Camel makes integration easy"))
.to("ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/slate-125m-english-rtrvr&operation=embedding")
.log("Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}"); <route>
<from uri="direct:embedSingle"/>
<setBody>
<constant>Apache Camel makes integration easy</constant>
</setBody>
<to uri="ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/slate-125m-english-rtrvr&operation=embedding"/>
<log message="Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}"/>
</route> - route:
from:
uri: direct:embedSingle
steps:
- setBody:
constant: "Apache Camel makes integration easy"
- to:
uri: ibm-watsonx-ai:embed
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/slate-125m-english-rtrvr
operation: embedding
- log:
message: "Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}" Embedding with Vector Database (Qdrant)
Generate an embedding and store it in a Qdrant vector database for semantic search:
Points.PointStruct, VectorsFactory, etc.) for vector constructionimport org.apache.camel.component.qdrant.QdrantHeaders;
import org.apache.camel.component.qdrant.QdrantAction;
import io.qdrant.client.PointIdFactory;
import io.qdrant.client.VectorsFactory;
import io.qdrant.client.ValueFactory;
import io.qdrant.client.grpc.Points;
from("direct:embedAndStore")
.setBody(constant("Apache Camel makes integration easy"))
.to("ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/slate-125m-english-rtrvr" +
"&operation=embedding")
// Transform to Qdrant format and upsert
.setHeader(QdrantHeaders.ACTION, constant(QdrantAction.UPSERT))
.process(exchange -> {
List<Float> embedding = exchange.getMessage().getBody(List.class);
exchange.getMessage().setBody(
Points.PointStruct.newBuilder()
.setId(PointIdFactory.id(UUID.randomUUID()))
.setVectors(VectorsFactory.vectors(embedding))
.putPayload("text", ValueFactory.value("Apache Camel makes integration easy"))
.build());
})
.to("qdrant:embeddings?host=localhost&port=6334")
.log("Embedding stored with ID: ${header.CamelQdrantOperationID}"); This example requires the camel-qdrant dependency. See the Qdrant component documentation for more details. |
Rerank Documents
Rerank documents by relevance to a query:
process lambda with List.of() for document inputfrom("direct:rerank")
.process(exchange -> {
// Set the query to rank against
exchange.getIn().setHeader("CamelIBMWatsonxAiRerankQuery",
"What is the best integration framework?");
// Set documents to rerank
exchange.getIn().setBody(List.of(
"Apache Camel provides enterprise integration patterns.",
"Quarkus is great for microservices.",
"Kubernetes orchestrates containers.",
"Apache Kafka handles event streaming."
));
})
.to("ibm-watsonx-ai:rerank?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=cross-encoder/ms-marco-minilm-l-12-v2" +
"&operation=rerank")
.process(exchange -> {
List results = exchange.getMessage().getBody(List.class);
System.out.println("Reranked results: " + results);
}); Rerank with Top N
Return only the top N most relevant documents:
List.of() for document inputfrom("direct:rerankTopN")
.setHeader("CamelIBMWatsonxAiRerankQuery", constant("Cloud computing platform"))
.setHeader("CamelIBMWatsonxAiRerankTopN", constant(3))
.setBody(constant(List.of(
"AWS is a cloud computing platform.",
"Azure provides cloud services.",
"IBM Cloud offers cloud solutions.",
"PostgreSQL is a database.",
"Infinispan is an in-memory store."
)))
.to("ibm-watsonx-ai:rerank?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=cross-encoder/ms-marco-minilm-l-12-v2" +
"&operation=rerank")
.log("Top 3 results: ${body}"); Tokenization
Count tokens in text (useful for context window management):
-
Java
-
XML
-
YAML
from("direct:tokenize")
.setBody(constant("Hello, how are you today?"))
.to("ibm-watsonx-ai:tokenize?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=tokenize")
.log("Token count: ${header.CamelIBMWatsonxAiTokenCount}")
.log("Tokens: ${header.CamelIBMWatsonxAiTokens}"); <route>
<from uri="direct:tokenize"/>
<setBody>
<constant>Hello, how are you today?</constant>
</setBody>
<to uri="ibm-watsonx-ai:tokenize?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=tokenize"/>
<log message="Token count: ${header.CamelIBMWatsonxAiTokenCount}"/>
<log message="Tokens: ${header.CamelIBMWatsonxAiTokens}"/>
</route> - route:
from:
uri: direct:tokenize
steps:
- setBody:
constant: "Hello, how are you today?"
- to:
uri: ibm-watsonx-ai:tokenize
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/granite-4-h-small
operation: tokenize
- log:
message: "Token count: ${header.CamelIBMWatsonxAiTokenCount}"
- log:
message: "Tokens: ${header.CamelIBMWatsonxAiTokens}" Content Detection (PII/HAP)
Detect personally identifiable information (PII) and harmful/abusive/profane (HAP) content:
-
Java
-
XML
-
YAML
from("direct:detect")
.setBody(constant("Contact John Smith at john.smith@example.com or call 555-123-4567"))
.to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectPii=true")
.choice()
.when(header("CamelIBMWatsonxAiDetected").isEqualTo(true))
.log("PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}")
.log("Detection details: ${header.CamelIBMWatsonxAiDetectionResults}")
.otherwise()
.log("No PII detected in content")
.end(); <route>
<from uri="direct:detect"/>
<setBody>
<constant>Contact John Smith at john.smith@example.com or call 555-123-4567</constant>
</setBody>
<to uri="ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectPii=true"/>
<choice>
<when>
<simple>${header.CamelIBMWatsonxAiDetected} == true</simple>
<log message="PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}"/>
<log message="Detection details: ${header.CamelIBMWatsonxAiDetectionResults}"/>
</when>
<otherwise>
<log message="No PII detected in content"/>
</otherwise>
</choice>
</route> - route:
from:
uri: direct:detect
steps:
- setBody:
constant: "Contact John Smith at john.smith@example.com or call 555-123-4567"
- to:
uri: ibm-watsonx-ai:detect
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: detect
detectPii: true
- choice:
when:
- simple: "${header.CamelIBMWatsonxAiDetected} == true"
steps:
- log:
message: "PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}"
- log:
message: "Detection details: ${header.CamelIBMWatsonxAiDetectionResults}"
otherwise:
steps:
- log:
message: "No PII detected in content" Content Detection with HAP Threshold
Detect harmful content with a custom threshold:
-
Java
-
XML
-
YAML
from("direct:detectHap")
.setBody(constant("Some text that might contain harmful content"))
.to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectHap=true&detectionThreshold=0.5")
.choice()
.when(header("CamelIBMWatsonxAiDetected").isEqualTo(true))
.log("ALERT: Harmful content detected!")
.otherwise()
.log("Content is safe")
.end(); <route>
<from uri="direct:detectHap"/>
<setBody>
<constant>Some text that might contain harmful content</constant>
</setBody>
<to uri="ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectHap=true&detectionThreshold=0.5"/>
<choice>
<when>
<simple>${header.CamelIBMWatsonxAiDetected} == true</simple>
<log message="ALERT: Harmful content detected!"/>
</when>
<otherwise>
<log message="Content is safe"/>
</otherwise>
</choice>
</route> - route:
from:
uri: direct:detectHap
steps:
- setBody:
constant: "Some text that might contain harmful content"
- to:
uri: ibm-watsonx-ai:detect
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: detect
detectHap: true
detectionThreshold: 0.5
- choice:
when:
- simple: "${header.CamelIBMWatsonxAiDetected} == true"
steps:
- log:
message: "ALERT: Harmful content detected!"
otherwise:
steps:
- log:
message: "Content is safe" Content Detection with Custom Detectors
Provide custom detectors via header:
Pii, Hap)import com.ibm.watsonx.ai.detection.detector.Pii;
import com.ibm.watsonx.ai.detection.detector.Hap;
from("direct:detectCustom")
.process(exchange -> {
exchange.getIn().setBody("Check this email: user@domain.com");
exchange.getIn().setHeader("CamelIBMWatsonxAiDetectors", List.of(
Pii.ofDefaults(),
Hap.builder().threshold(0.3).build()
));
})
.to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&operation=detect")
.log("Detections: ${body}"); Text Extraction from Cloud Object Storage
Extract text from documents stored in IBM Cloud Object Storage:
| This operation requires COS configuration including cosUrl, documentConnectionId, documentBucket, resultConnectionId, and resultBucket. |
-
Java
-
XML
-
YAML
from("direct:extract")
.setBody(constant("documents/report.pdf"))
.to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtraction&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket")
.log("Extraction job started: ${header.CamelIBMWatsonxAiExtractionId}")
.log("Status: ${header.CamelIBMWatsonxAiExtractionStatus}"); <route>
<from uri="direct:extract"/>
<setBody>
<constant>documents/report.pdf</constant>
</setBody>
<to uri="ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtraction&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket"/>
<log message="Extraction job started: ${header.CamelIBMWatsonxAiExtractionId}"/>
<log message="Status: ${header.CamelIBMWatsonxAiExtractionStatus}"/>
</route> - route:
from:
uri: direct:extract
steps:
- setBody:
constant: "documents/report.pdf"
- to:
uri: ibm-watsonx-ai:extract
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: textExtraction
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
resultConnectionId: your-cos-connection-id
resultBucket: your-output-bucket
- log:
message: "Extraction job started: ${header.CamelIBMWatsonxAiExtractionId}"
- log:
message: "Status: ${header.CamelIBMWatsonxAiExtractionStatus}" Fetch Text Extraction Results
Poll for extraction completion and get results:
-
Java
-
XML
-
YAML
from("direct:fetchExtraction")
.setHeader("CamelIBMWatsonxAiExtractionId", constant("your-extraction-job-id"))
.to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket")
.log("Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}"); <route>
<from uri="direct:fetchExtraction"/>
<setHeader name="CamelIBMWatsonxAiExtractionId">
<constant>your-extraction-job-id</constant>
</setHeader>
<to uri="ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket"/>
<log message="Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}"/>
</route> - route:
from:
uri: direct:fetchExtraction
steps:
- setHeader:
name: CamelIBMWatsonxAiExtractionId
constant: "your-extraction-job-id"
- to:
uri: ibm-watsonx-ai:extract
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: textExtractionFetch
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
resultConnectionId: your-cos-connection-id
resultBucket: your-output-bucket
- log:
message: "Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}" Upload and Extract Local Files (Synchronous)
Upload a local file and get extracted text synchronously using textExtractionUploadAndFetch:
-
Java
-
XML
-
YAML
from("file:/path/to/documents?noop=true")
.to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket")
.log("Extracted text: ${body}")
.log("File processed: ${header.CamelFileName}"); <route>
<from uri="file:/path/to/documents?noop=true"/>
<to uri="ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket"/>
<log message="Extracted text: ${body}"/>
<log message="File processed: ${header.CamelFileName}"/>
</route> - route:
from:
uri: file:/path/to/documents
parameters:
noop: true
steps:
- to:
uri: ibm-watsonx-ai:extract
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: textExtractionUploadAndFetch
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
resultConnectionId: your-cos-connection-id
resultBucket: your-output-bucket
- log:
message: "Extracted text: ${body}"
- log:
message: "File processed: ${header.CamelFileName}" This operation:
-
Automatically handles
File,GenericFile(fromfile://,ftp://,sftp://),InputStream, orbyte[]body types -
Uploads the file to COS
-
Starts text extraction
-
Polls until completion
-
Returns the extracted text as the message body (also available in
CamelIBMWatsonxAiExtractedTextheader)
Text Extraction with File Components
The text extraction operations integrate seamlessly with Camel file components:
// From local file system
from("file:/documents/incoming?noop=true")
.to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...")
.log("Extracted text from ${header.CamelFileName}: ${body}");
// From FTP/SFTP
from("sftp://server/documents?username=xxx&password=xxx")
.to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...")
.log("Extracted: ${header.CamelIBMWatsonxAiExtractedText}");
// From AWS S3
from("aws2-s3://my-bucket?region=us-east-1&prefix=docs/")
.to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...")
.log("Extracted text from S3 object");
// From Azure Blob Storage
from("azure-storage-blob://mycontainer?prefix=documents/")
.to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...")
.log("Extracted text from blob"); Document Classification
Text classification operations allow you to classify documents using IBM watsonx.ai’s document processing capabilities. These operations require Cloud Object Storage (COS) configuration.
| The COS connection in your watsonx.ai project must be configured with HMAC credentials (access_key_id and secret_access_key), not just IAM Service Credentials. See COS Connection Setup for details. |
Classify Documents from Cloud Object Storage
Classify documents already stored in Cloud Object Storage:
-
Java
-
XML
-
YAML
from("direct:classify")
.setBody(constant("documents/contract.pdf"))
.to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassification&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket")
.log("Classification job started: ${header.CamelIBMWatsonxAiClassificationId}"); <route>
<from uri="direct:classify"/>
<setBody>
<constant>documents/contract.pdf</constant>
</setBody>
<to uri="ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassification&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket"/>
<log message="Classification job started: ${header.CamelIBMWatsonxAiClassificationId}"/>
</route> - route:
from:
uri: direct:classify
steps:
- setBody:
constant: "documents/contract.pdf"
- to:
uri: ibm-watsonx-ai:classify
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: textClassification
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
- log:
message: "Classification job started: ${header.CamelIBMWatsonxAiClassificationId}" Upload and Classify Local Files (Synchronous)
Upload a local file and get classification results synchronously using textClassificationUploadAndFetch:
-
Java
-
XML
-
YAML
from("file:/path/to/documents?noop=true")
.to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassificationUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket")
.log("Document type: ${header.CamelIBMWatsonxAiClassificationResult}")
.log("Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}"); <route>
<from uri="file:/path/to/documents?noop=true"/>
<to uri="ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassificationUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket"/>
<log message="Document type: ${header.CamelIBMWatsonxAiClassificationResult}"/>
<log message="Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}"/>
</route> - route:
from:
uri: file:/path/to/documents
parameters:
noop: true
steps:
- to:
uri: ibm-watsonx-ai:classify
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
operation: textClassificationUploadAndFetch
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
- log:
message: "Document type: ${header.CamelIBMWatsonxAiClassificationResult}"
- log:
message: "Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}" This operation:
-
Automatically handles
File,GenericFile(fromfile://,ftp://,sftp://),InputStream, orbyte[]body types -
Uploads the file to COS
-
Starts classification
-
Polls until completion
-
Returns the classification result
Upload and Classify (Asynchronous with Polling)
For more control, use the async flow with textClassificationUpload and textClassificationFetch in a single route with polling loop:
loopDoWhile, delay, exchangeProperty, and `choice`// Start classification and poll until complete
from("direct:startClassification")
.to("ibm-watsonx-ai:classify?operation=textClassificationUpload" +
"&apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" +
"&documentConnectionId=your-cos-connection-id" +
"&documentBucket=your-input-bucket")
.log("Classification started - ID: ${header.CamelIBMWatsonxAiClassificationId}")
.setProperty("classificationId", header("CamelIBMWatsonxAiClassificationId"))
// Poll until complete or failed
.loopDoWhile(simple("${header.CamelIBMWatsonxAiClassificationStatus} != 'completed' && ${header.CamelIBMWatsonxAiClassificationStatus} != 'failed'"))
.delay(2000)
.setHeader("CamelIBMWatsonxAiClassificationId", exchangeProperty("classificationId"))
.to("ibm-watsonx-ai:classify?operation=textClassificationFetch" +
"&apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" +
"&documentConnectionId=your-cos-connection-id" +
"&documentBucket=your-input-bucket")
.log("Status: ${header.CamelIBMWatsonxAiClassificationStatus}")
.end()
.choice()
.when(header("CamelIBMWatsonxAiClassificationStatus").isEqualTo("completed"))
.log("Classification result: ${header.CamelIBMWatsonxAiClassificationResult}")
.otherwise()
.log("Classification failed: ${header.CamelIBMWatsonxAiErrorMessage}")
.end(); Classification with File Components
The classification operations integrate seamlessly with Camel file components:
// From local file system
from("file:/documents/incoming?noop=true")
.to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...")
.log("Classified ${header.CamelFileName} as ${header.CamelIBMWatsonxAiClassificationResult}");
// From FTP/SFTP
from("sftp://server/documents?username=xxx&password=xxx")
.to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...")
.log("Classified: ${header.CamelIBMWatsonxAiClassificationResult}");
// From AWS S3
from("aws2-s3://my-bucket?region=us-east-1&prefix=docs/")
.to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...")
.log("Classified S3 object: ${header.CamelIBMWatsonxAiClassificationResult}");
// From Azure Blob Storage
from("azure-storage-blob://mycontainer?prefix=documents/")
.to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...")
.log("Classified blob: ${header.CamelIBMWatsonxAiClassificationResult}"); Delete Classification Request
Clean up a classification job:
-
Java
-
XML
-
YAML
from("direct:deleteClassification")
.setBody(constant("classification-job-id"))
.to("ibm-watsonx-ai:classify?operation=textClassificationDeleteRequest&apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket")
.log("Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}"); <route>
<from uri="direct:deleteClassification"/>
<setBody>
<constant>classification-job-id</constant>
</setBody>
<to uri="ibm-watsonx-ai:classify?operation=textClassificationDeleteRequest&apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket"/>
<log message="Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}"/>
</route> - route:
from:
uri: direct:deleteClassification
steps:
- setBody:
constant: "classification-job-id"
- to:
uri: ibm-watsonx-ai:classify
parameters:
operation: textClassificationDeleteRequest
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud"
documentConnectionId: your-cos-connection-id
documentBucket: your-input-bucket
- log:
message: "Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}" Supported File Types
Text classification supports the following input file types:
-
Documents: PDF, DOC, DOCX, PPT, PPTX, XLSX
-
Images: BMP, GIF, JFIF, JPG, PNG, TIFF
-
Text: HTML, Markdown
For complete details on supported file formats, see:
Supported Foundation Models for Classification
-
mistral-small-3-1-24b-instruct-2503(certified for key-value pair classification) -
llama-4-maverick-17b-128e-instruct-fp8 -
mistral-medium-2505
For the latest list of supported models, see the IBM watsonx.ai Text Classification documentation.
Using Input Header
Provide input via header instead of body:
-
Java
-
XML
-
YAML
from("direct:headerInput")
.setHeader("CamelIBMWatsonxAiInput", constant("What is machine learning?"))
.to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration")
.log("Generated text: ${body}"); <route>
<from uri="direct:headerInput"/>
<setHeader name="CamelIBMWatsonxAiInput">
<constant>What is machine learning?</constant>
</setHeader>
<to uri="ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration"/>
<log message="Generated text: ${body}"/>
</route> - route:
from:
uri: direct:headerInput
steps:
- setHeader:
name: CamelIBMWatsonxAiInput
constant: "What is machine learning?"
- to:
uri: ibm-watsonx-ai:gen
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/granite-13b-instruct-v2
operation: textGeneration
- log:
message: "Generated text: ${body}" Accessing Response Metadata
Access token counts and stop reason from response headers:
-
Java
-
XML
-
YAML
from("direct:metadata")
.setBody(constant("Summarize the benefits of cloud computing"))
.to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration")
.log("Generated: ${body}")
.log("Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}")
.log("Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}")
.log("Stop reason: ${header.CamelIBMWatsonxAiStopReason}"); <route>
<from uri="direct:metadata"/>
<setBody>
<constant>Summarize the benefits of cloud computing</constant>
</setBody>
<to uri="ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration"/>
<log message="Generated: ${body}"/>
<log message="Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}"/>
<log message="Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}"/>
<log message="Stop reason: ${header.CamelIBMWatsonxAiStopReason}"/>
</route> - route:
from:
uri: direct:metadata
steps:
- setBody:
constant: "Summarize the benefits of cloud computing"
- to:
uri: ibm-watsonx-ai:gen
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
projectId: yourProjectId
modelId: ibm/granite-13b-instruct-v2
operation: textGeneration
- log:
message: "Generated: ${body}"
- log:
message: "Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}"
- log:
message: "Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}"
- log:
message: "Stop reason: ${header.CamelIBMWatsonxAiStopReason}" Time Series Forecasting
Generate time series forecasts:
InputSchema, ForecastData) for time series data constructionimport com.ibm.watsonx.ai.timeseries.InputSchema;
import com.ibm.watsonx.ai.timeseries.ForecastData;
from("direct:forecast")
.process(exchange -> {
// Define the schema
InputSchema schema = InputSchema.builder()
.timestampColumn("date")
.addIdColumn("series_id")
.build();
// Create forecast data
ForecastData data = ForecastData.create()
.addAll("date", "2024-01-01T00:00:00", "2024-01-02T00:00:00", "2024-01-03T00:00:00")
.add("series_id", "S1", 3)
.addAll("value", 10.5, 12.3, 11.8);
exchange.getIn().setHeader("CamelIBMWatsonxAiForecastInputSchema", schema);
exchange.getIn().setHeader("CamelIBMWatsonxAiForecastData", data);
})
.to("ibm-watsonx-ai:forecast?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&projectId=yourProjectId" +
"&modelId=ibm/granite-ttm-1536-96-r2" +
"&operation=forecast")
.log("Forecast results: ${body}"); List Available Models
Explore the model catalog:
-
Java
-
XML
-
YAML
from("direct:listModels")
.to("ibm-watsonx-ai:models?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listModels")
.log("Available models: ${body}"); <route>
<from uri="direct:listModels"/>
<to uri="ibm-watsonx-ai:models?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listModels"/>
<log message="Available models: ${body}"/>
</route> - route:
from:
uri: direct:listModels
steps:
- to:
uri: ibm-watsonx-ai:models
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
operation: listModels
- log:
message: "Available models: ${body}" List Supported Tasks
Discover available tasks:
-
Java
-
XML
-
YAML
from("direct:listTasks")
.to("ibm-watsonx-ai:tasks?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTasks")
.log("Available tasks: ${body}"); <route>
<from uri="direct:listTasks"/>
<to uri="ibm-watsonx-ai:tasks?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTasks"/>
<log message="Available tasks: ${body}"/>
</route> - route:
from:
uri: direct:listTasks
steps:
- to:
uri: ibm-watsonx-ai:tasks
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
operation: listTasks
- log:
message: "Available tasks: ${body}" Deployment Chat
Chat using a deployed model:
-
Java
-
XML
-
YAML
from("direct:deploymentChat")
.setBody(constant("What is the capital of France?"))
.to("ibm-watsonx-ai:deploy?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&deploymentId=your-deployment-id&operation=deploymentChat")
.log("Response: ${body}"); <route>
<from uri="direct:deploymentChat"/>
<setBody>
<constant>What is the capital of France?</constant>
</setBody>
<to uri="ibm-watsonx-ai:deploy?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&deploymentId=your-deployment-id&operation=deploymentChat"/>
<log message="Response: ${body}"/>
</route> - route:
from:
uri: direct:deploymentChat
steps:
- setBody:
constant: "What is the capital of France?"
- to:
uri: ibm-watsonx-ai:deploy
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
deploymentId: your-deployment-id
operation: deploymentChat
- log:
message: "Response: ${body}" Run Utility Tool
Use watsonx.ai utility tools (experimental):
process lambda with Map.of() for tool input and configfrom("direct:runTool")
.process(exchange -> {
// Set tool name
exchange.getIn().setHeader("CamelIBMWatsonxAiToolName", "GoogleSearch");
// Set structured input
exchange.getIn().setBody(Map.of("q", "Apache Camel integration framework"));
// Optional: set config
exchange.getIn().setHeader("CamelIBMWatsonxAiToolConfig", Map.of("maxResults", 5));
})
.to("ibm-watsonx-ai:tool?apiKey=RAW(yourApiKey)" +
"&baseUrl=https://us-south.ml.cloud.ibm.com" +
"&operation=runTool")
.log("Tool result: ${body}"); List Available Tools
Discover available utility tools:
-
Java
-
XML
-
YAML
from("direct:listTools")
.to("ibm-watsonx-ai:tools?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTools")
.log("Available tools: ${body}"); <route>
<from uri="direct:listTools"/>
<to uri="ibm-watsonx-ai:tools?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTools"/>
<log message="Available tools: ${body}"/>
</route> - route:
from:
uri: direct:listTools
steps:
- to:
uri: ibm-watsonx-ai:tools
parameters:
apiKey: "RAW(yourApiKey)"
baseUrl: "https://us-south.ml.cloud.ibm.com"
operation: listTools
- log:
message: "Available tools: ${body}"