Spring Boot Starter for OpenAI integration providing auto-configuration for chat completion, embeddings, image generation, audio speech synthesis, audio transcription, and content moderation models. Includes high-level ChatClient API and conversation memory support.
The OpenAiChatModel provides complete chat completion capabilities with support for streaming, tool/function calling, JSON mode, vision, and audio output.
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.content.Media;
import org.springframework.util.MimeType;
import reactor.core.publisher.Flux;package org.springframework.ai.openai;
public class OpenAiChatModel implements ChatModel, StreamingChatModel {
// Synchronous chat completion
public ChatResponse call(Prompt prompt);
// Streaming chat completion
public Flux<ChatResponse> stream(Prompt prompt);
// Get default options
public ChatOptions getDefaultOptions();
// Set observation convention
public void setObservationConvention(ChatModelObservationConvention convention);
// Create builder from existing instance
public Builder mutate();
// Create new builder
public static Builder builder();
// Clone the model
public OpenAiChatModel clone();
}package org.springframework.ai.openai;
public static class Builder {
// Set OpenAI API client
public Builder openAiApi(OpenAiApi openAiApi);
// Set default options
public Builder defaultOptions(OpenAiChatOptions defaultOptions);
// Set tool calling manager
public Builder toolCallingManager(ToolCallingManager toolCallingManager);
// Set tool execution eligibility predicate
public Builder toolExecutionEligibilityPredicate(ToolExecutionEligibilityPredicate predicate);
// Set retry template
public Builder retryTemplate(RetryTemplate retryTemplate);
// Set observation registry
public Builder observationRegistry(ObservationRegistry observationRegistry);
// Build the chat model
public OpenAiChatModel build();
}package org.springframework.ai.openai;
public class OpenAiChatOptions implements ChatOptions, ToolCallingChatOptions {
// Builder methods
public static OpenAiChatOptions.Builder builder();
// Static factory methods
public static OpenAiChatOptions create();
public static OpenAiChatOptions fromOptions(ChatOptions options);
// Utility methods
public OpenAiChatOptions copy();
// Core configuration - Getters
public String getModel();
public Double getTemperature();
public Double getTopP();
public Integer getMaxTokens();
public Integer getMaxCompletionTokens();
public Double getFrequencyPenalty();
public Double getPresencePenalty();
public List<String> getStop();
public List<String> getStopSequences();
public Integer getN();
public Map<Integer, Integer> getLogitBias();
// Core configuration - Setters
public void setModel(String model);
public void setTemperature(Double temperature);
public void setTopP(Double topP);
public void setMaxTokens(Integer maxTokens);
public void setMaxCompletionTokens(Integer maxCompletionTokens);
public void setFrequencyPenalty(Double frequencyPenalty);
public void setPresencePenalty(Double presencePenalty);
public void setStop(List<String> stop);
public void setStopSequences(List<String> stopSequences);
public void setN(Integer n);
public void setLogitBias(Map<Integer, Integer> logitBias);
// Advanced features - Getters
public Boolean getLogprobs();
public Integer getTopLogprobs();
public Integer getSeed();
public String getUser();
public ResponseFormat getResponseFormat();
public Object getToolChoice();
public List<OpenAiApi.FunctionTool> getTools();
public Object getOutputSchema();
// Advanced features - Setters
public void setLogprobs(Boolean logprobs);
public void setTopLogprobs(Integer topLogprobs);
public void setSeed(Integer seed);
public void setUser(String user);
public void setResponseFormat(ResponseFormat responseFormat);
public void setToolChoice(Object toolChoice);
public void setTools(List<OpenAiApi.FunctionTool> tools);
public void setOutputSchema(Object outputSchema);
// Tool/function calling configuration (from ToolCallingChatOptions)
public Boolean getParallelToolCalls();
public List<FunctionCallback> getToolCallbacks();
public List<String> getToolNames();
public Map<String, Object> getToolContext();
public void setParallelToolCalls(Boolean parallelToolCalls);
public void setToolCallbacks(List<FunctionCallback> toolCallbacks);
public void setToolNames(List<String> toolNames);
public void setToolContext(Map<String, Object> toolContext);
// Streaming configuration - Getters
public OpenAiApi.ChatCompletionRequest.StreamOptions getStreamOptions();
public Boolean getStreamUsage();
// Streaming configuration - Setters
public void setStreamOptions(OpenAiApi.ChatCompletionRequest.StreamOptions streamOptions);
public void setStreamUsage(Boolean streamUsage);
// Audio output (multimodal) - Getters
public AudioParameters getAudioParameters();
public List<String> getOutputModalities();
// Audio output (multimodal) - Setters
public void setAudioParameters(AudioParameters audioParameters);
public void setOutputModalities(List<String> outputModalities);
// Reasoning models (o1/o3 series) - Getters
public String getReasoningEffort();
// Reasoning models (o1/o3 series) - Setters
public void setReasoningEffort(String reasoningEffort);
// Web search - Getters
public String getVerbosity();
public WebSearchOptions getWebSearchOptions();
// Web search - Setters
public void setVerbosity(String verbosity);
public void setWebSearchOptions(WebSearchOptions webSearchOptions);
// Performance and caching - Getters
public String getServiceTier();
public String getPromptCacheKey();
public String getSafetyIdentifier();
// Performance and caching - Setters
public void setServiceTier(String serviceTier);
public void setPromptCacheKey(String promptCacheKey);
public void setSafetyIdentifier(String safetyIdentifier);
// Storage and metadata - Getters
public Boolean getStore();
public Map<String, String> getMetadata();
// Storage and metadata - Setters
public void setStore(Boolean store);
public void setMetadata(Map<String, String> metadata);
// OpenAI-compatible servers (vLLM, Ollama, etc.) - Getters
public Map<String, Object> getExtraBody();
public Map<String, String> getHttpHeaders();
// OpenAI-compatible servers (vLLM, Ollama, etc.) - Setters
public void setExtraBody(Map<String, Object> extraBody);
public void setHttpHeaders(Map<String, String> httpHeaders);
}import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;
@Service
public class BasicChatService {
private final OpenAiChatModel chatModel;
public BasicChatService(OpenAiChatModel chatModel) {
this.chatModel = chatModel;
}
public String chat(String userMessage) {
Prompt prompt = new Prompt(userMessage);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
}import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import java.util.List;
public String chatWithSystem(String userMessage) {
List<Message> messages = List.of(
new SystemMessage("You are a helpful assistant that answers in a concise manner."),
new UserMessage(userMessage)
);
Prompt prompt = new Prompt(messages);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}import org.springframework.ai.openai.OpenAiChatOptions;
public String chatWithOptions(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("gpt-4o")
.temperature(0.7)
.maxTokens(500)
.topP(0.9)
.frequencyPenalty(0.5)
.presencePenalty(0.5)
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}import reactor.core.publisher.Flux;
public Flux<String> streamChat(String userMessage) {
Prompt prompt = new Prompt(userMessage);
return chatModel.stream(prompt)
.map(response -> response.getResult().getOutput().getContent())
.filter(content -> content != null && !content.isEmpty());
}import java.util.Map;
public String chatJsonMode(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.responseFormat(Map.of("type", "json_object"))
.build();
Prompt prompt = new Prompt(
"Extract name and age from: John is 30 years old. Return as JSON.",
options
);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent(); // Returns JSON string
}import org.springframework.ai.tool.function.FunctionToolCallback;
import java.util.List;
public String chatWithToolCalling(String userMessage) {
// Create function callback
FunctionToolCallback weatherCallback = FunctionToolCallback.builder("getCurrentWeather",
(WeatherRequest request) -> {
// Function logic
return new WeatherResponse(request.location(), "72°F", "Sunny");
})
.description("Get the current weather in a location")
.inputType(WeatherRequest.class)
.build();
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("gpt-4o")
.toolCallbacks(List.of(weatherCallback))
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}
// Supporting types
record WeatherRequest(String location) {}
record WeatherResponse(String location, String temperature, String weather) {}import org.springframework.core.io.ClassPathResource;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.content.Media;
import org.springframework.util.MimeType;
import java.util.List;
public String analyzeImage(String prompt, String imagePath) {
// Create media using builder
Media media = Media.builder()
.mimeType(MimeType.valueOf("image/png"))
.data(new ClassPathResource(imagePath))
.build();
UserMessage userMessage = new UserMessage(prompt, List.of(media));
ChatResponse response = chatModel.call(new Prompt(List.of(userMessage)));
return response.getResult().getOutput().getContent();
}import org.springframework.ai.chat.messages.AssistantMessage;
import java.util.ArrayList;
public String multiTurnChat(List<String> conversationHistory) {
List<Message> messages = new ArrayList<>();
// Add conversation history
for (int i = 0; i < conversationHistory.size(); i++) {
if (i % 2 == 0) {
messages.add(new UserMessage(conversationHistory.get(i)));
} else {
messages.add(new AssistantMessage(conversationHistory.get(i)));
}
}
Prompt prompt = new Prompt(messages);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String reasoningChat(String complexProblem) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("o3") // or "o3-mini", "o4-mini", "o1", "o1-mini"
.maxCompletionTokens(10000) // Use max_completion_tokens for reasoning models
.reasoningEffort("high") // "low", "medium", or "high"
.build();
Prompt prompt = new Prompt(complexProblem, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String searchChat(String query) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("gpt-4o-search-preview")
.verbosity("medium") // "low", "medium", or "high"
.build();
Prompt prompt = new Prompt(query, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}import java.util.Map;
public String compatibleServerChat(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("llama-3.1-70b") // vLLM or Ollama model
.temperature(0.7)
.extraBody(Map.of(
"top_k", 50,
"repetition_penalty", 1.1
))
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String chatWithParallelTools(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.toolCallbacks(List.of(callback1, callback2, callback3))
.parallelToolCalls(true) // Enable parallel execution
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String cachedPromptChat(String systemPrompt, String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.promptCacheKey("my-system-prompt-v1") // Cache key for optimization
.build();
List<Message> messages = List.of(
new SystemMessage(systemPrompt),
new UserMessage(userMessage)
);
Prompt prompt = new Prompt(messages, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String chatWithStorage(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.store(true) // Store for distillation/evals
.metadata(Map.of(
"user_id", "user-123",
"session_id", "session-456"
))
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String chatWithStopSequences(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.stop(List.of("\n", "END"))
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}public String deterministicChat(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.seed(12345)
.temperature(0.0)
.build();
Prompt prompt = new Prompt(userMessage, options);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
}Configure via application.properties:
# API Connection
spring.ai.openai.chat.api-key=sk-...
spring.ai.openai.chat.base-url=https://api.openai.com
spring.ai.openai.chat.project-id=proj_...
spring.ai.openai.chat.organization-id=org-...
# Model Configuration
spring.ai.openai.chat.model=gpt-4o-mini
spring.ai.openai.chat.temperature=0.7
spring.ai.openai.chat.max-tokens=1000
spring.ai.openai.chat.top-p=1.0
spring.ai.openai.chat.frequency-penalty=0.0
spring.ai.openai.chat.presence-penalty=0.0Access metadata from chat responses:
ChatResponse response = chatModel.call(prompt);
// Token usage
ChatResponseMetadata metadata = response.getMetadata();
Integer promptTokens = metadata.getUsage().getPromptTokens();
Integer completionTokens = metadata.getUsage().getGenerationTokens();
Integer totalTokens = metadata.getUsage().getTotalTokens();
// Model information
String model = metadata.getModel();
// Finish reason
String finishReason = response.getResult().getMetadata().getFinishReason();Reasoning Models:
o4-mini - Latest compact reasoning modelo3 - Advanced reasoning modelo3-mini - Compact reasoning modelo1 - Advanced reasoning modelo1-mini - Faster reasoning modelo1-pro - Professional reasoning modelFlagship Models:
gpt-4.1 - Latest flagship modelgpt-4o - Most capable multimodal modelgpt-4o-mini - Affordable and efficient (default)gpt-4-turbo - Previous generation GPT-4 Turbogpt-4 - Original GPT-4Search Models:
gpt-4o-search-preview - GPT-4o with web searchgpt-4o-mini-search-preview - GPT-4o-mini with web searchLegacy Models:
gpt-3.5-turbo - Fast and cost-effectivegpt-3.5-turbo-instruct - Legacy instruct modelControls randomness (0.0-2.0):
maxTokens: Maximum total tokens (prompt + completion)maxCompletionTokens: Maximum completion tokens only (for reasoning models like o1)frequencyPenalty (0.0-2.0): Reduces repetition based on frequencypresencePenalty (0.0-2.0): Reduces repetition based on presenceimport org.springframework.ai.openai.api.OpenAiApiException;
public String safeChat(String userMessage) {
try {
Prompt prompt = new Prompt(userMessage);
ChatResponse response = chatModel.call(prompt);
return response.getResult().getOutput().getContent();
} catch (OpenAiApiException e) {
// Handle API errors (rate limits, invalid API key, etc.)
return "Error: " + e.getMessage();
}
}package org.springframework.ai.openai;
public static class Builder {
// Core parameters
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 frequencyPenalty(Double frequencyPenalty);
public Builder presencePenalty(Double presencePenalty);
public Builder stop(List<String> stop);
public Builder stop(String... stop);
public Builder stopSequences(List<String> stopSequences);
public Builder n(Integer n);
public Builder logitBias(Map<Integer, Integer> logitBias);
// Advanced parameters
public Builder logprobs(Boolean logprobs);
public Builder topLogprobs(Integer topLogprobs);
public Builder seed(Integer seed);
public Builder user(String user);
public Builder responseFormat(ResponseFormat responseFormat);
public Builder outputSchema(Object outputSchema);
// Tool/function calling
public Builder toolChoice(Object toolChoice);
public Builder tools(List<OpenAiApi.FunctionTool> tools);
public Builder toolCallbacks(List<FunctionCallback> toolCallbacks);
public Builder toolCallbacks(FunctionCallback... toolCallbacks);
public Builder toolNames(List<String> toolNames);
public Builder toolNames(String... toolNames);
public Builder toolContext(Map<String, Object> toolContext);
public Builder parallelToolCalls(Boolean parallelToolCalls);
// Streaming
public Builder streamOptions(OpenAiApi.ChatCompletionRequest.StreamOptions streamOptions);
public Builder streamUsage(Boolean streamUsage);
// Audio output
public Builder audioParameters(AudioParameters audioParameters);
public Builder outputModalities(List<String> outputModalities);
public Builder outputModalities(String... outputModalities);
// Reasoning models
public Builder reasoningEffort(String reasoningEffort);
// Web search
public Builder verbosity(String verbosity);
public Builder webSearchOptions(WebSearchOptions webSearchOptions);
// Performance and caching
public Builder serviceTier(String serviceTier);
public Builder promptCacheKey(String promptCacheKey);
public Builder safetyIdentifier(String safetyIdentifier);
// Storage and metadata
public Builder store(Boolean store);
public Builder metadata(Map<String, String> metadata);
// OpenAI-compatible servers
public Builder extraBody(Map<String, Object> extraBody);
public Builder httpHeaders(Map<String, String> httpHeaders);
public OpenAiChatOptions build();
}package org.springframework.ai.openai;
public class ToolChoice {
// Predefined constants (String values)
public static final String NONE = "none";
public static final String AUTO = "auto";
public static final String REQUIRED = "required";
// Builder for specific function choice
public static Builder builder();
public static class Builder {
public Builder type(String type);
public Builder function(String functionName);
public Object build();
}
}package org.springframework.ai.openai;
public class ResponseFormat {
public static final String TEXT = "text";
public static final String JSON_OBJECT = "json_object";
public static final String JSON_SCHEMA = "json_schema";
public ResponseFormat(String type);
public ResponseFormat(String type, String jsonSchema);
public String getType();
public String getJsonSchema();
}package org.springframework.ai.openai;
public class AudioParameters {
public AudioParameters(Voice voice, AudioResponseFormat format);
public Voice getVoice();
public AudioResponseFormat getFormat();
public enum Voice {
ALLOY("alloy"),
ECHO("echo"),
FABLE("fable"),
ONYX("onyx"),
NOVA("nova"),
SHIMMER("shimmer");
private final String value;
Voice(String value) { this.value = value; }
public String getValue() { return value; }
}
public enum AudioResponseFormat {
WAV("wav"),
MP3("mp3"),
FLAC("flac"),
OPUS("opus"),
PCM16("pcm16");
private final String value;
AudioResponseFormat(String value) { this.value = value; }
public String getValue() { return value; }
}
}package org.springframework.ai.openai;
public class WebSearchOptions {
public WebSearchOptions(SearchContextSize contextSize);
public SearchContextSize getContextSize();
public enum SearchContextSize {
LOW("low"),
MEDIUM("medium"),
HIGH("high");
private final String value;
SearchContextSize(String value) { this.value = value; }
public String getValue() { return value; }
}
}package org.springframework.ai.openai.api.OpenAiApi.ChatCompletionRequest;
public class StreamOptions {
public StreamOptions(Boolean includeUsage);
public Boolean getIncludeUsage();
}tessl i tessl/maven-org-springframework-ai--spring-ai-starter-model-openai@1.1.1