Bug description Create a prompt with

Prompt prompt = new Prompt(messages); // list of messages including UserMessage

And set MessageChatMemoryAdvisor as an advisor.

chatClient
  .prompt(prompt)
  .system(systemText)
  .advisors(new MessageChatMemoryAdvisor(chatMemory))

Results in an error that Content cannot be null because MessageChatMemoryAdvisor is looking for userText() which is not present but the prompt already has the UserMessage in list of messages.

Environment Spring AI 1.0.0-SNAPSHOT SpringBoot 3.4.2 Java 21

Comment From: dev-jonghoonpark

What chat model and chat memory are you using? Can you attach an error messages?

Comment From: rwankar

I'm using Azure OpenAI

Here is the stack trace..

java.lang.IllegalArgumentException: Content must not be null for SYSTEM or USER messages
    at org.springframework.util.Assert.notNull(Assert.java:181) ~[spring-core-6.2.2.jar!/:6.2.2]
    at org.springframework.ai.chat.messages.AbstractMessage.<init>(AbstractMessage.java:69) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.messages.UserMessage.<init>(UserMessage.java:62) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.messages.UserMessage.<init>(UserMessage.java:49) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor.before(MessageChatMemoryAdvisor.java:97) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor.aroundCall(MessageChatMemoryAdvisor.java:62) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.lambda$nextAroundCall$1(DefaultAroundAdvisorChain.java:98) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.14.3.jar!/:1.14.3]
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.nextAroundCall(DefaultAroundAdvisorChain.java:98) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at com.celoxis.psa.base.ai.HintChatMemoryAdvisor.aroundCall(HintChatMemoryAdvisor.java:47) ~[!/:14.5.0] 
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.lambda$nextAroundCall$1(DefaultAroundAdvisorChain.java:98) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.14.3.jar!/:1.14.3] 
    at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.nextAroundCall(DefaultAroundAdvisorChain.java:98) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetChatResponse(DefaultChatClient.java:493) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT] 
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.lambda$doGetObservableChatResponse$1(DefaultChatClient.java:482) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.14.3.jar!/:1.14.3]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetObservableChatResponse(DefaultChatClient.java:482) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetChatResponse(DefaultChatClient.java:466) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]
    at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.chatResponse(DefaultChatClient.java:510) ~[spring-ai-core-1.0.0-SNAPSHOT.jar!/:1.0.0-SNAPSHOT]

Comment From: dev-jonghoonpark

ChatMemory chatMemory = new InMemoryChatMemory();
String content = ChatClient.builder(chatModel).build()
        .prompt("hi")
        .system("systemText")
        .advisors(new MessageChatMemoryAdvisor(chatMemory))
        .call()
        .content();
System.out.println(content);

I have tried testing in the same environment, but it is not reproduced.

Could you check if the prompt or systemText variable is null? The logs show the message: "Content must not be null for SYSTEM or USER messages."

Comment From: rwankar

If you create prompt from text it works. You need to create Prompt from a list of messages which contains a UserMessage. I've mentioned this in my first post.

The stack trace show an issue on line 97 in MessageChatMemoryAdvisor

UserMessage userMessage = new UserMessage(request.userText(), request.media());

It should probably create a UserMessage only if request.userText() is not null.

Comment From: dev-jonghoonpark

Prompt prompt = new Prompt(List.of(new UserMessage("hi")));

ChatMemory chatMemory = new InMemoryChatMemory();
String content = ChatClient.builder(chatModel).build()
        .prompt(prompt)
        .system("systemText")
        .advisors(new MessageChatMemoryAdvisor(chatMemory))
        .call()
        .content();
System.out.println(content);

This also works. It would be nice if you could provide a more specific example.

Comment From: rwankar

Here is a working example. It's a SpringBoot maven project. The example is a bit about getting the weather in a city. There are two tools provided. getZip() and getWeather(). To get the weather in a city, the LLM should first call the getZip tool to get the zip code and then use the zip code to call the getWeather() function.

I'm trying to get the ChatMemory updated with all the messages including the tool call and tool call result. So I'm following the example as suggested in the "User-controlled tool execution" in the Tools documentation.

There are 4 files. AiClient.java - responsible for building the ChatClient with the tools and the actual Chat. Application.java - The main SpringBoot app ChatController.java - The RestController with /chat GET endpoint. ApiKeys.java - reads the keys from Environment.

Set 2 environment variables azure.openai.key azure.openai.endpoint

Access localhost:8080/chat?q=what is the weather in Seattle?

On a side note, ToolCallingChatOptions.builder().toolCallbacks() expects List<FunctionCallback>. But FunctionCallback is deprecated. Should I be doing this a different way?

spring-ai-test.zip