From de9c46dc5f1865f4ad18b22ee88c2b8fcd4e9a49 Mon Sep 17 00:00:00 2001
From: yuluo-yx <yuluo08290126@gmail.com>
Date: Tue, 16 Jul 2024 13:01:49 +0800
Subject: [PATCH 1/4] example: add chat msg context manager example

Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
---
 spring-cloud-alibaba-dependencies/pom.xml     |  2 +-
 .../pom.xml                                   | 81 +++++++++++++++++++
 .../ai/example/tongyi/ChatMsgApplication.java | 19 +++++
 .../tongyi/context/MessageContextHolder.java  | 27 +++++++
 .../defaults/MemoryMessageContextHolder.java  | 60 ++++++++++++++
 .../defaults/RedisMessageContextHolder.java   | 35 ++++++++
 .../tongyi/controller/ChatMsgController.java  | 29 +++++++
 .../tongyi/service/ChatMsgService.java        | 53 ++++++++++++
 .../src/main/resources/application.yml        | 26 ++++++
 spring-cloud-alibaba-examples/pom.xml         |  1 +
 .../spring-cloud-starter-alibaba-ai/pom.xml   |  6 ++
 .../ai/tongyi/TongYiAutoConfiguration.java    | 10 ---
 .../cloud/ai/tongyi/chat/TongYiChatModel.java | 29 ++-----
 .../TongYiAiChatResponseMetadata.java         |  2 -
 .../TongYiAudioSpeechResponseMetadata.java    |  2 -
 ...gYiAudioTranscriptionResponseMetadata.java |  5 +-
 16 files changed, 345 insertions(+), 42 deletions(-)
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/pom.xml
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
 create mode 100644 spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/resources/application.yml

diff --git a/spring-cloud-alibaba-dependencies/pom.xml b/spring-cloud-alibaba-dependencies/pom.xml
index b997fe008..c12f285e3 100644
--- a/spring-cloud-alibaba-dependencies/pom.xml
+++ b/spring-cloud-alibaba-dependencies/pom.xml
@@ -28,7 +28,7 @@
 
         <!-- Spring AI -->
         <spring.ai.version>1.0.0-M1</spring.ai.version>
-        <dashscope-sdk-java.version>2.14.0</dashscope-sdk-java.version>
+        <dashscope-sdk-java.version>2.15.1</dashscope-sdk-java.version>
 
         <!-- scheduling -->
         <shedlock.version>4.23.0</shedlock.version>
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/pom.xml b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/pom.xml
new file mode 100644
index 000000000..5a3198ac9
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Copyright 2023-2024 the original author or authors.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        https://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<parent>
+		<artifactId>spring-cloud-alibaba-examples</artifactId>
+		<groupId>com.alibaba.cloud</groupId>
+		<version>${revision}</version>
+		<relativePath>../../pom.xml</relativePath>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>spring-cloud-ai-chat-msg-context-example</artifactId>
+	<name>Spring Cloud Starter Alibaba AI Chat Message Context Holder Example</name>
+	<description>Example for Chat Message Context Holder By Spring Cloud Alibaba AI</description>
+	<packaging>jar</packaging>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>com.alibaba.cloud</groupId>
+			<artifactId>spring-cloud-starter-alibaba-ai</artifactId>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-deploy-plugin</artifactId>
+				<version>${maven-deploy-plugin.version}</version>
+				<configuration>
+					<skip>true</skip>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+		<repository>
+			<id>spring-milestones</id>
+			<name>Spring Milestones</name>
+			<url>https://repo.spring.io/milestone</url>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+		<repository>
+			<id>spring-snapshots</id>
+			<name>Spring Snapshots</name>
+			<url>https://repo.spring.io/snapshot</url>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+		</repository>
+	</repositories>
+
+</project>
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
new file mode 100644
index 000000000..8f0db5482
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
@@ -0,0 +1,19 @@
+package com.alibaba.cloud.ai.example.tongyi;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+@SpringBootApplication
+public class ChatMsgApplication {
+
+	public static void main(String[] args) {
+
+		SpringApplication.run(ChatMsgApplication.class, args);
+	}
+
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
new file mode 100644
index 000000000..4026c3937
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
@@ -0,0 +1,27 @@
+package com.alibaba.cloud.ai.example.tongyi.context;
+
+import java.util.List;
+
+import org.springframework.ai.chat.messages.Message;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+public interface MessageContextHolder {
+
+	String SCA_SESSION_ID = "SCA_SESSION_ID";
+
+	void addMsg(String sessionId, Message msg);
+
+	void removeMsg(String sessionId);
+
+	List<Message> getMsg(String sessionId);
+
+	default String getSCASessionId() {
+
+		return SCA_SESSION_ID;
+	}
+
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
new file mode 100644
index 000000000..39dd8d0e6
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
@@ -0,0 +1,60 @@
+package com.alibaba.cloud.ai.example.tongyi.context.defaults;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
+
+import com.alibaba.cloud.ai.example.tongyi.context.MessageContextHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+@Component
+public class MemoryMessageContextHolder implements MessageContextHolder {
+
+	private static final Logger log = LoggerFactory.getLogger(MemoryMessageContextHolder.class);
+
+	private final Map<String, List<Message>> msgContextHolderMap = new HashMap<>();
+
+	@Override
+	public void addMsg(String sessionId, Message msg) {
+
+		msgContextHolderMap.computeIfAbsent(sessionId, k -> new ArrayList<>());
+		log.info("addMsg: sessionId={}, msg={}", sessionId, msg);
+	}
+
+	@Override
+	public void removeMsg(String sessionId) {
+
+		msgContextHolderMap.remove(sessionId);
+	}
+
+	@Override
+	public List<Message> getMsg(String sessionId) {
+
+		return new ArrayList<>(msgContextHolderMap.getOrDefault(sessionId, new ArrayList<>()));
+	}
+
+	@Override
+	public String toString() {
+
+		StringBuilder sb = new StringBuilder();
+		sb.append("MessageContextHolderImpl{");
+		StringJoiner joiner = new StringJoiner(", ", "{", "}");
+		for (Map.Entry<String, List<Message>> entry : msgContextHolderMap.entrySet()) {
+			joiner.add(entry.getKey() + "=" + entry.getValue().toString());
+		}
+		sb.append("msgContextHolderMap=").append(joiner);
+		sb.append('}');
+		return sb.toString();
+	}
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
new file mode 100644
index 000000000..56c16e84d
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
@@ -0,0 +1,35 @@
+package com.alibaba.cloud.ai.example.tongyi.context.defaults;
+
+import java.util.List;
+
+import com.alibaba.cloud.ai.example.tongyi.context.MessageContextHolder;
+
+import org.springframework.ai.chat.messages.Message;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+//@Component
+public class RedisMessageContextHolder implements MessageContextHolder{
+	@Override
+	public void addMsg(String sessionId, Message msg) {
+
+		System.out.println("RedisMessageContextHolder addMsg");
+	}
+
+	@Override
+	public void removeMsg(String sessionId) {
+
+		System.out.println("RedisMessageContextHolder removeMsg");
+	}
+
+	@Override
+	public List<Message> getMsg(String sessionId) {
+
+		System.out.println("RedisMessageContextHolder getMsg");
+		return null;
+	}
+
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
new file mode 100644
index 000000000..2a6827dfe
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
@@ -0,0 +1,29 @@
+package com.alibaba.cloud.ai.example.tongyi.controller;
+
+import com.alibaba.cloud.ai.example.tongyi.service.ChatMsgService;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+@RestController
+@RequestMapping("/chat")
+public class ChatMsgController {
+
+	@Autowired
+	private ChatMsgService msgService;
+
+	@GetMapping("/msg")
+	public String completion(@RequestParam String message) {
+
+		return msgService.completion(message);
+	}
+
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
new file mode 100644
index 000000000..7e724977a
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
@@ -0,0 +1,53 @@
+package com.alibaba.cloud.ai.example.tongyi.service;
+
+import com.alibaba.cloud.ai.example.tongyi.context.MessageContextHolder;
+
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.ai.chat.model.ChatModel;
+import org.springframework.ai.chat.model.ChatResponse;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author yuluo
+ * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
+ */
+
+@Service
+public class ChatMsgService {
+
+	private final ChatModel chatModel;
+
+	private final MessageContextHolder messageContextHolder;
+
+	@Autowired
+	public ChatMsgService(ChatModel chatModel, MessageContextHolder messageContextHolder) {
+		this.chatModel = chatModel;
+		this.messageContextHolder = messageContextHolder;
+	}
+
+	public String completion(String message) {
+
+		// create chat prompt
+		Prompt prompt = new Prompt(new UserMessage(message));
+
+		// collect user message
+		messageContextHolder.addMsg(
+				messageContextHolder.getSCASessionId(),
+				prompt.getInstructions().get(0)
+		);
+
+		ChatResponse resp = chatModel.call(prompt);
+
+		// collect model response
+		messageContextHolder.addMsg(
+				messageContextHolder.getSCASessionId(),
+				resp.getResult().getOutput()
+		);
+
+		return resp.getResult().getOutput().getContent();
+
+	}
+
+}
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/resources/application.yml b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/resources/application.yml
new file mode 100644
index 000000000..ae8fa1f42
--- /dev/null
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/resources/application.yml
@@ -0,0 +1,26 @@
+#
+#  Copyright 2023-2024 the original author or authors.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       https://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+
+server:
+  port: 8084
+
+spring:
+  application:
+    name: tongyi-example
+
+# please setting api-key. suggestion by environment variable.
+# Note: api-key is invalid, please apply for a new one.
+# export SPRING_CLOUD_AI_TONGYI_API_KEY=sk-a3d73b1709bf4a178c28ed7c8b3b5a345
diff --git a/spring-cloud-alibaba-examples/pom.xml b/spring-cloud-alibaba-examples/pom.xml
index def6e1d54..cf858d2fb 100644
--- a/spring-cloud-alibaba-examples/pom.xml
+++ b/spring-cloud-alibaba-examples/pom.xml
@@ -53,6 +53,7 @@
 		<module>integrated-example/integrated-frontend</module>
         <module>ai-example/spring-cloud-ai-example</module>
         <module>ai-example/spring-cloud-ai-rag-example</module>
+        <module>ai-example/spring-cloud-ai-chat-msg-context-example</module>
         <module>spring-cloud-scheduling-example</module>
     </modules>
 
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/pom.xml
index 6b9e0f1fb..2658378b2 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/pom.xml
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/pom.xml
@@ -91,6 +91,12 @@
 			<scope>test</scope>
 		</dependency>
 
+		<dependency>
+			<groupId>javax.annotation</groupId>
+			<artifactId>jsr250-api</artifactId>
+			<version>1.0</version>
+		</dependency>
+
 	</dependencies>
 
 	<repositories>
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/TongYiAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/TongYiAutoConfiguration.java
index 00caf3d8b..30a75dc0b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/TongYiAutoConfiguration.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/TongYiAutoConfiguration.java
@@ -34,7 +34,6 @@
 import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
 import com.alibaba.dashscope.audio.asr.transcription.Transcription;
 import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
-import com.alibaba.dashscope.common.MessageManager;
 import com.alibaba.dashscope.embeddings.TextEmbedding;
 import com.alibaba.dashscope.exception.NoApiKeyException;
 import com.alibaba.dashscope.utils.ApiKey;
@@ -58,7 +57,6 @@
 
 @AutoConfiguration
 @ConditionalOnClass({
-		MessageManager.class,
 		TongYiChatModel.class,
 		TongYiImagesModel.class,
 		TongYiAudioSpeechModel.class,
@@ -83,14 +81,6 @@ public Generation generation() {
 		return new Generation();
 	}
 
-	@Bean
-	@Scope("prototype")
-	@ConditionalOnMissingBean
-	public MessageManager msgManager() {
-
-		return new MessageManager(10);
-	}
-
 	@Bean
 	@Scope("prototype")
 	@ConditionalOnMissingBean
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/chat/TongYiChatModel.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/chat/TongYiChatModel.java
index 964045e9d..d6c2dbc56 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/chat/TongYiChatModel.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/chat/TongYiChatModel.java
@@ -15,18 +15,17 @@
  */
 
 package com.alibaba.cloud.ai.tongyi.chat;
+
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
-
 import com.alibaba.cloud.ai.tongyi.common.exception.TongYiException;
 import com.alibaba.dashscope.aigc.conversation.ConversationParam;
 import com.alibaba.dashscope.aigc.generation.Generation;
 import com.alibaba.dashscope.aigc.generation.GenerationOutput;
 import com.alibaba.dashscope.aigc.generation.GenerationResult;
-import com.alibaba.dashscope.common.MessageManager;
 import com.alibaba.dashscope.common.Role;
 import com.alibaba.dashscope.exception.InputRequiredException;
 import com.alibaba.dashscope.exception.NoApiKeyException;
@@ -51,7 +50,6 @@
 import org.springframework.ai.model.ModelOptionsUtils;
 import org.springframework.ai.model.function.AbstractFunctionCallSupport;
 import org.springframework.ai.model.function.FunctionCallbackContext;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
 
 
@@ -85,12 +83,6 @@ public class TongYiChatModel extends
 	 */
 	private TongYiChatOptions defaultOptions;
 
-	/**
-	 * User role message manager.
-	 */
-	@Autowired
-	private MessageManager msgManager;
-
 	/**
 	 * Initializes an instance of the TongYiChatClient.
 	 * @param generation DashScope generation client.
@@ -144,19 +136,7 @@ public TongYiChatOptions getDefaultOptions() {
 	public ChatResponse call(Prompt prompt) {
 
 		ConversationParam params = toTongYiChatParams(prompt);
-
-		// TongYi models context loader.
-		com.alibaba.dashscope.common.Message message = new com.alibaba.dashscope.common.Message();
-		message.setRole(Role.USER.getValue());
-		message.setContent(prompt.getContents());
-		msgManager.add(message);
-		params.setMessages(msgManager.get());
-
-		logger.trace("TongYi ConversationOptions: {}", params);
 		GenerationResult chatCompletions = this.callWithFunctionSupport(params);
-		logger.trace("TongYi ConversationOptions: {}", params);
-
-		msgManager.add(chatCompletions);
 
 		List<org.springframework.ai.chat.model.Generation> generations =
 				chatCompletions
@@ -183,7 +163,8 @@ public Flux<ChatResponse> stream(Prompt prompt) {
 		ConversationParam tongYiChatParams = toTongYiChatParams(prompt);
 
 		// See https://help.aliyun.com/zh/dashscope/developer-reference/api-details?spm=a2c4g.11186623.0.0.655fc11aRR0jj7#b9ad0a10cfhpe
-		// tongYiChatParams.setIncrementalOutput(true);
+		// enable incremental output
+		tongYiChatParams.setIncrementalOutput(true);
 
 		try {
 			genRes = generation.streamCall(tongYiChatParams);
@@ -226,7 +207,9 @@ public ConversationParam toTongYiChatParams(Prompt prompt) {
 
 		Set<String> functionsForThisRequest = new HashSet<>();
 
-		List<com.alibaba.dashscope.common.Message> tongYiMessage = prompt.getInstructions().stream()
+		List<com.alibaba.dashscope.common.Message> tongYiMessage = prompt
+				.getInstructions()
+				.stream()
 				.map(this::fromSpringAIMessage)
 				.toList();
 
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/TongYiAiChatResponseMetadata.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/TongYiAiChatResponseMetadata.java
index 2afdcc9bc..e979ab696 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/TongYiAiChatResponseMetadata.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/TongYiAiChatResponseMetadata.java
@@ -25,8 +25,6 @@
 import org.springframework.ai.chat.metadata.Usage;
 import org.springframework.util.Assert;
 
-
-
 /**
  * {@link ChatResponseMetadata} implementation for {@literal Alibaba DashScope}.
  *
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioSpeechResponseMetadata.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioSpeechResponseMetadata.java
index ddd516813..0170a64f7 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioSpeechResponseMetadata.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioSpeechResponseMetadata.java
@@ -27,8 +27,6 @@
 import org.springframework.lang.Nullable;
 import org.springframework.util.Assert;
 
-
-
 /**
  * @author yuluo
  * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioTranscriptionResponseMetadata.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioTranscriptionResponseMetadata.java
index 6479782fd..1fcc8dfac 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioTranscriptionResponseMetadata.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-ai/src/main/java/com/alibaba/cloud/ai/tongyi/metadata/audio/TongYiAudioTranscriptionResponseMetadata.java
@@ -18,18 +18,15 @@
 
 import java.util.HashMap;
 
-import javax.annotation.Nullable;
-
 import com.alibaba.dashscope.audio.asr.transcription.TranscriptionResult;
 import com.google.gson.JsonObject;
 
 import org.springframework.ai.chat.metadata.EmptyRateLimit;
 import org.springframework.ai.chat.metadata.RateLimit;
 import org.springframework.ai.model.ResponseMetadata;
+import org.springframework.lang.Nullable;
 import org.springframework.util.Assert;
 
-
-
 /**
  * @author yuluo
  * @author <a href="mailto:yuluo08290126@gmail.com">yuluo</a>

From 8e441a6feb9b554fbb8090d36073bd400f43ae92 Mon Sep 17 00:00:00 2001
From: yuluo-yx <yuluo08290126@gmail.com>
Date: Tue, 16 Jul 2024 13:02:55 +0800
Subject: [PATCH 2/4] chore: add license header

Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
---
 .../ai/example/tongyi/ChatMsgApplication.java    | 16 ++++++++++++++++
 .../tongyi/context/MessageContextHolder.java     | 16 ++++++++++++++++
 .../defaults/MemoryMessageContextHolder.java     | 16 ++++++++++++++++
 .../defaults/RedisMessageContextHolder.java      | 16 ++++++++++++++++
 .../tongyi/controller/ChatMsgController.java     | 16 ++++++++++++++++
 .../example/tongyi/service/ChatMsgService.java   | 16 ++++++++++++++++
 6 files changed, 96 insertions(+)

diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
index 8f0db5482..c727befca 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/ChatMsgApplication.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi;
 
 import org.springframework.boot.SpringApplication;
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
index 4026c3937..bed9768c5 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi.context;
 
 import java.util.List;
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
index 39dd8d0e6..f67226620 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/MemoryMessageContextHolder.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi.context.defaults;
 
 import java.util.ArrayList;
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
index 56c16e84d..c783fa285 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi.context.defaults;
 
 import java.util.List;
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
index 2a6827dfe..3f0244204 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/controller/ChatMsgController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi.controller;
 
 import com.alibaba.cloud.ai.example.tongyi.service.ChatMsgService;
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
index 7e724977a..7453cf56b 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/service/ChatMsgService.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.alibaba.cloud.ai.example.tongyi.service;
 
 import com.alibaba.cloud.ai.example.tongyi.context.MessageContextHolder;

From 23d886e06df3eeefee0de18d4bf843f2603f5f96 Mon Sep 17 00:00:00 2001
From: yuluo-yx <yuluo08290126@gmail.com>
Date: Tue, 16 Jul 2024 13:53:01 +0800
Subject: [PATCH 3/4] fix

Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
---
 .../cloud/ai/example/tongyi/context/MessageContextHolder.java | 4 ++++
 .../tongyi/context/defaults/RedisMessageContextHolder.java    | 1 +
 2 files changed, 5 insertions(+)

diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
index bed9768c5..347037a6b 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/MessageContextHolder.java
@@ -27,6 +27,10 @@
 
 public interface MessageContextHolder {
 
+	/**
+	 * Th default session id key.
+	 * Can use session_id request_id &etc.
+	 */
 	String SCA_SESSION_ID = "SCA_SESSION_ID";
 
 	void addMsg(String sessionId, Message msg);
diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
index c783fa285..50546b987 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
@@ -29,6 +29,7 @@
 
 //@Component
 public class RedisMessageContextHolder implements MessageContextHolder{
+
 	@Override
 	public void addMsg(String sessionId, Message msg) {
 

From f98217aaea373c98df8f5deb2df5d3e522580785 Mon Sep 17 00:00:00 2001
From: yuluo-yx <yuluo08290126@gmail.com>
Date: Tue, 16 Jul 2024 13:56:05 +0800
Subject: [PATCH 4/4] fix

Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
---
 .../tongyi/context/defaults/RedisMessageContextHolder.java      | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
index 50546b987..9aaf2409b 100644
--- a/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
+++ b/spring-cloud-alibaba-examples/ai-example/spring-cloud-ai-chat-msg-context-example/src/main/java/com/alibaba/cloud/ai/example/tongyi/context/defaults/RedisMessageContextHolder.java
@@ -28,7 +28,7 @@
  */
 
 //@Component
-public class RedisMessageContextHolder implements MessageContextHolder{
+public class RedisMessageContextHolder implements MessageContextHolder {
 
 	@Override
 	public void addMsg(String sessionId, Message msg) {