This is an automated email from the ASF dual-hosted git repository.
moremind pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new e3cf5ce54a fix(ai-prompt): preserve all original messages in
decorateBody (#6343)
e3cf5ce54a is described below
commit e3cf5ce54a4448ce246fba3d2bdfdb4a5e651cbd
Author: eye-gu <[email protected]>
AuthorDate: Mon Jun 1 14:50:06 2026 +0800
fix(ai-prompt): preserve all original messages in decorateBody (#6343)
* fix(ai-prompt): preserve all original messages in decorateBody
* move SuppressWarnings
---------
Co-authored-by: moremind <[email protected]>
---
.../shenyu/plugin/ai/prompt/AiPromptPlugin.java | 2 +-
.../plugin/ai/prompt/AiPromptPluginTest.java | 146 +++++++++++++++++++++
2 files changed, 147 insertions(+), 1 deletion(-)
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/main/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPlugin.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/main/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPlugin.java
index b46b56b83d..9e38002748 100644
---
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/main/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/main/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPlugin.java
@@ -111,7 +111,7 @@ public class AiPromptPlugin extends AbstractShenyuPlugin {
prependMap.put(Constants.ROLE, aiPromptConfig.getPreRole());
decoratedMessages.add(prependMap);
}
- decoratedMessages.add(messages.get(0));
+ decoratedMessages.addAll(messages);
// If append in aiPromptConfig is not empty, add append to the end of
message body
if (Objects.nonNull(aiPromptConfig.getAppend()) &&
Objects.nonNull(aiPromptConfig.getPostRole())) {
// Assemble append content role
diff --git
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/test/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPluginTest.java
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/test/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPluginTest.java
index b2aeb29b32..f4b57e69c4 100644
---
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/test/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-prompt/src/test/java/org/apache/shenyu/plugin/ai/prompt/AiPromptPluginTest.java
@@ -17,12 +17,16 @@
package org.apache.shenyu.plugin.ai.prompt;
+import org.apache.shenyu.common.dto.convert.plugin.AiPromptConfig;
import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.codec.HttpMessageReader;
+import java.lang.reflect.Method;
import java.util.List;
+import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
@@ -50,4 +54,146 @@ class AiPromptPluginTest {
assertEquals(PluginEnum.AI_PROMPT.getCode(), plugin.getOrder());
}
+
+ @Test
+ void testDecorateBodyReturnsOriginalWhenNoMessages() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ String body = "{\"model\":\"gpt-4\"}";
+ String result = invokeDecorateBody(body, config);
+ assertEquals(body, result);
+ }
+
+ @Test
+ void testDecorateBodyReturnsOriginalWhenMessagesEmpty() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ String body = "{\"messages\":[]}";
+ String result = invokeDecorateBody(body, config);
+ assertEquals(body, result);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyWithPrependAndAppend() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ config.setPrepend("system instruction");
+ config.setPreRole("system");
+ config.setAppend("post instruction");
+ config.setPostRole("assistant");
+
+ String body =
"{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+
+ assertEquals(3, messages.size());
+ assertEquals("system instruction", messages.get(0).get("content"));
+ assertEquals("system", messages.get(0).get("role"));
+ assertEquals("hello", messages.get(1).get("content"));
+ assertEquals("user", messages.get(1).get("role"));
+ assertEquals("post instruction", messages.get(2).get("content"));
+ assertEquals("assistant", messages.get(2).get("role"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyWithOnlyPrepend() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ config.setPrepend("system instruction");
+ config.setPreRole("system");
+
+ String body =
"{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+
+ assertEquals(2, messages.size());
+ assertEquals("system instruction", messages.get(0).get("content"));
+ assertEquals("hello", messages.get(1).get("content"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyPreservesAllOriginalMessages() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ config.setPrepend("system prompt");
+ config.setPreRole("system");
+ config.setAppend("footer");
+ config.setPostRole("assistant");
+
+ String body = "{\"messages\":["
+ + "{\"role\":\"system\",\"content\":\"sys\"},"
+ + "{\"role\":\"user\",\"content\":\"hi\"},"
+ + "{\"role\":\"assistant\",\"content\":\"hello\"},"
+ + "{\"role\":\"user\",\"content\":\"how are you\"}"
+ + "]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+
+ assertEquals(6, messages.size());
+ assertEquals("system prompt", messages.get(0).get("content"));
+ assertEquals("sys", messages.get(1).get("content"));
+ assertEquals("hi", messages.get(2).get("content"));
+ assertEquals("hello", messages.get(3).get("content"));
+ assertEquals("how are you", messages.get(4).get("content"));
+ assertEquals("footer", messages.get(5).get("content"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyNoPrependOrAppend() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+
+ String body =
"{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+
+ assertEquals(1, messages.size());
+ assertEquals("hello", messages.get(0).get("content"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyPrependWithoutRoleIgnored() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ config.setPrepend("system instruction");
+
+ String body =
"{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+
+ assertEquals(1, messages.size());
+ assertEquals("hello", messages.get(0).get("content"));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testDecorateBodyPreservesOtherFields() throws Exception {
+ AiPromptConfig config = new AiPromptConfig();
+ config.setPrepend("prefix");
+ config.setPreRole("system");
+
+ String body =
"{\"model\":\"gpt-4\",\"temperature\":0.7,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}";
+ String result = invokeDecorateBody(body, config);
+
+ Map<String, Object> resultMap =
GsonUtils.getInstance().convertToMap(result);
+ assertEquals("gpt-4", resultMap.get("model"));
+ assertEquals(0.7, ((Number)
resultMap.get("temperature")).doubleValue(), 0.001);
+
+ List<Map<String, Object>> messages = (List<Map<String, Object>>)
resultMap.get("messages");
+ assertEquals(2, messages.size());
+ }
+
+ private String invokeDecorateBody(final String body, final AiPromptConfig
config) throws Exception {
+ Method method = AiPromptPlugin.class.getDeclaredMethod("decorateBody",
String.class, AiPromptConfig.class);
+ method.setAccessible(true);
+ return (String) method.invoke(plugin, body, config);
+ }
}