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 ChatClient provides a high-level, fluent DSL for building and executing chat interactions with built-in advisor support, observation logging, and simplified API.
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.Advisor;
import org.springframework.ai.chat.model.ChatOptions;
import org.springframework.beans.factory.annotation.Autowired;package org.springframework.ai.chat.client;
import org.springframework.core.io.Resource;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public interface Builder {
// Set default system message
Builder defaultSystem(String text);
Builder defaultSystem(Resource text);
Builder defaultSystem(Consumer<PromptSystemSpec> systemSpecConsumer);
// Set default user message
Builder defaultUser(String text);
Builder defaultUser(Resource text);
Builder defaultUser(Consumer<PromptUserSpec> userSpecConsumer);
// Set default messages
Builder defaultMessages(Message... messages);
Builder defaultMessages(List<Message> messages);
// Set default advisors
Builder defaultAdvisors(Advisor... advisors);
Builder defaultAdvisors(List<Advisor> advisors);
Builder defaultAdvisors(Consumer<AdvisorSpec> advisorSpecConsumer);
// Set default advisor parameters
Builder defaultAdvisorParams(Map<String, Object> params);
// Set default options
Builder defaultOptions(ChatOptions options);
// Set default tool support
Builder defaultToolNames(String... toolNames);
Builder defaultTools(Object... tools);
Builder defaultToolCallbacks(FunctionCallback... functionCallbacks);
Builder defaultToolCallbacks(List<FunctionCallback> functionCallbacks);
Builder defaultToolContext(Map<String, Object> toolContext);
// Build the ChatClient
ChatClient build();
}package org.springframework.ai.chat.client;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.observation.conventions.AiObservationConventions;
import io.micrometer.observation.ObservationRegistry;
public interface ChatClient {
// Static factory methods
static Builder builder(ChatModel chatModel);
static ChatClient create(ChatModel chatModel);
static ChatClient create(ChatModel chatModel, ObservationRegistry observationRegistry);
static ChatClient create(
ChatModel chatModel,
ObservationRegistry observationRegistry,
ChatClientObservationConvention chatClientObservationConvention,
AdvisorObservationConvention advisorObservationConvention
);
// Start building a prompt
ChatClientRequestSpec prompt();
// Start building a prompt with text
ChatClientRequestSpec prompt(String text);
// Advanced prompt with Prompt object
ChatClientRequestSpec prompt(Prompt prompt);
// Create a mutable copy of this ChatClient
Builder mutate();
}package org.springframework.ai.chat.client;
import org.springframework.ai.model.function.FunctionCallback;
import java.util.function.Consumer;
public interface ChatClientRequestSpec {
// Add system message
ChatClientRequestSpec system(String text);
ChatClientRequestSpec system(Resource text);
ChatClientRequestSpec system(Consumer<PromptSystemSpec> systemSpecConsumer);
// Add user message
ChatClientRequestSpec user(String text);
ChatClientRequestSpec user(Resource text);
ChatClientRequestSpec user(Consumer<PromptUserSpec> userSpecConsumer);
// Add messages
ChatClientRequestSpec messages(Message... messages);
ChatClientRequestSpec messages(List<Message> messages);
// Add advisors
ChatClientRequestSpec advisors(Advisor... advisors);
ChatClientRequestSpec advisors(List<Advisor> advisors);
ChatClientRequestSpec advisors(Consumer<AdvisorSpec> advisorSpecConsumer);
// Set options
ChatClientRequestSpec options(ChatOptions options);
// Tool support
ChatClientRequestSpec toolNames(String... toolNames);
ChatClientRequestSpec tools(Object... tools);
ChatClientRequestSpec toolCallbacks(FunctionCallback... functionCallbacks);
ChatClientRequestSpec toolCallbacks(List<FunctionCallback> functionCallbacks);
ChatClientRequestSpec toolContext(Map<String, Object> toolContext);
// Execute the call
CallResponseSpec call();
// Stream the response
StreamResponseSpec stream();
// Create a mutable copy
ChatClientRequestSpec mutate();
}package org.springframework.ai.chat.client;
import org.springframework.ai.converter.StructuredOutputConverter;
public interface CallResponseSpec {
// Get full response
ChatResponse chatResponse();
// Get ChatClient-specific response wrapper
ChatClientResponse chatClientResponse();
// Get response entity (with metadata)
ResponseEntity<ChatResponse> responseEntity();
// Get content string
String content();
// Get content as ResponseEntity
ResponseEntity<String> contentEntity();
// Get entity (deserialize response)
<T> T entity(Class<T> type);
<T> T entity(ParameterizedTypeReference<T> type);
<T> T entity(StructuredOutputConverter<T> structuredOutputConverter);
// Get entity as ResponseEntity
<T> ResponseEntity<T> entityEntity(Class<T> type);
<T> ResponseEntity<T> entityEntity(ParameterizedTypeReference<T> type);
}package org.springframework.ai.chat.client;
import reactor.core.publisher.Flux;
public interface StreamResponseSpec {
// Stream full responses
Flux<ChatResponse> chatResponse();
// Stream ChatClient-specific responses
Flux<ChatClientResponse> chatClientResponse();
// Stream content
Flux<String> content();
}package org.springframework.ai.chat.client;
import org.springframework.ai.chat.prompt.ChatOptionsBuilder;
import org.springframework.util.MimeType;
import java.net.URL;
import java.util.Map;
public interface PromptUserSpec {
// Set text content
PromptUserSpec text(String text);
PromptUserSpec text(Resource text);
// Set template parameters
PromptUserSpec params(Map<String, Object> params);
PromptUserSpec param(String key, Object value);
// Add media content
PromptUserSpec media(MimeType mimeType, String data);
PromptUserSpec media(MimeType mimeType, URL url);
PromptUserSpec media(MimeType mimeType, Resource resource);
// Set message metadata
PromptUserSpec metadata(Map<String, Object> metadata);
PromptUserSpec metadata(String key, Object value);
// Options builder access
ChatOptionsBuilder options();
}package org.springframework.ai.chat.client;
import java.util.Map;
public interface PromptSystemSpec {
// Set text content
PromptSystemSpec text(String text);
PromptSystemSpec text(Resource text);
// Set template parameters
PromptSystemSpec params(Map<String, Object> params);
PromptSystemSpec param(String key, Object value);
// Set message metadata
PromptSystemSpec metadata(Map<String, Object> metadata);
PromptSystemSpec metadata(String key, Object value);
}package org.springframework.ai.chat.client;
import java.util.Map;
public interface AdvisorSpec {
// Set advisor parameters
AdvisorSpec params(Map<String, Object> params);
AdvisorSpec param(String key, Object value);
}import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ChatClientService {
private final ChatClient chatClient;
@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultSystem("You are a helpful assistant that provides concise answers.")
.build();
}
public String chat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}import org.springframework.ai.openai.OpenAiChatOptions;
@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.model("gpt-4o")
.temperature(0.7)
.maxTokens(500)
.build();
this.chatClient = chatClientBuilder
.defaultOptions(options)
.build();
}public String simpleChat(String question) {
return chatClient.prompt(question)
.call()
.content();
}public String chatWithSystem(String systemPrompt, String userMessage) {
return chatClient.prompt()
.system(systemPrompt)
.user(userMessage)
.call()
.content();
}import org.springframework.ai.openai.OpenAiChatOptions;
public String chatWithOptions(String userMessage) {
OpenAiChatOptions options = OpenAiChatOptions.builder()
.temperature(0.9)
.build();
return chatClient.prompt()
.user(userMessage)
.options(options)
.call()
.content();
}import org.springframework.ai.chat.model.ChatResponse;
public ChatResponse getFullResponse(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.chatResponse();
}
public void analyzeResponse(String userMessage) {
ChatResponse response = getFullResponse(userMessage);
String content = response.getResult().getOutput().getContent();
Integer promptTokens = response.getMetadata().getUsage().getPromptTokens();
Integer completionTokens = response.getMetadata().getUsage().getGenerationTokens();
System.out.println("Content: " + content);
System.out.println("Prompt tokens: " + promptTokens);
System.out.println("Completion tokens: " + completionTokens);
}import reactor.core.publisher.Flux;
public Flux<String> streamChat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.stream()
.content();
}
public void streamChatToConsole(String userMessage) {
streamChat(userMessage)
.doOnNext(System.out::print)
.blockLast();
}import org.springframework.ai.chat.model.ChatResponse;
public Flux<ChatResponse> streamFullResponse(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.stream()
.chatResponse();
}public record Person(String name, int age, String occupation) {}
public Person extractPerson(String text) {
return chatClient.prompt()
.user("Extract person information from: " + text)
.call()
.entity(Person.class);
}
// Usage
public void demonstrateEntityMapping() {
Person person = extractPerson("John Doe is a 30-year-old software engineer.");
System.out.println(person.name()); // "John Doe"
System.out.println(person.age()); // 30
}import org.springframework.core.ParameterizedTypeReference;
import java.util.List;
public record Book(String title, String author, int year) {}
public List<Book> extractBooks(String text) {
return chatClient.prompt()
.user("Extract all books mentioned in: " + text)
.call()
.entity(new ParameterizedTypeReference<List<Book>>() {});
}import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory) {
this.chatClient = chatClientBuilder
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
.build();
}
public String chatWithMemory(String conversationId, String userMessage) {
return chatClient.prompt()
.user(userMessage)
.advisors(advisor -> advisor.param("conversationId", conversationId))
.call()
.content();
}import org.springframework.ai.rag.preretrieval.query.expansion.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.rag.preretrieval.query.expansion.advisor.VectorStoreChatMemoryAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
@Autowired
public ChatClientService(
ChatClient.Builder chatClientBuilder,
VectorStore vectorStore,
ChatMemory chatMemory
) {
this.chatClient = chatClientBuilder
.defaultAdvisors(
new QuestionAnswerAdvisor(vectorStore),
new MessageChatMemoryAdvisor(chatMemory)
)
.build();
}public String chatWithTemplate(String name, String topic) {
return chatClient.prompt()
.user("Tell {name} about {topic}")
.advisors(advisor -> advisor
.param("name", name)
.param("topic", topic))
.call()
.content();
}import org.springframework.core.io.Resource;
import org.springframework.beans.factory.annotation.Value;
@Value("classpath:prompts/system-message.txt")
private Resource systemPrompt;
@Value("classpath:prompts/user-template.txt")
private Resource userPrompt;
public String chatWithResources() {
return chatClient.prompt()
.system(systemPrompt)
.user(userPrompt)
.call()
.content();
}import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Description;
// Define a tool function
@Bean
@Description("Get the current weather for a location")
public FunctionCallback weatherFunction() {
return FunctionCallback.builder()
.function("getCurrentWeather", this::getCurrentWeather)
.description("Get the current weather for a location")
.inputType(WeatherRequest.class)
.build();
}
record WeatherRequest(String location, String unit) {}
record WeatherResponse(double temperature, String conditions) {}
private WeatherResponse getCurrentWeather(WeatherRequest request) {
// Implementation
return new WeatherResponse(72.0, "sunny");
}
// Use tool in ChatClient
public String chatWithTools(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.tools(weatherFunction())
.call()
.content();
}
// Or specify tool names from registered beans
public String chatWithToolNames(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.toolNames("getCurrentWeather", "getStockPrice")
.call()
.content();
}import org.springframework.util.MimeType;
public String chatWithMedia(String question, Resource imageResource) {
return chatClient.prompt()
.user(userSpec -> userSpec
.text("Describe this image: {question}")
.param("question", question)
.media(MimeType.valueOf("image/jpeg"), imageResource)
.metadata("source", "user-upload"))
.call()
.content();
}public String chatWithSystemParams(String role, String expertise) {
return chatClient.prompt()
.system(systemSpec -> systemSpec
.text("You are a {role} with expertise in {field}.")
.param("role", role)
.param("field", expertise)
.metadata("version", "2.0"))
.user("Help me with my problem")
.call()
.content();
}public String chatWithAdvisorParams(String conversationId, String userMessage) {
return chatClient.prompt()
.user(userMessage)
.advisors(advisorSpec -> advisorSpec
.param("conversationId", conversationId)
.param("maxMessages", 10))
.call()
.content();
}import org.springframework.ai.chat.model.ChatModel;
import io.micrometer.observation.ObservationRegistry;
@Autowired
private ChatModel chatModel;
@Autowired
private ObservationRegistry observationRegistry;
public void createChatClients() {
// Create with just ChatModel
ChatClient simpleClient = ChatClient.create(chatModel);
// Create with ObservationRegistry
ChatClient observableClient = ChatClient.create(chatModel, observationRegistry);
// Create with builder
ChatClient customClient = ChatClient.builder(chatModel)
.defaultSystem("You are a helpful assistant")
.build();
}public class ChatClientManager {
private final ChatClient baseChatClient;
public ChatClientManager(ChatClient baseChatClient) {
this.baseChatClient = baseChatClient;
}
public ChatClient createSpecializedClient() {
return baseChatClient.mutate()
.defaultSystem("You are a specialized technical expert")
.defaultAdvisors(new SimpleLoggerAdvisor())
.build();
}
}import org.springframework.ai.chat.client.ChatClientResponse;
public void analyzeChatClientResponse(String userMessage) {
ChatClientResponse response = chatClient.prompt()
.user(userMessage)
.call()
.chatClientResponse();
String content = response.content();
Map<String, Object> metadata = response.metadata();
AssistantMessage message = response.assistantMessage();
System.out.println("Content: " + content);
System.out.println("Metadata: " + metadata);
}import org.springframework.ai.chat.client.ResponseEntity;
import org.springframework.ai.chat.model.ChatResponse;
public void analyzeResponseEntity(String userMessage) {
ResponseEntity<ChatResponse> responseEntity = chatClient.prompt()
.user(userMessage)
.call()
.responseEntity();
ChatResponse body = responseEntity.getBody();
int statusCode = responseEntity.getStatusCode().value();
Map<String, List<String>> headers = responseEntity.getHeaders();
System.out.println("Status: " + statusCode);
}
// Get content as ResponseEntity
public void getContentEntity(String userMessage) {
ResponseEntity<String> contentEntity = chatClient.prompt()
.user(userMessage)
.call()
.contentEntity();
String content = contentEntity.getBody();
int statusCode = contentEntity.getStatusCode().value();
}import org.springframework.ai.converter.StructuredOutputConverter;
public class CustomOutputConverter implements StructuredOutputConverter<Person> {
@Override
public Person convert(String text) {
// Custom parsing logic
return parsePersonFromText(text);
}
@Override
public String getFormat() {
return "name:string, age:integer, occupation:string";
}
}
public Person extractPersonWithConverter(String text) {
return chatClient.prompt()
.user("Extract person information from: " + text)
.call()
.entity(new CustomOutputConverter());
}import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import java.util.List;
public String chatWithMessages(List<Message> conversationHistory, String newMessage) {
return chatClient.prompt()
.messages(conversationHistory)
.messages(new UserMessage(newMessage))
.call()
.content();
}
// Or use varargs
public String chatWithMultipleMessages(String systemText, String userText) {
return chatClient.prompt()
.messages(
new SystemMessage(systemText),
new UserMessage(userText)
)
.call()
.content();
}import java.util.Map;
public String chatWithToolContext(String userMessage, Map<String, Object> context) {
return chatClient.prompt()
.user(userMessage)
.toolNames("databaseQuery", "apiCall")
.toolContext(Map.of(
"databaseConnection", context.get("dbConn"),
"apiKey", context.get("apiKey"),
"environment", "production"
))
.call()
.content();
}import org.springframework.ai.model.function.FunctionCallback;
@Autowired
public ChatClientService(
ChatClient.Builder chatClientBuilder,
List<FunctionCallback> functionCallbacks
) {
this.chatClient = chatClientBuilder
.defaultToolCallbacks(functionCallbacks)
.defaultToolContext(Map.of("environment", "production"))
.build();
}import org.springframework.ai.chat.client.advisor.SafeGuardAdvisor;
import org.springframework.ai.openai.OpenAiModerationModel;
@Autowired
public ChatClientService(
ChatClient.Builder chatClientBuilder,
OpenAiModerationModel moderationModel
) {
this.chatClient = chatClientBuilder
.defaultAdvisors(new SafeGuardAdvisor(moderationModel))
.build();
}
public String moderatedChat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}import org.springframework.ai.chat.client.advisor.StructuredOutputValidationAdvisor;
@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultAdvisors(new StructuredOutputValidationAdvisor())
.build();
}
public Person getValidatedPerson(String text) {
return chatClient.prompt()
.user("Extract person information from: " + text)
.call()
.entity(Person.class);
}import org.springframework.ai.chat.client.advisor.ToolCallAdvisor;
@Autowired
public ChatClientService(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder
.defaultAdvisors(new ToolCallAdvisor())
.build();
}
public String chatWithToolCallHandling(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.toolNames("getCurrentWeather", "getStockPrice")
.call()
.content();
}import reactor.core.publisher.Flux;
public Flux<ChatClientResponse> streamChatClientResponse(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.stream()
.chatClientResponse();
}
public void streamWithMetadata(String userMessage) {
streamChatClientResponse(userMessage)
.doOnNext(response -> {
System.out.println("Content: " + response.content());
System.out.println("Metadata: " + response.metadata());
})
.blockLast();
}import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.openai.OpenAiChatOptions;
public String chatWithPromptObject(String userMessage) {
Prompt prompt = new Prompt(
List.of(new UserMessage(userMessage)),
OpenAiChatOptions.builder()
.model("gpt-4o")
.temperature(0.7)
.build()
);
return chatClient.prompt(prompt)
.call()
.content();
}import org.springframework.ai.openai.api.OpenAiApiException;
public String safeChat(String userMessage) {
try {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
} catch (OpenAiApiException e) {
return "Error: " + e.getMessage();
}
}import java.util.ArrayList;
import java.util.List;
public class ConversationManager {
private final ChatClient chatClient;
private final List<String> conversationHistory = new ArrayList<>();
public ConversationManager(ChatClient chatClient) {
this.chatClient = chatClient;
}
public String chat(String userMessage) {
String response = chatClient.prompt()
.user(buildConversationPrompt(userMessage))
.call()
.content();
conversationHistory.add("User: " + userMessage);
conversationHistory.add("Assistant: " + response);
return response;
}
private String buildConversationPrompt(String newMessage) {
StringBuilder prompt = new StringBuilder();
for (String message : conversationHistory) {
prompt.append(message).append("\n");
}
prompt.append("User: ").append(newMessage);
return prompt.toString();
}
}Configure ChatClient via application.properties:
# Enable/disable ChatClient
spring.ai.chat.client.enabled=true
# Observation logging
spring.ai.chat.client.observations.log-prompt=false
spring.ai.chat.client.observations.log-completion=falseChatClient integrates with Micrometer for observability:
# Enable observation logging
spring.ai.chat.client.observations.log-prompt=true
spring.ai.chat.client.observations.log-completion=trueThis logs:
Advisors enhance ChatClient with additional capabilities:
org.springframework.ai.chat.client.advisor) - Adds conversation memoryorg.springframework.ai.rag.preretrieval.query.expansion.advisor) - RAG with vector storeorg.springframework.ai.rag.preretrieval.query.expansion.advisor) - Vector-based memoryorg.springframework.ai.chat.client.advisor) - Prompt-based memoryorg.springframework.ai.chat.client.advisor) - Logging advisororg.springframework.ai.chat.client.advisor) - Content safety and moderationorg.springframework.ai.chat.client.advisor) - Validates structured outputsorg.springframework.ai.chat.client.advisor) - Handles tool/function callingImplement the CallAroundAdvisor or RequestResponseAdvisor interface to create custom advisors:
package org.springframework.ai.chat.client.advisor.api;
import org.springframework.ai.chat.model.ChatResponse;
import reactor.core.publisher.Flux;
// Call-around advisor interface (wraps entire call)
public interface CallAroundAdvisor extends Advisor {
ChatResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain);
Flux<ChatResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain);
}
// Request/response advisor interface (modifies request/response)
public interface RequestResponseAdvisor extends Advisor {
AdvisedRequest adviseRequest(AdvisedRequest request, Map<String, Object> context);
ChatResponse adviseResponse(ChatResponse response, Map<String, Object> context);
}
// Base Advisor interface
public interface Advisor {
String getName();
int getOrder();
}package org.springframework.ai.chat.client.advisor.api;
import org.springframework.ai.chat.model.ChatResponse;
import reactor.core.publisher.Flux;
import java.util.Map;
// Base Advisor interface
public interface Advisor {
String getName();
int getOrder();
}
// Call-around advisor
public interface CallAroundAdvisor extends Advisor {
ChatResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain);
Flux<ChatResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain);
}
// Request/response advisor
public interface RequestResponseAdvisor extends Advisor {
AdvisedRequest adviseRequest(AdvisedRequest request, Map<String, Object> context);
ChatResponse adviseResponse(ChatResponse response, Map<String, Object> context);
}package org.springframework.ai.chat.client.advisor.api;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.model.ChatOptions;
import java.util.Map;
public class AdvisedRequest {
public Prompt prompt();
public Map<String, Object> adviseContext();
public Map<String, Object> userParams();
public Map<String, Object> systemParams();
public String systemText();
public String userText();
public ChatOptions chatOptions();
public List<FunctionCallback> functionCallbacks();
public Set<String> functionNames();
public List<Message> messages();
}package org.springframework.ai.chat.client;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.messages.AssistantMessage;
import java.util.Map;
public class ChatClientResponse {
public ChatResponse chatResponse();
public AssistantMessage assistantMessage();
public String content();
public Map<String, Object> metadata();
}package org.springframework.ai.chat.client;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
public class ResponseEntity<T> {
public T getBody();
public HttpHeaders getHeaders();
public HttpStatusCode getStatusCode();
}package org.springframework.ai.chat.messages;
import java.util.Map;
public interface Message {
String getContent();
MessageType getMessageType();
Map<String, Object> getMetadata();
}The ChatClient.Builder bean is registered with prototype scope, meaning each injection creates a new instance. This allows for different configurations in different services:
@Service
public class TechnicalChatService {
private final ChatClient chatClient;
@Autowired
public TechnicalChatService(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("You are a technical expert.")
.build();
}
}
@Service
public class CreativeChatService {
private final ChatClient chatClient;
@Autowired
public CreativeChatService(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("You are a creative writer.")
.build();
}
}tessl i tessl/maven-org-springframework-ai--spring-ai-starter-model-openai@1.1.1