Quarkus LangChain4j OpenAI extension provides seamless integration between Quarkus and OpenAI's Large Language Models, enabling developers to easily incorporate LLMs into their applications with support for chat, streaming, embeddings, moderation, and image generation.
A Quarkus extension that provides seamless integration between Quarkus applications and OpenAI's Large Language Models through the LangChain4j framework. This extension enables developers to easily incorporate chat models, streaming chat, embeddings, content moderation, and image generation into their Quarkus applications using configuration-driven development with full support for dependency injection, observability, and native compilation.
pom.xml:<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-openai</artifactId>
<version>1.7.4</version>
</dependency>// Builder factories for programmatic model creation
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiChatModelBuilderFactory;
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiStreamingChatModelBuilderFactory;
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiEmbeddingModelBuilderFactory;
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiModerationModelBuilderFactory;
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
// Configuration interfaces (for reference)
import io.quarkiverse.langchain4j.openai.runtime.config.LangChain4jOpenAiConfig;
import io.quarkiverse.langchain4j.openai.runtime.config.ChatModelConfig;
// Standard LangChain4j interfaces (typically used via CDI)
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.moderation.ModerationModel;
import dev.langchain4j.model.image.ImageModel;Configure OpenAI models in application.properties:
# OpenAI API Configuration
quarkus.langchain4j.openai.api-key=sk-your-api-key
quarkus.langchain4j.openai.base-url=https://api.openai.com/v1/
# Chat Model Configuration
quarkus.langchain4j.openai.chat-model.model-name=gpt-4o-mini
quarkus.langchain4j.openai.chat-model.temperature=0.7
quarkus.langchain4j.openai.chat-model.max-completion-tokens=2048Inject and use the model:
import jakarta.inject.Inject;
import dev.langchain4j.model.chat.ChatModel;
public class MyService {
@Inject
ChatModel chatModel;
public String generateResponse(String userMessage) {
return chatModel.generate(userMessage);
}
}Create models programmatically using builder pattern:
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.output.Response;
// Builder automatically uses Quarkus-enhanced implementation via SPI
ChatModel chatModel = OpenAiChatModel.builder()
.apiKey("sk-your-api-key")
.modelName("gpt-4o-mini")
.temperature(0.7)
.maxCompletionTokens(2048)
.build();
Response<AiMessage> response = chatModel.generate("What is the capital of France?");
System.out.println(response.content().text());Configure multiple OpenAI model instances with different settings:
# Default configuration
quarkus.langchain4j.openai.api-key=sk-default-key
# Named "premium" configuration for GPT-4
quarkus.langchain4j.openai.premium.api-key=sk-premium-key
quarkus.langchain4j.openai.premium.chat-model.model-name=gpt-4o
quarkus.langchain4j.openai.premium.chat-model.temperature=0.3
# Named "creative" configuration
quarkus.langchain4j.openai.creative.api-key=sk-creative-key
quarkus.langchain4j.openai.creative.chat-model.model-name=gpt-4o
quarkus.langchain4j.openai.creative.chat-model.temperature=1.5Use named configurations programmatically:
ChatModel premiumModel = OpenAiChatModel.builder()
.configName("premium") // Reference named configuration
.build();
ChatModel creativeModel = OpenAiChatModel.builder()
.configName("creative")
.build();The extension follows Quarkus extension patterns with a clear separation of concerns:
The extension registers custom builder factories that extend LangChain4j's base builders through Java's SPI mechanism. When developers use standard LangChain4j builder APIs like OpenAiChatModel.builder(), the SPI automatically returns Quarkus-enhanced builders that include additional methods for:
configName())tlsConfigurationName())proxy())logCurl())Uses Quarkus SmallRye Config for declarative configuration with strong typing:
LangChain4jOpenAiConfig with prefix quarkus.langchain4j.openaiThe OpenAiRecorder manages runtime initialization using Quarkus's build-time recording mechanism. It creates model supplier functions that are invoked at runtime to instantiate models based on configuration.
/**
* Quarkus build-time recorder for OpenAI runtime integration.
*
* This class uses Quarkus's @Recorder annotation to create functions that
* are executed at runtime to instantiate and configure OpenAI models based
* on the runtime configuration. It bridges the build-time deployment module
* with runtime model creation.
*/
@Recorder
public class OpenAiRecorder {
/**
* Create a function to instantiate chat models at runtime.
*
* Parameters:
* configName - Named configuration to use, or null for default
*
* Returns:
* Function that creates ChatModel instances from SyntheticCreationalContext
*
* The returned function is invoked by Quarkus CDI system when a ChatModel
* is injected, using the appropriate configuration.
*/
public Function<SyntheticCreationalContext<ChatModel>, ChatModel> chatModel(String configName);
/**
* Create a function to instantiate streaming chat models at runtime.
*
* Parameters:
* configName - Named configuration to use, or null for default
*
* Returns:
* Function that creates StreamingChatModel instances from SyntheticCreationalContext
*/
public Function<SyntheticCreationalContext<StreamingChatModel>, StreamingChatModel> streamingChatModel(String configName);
/**
* Create a supplier to instantiate embedding models at runtime.
*
* Parameters:
* configName - Named configuration to use, or null for default
*
* Returns:
* Supplier that creates EmbeddingModel instances
*/
public Supplier<EmbeddingModel> embeddingModel(String configName);
/**
* Create a supplier to instantiate moderation models at runtime.
*
* Parameters:
* configName - Named configuration to use, or null for default
*
* Returns:
* Supplier that creates ModerationModel instances
*/
public Supplier<ModerationModel> moderationModel(String configName);
/**
* Create a supplier to instantiate image models at runtime.
*
* Parameters:
* configName - Named configuration to use, or null for default
*
* Returns:
* Supplier that creates ImageModel instances
*/
public Supplier<ImageModel> imageModel(String configName);
/**
* Register cleanup handlers for Quarkus shutdown.
*
* Parameters:
* shutdown - Quarkus shutdown context
*
* This method is called during Quarkus shutdown to properly clean up
* resources such as HTTP clients and thread pools used by OpenAI models.
*/
public void cleanUp(ShutdownContext shutdown);
}Key responsibilities:
enableIntegration=falseNote: OpenAiRecorder is primarily used internally by Quarkus and is not typically invoked directly by application code. Model instantiation is handled automatically through CDI injection or builder patterns.
The extension provides five model types, each with dedicated configuration and builder support:
Comprehensive configuration for OpenAI models through Quarkus properties, supporting global settings, model-specific parameters, named configurations for multiple instances, TLS configuration, HTTP proxy settings, and enterprise features like logging and observability.
public interface LangChain4jOpenAiConfig {
OpenAiConfig defaultConfig();
Map<String, OpenAiConfig> namedConfig();
}
public interface OpenAiConfig {
String baseUrl(); // default: "https://api.openai.com/v1/"
Optional<String> tlsConfigurationName();
String apiKey();
Optional<String> organizationId();
Optional<Duration> timeout(); // default: 10s
Integer maxRetries(); // default: 1
Optional<Boolean> logRequests();
Optional<Boolean> logResponses();
Optional<Boolean> logRequestsCurl();
Boolean enableIntegration(); // default: true
String proxyType(); // default: "HTTP"
Optional<String> proxyHost();
Integer proxyPort(); // default: 3128
ChatModelConfig chatModel();
EmbeddingModelConfig embeddingModel();
ModerationModelConfig moderationModel();
ImageModelConfig imageModel();
}Synchronous and streaming chat model integration with support for GPT-4, GPT-4O, reasoning models (O1 series), and various model parameters including temperature, top-p sampling, token limits, penalties, response formatting, JSON mode, reasoning effort control, and service tiers.
// Factory for creating chat models with Quarkus enhancements
public class QuarkusOpenAiChatModelBuilderFactory implements OpenAiChatModelBuilderFactory {
public OpenAiChatModel.OpenAiChatModelBuilder get();
}
// Quarkus-enhanced builder (returned by OpenAiChatModel.builder())
public static class Builder extends OpenAiChatModel.OpenAiChatModelBuilder {
public Builder configName(String configName);
public Builder tlsConfigurationName(String tlsConfigurationName);
public Builder proxy(Proxy proxy);
public Builder logCurl(boolean logCurl);
public OpenAiChatModel build();
}Text embedding generation for semantic search, similarity comparison, and RAG (Retrieval-Augmented Generation) applications using OpenAI's embedding models like text-embedding-ada-002 and newer text-embedding-3 models.
// Factory for creating embedding models with Quarkus enhancements
public class QuarkusOpenAiEmbeddingModelBuilderFactory implements OpenAiEmbeddingModelBuilderFactory {
public OpenAiEmbeddingModel.OpenAiEmbeddingModelBuilder get();
}
// Quarkus-enhanced builder (returned by OpenAiEmbeddingModel.builder())
public static class Builder extends OpenAiEmbeddingModel.OpenAiEmbeddingModelBuilder {
public Builder configName(String configName);
public Builder tlsConfigurationName(String tlsConfigurationName);
public Builder proxy(Proxy proxy);
public OpenAiEmbeddingModel build();
}Content moderation and safety checking using OpenAI's moderation models to detect potentially harmful content including hate speech, self-harm, sexual content, and violence.
// Factory for creating moderation models with Quarkus enhancements
public class QuarkusOpenAiModerationModelBuilderFactory implements OpenAiModerationModelBuilderFactory {
public OpenAiModerationModel.OpenAiModerationModelBuilder get();
}
// Quarkus-enhanced builder (returned by OpenAiModerationModel.builder())
public static class Builder extends OpenAiModerationModel.OpenAiModerationModelBuilder {
public Builder configName(String configName);
public Builder tlsConfigurationName(String tlsConfigurationName);
public Builder proxy(Proxy proxy);
public Builder logCurl(boolean logCurl);
public OpenAiModerationModel build();
}Image generation using DALL-E 2 and DALL-E 3 with support for different sizes, qualities, styles, automatic image persistence to disk, and both URL and base64 response formats.
// Standalone image model implementation
public class QuarkusOpenAiImageModel implements ImageModel {
public static Builder builder();
public Response<Image> generate(String prompt);
public Response<List<Image>> generate(String prompt, int n);
}
public static class Builder {
public Builder baseUrl(String baseUrl);
public Builder configName(String configName);
public Builder tlsConfigurationName(String tlsConfigurationName);
public Builder apiKey(String apiKey);
public Builder organizationId(String organizationId);
public Builder timeout(Duration timeout);
public Builder maxRetries(Integer maxRetries);
public Builder logRequests(Boolean logRequests);
public Builder logResponses(Boolean logResponses);
public Builder logCurl(Boolean logCurl);
public Builder modelName(String modelName);
public Builder size(String size);
public Builder quality(String quality);
public Builder style(String style);
public Builder user(Optional<String> user);
public Builder responseFormat(String responseFormat);
public Builder persistDirectory(Optional<Path> persistDirectory);
public QuarkusOpenAiImageModel build();
}Automatic cost estimation for OpenAI API usage based on token consumption. Pre-built cost estimators for common OpenAI models (GPT-4o, GPT-4o-mini, O1-mini, O1-preview, text-embedding-3-small, text-embedding-3-large) automatically calculate costs when token usage information is available.
/**
* Cost estimators are CDI-managed singleton beans that implement the
* CostEstimator interface, automatically calculating API costs based on
* token usage and model-specific pricing.
*/
@Singleton
@Priority(Integer.MIN_VALUE)
public class BasicGpt4oCostEstimator implements CostEstimator {
public boolean supports(SupportsContext context);
public CostResult estimate(CostContext context);
}
// Additional estimators for:
// - BasicGpt4oMiniCostEstimator (gpt-4o-mini)
// - BasicO1MiniCostEstimator (o1-mini)
// - BasicO1PreviewCostEstimator (o1-preview)
// - BasicE3SmallCostEstimator (text-embedding-3-small)
// - BasicE3BigCostEstimator (text-embedding-3-large)JSON-RPC services for testing OpenAI integration in Quarkus Dev UI, enabling interactive testing of image generation and content moderation without writing code. Available only in development mode for validating configurations and experimenting with models.
/**
* JSON-RPC service for testing image generation in Quarkus Dev UI.
*/
public class OpenAiImagesJsonRPCService {
public JsonObject generate(String configuration, String modelName, String size, String prompt, String quality);
}
/**
* JSON-RPC service for testing content moderation in Quarkus Dev UI.
*/
public class OpenAiModerationModelsJsonRPCService {
public JsonObject moderate(String configuration, String modelName, String prompt);
}The extension uses standard LangChain4j interfaces that are typically injected via CDI:
// Chat model interface
public interface ChatModel {
Response<AiMessage> generate(String userMessage);
Response<AiMessage> generate(UserMessage userMessage);
Response<AiMessage> generate(List<ChatMessage> messages);
}
// Streaming chat model interface
public interface StreamingChatModel {
void generate(String userMessage, StreamingResponseHandler<AiMessage> handler);
void generate(List<ChatMessage> messages, StreamingResponseHandler<AiMessage> handler);
}
// Embedding model interface
public interface EmbeddingModel {
Response<Embedding> embed(String text);
Response<List<Embedding>> embedAll(List<TextSegment> textSegments);
}
// Moderation model interface
public interface ModerationModel {
Response<Moderation> moderate(String text);
Response<Moderation> moderate(List<ChatMessage> messages);
}
// Image model interface
public interface ImageModel {
Response<Image> generate(String prompt);
Response<List<Image>> generate(String prompt, int n);
}// Generic response wrapper
public class Response<T> {
public T content();
public TokenUsage tokenUsage();
public FinishReason finishReason();
}
// Message types
public class AiMessage {
public String text();
public List<ToolExecutionRequest> toolExecutionRequests();
}
// Image type
public class Image {
public URI url();
public String base64Data();
public String revisedPrompt();
}
// Embedding type
public class Embedding {
public float[] vector();
}
// Moderation result
public class Moderation {
public boolean flagged();
public Map<String, Double> categoryScores();
}All configuration is under the quarkus.langchain4j.openai prefix. For complete details on all configuration properties, see the Configuration documentation.
The most common pattern in Quarkus applications is to configure models via properties and inject them:
import jakarta.inject.Inject;
import dev.langchain4j.model.chat.ChatModel;
@ApplicationScoped
public class ChatService {
@Inject
ChatModel chatModel;
public String chat(String message) {
return chatModel.chat(message);
}
}Use named configurations when you need different model settings:
quarkus.langchain4j.openai.fast.chat-model.model-name=gpt-4o-mini
quarkus.langchain4j.openai.fast.chat-model.temperature=0.3
quarkus.langchain4j.openai.creative.chat-model.model-name=gpt-4o
quarkus.langchain4j.openai.creative.chat-model.temperature=1.5Reference them programmatically:
ChatModel fastModel = OpenAiChatModel.builder()
.configName("fast")
.build();For real-time streaming of chat responses:
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
StreamingChatModel streamingModel = OpenAiStreamingChatModel.builder()
.apiKey("sk-your-api-key")
.modelName("gpt-4o-mini")
.build();
streamingModel.chat("Tell me a story", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String token) {
System.out.print(token);
}
@Override
public void onCompleteResponse(ChatResponse response) {
System.out.println("\nComplete!");
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
});The extension works with OpenAI-compatible API providers by configuring a custom base URL:
# For OpenShift AI or other OpenAI-compatible services
quarkus.langchain4j.openai.base-url=https://your-openai-compatible-api.com/v1/
quarkus.langchain4j.openai.api-key=your-custom-api-keyFor enterprise environments:
# Named TLS configuration
quarkus.langchain4j.openai.tls-configuration-name=my-tls-config
# HTTP proxy
quarkus.langchain4j.openai.proxy-type=HTTP
quarkus.langchain4j.openai.proxy-host=proxy.company.com
quarkus.langchain4j.openai.proxy-port=8080Enable logging for debugging and monitoring:
# Enable request/response logging
quarkus.langchain4j.openai.log-requests=true
quarkus.langchain4j.openai.log-responses=true
# Enable curl-style logging for debugging
quarkus.langchain4j.openai.log-requests-curl=trueDisable integration for testing or feature flags:
# Disable OpenAI integration
quarkus.langchain4j.openai.enable-integration=falseWhen disabled, the extension provides "disabled" model implementations that don't make API calls.
Install with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-openai