LangChain4j OpenAI Integration providing Java access to OpenAI APIs including chat models, embeddings, image generation, audio transcription, and moderation.
The Model Catalog provides programmatic access to query available OpenAI models and their capabilities through the API. This enables dynamic model selection, capability discovery, and automated configuration based on model availability.
The catalog returns detailed information about each model including its ID, ownership, creation date, and capabilities. This is useful for building adaptive applications that can respond to new model releases or availability changes.
Query the OpenAI API to list available models with their metadata.
public class OpenAiModelCatalog implements ModelCatalog {
public static Builder builder();
// Core methods
public List<ModelDescription> listModels();
public ModelProvider provider();
}public static class Builder {
// Core configuration
public Builder apiKey(String apiKey);
public Builder baseUrl(String baseUrl);
public Builder organizationId(String organizationId);
public Builder projectId(String projectId);
// HTTP configuration
public Builder httpClientBuilder(HttpClientBuilder httpClientBuilder);
public Builder connectTimeout(Duration connectTimeout);
public Builder readTimeout(Duration readTimeout);
public Builder userAgent(String userAgent);
// Custom headers and params
public Builder customHeaders(Map<String, String> customHeaders);
public Builder customQueryParams(Map<String, String> customQueryParams);
// Logging
public Builder logRequests(Boolean logRequests);
public Builder logResponses(Boolean logResponses);
public Builder logger(Logger logger);
public OpenAiModelCatalog build();
}import dev.langchain4j.model.openai.OpenAiModelCatalog;
import dev.langchain4j.model.catalog.ModelDescription;
// Create model catalog
OpenAiModelCatalog catalog = OpenAiModelCatalog.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// List all available models
List<ModelDescription> models = catalog.listModels();
System.out.println("Available models: " + models.size());
for (ModelDescription model : models) {
System.out.println("- " + model.id());
}// Find chat models
List<ModelDescription> chatModels = catalog.listModels().stream()
.filter(model -> model.id().startsWith("gpt-"))
.collect(Collectors.toList());
System.out.println("Chat models:");
for (ModelDescription model : chatModels) {
System.out.println("- " + model.id());
}
// Find embedding models
List<ModelDescription> embeddingModels = catalog.listModels().stream()
.filter(model -> model.id().contains("embedding"))
.collect(Collectors.toList());
System.out.println("\nEmbedding models:");
for (ModelDescription model : embeddingModels) {
System.out.println("- " + model.id());
}public class DynamicModelSelector {
private final OpenAiModelCatalog catalog;
public DynamicModelSelector(String apiKey) {
this.catalog = OpenAiModelCatalog.builder()
.apiKey(apiKey)
.build();
}
public String selectBestChatModel() {
List<ModelDescription> models = catalog.listModels();
// Prefer GPT-4o if available
Optional<ModelDescription> gpt4o = models.stream()
.filter(m -> m.id().equals("gpt-4o"))
.findFirst();
if (gpt4o.isPresent()) {
return gpt4o.get().id();
}
// Fallback to GPT-4 Turbo
Optional<ModelDescription> gpt4turbo = models.stream()
.filter(m -> m.id().equals("gpt-4-turbo"))
.findFirst();
if (gpt4turbo.isPresent()) {
return gpt4turbo.get().id();
}
// Default to GPT-3.5 Turbo
return "gpt-3.5-turbo";
}
public boolean isModelAvailable(String modelId) {
return catalog.listModels().stream()
.anyMatch(m -> m.id().equals(modelId));
}
public List<String> getAvailableModelIds() {
return catalog.listModels().stream()
.map(ModelDescription::id)
.sorted()
.collect(Collectors.toList());
}
}
// Usage
DynamicModelSelector selector = new DynamicModelSelector(apiKey);
if (selector.isModelAvailable("gpt-4o")) {
System.out.println("GPT-4o is available");
} else {
System.out.println("Selecting best alternative...");
String bestModel = selector.selectBestChatModel();
System.out.println("Using: " + bestModel);
}public void displayModelInfo() {
OpenAiModelCatalog catalog = OpenAiModelCatalog.builder()
.apiKey(apiKey)
.build();
List<ModelDescription> models = catalog.listModels();
System.out.println("=== OpenAI Models ===\n");
// Group by type
Map<String, List<ModelDescription>> byType = models.stream()
.collect(Collectors.groupingBy(this::getModelType));
for (Map.Entry<String, List<ModelDescription>> entry : byType.entrySet()) {
System.out.println(entry.getKey() + ":");
for (ModelDescription model : entry.getValue()) {
System.out.println(" - " + model.id());
System.out.println(" Owner: " + model.ownedBy());
System.out.println(" Created: " + formatDate(model.created()));
}
System.out.println();
}
}
private String getModelType(ModelDescription model) {
String id = model.id();
if (id.contains("gpt")) return "Chat Models";
if (id.contains("embedding")) return "Embedding Models";
if (id.contains("dall-e")) return "Image Models";
if (id.contains("whisper")) return "Audio Models";
if (id.contains("moderation")) return "Moderation Models";
return "Other";
}
private String formatDate(Long timestamp) {
if (timestamp == null) return "Unknown";
return new SimpleDateFormat("yyyy-MM-dd").format(new Date(timestamp * 1000));
}public class CachedModelCatalog {
private final OpenAiModelCatalog catalog;
private List<ModelDescription> cachedModels;
private long lastFetch;
private final long cacheValidityMs;
public CachedModelCatalog(String apiKey, long cacheValidityMs) {
this.catalog = OpenAiModelCatalog.builder()
.apiKey(apiKey)
.build();
this.cacheValidityMs = cacheValidityMs;
}
public synchronized List<ModelDescription> listModels() {
long now = System.currentTimeMillis();
if (cachedModels == null || (now - lastFetch) > cacheValidityMs) {
cachedModels = catalog.listModels();
lastFetch = now;
}
return new ArrayList<>(cachedModels);
}
public synchronized void invalidateCache() {
cachedModels = null;
}
}
// Usage with 1 hour cache
CachedModelCatalog cachedCatalog = new CachedModelCatalog(
apiKey,
TimeUnit.HOURS.toMillis(1)
);
// Fast subsequent calls
List<ModelDescription> models = cachedCatalog.listModels();public class ModelVersionChecker {
private final OpenAiModelCatalog catalog;
private final Map<String, Long> knownVersions = new ConcurrentHashMap<>();
public ModelVersionChecker(String apiKey) {
this.catalog = OpenAiModelCatalog.builder()
.apiKey(apiKey)
.build();
initializeKnownVersions();
}
private void initializeKnownVersions() {
for (ModelDescription model : catalog.listModels()) {
knownVersions.put(model.id(), model.created());
}
}
public boolean hasNewVersion(String modelId) {
List<ModelDescription> models = catalog.listModels();
Optional<ModelDescription> current = models.stream()
.filter(m -> m.id().equals(modelId))
.findFirst();
if (!current.isPresent()) {
return false;
}
Long previousVersion = knownVersions.get(modelId);
Long currentVersion = current.get().created();
if (previousVersion == null) {
knownVersions.put(modelId, currentVersion);
return false;
}
if (!previousVersion.equals(currentVersion)) {
knownVersions.put(modelId, currentVersion);
return true;
}
return false;
}
public List<String> checkForUpdates() {
List<String> updated = new ArrayList<>();
for (String modelId : knownVersions.keySet()) {
if (hasNewVersion(modelId)) {
updated.add(modelId);
}
}
return updated;
}
}public class ModelDescription {
public String id();
public String object();
public Long created();
public String ownedBy();
}public interface ModelCatalog {
List<ModelDescription> listModels();
ModelProvider provider();
}Unique identifier for the model:
gpt-4o, gpt-3.5-turbo, text-embedding-3-smallType of object returned:
"model"Unix timestamp when model was created:
Organization that owns the model:
"openai" or "openai-internal""system" for internal models// Check for new models periodically
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
try {
List<ModelDescription> models = catalog.listModels();
System.out.println("Model count: " + models.size());
// Check for new models
List<String> modelIds = models.stream()
.map(ModelDescription::id)
.collect(Collectors.toList());
// Store or compare with previous list
checkForNewModels(modelIds);
} catch (Exception e) {
logger.error("Failed to update model catalog", e);
}
}, 0, 1, TimeUnit.HOURS);public List<ModelDescription> safeListModels() {
try {
return catalog.listModels();
} catch (Exception e) {
logger.error("Failed to fetch models", e);
// Return cached or default list
return getDefaultModels();
}
}
private List<ModelDescription> getDefaultModels() {
// Return known stable models as fallback
return List.of(
createModelDescription("gpt-4o"),
createModelDescription("gpt-3.5-turbo"),
createModelDescription("text-embedding-3-small")
);
}public class ModelCapabilitiesDetector {
public enum Capability {
CHAT,
COMPLETION,
EMBEDDING,
IMAGE_GENERATION,
AUDIO_TRANSCRIPTION,
MODERATION,
FUNCTION_CALLING,
VISION,
JSON_MODE
}
public Set<Capability> detectCapabilities(String modelId) {
Set<Capability> capabilities = new HashSet<>();
if (modelId.startsWith("gpt-")) {
capabilities.add(Capability.CHAT);
capabilities.add(Capability.FUNCTION_CALLING);
if (modelId.contains("gpt-4") || modelId.contains("gpt-3.5-turbo")) {
capabilities.add(Capability.JSON_MODE);
}
if (modelId.contains("vision") || modelId.contains("gpt-4")) {
capabilities.add(Capability.VISION);
}
}
if (modelId.contains("embedding")) {
capabilities.add(Capability.EMBEDDING);
}
if (modelId.contains("dall-e")) {
capabilities.add(Capability.IMAGE_GENERATION);
}
if (modelId.contains("whisper") || modelId.contains("transcribe")) {
capabilities.add(Capability.AUDIO_TRANSCRIPTION);
}
if (modelId.contains("moderation")) {
capabilities.add(Capability.MODERATION);
}
return capabilities;
}
public boolean supportsFeature(String modelId, Capability capability) {
return detectCapabilities(modelId).contains(capability);
}
}public class ModelConfiguration {
private final OpenAiModelCatalog catalog;
private final Map<String, ModelConfig> configurations;
public ModelConfiguration(String apiKey) {
this.catalog = OpenAiModelCatalog.builder()
.apiKey(apiKey)
.build();
this.configurations = new HashMap<>();
loadConfigurations();
}
private void loadConfigurations() {
List<ModelDescription> models = catalog.listModels();
for (ModelDescription model : models) {
ModelConfig config = createDefaultConfig(model);
configurations.put(model.id(), config);
}
}
private ModelConfig createDefaultConfig(ModelDescription model) {
String id = model.id();
if (id.contains("gpt-4o")) {
return new ModelConfig(0.7, 2000, true);
} else if (id.contains("gpt-4")) {
return new ModelConfig(0.7, 1000, true);
} else if (id.contains("gpt-3.5")) {
return new ModelConfig(0.7, 500, false);
}
return new ModelConfig(0.7, 1000, false);
}
public ModelConfig getConfig(String modelId) {
return configurations.getOrDefault(
modelId,
new ModelConfig(0.7, 1000, false)
);
}
private static class ModelConfig {
final double defaultTemperature;
final int defaultMaxTokens;
final boolean supportsVision;
ModelConfig(double temperature, int maxTokens, boolean vision) {
this.defaultTemperature = temperature;
this.defaultMaxTokens = maxTokens;
this.supportsVision = vision;
}
}
}Choose the best available model based on current availability and requirements.
Track when models become available or are deprecated.
Determine which features are supported by available models.
Select models based on cost and capability trade-offs.
Fall back to alternative models when preferred models are unavailable.
Generate up-to-date documentation of available models.
Verify model availability before running test suites.
Install with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-open-ai@1.11.0