From ecc0db3e535731341a13998be4ee792ca3eeb613 Mon Sep 17 00:00:00 2001 From: LuanY77 <2307984361@qq.com> Date: Thu, 28 Aug 2025 17:48:47 +0800 Subject: [PATCH] =?UTF-8?q?Feat:=20AI=20=E6=84=8F=E5=9B=BE=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E8=8A=82=E7=82=B9=E5=A4=9A=E8=B7=AF=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/AbstractAIComponentHandler.java | 1 + .../handler/ClassifyComponentHandler.java | 9 +--- .../ClassifyAIInvocationHandler.java | 6 ++- .../openai/model/chat/OpenAIChatRequest.java | 2 +- .../test/ai/core/classify/ClassifyTest.java | 9 ++++ .../ai/core/classify/cmp/AIClassifyCmp.java | 8 ++-- .../core/classify/cmp/AIMultiClassifyCmp.java | 46 +++++++++++++++++++ .../test/resources/core/classify/flow.el.xml | 6 ++- 8 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIMultiClassifyCmp.java diff --git a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/AbstractAIComponentHandler.java b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/AbstractAIComponentHandler.java index d9999d508..6e7249e29 100644 --- a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/AbstractAIComponentHandler.java +++ b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/AbstractAIComponentHandler.java @@ -172,6 +172,7 @@ public abstract class AbstractAIComponentHandler { /** * 获取拦截方法名称 * + * @param wrapBean 包装bean,现在暂时不用,后续如果单节点需要根据条件判断拦截方法,可以用上 * @return 拦截方法名称 */ protected abstract ElementMatcher getInterceptMethodName(AIProxyWrapBean wrapBean); diff --git a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/ClassifyComponentHandler.java b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/ClassifyComponentHandler.java index eff1c0c2d..4dcca65a0 100644 --- a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/ClassifyComponentHandler.java +++ b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/handler/ClassifyComponentHandler.java @@ -1,7 +1,7 @@ package com.yomahub.liteflow.ai.proxy.handler; -import com.yomahub.liteflow.ai.annotation.model.node.AIClassify; import com.yomahub.liteflow.ai.annotation.AIComponent; +import com.yomahub.liteflow.ai.annotation.model.node.AIClassify; import com.yomahub.liteflow.ai.domain.enums.AITypeEnum; import com.yomahub.liteflow.ai.proxy.invocation.ClassifyAIInvocationHandler; import com.yomahub.liteflow.ai.proxy.wrap.AIProxyWrapBean; @@ -22,7 +22,6 @@ import java.lang.reflect.InvocationHandler; public class ClassifyComponentHandler extends AbstractAIComponentHandler { private static final String INTERCEPT_SWITCH_METHOD_NAME = "processSwitch"; - private static final String INTERCEPT_MULTI_SWITCH_METHOD_NAME = "processMultiSwitch"; @Override public AITypeEnum getAIType() { @@ -47,10 +46,6 @@ public class ClassifyComponentHandler extends AbstractAIComponentHandler getInterceptMethodName(AIProxyWrapBean wrapBean) { - if (wrapBean.getAnnotation().multiLabel()) { - return ElementMatchers.named(INTERCEPT_MULTI_SWITCH_METHOD_NAME); - } else { - return ElementMatchers.named(INTERCEPT_SWITCH_METHOD_NAME); - } + return ElementMatchers.named(INTERCEPT_SWITCH_METHOD_NAME); } } \ No newline at end of file diff --git a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/invocation/ClassifyAIInvocationHandler.java b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/invocation/ClassifyAIInvocationHandler.java index b485e4d8e..94a8d2208 100644 --- a/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/invocation/ClassifyAIInvocationHandler.java +++ b/liteflow-ai/liteflow-ai-core/src/main/java/com/yomahub/liteflow/ai/proxy/invocation/ClassifyAIInvocationHandler.java @@ -9,6 +9,8 @@ import com.yomahub.liteflow.ai.parse.context.ProcessorContext; import com.yomahub.liteflow.ai.proxy.wrap.ClassifyProxyWrapBean; import com.yomahub.liteflow.ai.util.SetUtil; +import java.util.List; + /** * 分类组件的调用处理器 * @@ -33,6 +35,7 @@ public class ClassifyAIInvocationHandler extends AbstractAIInvocationHandler processorContext, Object[] args) { ChatModel chatModel = ModelFactory.getChatModel(wrapBean); @@ -40,7 +43,8 @@ public class ClassifyAIInvocationHandler extends AbstractAIInvocationHandler resList = (List) response.as(processorContext.getModelRequest().toChatRequest().getOutputParser()); + return String.join(",", resList); } else { return response.getContent().getContent(); } diff --git a/liteflow-ai/liteflow-ai-model/liteflow-ai-openai/src/main/java/com/yomahub/liteflow/ai/model/openai/model/chat/OpenAIChatRequest.java b/liteflow-ai/liteflow-ai-model/liteflow-ai-openai/src/main/java/com/yomahub/liteflow/ai/model/openai/model/chat/OpenAIChatRequest.java index 0a96af713..a6a769d6a 100644 --- a/liteflow-ai/liteflow-ai-model/liteflow-ai-openai/src/main/java/com/yomahub/liteflow/ai/model/openai/model/chat/OpenAIChatRequest.java +++ b/liteflow-ai/liteflow-ai-model/liteflow-ai-openai/src/main/java/com/yomahub/liteflow/ai/model/openai/model/chat/OpenAIChatRequest.java @@ -78,7 +78,7 @@ public class OpenAIChatRequest extends ChatRequest { ObjectNode responseFormat = ObjectMapperHolder.createObjectNode(); responseFormat.put("type", "json_schema"); ObjectNode jsonSchema = ObjectMapperHolder.createObjectNode(); - jsonSchema.put("name", ((Class) outputParser.getTargetType()).getSimpleName()); + jsonSchema.put("name", outputParser.getTargetType().getTypeName()); jsonSchema.set("schema", outputParser.getJsonSchema()); responseFormat.set("json_schema", jsonSchema); diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/ClassifyTest.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/ClassifyTest.java index af42fdb54..fc02f1e27 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/ClassifyTest.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/ClassifyTest.java @@ -33,5 +33,14 @@ public class ClassifyTest { public void testClassify() { LiteflowResponse response = flowExecutor.execute2Resp("chain1", null, ChatContext.class); Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>aiSwitch[aiSwitch]==>java", response.getExecuteStepStr()); } + + @Test + public void testMultiClassify() { + LiteflowResponse response = flowExecutor.execute2Resp("chain2", null, ChatContext.class); + Assertions.assertTrue(response.isSuccess()); + Assertions.assertEquals("a==>aiMultiSwitch[aiMultiSwitch]==>java==>python", response.getExecuteStepStr()); + } + } diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIClassifyCmp.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIClassifyCmp.java index 2363e64d3..1d45fbffd 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIClassifyCmp.java +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIClassifyCmp.java @@ -15,8 +15,8 @@ import com.yomahub.liteflow.ai.util.TriState; */ @AIComponent( - nodeId = "ai", - nodeName = "ai", + nodeId = "aiSwitch", + nodeName = "aiSwitch", // provider = "ollama", // apiUrl = "http://localhost:11434", // model = "qwen3:32b", @@ -28,9 +28,9 @@ import com.yomahub.liteflow.ai.util.TriState; connectTimeout = "10m" ) @AIClassify( - systemPrompt = "你是一个意图识别高手,你需要识别用户的意图", userPrompt = "{{question}}", - categories = {"java", "python"}) + categories = {"java", "python"} +) @AIInput( mapping = { @InputField(name = "question", expression = "test", defaultValue = "请帮我写一段Java代码"), diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIMultiClassifyCmp.java b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIMultiClassifyCmp.java new file mode 100644 index 000000000..d99431ad8 --- /dev/null +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/java/com/yomahub/liteflow/test/ai/core/classify/cmp/AIMultiClassifyCmp.java @@ -0,0 +1,46 @@ +package com.yomahub.liteflow.test.ai.core.classify.cmp; + +import com.yomahub.liteflow.ai.annotation.AIComponent; +import com.yomahub.liteflow.ai.annotation.model.io.AIInput; +import com.yomahub.liteflow.ai.annotation.model.io.AIOutput; +import com.yomahub.liteflow.ai.annotation.model.io.InputField; +import com.yomahub.liteflow.ai.annotation.model.node.AIClassify; +import com.yomahub.liteflow.ai.util.TriState; + +/** + * TODO + * + * @author 苍镜月 + * @since TODO + */ + +@AIComponent( + nodeId = "aiMultiSwitch", + nodeName = "aiMultiSwitch", +// provider = "ollama", +// apiUrl = "http://localhost:11434", +// model = "qwen3:32b", + provider = "openai", + apiUrl = "https://ark.cn-beijing.volces.com/api/v3", + model = "doubao-seed-1-6-250615", + enableThinking = TriState.FALSE, + readTimeout = "10m", + connectTimeout = "10m" +) +@AIClassify( + userPrompt = "{{question}}", + categories = {"java", "python"}, + multiLabel = true +) +@AIInput( + mapping = { + @InputField(name = "question", expression = "test", defaultValue = "请帮我写一段Java代码, 同时给出 Python 代码"), + } +) +@AIOutput( + methodExpress = "setData", + useKeyIndex = true, + key = "result" +) +public interface AIMultiClassifyCmp { +} diff --git a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/core/classify/flow.el.xml b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/core/classify/flow.el.xml index b5e3ef41a..7e544d586 100644 --- a/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/core/classify/flow.el.xml +++ b/liteflow-testcase-el/liteflow-testcase-el-ai/src/test/resources/core/classify/flow.el.xml @@ -2,6 +2,10 @@ - THEN(a, SWITCH(ai).TO(java, python)); + THEN(a, SWITCH(aiSwitch).TO(java, python)); + + + + THEN(a, SWITCH(aiMultiSwitch).TO(java, python));