OpenAI models support for Spring AI, providing comprehensive integration for chat completion, embeddings, image generation, audio transcription, text-to-speech, and content moderation capabilities within Spring Boot applications.
Comprehensive chat completion functionality using OpenAI's GPT models, including support for tool/function calling, structured outputs, multimodal inputs, and both synchronous and streaming responses.
Primary implementation for OpenAI chat completion, providing Spring-idiomatic APIs for conversational AI with support for tools, structured outputs, and reactive streaming.
/**
* OpenAI chat model implementation supporting synchronous and streaming responses
*/
public class OpenAiChatModel implements ChatModel {
/**
* Create a new builder for configuring OpenAiChatModel
* @return Builder instance
*/
public static Builder builder();
/**
* Generate chat completion synchronously
* @param prompt The prompt containing messages and options
* @return ChatResponse containing generated content and metadata
*/
public ChatResponse call(Prompt prompt);
/**
* Generate chat completion with streaming response
* @param prompt The prompt containing messages and options
* @return Flux of ChatResponse chunks
*/
public Flux<ChatResponse> stream(Prompt prompt);
/**
* Get the default options for this model
* @return ChatOptions configuration
*/
public ChatOptions getDefaultOptions();
/**
* Set custom observation convention for observability
* @param observationConvention Custom observation convention
*/
public void setObservationConvention(ChatModelObservationConvention observationConvention);
/**
* Create a builder from this model instance
* @return Builder pre-populated with current configuration
*/
public Builder mutate();
/**
* Clone this model instance
* @return New OpenAiChatModel with same configuration
*/
public OpenAiChatModel clone();
/**
* Direct constructor (5 parameters)
* @param openAiApi Low-level API client
* @param defaultOptions Default chat options
* @param toolCallingManager Manager for tool/function calling
* @param retryTemplate Template for retry logic
* @param observationRegistry Registry for observability
*/
public OpenAiChatModel(OpenAiApi openAiApi, OpenAiChatOptions defaultOptions,
ToolCallingManager toolCallingManager, RetryTemplate retryTemplate,
ObservationRegistry observationRegistry);
/**
* Direct constructor (6 parameters) - Full control
* @param openAiApi Low-level API client
* @param defaultOptions Default chat options
* @param toolCallingManager Manager for tool/function calling
* @param retryTemplate Template for retry logic
* @param observationRegistry Registry for observability
* @param toolExecutionEligibilityPredicate Predicate to determine if tool can be executed
*/
public OpenAiChatModel(OpenAiApi openAiApi, OpenAiChatOptions defaultOptions,
ToolCallingManager toolCallingManager, RetryTemplate retryTemplate,
ObservationRegistry observationRegistry,
ToolExecutionEligibilityPredicate toolExecutionEligibilityPredicate);
}Note: OpenAiChatModel supports both direct constructor instantiation and builder pattern. The builder pattern is recommended for most use cases as it provides a more fluent API.
Builder Pattern:
public static class Builder {
public Builder openAiApi(OpenAiApi openAiApi);
public Builder defaultOptions(OpenAiChatOptions defaultOptions);
public Builder toolCallingManager(ToolCallingManager toolCallingManager);
public Builder retryTemplate(RetryTemplate retryTemplate);
public Builder observationRegistry(ObservationRegistry observationRegistry);
public Builder toolExecutionEligibilityPredicate(ToolExecutionEligibilityPredicate predicate);
public OpenAiChatModel build();
}Usage Example:
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.retry.support.RetryTemplate;
// Create API client
var openAiApi = OpenAiApi.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
// Configure retry template
var retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2.0, 10000)
.build();
// Create chat model with custom options
var chatModel = OpenAiChatModel.builder()
.openAiApi(openAiApi)
.defaultOptions(OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O.getValue())
.temperature(0.7)
.maxTokens(1000)
.build())
.retryTemplate(retryTemplate)
.build();
// Synchronous completion
var response = chatModel.call(
new Prompt("Explain the theory of relativity")
);
System.out.println(response.getResult().getOutput().getContent());
// Streaming completion
chatModel.stream(new Prompt("Write a short story"))
.subscribe(chunk -> {
System.out.print(chunk.getResult().getOutput().getContent());
});Configuration options for chat completion requests, supporting extensive customization of model behavior, output format, tool calling, and advanced features.
/**
* Configuration options for OpenAI chat completion
*/
public class OpenAiChatOptions implements ToolCallingChatOptions, StructuredOutputChatOptions {
/**
* Create a new builder for chat options
* @return Builder instance
*/
public static Builder builder();
/**
* Create options from existing options instance
* @param fromOptions Source options to copy from
* @return New OpenAiChatOptions instance
*/
public static OpenAiChatOptions fromOptions(OpenAiChatOptions fromOptions);
/**
* Create a copy of these options
* @return New OpenAiChatOptions with same values
*/
public OpenAiChatOptions copy();
// Core Configuration
public String getModel();
public void setModel(String model);
public Double getTemperature();
public void setTemperature(Double temperature);
public Double getTopP();
public void setTopP(Double topP);
public Integer getMaxTokens();
public void setMaxTokens(Integer maxTokens);
public Integer getMaxCompletionTokens();
public void setMaxCompletionTokens(Integer maxCompletionTokens);
public Integer getN();
public void setN(Integer n);
// Penalties and Biases
public Double getFrequencyPenalty();
public void setFrequencyPenalty(Double frequencyPenalty);
public Double getPresencePenalty();
public void setPresencePenalty(Double presencePenalty);
public Map<String, Integer> getLogitBias();
public void setLogitBias(Map<String, Integer> logitBias);
// Stop Sequences
public List<String> getStop();
public void setStop(List<String> stop);
// Response Format and Structured Output
public ResponseFormat getResponseFormat();
public void setResponseFormat(ResponseFormat responseFormat);
// Tool/Function Calling
public List<FunctionTool> getTools();
public void setTools(List<FunctionTool> tools);
public String getToolChoice();
public void setToolChoice(String toolChoice);
public Boolean getParallelToolCalls();
public void setParallelToolCalls(Boolean parallelToolCalls);
public Map<String, FunctionCallback> getToolCallbacks();
public void setToolCallbacks(Map<String, FunctionCallback> toolCallbacks);
public Set<String> getToolNames();
public void setToolNames(Set<String> toolNames);
public Boolean getInternalToolExecutionEnabled();
public void setInternalToolExecutionEnabled(Boolean enabled);
public Map<String, Object> getToolContext();
public void setToolContext(Map<String, Object> toolContext);
// Multimodal Configuration
public List<OutputModality> getOutputModalities();
public void setOutputModalities(List<OutputModality> outputModalities);
public AudioParameters getOutputAudio();
public void setOutputAudio(AudioParameters outputAudio);
// Advanced Features
public Boolean getLogprobs();
public void setLogprobs(Boolean logprobs);
public Integer getTopLogprobs();
public void setTopLogprobs(Integer topLogprobs);
public Integer getSeed();
public void setSeed(Integer seed);
public StreamOptions getStreamOptions();
public void setStreamOptions(StreamOptions streamOptions);
public String getUser();
public void setUser(String user);
public Boolean getStore();
public void setStore(Boolean store);
public Map<String, String> getMetadata();
public void setMetadata(Map<String, String> metadata);
// Reasoning and Search
public String getReasoningEffort();
public void setReasoningEffort(String reasoningEffort);
public String getVerbosity();
public void setVerbosity(String verbosity);
public WebSearchOptions getWebSearchOptions();
public void setWebSearchOptions(WebSearchOptions webSearchOptions);
// Service Configuration
public ServiceTier getServiceTier();
public void setServiceTier(ServiceTier serviceTier);
public String getPromptCacheKey();
public void setPromptCacheKey(String promptCacheKey);
public String getSafetyIdentifier();
public void setSafetyIdentifier(String safetyIdentifier);
public MultiValueMap<String, String> getHttpHeaders();
public void setHttpHeaders(MultiValueMap<String, String> httpHeaders);
public Map<String, Object> getExtraBody();
public void setExtraBody(Map<String, Object> extraBody);
}Builder Pattern:
public static class Builder {
public Builder model(String model);
public Builder temperature(Double temperature);
public Builder topP(Double topP);
public Builder maxTokens(Integer maxTokens);
public Builder maxCompletionTokens(Integer maxCompletionTokens);
public Builder n(Integer n);
public Builder frequencyPenalty(Double frequencyPenalty);
public Builder presencePenalty(Double presencePenalty);
public Builder logitBias(Map<String, Integer> logitBias);
public Builder stop(List<String> stop);
public Builder responseFormat(ResponseFormat responseFormat);
public Builder tools(List<FunctionTool> tools);
public Builder toolChoice(String toolChoice);
public Builder parallelToolCalls(Boolean parallelToolCalls);
public Builder toolCallbacks(Map<String, FunctionCallback> toolCallbacks);
public Builder outputModalities(List<OutputModality> outputModalities);
public Builder seed(Integer seed);
public Builder user(String user);
public Builder reasoningEffort(String reasoningEffort);
public Builder webSearchOptions(WebSearchOptions webSearchOptions);
// ... and more builder methods
public OpenAiChatOptions build();
}Usage Example - Basic Configuration:
var options = OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O.getValue())
.temperature(0.8)
.maxTokens(500)
.stop(List.of("END", "DONE"))
.build();
var response = chatModel.call(new Prompt("Generate a poem", options));Usage Example - Tool/Function Calling:
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.ai.openai.api.OpenAiApi.FunctionTool;
// Define function callback
FunctionCallback weatherCallback = FunctionCallback.builder()
.function("get_weather", "Get weather for a location")
.inputType(WeatherRequest.class)
.apply(request -> {
// Implementation to fetch weather
return new WeatherResponse(request.location(), "72°F", "Sunny");
})
.build();
// Configure options with tools
var options = OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O.getValue())
.tools(List.of(
FunctionTool.builder()
.type(FunctionTool.Type.FUNCTION)
.function(Function.builder()
.name("get_weather")
.description("Get current weather for a location")
.parameters(/* JSON schema */)
.build())
.build()
))
.toolCallbacks(Map.of("get_weather", weatherCallback))
.build();
var response = chatModel.call(
new Prompt("What's the weather in San Francisco?", options)
);Usage Example - Structured Output:
import org.springframework.ai.openai.api.ResponseFormat;
// Define response schema
var responseFormat = ResponseFormat.builder()
.type(ResponseFormat.Type.JSON_SCHEMA)
.jsonSchema(ResponseFormat.JsonSchema.builder()
.name("person")
.schema("""
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string"}
},
"required": ["name", "age"],
"additionalProperties": false
}
""")
.strict(true)
.build())
.build();
var options = OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O.getValue())
.responseFormat(responseFormat)
.build();
var response = chatModel.call(
new Prompt("Extract person info: John Smith is 30 years old, email john@example.com", options)
);Usage Example - Multimodal Input (Vision):
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.model.Media;
import org.springframework.core.io.ClassPathResource;
var imageResource = new ClassPathResource("image.jpg");
var userMessage = new UserMessage(
"What's in this image?",
List.of(new Media(MimeTypeUtils.IMAGE_JPEG, imageResource))
);
var options = OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O.getValue())
.build();
var response = chatModel.call(new Prompt(List.of(userMessage), options));Usage Example - Audio Output:
import org.springframework.ai.openai.api.OpenAiApi.OutputModality;
import org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest.AudioParameters;
var options = OpenAiChatOptions.builder()
.model(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW.getValue())
.outputModalities(List.of(OutputModality.TEXT, OutputModality.AUDIO))
.outputAudio(new AudioParameters(
"alloy", // voice
"pcm16" // format
))
.build();
var response = chatModel.call(new Prompt("Tell me a joke", options));
// Response includes both text and audioControls randomness in responses. Range: 0.0 to 2.0
Nucleus sampling parameter. Range: 0.0 to 1.0
Maximum number of tokens to generate in completion
Alternative to maxTokens for specifying completion length limit
Penalizes tokens based on frequency in text so far. Range: 0.0 to 2.0
Penalizes tokens based on presence in text so far. Range: 0.0 to 2.0
Modify likelihood of specific tokens appearing
Up to 4 sequences where API will stop generating
["\\n\\n", "END", "###"]Random seed for deterministic sampling
Control output structure:
Control tool/function calling behavior:
Enable/disable parallel execution of multiple tool calls in single response
Choose between service tiers:
For O-series reasoning models, control reasoning depth:
Enable web search integration (when available):
// Spring AI message types (from spring-ai-core)
public interface Message {
String getContent();
MessageType getMessageType();
Map<String, Object> getMetadata();
}
public class UserMessage implements Message {
public UserMessage(String content);
public UserMessage(String content, List<Media> media);
}
public class SystemMessage implements Message {
public SystemMessage(String content);
}
public class AssistantMessage implements Message {
public AssistantMessage(String content);
public AssistantMessage(String content, Map<String, Object> metadata);
}
public class ToolCallMessage implements Message {
// Message containing tool call requests
}
public class ToolResponseMessage implements Message {
// Message containing tool call results
}// Low-level OpenAI message structure
public record ChatCompletionMessage(
Object content, // String or List<MediaContent>
Role role, // Message role
String name, // Optional participant name
List<ToolCall> toolCalls, // Tool/function calls
String toolCallId, // Tool call ID for responses
String refusal, // Refusal reason
InputAudio inputAudio, // Input audio data
AudioOutput audio // Output audio data
) {}
public enum Role {
SYSTEM,
USER,
ASSISTANT,
TOOL,
FUNCTION // Deprecated, use TOOL
}
// Multi-modal content types
public record MediaContent(
String type, // "text", "image_url", "input_audio", "input_file"
String text, // Text content
ImageUrl imageUrl, // Image reference
InputAudio inputAudio, // Audio input
InputFile inputFile // File reference
) {}
public record ImageUrl(
String url, // Image URL or data URI
String detail // "auto", "low", "high"
) {}
public record ToolCall(
String id, // Unique tool call ID
String type, // "function"
ChatCompletionFunction function // Function details
) {}
public record ChatCompletionFunction(
String name, // Function name
String arguments // JSON string of arguments
) {}// High-level chat response
public record ChatCompletion(
String id, // Completion ID
List<Choice> choices, // Generated choices
Long created, // Unix timestamp
String model, // Model used
String systemFingerprint, // System fingerprint
String object, // "chat.completion"
Usage usage, // Token usage
String serviceTier // Service tier used
) {}
public record Choice(
ChatCompletionMessage message, // Generated message
Integer index, // Choice index
ChatCompletionFinishReason finishReason, // Why generation stopped
LogProbs logprobs // Log probabilities
) {}
// Streaming response chunk
public record ChatCompletionChunk(
String id,
String object, // "chat.completion.chunk"
Long created,
String model,
String systemFingerprint,
List<ChunkChoice> choices,
Usage usage, // Only in final chunk
String serviceTier
) {}
public record ChunkChoice(
ChatCompletionMessage delta, // Incremental content
Integer index,
ChatCompletionFinishReason finishReason,
LogProbs logprobs
) {}public record LogProbs(
List<Content> content
) {}
public record Content(
String token, // Token text
Double logprob, // Log probability
List<Integer> bytes, // Token bytes
List<TopLogProbs> topLogprobs // Alternative tokens
) {}
public record TopLogProbs(
String token,
Double logprob,
List<Integer> bytes
) {}public record Usage(
Integer promptTokens, // Prompt token count
Integer completionTokens, // Completion token count
Integer totalTokens, // Total token count
PromptTokensDetails promptTokensDetails,
CompletionTokenDetails completionTokensDetails
) {}
public record PromptTokensDetails(
Integer cachedTokens, // Tokens from cache
Integer textTokens, // Text tokens
Integer audioTokens, // Audio tokens
Integer imageTokens // Image tokens
) {}
public record CompletionTokenDetails(
Integer reasoningTokens, // Reasoning tokens (O-series)
Integer audioTokens, // Audio output tokens
Integer textTokens, // Text output tokens
Integer acceptedPredictionTokens, // Accepted predictions
Integer rejectedPredictionTokens // Rejected predictions
) {}public record FunctionTool(
Type type, // Tool type
Function function // Function definition
) {
public enum Type {
FUNCTION
}
public record Function(
String name, // Function name
String description, // Function description
Map<String, Object> parameters, // JSON schema
Boolean strict // Strict schema mode
) {}
}/**
* Specifies the format that the model must output.
* Setting type to JSON_SCHEMA enables Structured Outputs.
*/
public class ResponseFormat {
/**
* Default constructor
*/
public ResponseFormat();
/**
* Constructor with type and JSON schema
* @param type The response format type
* @param jsonSchema The JSON schema definition (null for TEXT/JSON_OBJECT)
*/
public ResponseFormat(Type type, JsonSchema jsonSchema);
/**
* Constructor with type and schema string
* @param type The response format type
* @param schema JSON schema as string (automatically converted to JsonSchema with strict=true)
*/
public ResponseFormat(Type type, String schema);
// Getters
public Type getType();
public JsonSchema getJsonSchema();
public String getSchema();
// Setters
public void setType(Type type);
public void setJsonSchema(JsonSchema jsonSchema);
public void setSchema(String schema);
public static Builder builder();
public static class Builder {
public Builder type(Type type);
public Builder jsonSchema(JsonSchema jsonSchema);
public Builder jsonSchema(String jsonSchema);
public ResponseFormat build();
}
public enum Type {
TEXT, // Plain text (default)
JSON_OBJECT, // Valid JSON object
JSON_SCHEMA // JSON schema validation (Structured Outputs)
}
/**
* JSON schema definition for structured outputs
*/
public static class JsonSchema {
/**
* Default constructor
*/
public JsonSchema();
// Getters
public String getName();
public Map<String, Object> getSchema();
public Boolean getStrict();
public static Builder builder();
public static class Builder {
/**
* Set schema name (default: "custom_schema")
*/
public Builder name(String name);
/**
* Set JSON schema as Map
*/
public Builder schema(Map<String, Object> schema);
/**
* Set JSON schema from string (automatically parsed)
*/
public Builder schema(String schema);
/**
* Set strict mode (default: true)
*/
public Builder strict(Boolean strict);
public JsonSchema build();
}
}
}public record StreamOptions(
Boolean includeUsage // Include usage in final chunk
) {}public enum OutputModality {
TEXT,
AUDIO
}
public record AudioParameters(
String voice, // Voice name
String format // Audio format
) {}
public record InputAudio(
String data, // Base64 audio data
String format // Audio format
) {}
public record AudioOutput(
String id, // Audio ID
Integer expiresAt, // Expiration timestamp
String data, // Base64 audio data
String transcript // Audio transcript
) {}public record WebSearchOptions(
SearchContextSize searchContextSize,
UserLocation userLocation
) {}
public enum SearchContextSize {
LOW,
MEDIUM,
HIGH
}
public record UserLocation(
String country, // ISO 3166-1 alpha-2 country code
String region, // State/province code
String city, // City name
String timezone // IANA timezone
) {}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-ai--spring-ai-openai@1.1.0