Quarkus extension for integrating IBM watsonx.ai foundation models with LangChain4j. Provides chat models, generation models, streaming models, embedding models, and scoring models for IBM watsonx.ai. Includes comprehensive configuration options, support for tool/function calling, text extraction from documents in Cloud Object Storage, and experimental built-in services for Google search, weather, and web crawling. Designed for enterprise Java applications using the Quarkus framework with built-in dependency injection and native compilation support.
A Quarkus extension that provides seamless integration between Quarkus applications and IBM watsonx.ai foundation models through the LangChain4j framework. This extension enables Java developers to incorporate IBM's generative AI capabilities into enterprise applications with chat models, generation models, streaming support, embedding models, scoring models, text extraction from documents, and experimental built-in services.
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-watsonx</artifactId>
<version>1.7.4</version>
</dependency>import io.quarkiverse.langchain4j.watsonx.*;
import io.quarkiverse.langchain4j.watsonx.runtime.config.*;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.scoring.ScoringModel;Configure in application.properties:
quarkus.langchain4j.watsonx.base-url=https://us-south.ml.cloud.ibm.com
quarkus.langchain4j.watsonx.api-key=your-api-key
quarkus.langchain4j.watsonx.project-id=your-project-id
quarkus.langchain4j.watsonx.chat-model.model-name=meta-llama/llama-4-maverick-17b-128e-instruct-fp8
quarkus.langchain4j.watsonx.chat-model.temperature=0.7
quarkus.langchain4j.watsonx.chat-model.max-tokens=2048Inject and use the models:
import jakarta.inject.Inject;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.response.ChatResponse;
public class MyService {
@Inject
ChatModel chatModel;
public String chat(String userMessage) {
ChatResponse response = chatModel.chat(UserMessage.from(userMessage));
return response.aiMessage().text();
}
}import io.quarkiverse.langchain4j.watsonx.WatsonxChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.data.message.UserMessage;
import java.net.URL;
WatsonxChatModel model = WatsonxChatModel.builder()
.modelId("meta-llama/llama-4-maverick-17b-128e-instruct-fp8")
.url(new URL("https://us-south.ml.cloud.ibm.com"))
.projectId("your-project-id")
.tokenGenerator(tokenGenerator) // Handles IBM Cloud IAM authentication
.temperature(0.7)
.maxTokens(2048)
.build();
ChatResponse response = model.chat(UserMessage.from("Hello!"));
String aiResponse = response.aiMessage().text();The extension follows Quarkus extension patterns with:
Key components:
Modern chat-based text generation supporting tool/function calling, streaming responses, and JSON schema-based outputs. Implements LangChain4j's ChatModel and StreamingChatModel interfaces.
public class WatsonxChatModel implements ChatModel {
public static Builder builder();
public ChatResponse doChat(ChatRequest chatRequest);
public List<ChatModelListener> listeners();
public ChatRequestParameters defaultRequestParameters();
public Set<Capability> supportedCapabilities();
}
public class WatsonxStreamingChatModel implements StreamingChatModel {
public static Builder builder();
public void doChat(ChatRequest chatRequest, StreamingChatResponseHandler handler);
public List<ChatModelListener> listeners();
public ChatRequestParameters defaultRequestParameters();
public Set<Capability> supportedCapabilities();
}Legacy text generation models without tool support, providing backward compatibility with older Watsonx generation APIs. Supports both synchronous and streaming responses.
public class WatsonxGenerationModel implements ChatModel {
public static Builder builder();
public ChatResponse doChat(ChatRequest chatRequest);
public List<ChatModelListener> listeners();
public ChatRequestParameters defaultRequestParameters();
public Set<Capability> supportedCapabilities();
}
public class WatsonxGenerationStreamingModel implements StreamingChatModel {
public static Builder builder();
public void doChat(ChatRequest chatRequest, StreamingChatResponseHandler handler);
public List<ChatModelListener> listeners();
public ChatRequestParameters defaultRequestParameters();
public Set<Capability> supportedCapabilities();
}Generate text embeddings for semantic search and score text segments for relevance ranking. Essential for RAG (Retrieval-Augmented Generation) applications.
public class WatsonxEmbeddingModel implements EmbeddingModel {
public static Builder builder();
public Response<List<Embedding>> embedAll(List<TextSegment> textSegments);
}
public class WatsonxScoringModel implements ScoringModel {
public static Builder builder();
public Response<List<Double>> scoreAll(List<TextSegment> textSegments, String query);
}Extract text content from documents (PDF, images) stored in IBM Cloud Object Storage. Supports multiple output formats including JSON, Markdown, HTML, and plain text.
public class TextExtraction {
public TextExtraction(Reference documentReference, Reference resultReference,
String projectId, String spaceId, String version,
COSRestApi cosClient, WatsonxRestApi watsonxClient);
// Synchronous extraction
public String extractAndFetch(String absolutePath);
public String extractAndFetch(String absolutePath, Parameters parameters);
public String uploadExtractAndFetch(File file);
public String uploadExtractAndFetch(File file, Parameters parameters);
public String uploadExtractAndFetch(InputStream is, String fileName);
public String uploadExtractAndFetch(InputStream is, String fileName, Parameters parameters);
// Asynchronous extraction
public String startExtraction(String absolutePath);
public String startExtraction(String absolutePath, Parameters parameters);
public String uploadAndStartExtraction(File file);
public String uploadAndStartExtraction(File file, Parameters parameters);
public String uploadAndStartExtraction(InputStream is, String fileName);
public String uploadAndStartExtraction(InputStream is, String fileName, Parameters parameters);
// Status and cleanup
public TextExtractionResponse checkExtractionStatus(String id);
public void deleteFile(String bucketName, String path);
public void deleteFile(String bucketName, String path, Duration timeout);
}Override default model parameters on a per-request basis with Watsonx-specific parameter classes that extend LangChain4j's default parameter system.
public class WatsonxChatRequestParameters extends DefaultChatRequestParameters {
public static Builder builder();
public Map<String, Integer> logitBias();
public Boolean logprobs();
public Integer topLogprobs();
public Integer n();
public Integer seed();
public String toolChoiceName();
public Duration timeLimit();
public ChatRequestParameters overrideWith(ChatRequestParameters that);
}
public class WatsonxGenerationRequestParameters extends DefaultChatRequestParameters {
public static Builder builder();
public String decodingMethod();
public LengthPenalty lengthPenalty();
public Integer minNewTokens();
public Integer randomSeed();
public Duration timeLimit();
public Double repetitionPenalty();
public Integer truncateInputTokens();
public Boolean includeStopSequence();
public ChatRequestParameters overrideWith(ChatRequestParameters that);
}Comprehensive Quarkus configuration for all models, authentication, and services through application.properties. Supports both default and named model configurations.
Configuration prefix: quarkus.langchain4j.watsonx
Key configuration interfaces:
LangChain4jWatsonxConfig - Root configurationWatsonConfig - Connection and model settingsChatModelConfig - Chat model parametersGenerationModelConfig - Generation model parametersEmbeddingModelConfig - Embedding model parametersScoringModelConfig - Scoring model parametersIAMConfig - IBM Cloud IAM authenticationTextExtractionConfig - Text extraction settingsBuiltinServiceConfig - Built-in services configurationExperimental utility services for Google search, weather information, and web page content extraction. These services integrate with Watsonx's utility agent tools API.
@Experimental
public class GoogleSearchService {
public GoogleSearchService(UtilityAgentToolsRestApi client, GoogleSearchConfig config);
public List<GoogleSearchResult> search(String input);
public List<GoogleSearchResult> search(String input, Integer maxResults);
}
@Experimental
public class WeatherService {
public WeatherService(UtilityAgentToolsRestApi client);
public String find(String name, String country)
throws WeatherServiceException, NoCityFoundException;
}
@Experimental
public class WebCrawlerService {
public WebCrawlerService(UtilityAgentToolsRestApi client);
public WebCrawlerResult process(String url) throws BuiltinServiceException;
}Helper utilities for retry logic, token expiration detection, and image handling.
public class WatsonxUtils {
public static <T> T retryOn(Callable<T> action);
public static boolean isTokenExpired(Throwable exception);
public static String base64Image(Image image);
}Comprehensive exception hierarchy for different error sources including Watsonx API errors, IBM Cloud IAM authentication errors, Cloud Object Storage errors, and built-in service errors.
public class WatsonxException extends RuntimeException {
public WatsonxException(String message, Integer statusCode, WatsonxError details);
public WatsonxException(String message, Integer statusCode);
public WatsonxException(Integer statusCode, WatsonxError details);
public WatsonxException(Throwable cause, Integer statusCode);
public Integer statusCode();
public WatsonxError details();
}
public class TextExtractionException extends RuntimeException {
public TextExtractionException(String code, String message);
public TextExtractionException(String code, String message, Throwable cause);
}
public class COSException extends RuntimeException {
public COSException(Integer statusCode, CosError details);
public COSException(String message, Integer statusCode);
public Integer statusCode();
public CosError details();
}
public class BuiltinServiceException extends RuntimeException {
public BuiltinServiceException(Integer statusCode, String details);
public Integer statusCode();
public String details();
}Configure multiple models with different settings:
# Default chat model
quarkus.langchain4j.watsonx.chat-model.temperature=0.7
quarkus.langchain4j.watsonx.chat-model.max-tokens=2048
# Named configuration for creative writing
quarkus.langchain4j.watsonx.creative.chat-model.temperature=1.5
quarkus.langchain4j.watsonx.creative.chat-model.max-tokens=4096
# Named configuration for factual responses
quarkus.langchain4j.watsonx.factual.chat-model.temperature=0.1
quarkus.langchain4j.watsonx.factual.chat-model.max-tokens=1024Inject named models using CDI qualifiers:
@Inject
@Named("creative")
ChatModel creativeModel;
@Inject
@Named("factual")
ChatModel factualModel;Override model defaults on a per-request basis:
import io.quarkiverse.langchain4j.watsonx.WatsonxChatRequestParameters;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.data.message.UserMessage;
WatsonxChatRequestParameters params = WatsonxChatRequestParameters.builder()
.temperature(0.9)
.maxOutputTokens(500)
.seed(42)
.build();
ChatRequest request = ChatRequest.builder()
.messages(List.of(UserMessage.from("Tell me a story")))
.parameters(params)
.build();
ChatResponse response = chatModel.chat(request);The extension automatically retries requests when IBM Cloud IAM tokens expire. For custom retry logic:
import io.quarkiverse.langchain4j.watsonx.WatsonxUtils;
String result = WatsonxUtils.retryOn(() -> {
// Your Watsonx API call here
return model.chat(message);
});Enable tools with chat models:
import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.model.chat.request.ToolChoice;
public class WeatherTools {
@Tool("Get current weather for a city")
public String getCurrentWeather(String city, String country) {
// Implementation
return "Weather data for " + city;
}
}
// Configure tool choice in application.properties
quarkus.langchain4j.watsonx.chat-model.tool-choice=auto
// Or set programmatically
WatsonxChatModel model = WatsonxChatModel.builder()
.toolChoice(ToolChoice.AUTO)
.build();Use streaming models for real-time responses:
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.output.StreamingResponseHandler;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
@Inject
StreamingChatModel streamingModel;
public void streamChat(String userMessage) {
streamingModel.chat(
ChatRequest.builder()
.messages(List.of(UserMessage.from(userMessage)))
.build(),
new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
System.out.print(partialResponse);
}
@Override
public void onComplete(ChatResponse response) {
System.out.println("\nComplete!");
}
@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
}
);
}IBM Watsonx.ai is available in multiple regions. Configure the base URL for your region:
quarkus.langchain4j.watsonx.base-url=https://us-south.ml.cloud.ibm.comThe extension uses IBM Cloud IAM (Identity and Access Management) for authentication. Provide your IBM Cloud API key:
quarkus.langchain4j.watsonx.api-key=your-ibm-cloud-api-keyThe extension automatically manages token lifecycle including:
For custom IAM configuration:
quarkus.langchain4j.watsonx.iam.base-url=https://iam.cloud.ibm.com
quarkus.langchain4j.watsonx.iam.timeout=10sWatsonx resources can be organized in either projects or deployment spaces. Specify one (mutually exclusive):
Project ID (for development and experimentation):
quarkus.langchain4j.watsonx.project-id=your-project-idSpace ID (for production deployments):
quarkus.langchain4j.watsonx.space-id=your-space-idEnable request/response logging for troubleshooting:
# Log request and response bodies
quarkus.langchain4j.watsonx.log-requests=true
quarkus.langchain4j.watsonx.log-responses=true
# Log requests as cURL commands for easy reproduction
quarkus.langchain4j.watsonx.log-requests-curl=trueOverride logging for specific models:
quarkus.langchain4j.watsonx.chat-model.log-requests=true
quarkus.langchain4j.watsonx.embedding-model.log-requests=falseInstall with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-watsonx@1.7.0