diff --git a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelIT.java b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelIT.java index 3f2b79bdf..eb9dd5d49 100644 --- a/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelIT.java +++ b/models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/AnthropicChatModelIT.java @@ -99,6 +99,25 @@ class AnthropicChatModelIT { logger.info(response.toString()); } + @Test + void testMessageHistory() { + UserMessage userMessage = new UserMessage( + "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."); + SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); + Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", "Bob", "voice", "pirate")); + Prompt prompt = new Prompt(List.of(userMessage, systemMessage), + AnthropicChatOptions.builder().withModel("claude-3-sonnet-20240229").build()); + + ChatResponse response = chatModel.call(prompt); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew"); + + var promptWithMessageHistory = new Prompt(List.of(new UserMessage("Dummy"), response.getResult().getOutput(), + new UserMessage("Repeat the last assistant message."))); + response = chatModel.call(promptWithMessageHistory); + + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew"); + } + @Test void streamingWithTokenUsage() { var promptOptions = AnthropicChatOptions.builder().withTemperature(0f).build(); diff --git a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatModelIT.java b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatModelIT.java index 957c8b9ce..24be25953 100644 --- a/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatModelIT.java +++ b/models/spring-ai-azure-openai/src/test/java/org/springframework/ai/azure/openai/AzureOpenAiChatModelIT.java @@ -82,6 +82,32 @@ class AzureOpenAiChatModelIT { assertThat(response.getResult().getOutput().getContent()).contains("Blackbeard"); } + @Test + void testMessageHistory() { + + Message systemMessage = new SystemPromptTemplate(""" + You are a helpful AI assistant. Your name is {name}. + You are an AI assistant that helps people find information. + Your name is {name} + You should reply to the user's request with your name and also in the style of a {voice}. + """).createMessage(Map.of("name", "Bob", "voice", "pirate")); + + UserMessage userMessage = new UserMessage( + "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."); + + Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); + + ChatResponse response = chatModel.call(prompt); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard"); + + var promptWithMessageHistory = new Prompt(List.of(new UserMessage("Dummy"), response.getResult().getOutput(), + new UserMessage("Repeat the last assistant message."))); + response = chatModel.call(promptWithMessageHistory); + + System.out.println(response.getResult().getOutput().getContent()); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard"); + } + @Test void listOutputConverter() { DefaultConversionService conversionService = new DefaultConversionService(); diff --git a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java index 8a526272a..81d45865c 100644 --- a/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java +++ b/models/spring-ai-mistral-ai/src/test/java/org/springframework/ai/mistralai/MistralAiChatClientIT.java @@ -27,7 +27,11 @@ import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.chat.prompt.SystemPromptTemplate; import org.springframework.ai.converter.BeanOutputConverter; import org.springframework.ai.converter.ListOutputConverter; import org.springframework.ai.mistralai.api.MistralAiApi; @@ -73,6 +77,32 @@ class MistralAiChatClientIT { assertThat(response.getResults().get(0).getOutput().getContent()).contains("Blackbeard"); } + @Test + void testMessageHistory() { + + // @formatter:off + ChatResponse response = ChatClient.create(chatModel).prompt() + .system(s -> s.text(systemTextResource) + .param("name", "Bob") + .param("voice", "pirate")) + .user("Tell me about 3 famous pirates from the Golden Age of Piracy and what they did") + .call() + .chatResponse(); + // @formatter:on + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard"); + + // @formatter:off + response = ChatClient.create(chatModel).prompt() + .messages(List.of(new UserMessage("Dummy"), response.getResult().getOutput())) + .user("Repeat the last assistant message.") + .call() + .chatResponse(); + // @formatter:on + + logger.info("" + response); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard"); + } + @Test void listOutputConverterString() { // @formatter:off diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelIT.java index a773a0546..8cd56fead 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelIT.java @@ -101,6 +101,31 @@ class OllamaChatModelIT extends BaseOllamaIT { } + @Test + void testMessageHistory() { + + Message systemMessage = new SystemPromptTemplate(""" + You are a helpful AI assistant. Your name is {name}. + You are an AI assistant that helps people find information. + Your name is {name} + You should reply to the user's request with your name and also in the style of a {voice}. + """).createMessage(Map.of("name", "Bob", "voice", "pirate")); + + UserMessage userMessage = new UserMessage( + "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."); + + Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); + + ChatResponse response = chatModel.call(prompt); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Bonny"); + + var promptWithMessageHistory = new Prompt(List.of(new UserMessage("Dummy"), response.getResult().getOutput(), + new UserMessage("Repeat the last assistant message."))); + response = chatModel.call(promptWithMessageHistory); + + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Bonny"); + } + @Test void usageTest() { Prompt prompt = new Prompt("Tell me a joke"); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelIT.java index dff6e18b5..6bfc6faa5 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/OpenAiChatModelIT.java @@ -84,6 +84,24 @@ class OpenAiChatModelIT extends AbstractIT { // needs fine tuning... evaluateQuestionAndAnswer(request, response, false); } + @Test + void testMessageHistory() { + UserMessage userMessage = new UserMessage( + "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."); + SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource); + Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", "Bob", "voice", "pirate")); + Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); + + ChatResponse response = chatModel.call(prompt); + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew"); + + var promptWithMessageHistory = new Prompt(List.of(new UserMessage("Dummy"), response.getResult().getOutput(), + new UserMessage("Repeat the last assistant message."))); + response = chatModel.call(promptWithMessageHistory); + + assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew"); + } + @Test void streamCompletenessTest() throws InterruptedException { UserMessage userMessage = new UserMessage( diff --git a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModelIT.java b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModelIT.java index 688291474..e74859d5d 100644 --- a/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModelIT.java +++ b/models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModelIT.java @@ -75,8 +75,8 @@ class VertexAiGeminiChatModelIT { ChatResponse response = chatModel.call(prompt); assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew"); - var promptWithMessageHistory = new Prompt(List.of(prompt.getInstructions().get(0), - response.getResult().getOutput(), new UserMessage("What was the answer from the previous question?"))); + var promptWithMessageHistory = new Prompt(List.of(new UserMessage("Dummy"), prompt.getInstructions().get(1), + response.getResult().getOutput(), new UserMessage("Repeat the last assistant message."))); response = chatModel.call(promptWithMessageHistory); assertThat(response.getResult().getOutput().getContent()).containsAnyOf("Blackbeard", "Bartholomew");