spring-ai icon indicating copy to clipboard operation
spring-ai copied to clipboard

The system message is the second to last message

Open YunKuiLu opened this issue 6 months ago • 1 comments
trafficstars

Bug description Why is the system message the second to last message, not the first? This arrangement yields notably distinct effects from the large language model compared to when the system message is placed at the beginning of the messages list.(I used ai to translate my issues, so please forgive me if there was any tone or emotion involved in my issues.)

Image

Environment The following code initially retrieves historical messages, then appends system messages, and finally appends user messages. Consequently, the system message is positioned as the second-to-last item in the messages list.

org.springframework.ai.chat.client.advisor.api.AdvisedRequest:

public Prompt toPrompt() {
	var messages = new ArrayList<>(this.messages());

	String processedSystemText = this.systemText();
	if (StringUtils.hasText(processedSystemText)) {
		if (!CollectionUtils.isEmpty(this.systemParams())) {
			processedSystemText = new PromptTemplate(processedSystemText, this.systemParams()).render();
		}
		messages.add(new SystemMessage(processedSystemText));
	}

	String formatParam = (String) this.adviseContext().get("formatParam");

	var processedUserText = StringUtils.hasText(formatParam)
			? this.userText() + System.lineSeparator() + "{spring_ai_soc_format}" : this.userText();

	if (StringUtils.hasText(processedUserText)) {
		Map<String, Object> userParams = new HashMap<>(this.userParams());
		if (StringUtils.hasText(formatParam)) {
			userParams.put("spring_ai_soc_format", formatParam);
		}
		if (!CollectionUtils.isEmpty(userParams)) {
			processedUserText = new PromptTemplate(processedUserText, userParams).render();
		}
		messages.add(new UserMessage(processedUserText, this.media()));
	}
... ...
}

Steps to reproduce Perform multiple rounds of conversation on the same conversation

Image

Expected behavior The SystemMessage should be placed as the first item in the messages when passed to the large model. Or, developers should be allowed to customize this situation.

Minimal Complete Reproducible example

@SpringBootTest
class ErrorTest {

    @Autowired
    ChatClient chatClient;

    @Test
    void testError() {
        String sessionId = "123";
        for (int i = 0; i < 10; i++) {
            String content = chatClient.prompt()
                    .system("""
                            You are an assistant.
                            """)
                    .advisors(advisor -> advisor
                            .param("chat_memory_conversation_id", sessionId)
                            .param("chat_memory_response_size", 100))
                    .user("hello")
                    .call()
                    .content();
            System.out.println(content);
        }
    }
}

YunKuiLu avatar Apr 24 '25 09:04 YunKuiLu