Core model interfaces and abstractions for Spring AI framework providing portable API for chat, embeddings, images, audio, and tool calling across multiple AI providers
Conversational AI capabilities including chat model interfaces, message types, prompt management, and response handling. Supports both synchronous and streaming interactions with comprehensive metadata.
Main interface for chat models supporting both synchronous and streaming operations.
public interface ChatModel extends Model<Prompt, ChatResponse>, StreamingChatModel {
/**
* Call with a simple string message.
*
* @param message the message text
* @return the response text
*/
String call(String message);
/**
* Call with an array of messages.
*
* @param messages the messages
* @return the response text
*/
String call(Message... messages);
/**
* Call with a prompt containing messages and options.
*
* @param prompt the prompt
* @return the chat response with metadata
*/
ChatResponse call(Prompt prompt);
/**
* Get the default options for this chat model.
*
* @return the default chat options
*/
ChatOptions getDefaultOptions();
/**
* Stream responses for the given prompt.
*
* @param prompt the prompt
* @return Flux of streaming chat responses
*/
Flux<ChatResponse> stream(Prompt prompt);
}Interface for models that support streaming chat responses.
public interface StreamingChatModel extends StreamingModel<Prompt, ChatResponse> {
/**
* Stream responses for a simple string message.
*
* @param message the message text
* @return Flux of response text chunks
*/
Flux<String> stream(String message);
/**
* Stream responses for an array of messages.
*
* @param messages the messages
* @return Flux of response text chunks
*/
Flux<String> stream(Message... messages);
/**
* Stream responses for the given prompt.
*
* @param prompt the prompt
* @return Flux of streaming chat responses
*/
Flux<ChatResponse> stream(Prompt prompt);
}Response from a chat model containing generated content and metadata.
public class ChatResponse implements ModelResponse<Generation> {
/**
* Construct a ChatResponse with generations.
*
* @param generations the list of generations
*/
public ChatResponse(List<Generation> generations);
/**
* Construct a ChatResponse with generations and metadata.
*
* @param generations the list of generations
* @param metadata the response metadata
*/
public ChatResponse(List<Generation> generations, ChatResponseMetadata metadata);
/**
* Get all generations in this response.
*
* @return list of generations
*/
List<Generation> getResults();
/**
* Get the first generation.
*
* @return the first generation
*/
Generation getResult();
/**
* Get response metadata including usage and rate limits.
*
* @return the chat response metadata
*/
ChatResponseMetadata getMetadata();
/**
* Check if this response has tool calls.
*
* @return true if any generation has tool calls
*/
boolean hasToolCalls();
/**
* Check if this response has any of the specified finish reasons.
*
* @param finishReasons the finish reasons to check for
* @return true if any generation has one of these finish reasons
*/
boolean hasFinishReasons(Set<String> finishReasons);
/**
* Create a new builder for ChatResponse.
*
* @return a new builder
*/
static Builder builder();
/**
* Builder for constructing ChatResponse instances.
*/
static final class Builder {
/**
* Copy properties from an existing ChatResponse.
*
* @param other the ChatResponse to copy from
* @return this builder
*/
Builder from(ChatResponse other);
/**
* Add a metadata key-value pair.
*
* @param key the metadata key
* @param value the metadata value
* @return this builder
*/
Builder metadata(String key, Object value);
/**
* Set metadata from an existing ChatResponseMetadata.
*
* @param other the metadata to copy
* @return this builder
*/
Builder metadata(ChatResponseMetadata other);
/**
* Set the list of generations.
*
* @param generations the generations to include in the response
* @return this builder
*/
Builder generations(List<Generation> generations);
/**
* Build the ChatResponse.
*
* @return the constructed ChatResponse
*/
ChatResponse build();
}
}Single generation result from a chat model.
public class Generation implements ModelResult<AssistantMessage> {
/**
* Construct a Generation with an assistant message.
*
* @param assistantMessage the assistant message
*/
public Generation(AssistantMessage assistantMessage);
/**
* Construct a Generation with an assistant message and metadata.
*
* @param assistantMessage the assistant message
* @param metadata the generation metadata
*/
public Generation(AssistantMessage assistantMessage, ChatGenerationMetadata metadata);
/**
* Get the output message from this generation.
*
* @return the assistant message
*/
AssistantMessage getOutput();
/**
* Get generation metadata including finish reason.
*
* @return the generation metadata
*/
ChatGenerationMetadata getMetadata();
}Utility for aggregating streaming chat responses into complete messages.
public class MessageAggregator {
/**
* Aggregate a Flux of chat responses into complete messages.
* Calls onComplete when aggregation finishes.
*
* @param fluxChatResponse the Flux of streaming responses
* @param onComplete callback invoked with complete response
* @return Flux of aggregated responses
*/
Flux<ChatResponse> aggregate(
Flux<ChatResponse> fluxChatResponse,
Consumer<ChatResponse> onComplete
);
}Context for tool execution containing state and history.
public class ToolContext {
/**
* Key for accessing tool call history in context.
*/
public static final String TOOL_CALL_HISTORY = "toolCallHistory";
/**
* Construct a ToolContext with a context map.
*
* @param context the context data
*/
public ToolContext(Map<String, Object> context);
/**
* Get the context map.
*
* @return the context data
*/
Map<String, Object> getContext();
/**
* Get the tool call history from context.
*
* @return list of messages representing tool call history
*/
List<Message> getToolCallHistory();
}import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class ChatService {
@Autowired
private ChatModel chatModel;
public String askQuestion(String question) {
// Simple string-based call
return chatModel.call(question);
}
}import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.messages.SystemMessage;
// Create messages
SystemMessage systemMessage = new SystemMessage("You are a helpful assistant.");
UserMessage userMessage = new UserMessage("What is quantum computing?");
// Create prompt
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
// Get response
ChatResponse response = chatModel.call(prompt);
String answer = response.getResult().getOutput().getText();import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import reactor.core.publisher.Flux;
// Stream response
Flux<ChatResponse> stream = chatModel.stream(prompt);
// Process chunks
stream.subscribe(chunk -> {
String content = chunk.getResult().getOutput().getText();
System.out.print(content);
});import org.springframework.ai.chat.model.MessageAggregator;
MessageAggregator aggregator = new MessageAggregator();
Flux<ChatResponse> aggregated = aggregator.aggregate(
chatModel.stream(prompt),
completeResponse -> {
System.out.println("Complete: " + completeResponse.getResult().getOutput().getText());
}
);
aggregated.subscribe();ChatResponse response = chatModel.call(prompt);
// Check if model requested tool calls
if (response.hasToolCalls()) {
List<AssistantMessage.ToolCall> toolCalls =
response.getResult().getOutput().getToolCalls();
for (AssistantMessage.ToolCall toolCall : toolCalls) {
System.out.println("Tool: " + toolCall.name());
System.out.println("Arguments: " + toolCall.arguments());
}
}ChatResponse response = chatModel.call(prompt);
// Check if response stopped due to length
if (response.hasFinishReasons(Set.of("length", "max_tokens"))) {
System.out.println("Response truncated due to length limit");
}
// Check finish reason for first generation
String finishReason = response.getResult().getMetadata().getFinishReason();
System.out.println("Finish reason: " + finishReason);