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.
Comprehensive API reference for OpenAI image generation models (DALL-E) in Quarkus. The extension provides a standalone implementation for generating images using DALL-E 3 and DALL-E 2, with support for automatic image persistence, quality controls, and style options.
Unlike other model types in the extension (chat, embedding, moderation), the image model implementation is standalone and not SPI-based. It directly implements LangChain4j's ImageModel interface and provides:
The extension automatically handles downloading URL-based images or decoding base64 images when persistence is enabled.
Standalone implementation for OpenAI DALL-E image generation models.
/**
* OpenAI image generation model implementation for DALL-E 2 and DALL-E 3.
*
* Implements: dev.langchain4j.model.image.ImageModel
*
* This class provides programmatic access to OpenAI's DALL-E models for
* generating images from text prompts. It supports both URL-based and
* base64-encoded image responses, with optional automatic persistence
* to disk.
*
* Key features:
* - Generate single or multiple images from text prompts
* - Automatic retry with configurable attempts
* - Persist generated images to local filesystem
* - Support for DALL-E 3 quality and style options
* - Access to revised prompts showing OpenAI's refinements
*
* Usage:
* ImageModel model = QuarkusOpenAiImageModel.builder()
* .apiKey("sk-...")
* .modelName("dall-e-3")
* .quality("hd")
* .build();
*
* Response<Image> response = model.generate("A sunset over mountains");
*/
public class QuarkusOpenAiImageModel implements ImageModel {
/**
* Constructs an image model from a builder.
*
* Parameters:
* builder - Configured builder instance
*
* Throws:
* IllegalArgumentException if maxRetries is less than 1
*
* The constructor validates configuration and initializes the internal
* QuarkusOpenAiClient with timeout, logging, and authentication settings.
*/
public QuarkusOpenAiImageModel(Builder builder);
/**
* Creates a new builder for configuring the image model.
*
* Returns:
* New builder instance
*
* Example:
* QuarkusOpenAiImageModel.builder()
* .apiKey("sk-...")
* .modelName("dall-e-3")
* .size("1024x1024")
* .build()
*/
public static Builder builder();
/**
* Generates a single image from a text prompt.
*
* Parameters:
* prompt - Text description of the desired image
*
* Returns:
* Response containing the generated Image with URL, base64 data,
* and revised prompt
*
* The image is automatically persisted to disk if persistDirectory
* is configured. The response includes the original or persisted URL,
* optional base64 data (if responseFormat is "b64_json"), and the
* revised prompt showing how OpenAI refined your input.
*
* Example:
* Response<Image> response = model.generate(
* "A futuristic city with flying cars"
* );
* Image image = response.content();
* System.out.println("Image URL: " + image.url());
* System.out.println("Revised: " + image.revisedPrompt());
*/
@Override
public Response<Image> generate(String prompt);
/**
* Generates multiple images from a text prompt.
*
* Parameters:
* prompt - Text description of the desired images
* n - Number of images to generate (1-10 for DALL-E 2, only 1 for DALL-E 3)
*
* Returns:
* Response containing list of generated Images
*
* Throws:
* IllegalArgumentException if n is out of range for the model
*
* Note: DALL-E 3 only supports generating 1 image at a time. Use DALL-E 2
* (dall-e-2) for generating multiple images in a single request.
*
* All images are automatically persisted to disk if persistDirectory
* is configured.
*
* Example:
* // Generate 3 variations with DALL-E 2
* Response<List<Image>> response = model.generate(
* "A serene lake at dawn", 3
* );
* for (Image image : response.content()) {
* System.out.println("Image: " + image.url());
* }
*/
@Override
public Response<List<Image>> generate(String prompt, int n);
}Builder for configuring QuarkusOpenAiImageModel instances with fluent API.
/**
* Builder for configuring OpenAI image generation models.
*
* Provides fluent API for setting all configuration options including
* API credentials, model selection, image parameters, and persistence
* settings.
*
* All builder methods return this builder for method chaining.
*/
public static class Builder {
/**
* Sets the OpenAI API base URL.
*
* Parameters:
* baseUrl - Base URL for OpenAI API
*
* Returns:
* This builder for method chaining
*
* Defaults to "https://api.openai.com/v1/" if not specified.
* Set to a custom URL for API-compatible services or proxies.
*
* Example:
* .baseUrl("https://api.openai.com/v1/")
* .baseUrl("https://custom-proxy.example.com/v1/")
*/
public Builder baseUrl(String baseUrl);
/**
* Sets the named configuration to use.
*
* Parameters:
* configName - Name of configuration in application.properties
*
* Returns:
* This builder for method chaining
*
* When specified, loads settings from the named configuration
* (quarkus.langchain4j.openai.{configName}.*) instead of the
* default configuration. Allows managing multiple model instances
* with different settings.
*
* Example:
* .configName("premium") // Uses premium.* properties
*/
public Builder configName(String configName);
/**
* Sets the named TLS configuration for HTTPS connections.
*
* Parameters:
* tlsConfigurationName - Name of Quarkus TLS configuration
*
* Returns:
* This builder for method chaining
*
* References a Quarkus named TLS configuration defined via
* quarkus.tls.{name}.* properties for custom certificates,
* client authentication, or custom trust stores.
*
* Example:
* .tlsConfigurationName("custom-certs")
*/
public Builder tlsConfigurationName(String tlsConfigurationName);
/**
* Sets the OpenAI API key for authentication.
*
* Parameters:
* apiKey - OpenAI API key (starts with "sk-")
*
* Returns:
* This builder for method chaining
*
* Required for accessing OpenAI's API. Get your API key from
* https://platform.openai.com/api-keys
*
* Example:
* .apiKey("sk-proj-...")
* .apiKey(System.getenv("OPENAI_API_KEY"))
*/
public Builder apiKey(String apiKey);
/**
* Sets the OpenAI organization ID.
*
* Parameters:
* organizationId - Organization identifier
*
* Returns:
* This builder for method chaining
*
* Optional. Used for users who belong to multiple organizations
* to specify which organization is used for API requests.
*
* Example:
* .organizationId("org-...")
*/
public Builder organizationId(String organizationId);
/**
* Sets the request timeout duration.
*
* Parameters:
* timeout - Timeout duration for API requests
*
* Returns:
* This builder for method chaining
*
* Applied to connect, read, and write operations. Image generation
* can take significant time, especially for high-quality DALL-E 3
* images, so consider setting a generous timeout.
*
* Example:
* .timeout(Duration.ofSeconds(60))
* .timeout(Duration.ofMinutes(2))
*/
public Builder timeout(Duration timeout);
/**
* Sets the maximum number of retry attempts.
*
* Parameters:
* maxRetries - Maximum retry attempts (minimum 1)
*
* Returns:
* This builder for method chaining
*
* Throws:
* IllegalArgumentException if maxRetries is less than 1
*
* The client will retry failed requests up to maxRetries times.
* Useful for handling transient network errors or API rate limits.
*
* Example:
* .maxRetries(3) // Try up to 3 times
*/
public Builder maxRetries(Integer maxRetries);
/**
* Enables or disables request logging.
*
* Parameters:
* logRequests - true to log requests, false to disable
*
* Returns:
* This builder for method chaining
*
* When enabled, logs outgoing API requests including headers
* and request body for debugging purposes.
*
* Example:
* .logRequests(true)
*/
public Builder logRequests(Boolean logRequests);
/**
* Enables or disables response logging.
*
* Parameters:
* logResponses - true to log responses, false to disable
*
* Returns:
* This builder for method chaining
*
* When enabled, logs incoming API responses including headers
* and response body. Note that base64 image data can be very
* large in logs.
*
* Example:
* .logResponses(true)
*/
public Builder logResponses(Boolean logResponses);
/**
* Enables or disables curl-style request logging.
*
* Parameters:
* logCurl - true to log curl commands, false to disable
*
* Returns:
* This builder for method chaining
*
* When enabled, logs requests as executable curl commands,
* useful for debugging or reproducing API calls outside
* the application.
*
* Example:
* .logCurl(true)
*/
public Builder logCurl(Boolean logCurl);
/**
* Sets the DALL-E model name.
*
* Parameters:
* modelName - Model identifier
*
* Returns:
* This builder for method chaining
*
* Supported models:
* - "dall-e-3": Latest model with higher quality, style control
* - "dall-e-2": Previous model supporting multiple images per request
*
* Different models support different features:
* - DALL-E 3: quality, style, 1 image only, larger sizes
* - DALL-E 2: multiple images, smaller sizes only
*
* Example:
* .modelName("dall-e-3")
* .modelName("dall-e-2")
*/
public Builder modelName(String modelName);
/**
* Sets the generated image size.
*
* Parameters:
* size - Image dimensions in WxH format
*
* Returns:
* This builder for method chaining
*
* Supported sizes by model:
*
* DALL-E 3 sizes:
* - "1024x1024" - Square, default
* - "1792x1024" - Wide/landscape
* - "1024x1792" - Tall/portrait
*
* DALL-E 2 sizes:
* - "256x256" - Small square
* - "512x512" - Medium square
* - "1024x1024" - Large square
*
* Example:
* .size("1024x1024") // Square
* .size("1792x1024") // Landscape (DALL-E 3 only)
*/
public Builder size(String size);
/**
* Sets the image quality level (DALL-E 3 only).
*
* Parameters:
* quality - Quality level: "standard" or "hd"
*
* Returns:
* This builder for method chaining
*
* Quality options:
* - "standard": Normal quality, faster generation, lower cost
* - "hd": High definition with finer details and greater consistency,
* slower generation, higher cost
*
* This parameter is only supported for DALL-E 3. It has no effect
* on DALL-E 2 models.
*
* Example:
* .quality("standard")
* .quality("hd")
*/
public Builder quality(String quality);
/**
* Sets the image generation style (DALL-E 3 only).
*
* Parameters:
* style - Style preset: "vivid" or "natural"
*
* Returns:
* This builder for method chaining
*
* Style options:
* - "vivid": Hyper-real and dramatic images with enhanced colors
* and contrast (default)
* - "natural": More natural, realistic, less hyper-real images
*
* This parameter is only supported for DALL-E 3. It has no effect
* on DALL-E 2 models.
*
* Example:
* .style("vivid") // Dramatic, enhanced
* .style("natural") // Realistic
*/
public Builder style(String style);
/**
* Sets the end-user identifier for abuse monitoring.
*
* Parameters:
* user - Optional user identifier
*
* Returns:
* This builder for method chaining
*
* A unique identifier representing your end-user, which can help
* OpenAI monitor and detect abuse. This is particularly useful
* in multi-tenant applications.
*
* Example:
* .user(Optional.of("user-12345"))
* .user(Optional.empty())
*/
public Builder user(Optional<String> user);
/**
* Sets the response format for generated images.
*
* Parameters:
* responseFormat - Format: "url" or "b64_json"
*
* Returns:
* This builder for method chaining
*
* Response formats:
* - "url": Image is uploaded to OpenAI's servers and a temporary
* URL is returned (default). URLs expire after 1 hour.
* - "b64_json": Image is returned as base64-encoded JSON data,
* useful for direct embedding or when persistence
* is enabled
*
* When persistDirectory is configured, both formats are downloaded
* and saved to disk automatically.
*
* Example:
* .responseFormat("url") // Default
* .responseFormat("b64_json") // Base64 encoding
*/
public Builder responseFormat(String responseFormat);
/**
* Sets the directory for persisting generated images.
*
* Parameters:
* persistDirectory - Optional directory path for saving images
*
* Returns:
* This builder for method chaining
*
* When set, all generated images are automatically downloaded
* and saved to the specified directory:
* - URL responses are downloaded from the URL
* - Base64 responses are decoded and written
* - Filenames are automatically generated
* - Directory is created if it doesn't exist
*
* After persistence, image URLs are updated to point to local files
* (file:// URIs).
*
* Example:
* .persistDirectory(Optional.of(Paths.get("/tmp/images")))
* .persistDirectory(Optional.of(
* Paths.get(System.getProperty("user.home"), "dall-e-images")
* ))
* .persistDirectory(Optional.empty()) // No persistence
*/
public Builder persistDirectory(Optional<Path> persistDirectory);
/**
* Builds the configured QuarkusOpenAiImageModel instance.
*
* Returns:
* Configured image model ready for use
*
* Throws:
* IllegalArgumentException if maxRetries is less than 1
*
* Validates the configuration and constructs the model with
* all specified settings. The returned model is thread-safe
* and can be reused for multiple generation requests.
*
* Example:
* QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
* .apiKey("sk-...")
* .modelName("dall-e-3")
* .quality("hd")
* .build();
*/
public QuarkusOpenAiImageModel build();
/**
* Public fields (direct access, though builder methods are recommended).
*/
public String baseUrl; // API base URL
public String configName; // Named configuration reference
public String tlsConfigurationName; // Named TLS configuration
public String apiKey; // OpenAI API key
public String organizationId; // Organization ID
public String modelName; // Model name (e.g., "dall-e-3")
public String size; // Image size (e.g., "1024x1024")
public String quality; // Image quality ("standard" or "hd")
public String style; // Image style ("vivid" or "natural")
public Optional<String> user; // End-user identifier
public String responseFormat; // Response format ("url" or "b64_json")
public Duration timeout; // Request timeout
public Integer maxRetries; // Maximum retry attempts
public Boolean logRequests; // Request logging flag
public Boolean logResponses; // Response logging flag
public Boolean logCurl; // Curl logging flag
public Optional<Path> persistDirectory; // Image persistence directory
}Configuration interface for declarative image model setup in application.properties.
/**
* Configuration interface for OpenAI image generation models.
*
* Annotation: @ConfigGroup
*
* Enables declarative configuration of DALL-E models through Quarkus
* configuration files. All properties support both default and named
* configurations.
*
* Configuration prefix:
* - Default: quarkus.langchain4j.openai.image-model
* - Named: quarkus.langchain4j.openai.{name}.image-model
*
* Example properties:
* quarkus.langchain4j.openai.image-model.model-name=dall-e-3
* quarkus.langchain4j.openai.image-model.quality=hd
* quarkus.langchain4j.openai.image-model.persist=true
*/
@ConfigGroup
public interface ImageModelConfig {
/**
* Model name to use.
*
* Returns:
* Model identifier (default: "dall-e-3")
*
* Property: quarkus.langchain4j.openai.image-model.model-name
*
* Supported values:
* - "dall-e-3": Latest DALL-E 3 model (default)
* - "dall-e-2": Previous generation model
*
* Example:
* quarkus.langchain4j.openai.image-model.model-name=dall-e-3
*/
@WithDefault("dall-e-3")
String modelName();
/**
* Configure whether generated images are saved to disk.
*
* Returns:
* Optional persistence flag (default: false, auto-enabled if
* persistDirectory is set)
*
* Property: quarkus.langchain4j.openai.image-model.persist
*
* By default, persistence is disabled. It is implicitly enabled when
* persistDirectory is set unless explicitly disabled.
*
* Example:
* quarkus.langchain4j.openai.image-model.persist=true
*/
@ConfigDocDefault("false")
Optional<Boolean> persist();
/**
* Directory path where generated images are persisted.
*
* Returns:
* Optional directory path (default: ${java.io.tmpdir}/dall-e-images)
*
* Property: quarkus.langchain4j.openai.image-model.persist-directory
*
* Only applies if persist is not explicitly set to false. The directory
* is created automatically if it doesn't exist. Images are saved with
* randomly generated filenames.
*
* Example:
* quarkus.langchain4j.openai.image-model.persist-directory=/var/app/images
*/
@ConfigDocDefault("${java.io.tmpdir}/dall-e-images")
Optional<Path> persistDirectory();
/**
* Format for returned images.
*
* Returns:
* Response format (default: "url")
*
* Property: quarkus.langchain4j.openai.image-model.response-format
*
* Must be one of:
* - "url": Returns temporary URLs (expire after 1 hour)
* - "b64_json": Returns base64-encoded image data
*
* Example:
* quarkus.langchain4j.openai.image-model.response-format=url
*/
@WithDefault("url")
String responseFormat();
/**
* Size of generated images.
*
* Returns:
* Image dimensions in WxH format (default: "1024x1024")
*
* Property: quarkus.langchain4j.openai.image-model.size
*
* DALL-E 3 sizes:
* - "1024x1024" - Square (default)
* - "1792x1024" - Wide landscape
* - "1024x1792" - Tall portrait
*
* DALL-E 2 sizes:
* - "256x256" - Small
* - "512x512" - Medium
* - "1024x1024" - Large
*
* Example:
* quarkus.langchain4j.openai.image-model.size=1792x1024
*/
@WithDefault("1024x1024")
String size();
/**
* Quality of generated images (DALL-E 3 only).
*
* Returns:
* Quality level (default: "standard")
*
* Property: quarkus.langchain4j.openai.image-model.quality
*
* Options:
* - "standard": Normal quality, faster, lower cost
* - "hd": High definition with finer details
*
* This parameter only affects DALL-E 3. HD creates images with
* finer details and greater consistency across the image.
*
* Example:
* quarkus.langchain4j.openai.image-model.quality=hd
*/
@WithDefault("standard")
String quality();
/**
* Number of images to generate per request.
*
* Returns:
* Image count (default: 1)
*
* Property: quarkus.langchain4j.openai.image-model.number
*
* Must be between 1 and 10. DALL-E 3 only supports n=1.
* Use DALL-E 2 for generating multiple images per request.
*
* Example:
* quarkus.langchain4j.openai.image-model.number=3
*/
@WithDefault("1")
int number();
/**
* Style of generated images (DALL-E 3 only).
*
* Returns:
* Style preset (default: "vivid")
*
* Property: quarkus.langchain4j.openai.image-model.style
*
* Options:
* - "vivid": Hyper-real and dramatic images
* - "natural": More natural, less hyper-real images
*
* Vivid causes the model to lean towards generating hyper-real
* and dramatic images. Natural produces more natural-looking images.
* This parameter only affects DALL-E 3.
*
* Example:
* quarkus.langchain4j.openai.image-model.style=natural
*/
@WithDefault("vivid")
String style();
/**
* End-user identifier for abuse monitoring.
*
* Returns:
* Optional user identifier
*
* Property: quarkus.langchain4j.openai.image-model.user
*
* A unique identifier representing your end-user, which can help
* OpenAI monitor and detect abuse.
*
* Example:
* quarkus.langchain4j.openai.image-model.user=user-12345
*/
Optional<String> user();
/**
* Whether to log image generation requests.
*
* Returns:
* Optional logging flag (default: false)
*
* Property: quarkus.langchain4j.openai.image-model.log-requests
*
* Example:
* quarkus.langchain4j.openai.image-model.log-requests=true
*/
@ConfigDocDefault("false")
Optional<Boolean> logRequests();
/**
* Whether to log image generation responses.
*
* Returns:
* Optional logging flag (default: false)
*
* Property: quarkus.langchain4j.openai.image-model.log-responses
*
* Note: Response logging can be verbose with base64 image data.
*
* Example:
* quarkus.langchain4j.openai.image-model.log-responses=true
*/
@ConfigDocDefault("false")
Optional<Boolean> logResponses();
}Understanding the differences between DALL-E 3 and DALL-E 2 is important for choosing the right model:
Use DALL-E 3 when:
Use DALL-E 2 when:
Using dependency injection for automatic configuration from application.properties:
import jakarta.inject.Inject;
import dev.langchain4j.model.image.ImageModel;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.image.Image;
@ApplicationScoped
public class ImageService {
@Inject
ImageModel imageModel;
public String generateImage(String description) {
Response<Image> response = imageModel.generate(description);
Image image = response.content();
return image.url().toString();
}
}Configuration in application.properties:
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.image-model.quality=standard
quarkus.langchain4j.openai.image-model.size=1024x1024Generate multiple variations of an image in a single request:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.time.Duration;
import java.util.List;
public class MultiImageGenerator {
public List<Image> generateVariations(String prompt) {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-2") // Only DALL-E 2 supports multiple images
.size("512x512")
.timeout(Duration.ofSeconds(60))
.maxRetries(3)
.build();
// Generate 5 variations
Response<List<Image>> response = model.generate(prompt, 5);
List<Image> images = response.content();
System.out.println("Generated " + images.size() + " variations");
for (int i = 0; i < images.size(); i++) {
Image image = images.get(i);
System.out.println("Variation " + (i + 1) + ": " + image.url());
}
return images;
}
}Configuration for multiple images:
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-2
quarkus.langchain4j.openai.image-model.number=5
quarkus.langchain4j.openai.image-model.size=512x512Generate high-definition images with DALL-E 3's enhanced quality:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.time.Duration;
public class HighQualityImageGenerator {
public Image generateHighQuality(String prompt) {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.quality("hd") // High definition
.style("vivid") // Dramatic, enhanced colors
.size("1792x1024") // Wide landscape
.timeout(Duration.ofMinutes(2)) // HD images take longer
.logRequests(true)
.build();
Response<Image> response = model.generate(prompt);
Image image = response.content();
System.out.println("Generated HD image: " + image.url());
System.out.println("Revised prompt: " + image.revisedPrompt());
return image;
}
}Configuration for HD images:
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.image-model.quality=hd
quarkus.langchain4j.openai.image-model.style=vivid
quarkus.langchain4j.openai.image-model.size=1792x1024Automatically save generated images to the local filesystem:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class PersistentImageGenerator {
public Path generateAndSave(String prompt, String saveDirectory) {
Path persistDir = Paths.get(saveDirectory);
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.persistDirectory(Optional.of(persistDir))
.responseFormat("url") // Will be downloaded and persisted
.build();
Response<Image> response = model.generate(prompt);
Image image = response.content();
// URL now points to local file after automatic persistence
Path localPath = Paths.get(image.url());
System.out.println("Image saved to: " + localPath);
return localPath;
}
}Configuration for automatic persistence:
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.image-model.persist=true
quarkus.langchain4j.openai.image-model.persist-directory=/var/app/generated-imagesWork with base64-encoded images for direct embedding or processing:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.util.Base64;
public class Base64ImageGenerator {
public String generateBase64Image(String prompt) {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.responseFormat("b64_json") // Get base64 instead of URL
.build();
Response<Image> response = model.generate(prompt);
Image image = response.content();
// Access base64 data directly
String base64Data = image.base64Data();
// Can be used in HTML img tags
String htmlImage = String.format(
"<img src=\"data:image/png;base64,%s\" alt=\"Generated image\"/>",
base64Data
);
// Or decode to bytes for processing
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
System.out.println("Image size: " + imageBytes.length + " bytes");
return base64Data;
}
}Configuration for base64 responses:
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.image-model.response-format=b64_jsonExplore different artistic styles and quality levels:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
public class StyleExplorer {
public void compareStyles(String prompt) {
// Vivid style - dramatic and hyper-real
QuarkusOpenAiImageModel vividModel = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.style("vivid")
.quality("hd")
.build();
Response<Image> vividResponse = vividModel.generate(prompt);
System.out.println("Vivid style: " + vividResponse.content().url());
// Natural style - realistic and subdued
QuarkusOpenAiImageModel naturalModel = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.style("natural")
.quality("hd")
.build();
Response<Image> naturalResponse = naturalModel.generate(prompt);
System.out.println("Natural style: " + naturalResponse.content().url());
}
public void compareQualities(String prompt) {
// Standard quality - faster and cheaper
QuarkusOpenAiImageModel standardModel = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.quality("standard")
.build();
Response<Image> standardResponse = standardModel.generate(prompt);
System.out.println("Standard: " + standardResponse.content().url());
// HD quality - finer details
QuarkusOpenAiImageModel hdModel = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.quality("hd")
.build();
Response<Image> hdResponse = hdModel.generate(prompt);
System.out.println("HD: " + hdResponse.content().url());
}
}Manage multiple image model configurations for different use cases:
# Default configuration - standard quality
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.image-model.quality=standard
# Premium configuration - high quality
quarkus.langchain4j.openai.premium.api-key=sk-proj-...
quarkus.langchain4j.openai.premium.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.premium.image-model.quality=hd
quarkus.langchain4j.openai.premium.image-model.style=vivid
# Batch configuration - DALL-E 2 for multiple images
quarkus.langchain4j.openai.batch.api-key=sk-proj-...
quarkus.langchain4j.openai.batch.image-model.model-name=dall-e-2
quarkus.langchain4j.openai.batch.image-model.number=5
quarkus.langchain4j.openai.batch.image-model.size=512x512Using named configurations programmatically:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.util.List;
public class MultiConfigGenerator {
public Image generatePremium(String prompt) {
// Use premium configuration for high-quality single images
QuarkusOpenAiImageModel premiumModel = QuarkusOpenAiImageModel.builder()
.configName("premium") // References premium.* properties
.build();
Response<Image> response = premiumModel.generate(prompt);
return response.content();
}
public List<Image> generateBatch(String prompt) {
// Use batch configuration for multiple images
QuarkusOpenAiImageModel batchModel = QuarkusOpenAiImageModel.builder()
.configName("batch") // References batch.* properties
.build();
Response<List<Image>> response = batchModel.generate(prompt, 5);
return response.content();
}
}DALL-E 3 automatically revises prompts to improve safety and quality. Access the revised prompt to understand how OpenAI interpreted your request:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
public class PromptRevisionExample {
public void analyzePromptRevision() {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.build();
String originalPrompt = "cat";
Response<Image> response = model.generate(originalPrompt);
Image image = response.content();
System.out.println("Original prompt: " + originalPrompt);
System.out.println("Revised prompt: " + image.revisedPrompt());
System.out.println("Image URL: " + image.url());
// Example output:
// Original prompt: cat
// Revised prompt: A close-up portrait of a domestic cat with
// vibrant green eyes, sitting gracefully on a
// wooden surface with soft natural lighting
}
}The revised prompt shows how DALL-E 3 enhanced your description with additional details about composition, lighting, and style.
The extension provides automatic image persistence through the FilePersistor utility:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class PersistenceExample {
public void demonstratePersistence() {
Path outputDir = Paths.get("/tmp/my-images");
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.persistDirectory(Optional.of(outputDir))
.responseFormat("url") // Will be downloaded
.build();
Response<Image> response = model.generate(
"A serene mountain landscape at sunset"
);
Image image = response.content();
// Before persistence (if it weren't automatic):
// https://oaidalleapiprodscus.blob.core.windows.net/...
// After automatic persistence:
// file:///tmp/my-images/a1b2c3d4e5f6g7h8i9j0
System.out.println("Persisted to: " + image.url());
}
}import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;
public class ImageManager {
public void listPersistedImages(String directory) throws IOException {
try (Stream<Path> paths = Files.walk(Paths.get(directory), 1)) {
paths.filter(Files::isRegularFile)
.forEach(path -> {
System.out.println("Image: " + path.getFileName());
try {
long size = Files.size(path);
System.out.println(" Size: " + size + " bytes");
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
public void cleanupOldImages(String directory, int maxAgeHours)
throws IOException {
long cutoffTime = System.currentTimeMillis() -
(maxAgeHours * 60 * 60 * 1000);
try (Stream<Path> paths = Files.walk(Paths.get(directory), 1)) {
paths.filter(Files::isRegularFile)
.filter(path -> {
try {
long lastModified = Files.getLastModifiedTime(path)
.toMillis();
return lastModified < cutoffTime;
} catch (IOException e) {
return false;
}
})
.forEach(path -> {
try {
Files.delete(path);
System.out.println("Deleted: " + path);
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
}The image model includes built-in retry logic for handling transient failures:
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.model.output.Response;
import java.time.Duration;
public class ResilientImageGenerator {
public Image generateWithRetry(String prompt) {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.timeout(Duration.ofSeconds(120))
.maxRetries(3) // Retry up to 3 times on failure
.logRequests(true)
.build();
try {
Response<Image> response = model.generate(prompt);
return response.content();
} catch (Exception e) {
System.err.println("Failed after retries: " + e.getMessage());
throw e;
}
}
}Craft effective prompts for better results:
public class PromptBestPractices {
// Good: Specific and detailed
public String goodPrompt() {
return "A photorealistic image of a golden retriever puppy "
+ "playing in a sun-dappled meadow with wildflowers, "
+ "shallow depth of field, warm afternoon lighting";
}
// Better: Include style and technical details
public String betterPrompt() {
return "Professional product photography of a minimalist "
+ "ceramic coffee mug on a wooden table, soft natural "
+ "light from window, neutral background, high resolution, "
+ "clean composition";
}
// Avoid: Too vague
public String vaguePrompt() {
return "nice picture"; // Lacks detail
}
}Properly manage image model instances:
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkiverse.langchain4j.openai.QuarkusOpenAiImageModel;
@ApplicationScoped
public class ImageGenerationService {
// Reuse model instances - they're thread-safe
private final QuarkusOpenAiImageModel model;
public ImageGenerationService() {
// Create once, reuse many times
this.model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.build();
}
public Image generate(String prompt) {
// Thread-safe - can be called concurrently
return model.generate(prompt).content();
}
}Manage costs effectively:
public class CostOptimization {
// Use DALL-E 2 for lower cost
public QuarkusOpenAiImageModel cheaperModel() {
return QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-2") // Lower cost than DALL-E 3
.size("512x512") // Smaller size = lower cost
.build();
}
// Use standard quality for DALL-E 3
public QuarkusOpenAiImageModel standardQuality() {
return QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.quality("standard") // Lower cost than "hd"
.build();
}
// Batch with DALL-E 2 for multiple variations
public QuarkusOpenAiImageModel batchGeneration() {
return QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-2")
.build(); // Generate up to 10 images per request
}
}Handle sensitive data securely:
public class SecurityBestPractices {
// DO: Use environment variables for API keys
public QuarkusOpenAiImageModel secureConfiguration() {
return QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY")) // Good
.build();
}
// DON'T: Hardcode API keys
public QuarkusOpenAiImageModel insecureConfiguration() {
return QuarkusOpenAiImageModel.builder()
.apiKey("sk-proj-abc123...") // BAD - never do this
.build();
}
// DO: Use user identifiers for monitoring
public Image generateWithTracking(String prompt, String userId) {
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.user(Optional.of(userId)) // Helps OpenAI detect abuse
.build();
return model.generate(prompt).content();
}
}Complete configuration options for image models:
# API Configuration
quarkus.langchain4j.openai.api-key=sk-proj-...
quarkus.langchain4j.openai.base-url=https://api.openai.com/v1/
quarkus.langchain4j.openai.organization-id=org-...
quarkus.langchain4j.openai.timeout=60s
# Model Selection
quarkus.langchain4j.openai.image-model.model-name=dall-e-3
# Image Parameters
quarkus.langchain4j.openai.image-model.size=1024x1024
quarkus.langchain4j.openai.image-model.quality=standard
quarkus.langchain4j.openai.image-model.style=vivid
quarkus.langchain4j.openai.image-model.number=1
# Response Configuration
quarkus.langchain4j.openai.image-model.response-format=url
# Persistence
quarkus.langchain4j.openai.image-model.persist=true
quarkus.langchain4j.openai.image-model.persist-directory=/var/app/images
# Monitoring
quarkus.langchain4j.openai.image-model.user=user-identifier
quarkus.langchain4j.openai.image-model.log-requests=false
quarkus.langchain4j.openai.image-model.log-responses=false
# Named Configuration Example
quarkus.langchain4j.openai.premium.api-key=sk-proj-...
quarkus.langchain4j.openai.premium.image-model.model-name=dall-e-3
quarkus.langchain4j.openai.premium.image-model.quality=hdIntegrate with reactive frameworks:
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import dev.langchain4j.data.image.Image;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ApplicationScoped
public class ReactiveImageService {
private final QuarkusOpenAiImageModel model;
private final ExecutorService executor;
public ReactiveImageService() {
this.model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.build();
this.executor = Executors.newFixedThreadPool(5);
}
public Uni<Image> generateAsync(String prompt) {
return Uni.createFrom().item(() -> model.generate(prompt).content())
.runSubscriptionOn(executor);
}
}Combine generation with post-processing:
import dev.langchain4j.data.image.Image;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
public class ImagePipeline {
public File generateAndProcess(String prompt) throws Exception {
// Generate image
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("dall-e-3")
.build();
Image generated = model.generate(prompt).content();
// Download and process
BufferedImage image = ImageIO.read(new URL(generated.url().toString()));
// Apply processing (resize, filter, etc.)
BufferedImage processed = applyWatermark(image);
// Save processed image
File output = new File("/tmp/processed-image.png");
ImageIO.write(processed, "PNG", output);
return output;
}
private BufferedImage applyWatermark(BufferedImage image) {
// Custom processing logic
return image;
}
}# Ensure persist is enabled and directory is writable
quarkus.langchain4j.openai.image-model.persist=true
quarkus.langchain4j.openai.image-model.persist-directory=/writable/path# Increase timeout for high-quality generation
quarkus.langchain4j.openai.timeout=120s// DALL-E 3 only supports n=1, use DALL-E 2 for multiple images
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.modelName("dall-e-2") // Not dall-e-3
.build();
model.generate(prompt, 5); // Works with DALL-E 2// Ensure size matches model capabilities
// DALL-E 3: 1024x1024, 1792x1024, 1024x1792
// DALL-E 2: 256x256, 512x512, 1024x1024
QuarkusOpenAiImageModel model = QuarkusOpenAiImageModel.builder()
.modelName("dall-e-3")
.size("1024x1024") // Valid for both models
.build();Install with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-openai