mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-03-13 20:53:42 +08:00
优化工作流注册节点以及相关其他代码优化
This commit is contained in:
@@ -21,4 +21,14 @@ public class NodeProcessResult {
|
||||
* 条件执行时使用
|
||||
*/
|
||||
private String nextNodeUuid;
|
||||
|
||||
/**
|
||||
* 是否发生错误
|
||||
*/
|
||||
private boolean error = false;
|
||||
|
||||
/**
|
||||
* 错误或提示信息
|
||||
*/
|
||||
private String message;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ import org.ruoyi.workflow.entity.WorkflowNode;
|
||||
import org.ruoyi.workflow.workflow.node.AbstractWfNode;
|
||||
import org.ruoyi.workflow.workflow.node.EndNode;
|
||||
import org.ruoyi.workflow.workflow.node.answer.LLMAnswerNode;
|
||||
import org.ruoyi.workflow.workflow.node.keywordExtractor.KeywordExtractorNode;
|
||||
import org.ruoyi.workflow.workflow.node.mailSend.MailSendNode;
|
||||
import org.ruoyi.workflow.workflow.node.start.StartNode;
|
||||
import org.ruoyi.workflow.workflow.node.switcher.SwitcherNode;
|
||||
|
||||
public class WfNodeFactory {
|
||||
public static AbstractWfNode create(WorkflowComponent wfComponent, WorkflowNode nodeDefinition,
|
||||
@@ -14,7 +17,10 @@ public class WfNodeFactory {
|
||||
switch (WfComponentNameEnum.getByName(wfComponent.getName())) {
|
||||
case START -> wfNode = new StartNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
case LLM_ANSWER -> wfNode = new LLMAnswerNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
case KEYWORD_EXTRACTOR -> wfNode = new KeywordExtractorNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
case END -> wfNode = new EndNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
case MAIL_SEND -> wfNode = new MailSendNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
case SWITCHER -> wfNode = new SwitcherNode(wfComponent, nodeDefinition, wfState, nodeState);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,10 @@ import org.ruoyi.workflow.workflow.data.NodeIOData;
|
||||
import org.ruoyi.workflow.workflow.data.NodeIODataContent;
|
||||
import org.ruoyi.workflow.workflow.def.WfNodeParamRef;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.ruoyi.workflow.cosntant.AdiConstant.WorkflowConstant.DEFAULT_OUTPUT_PARAM_NAME;
|
||||
|
||||
@Slf4j
|
||||
@@ -35,22 +33,48 @@ public class WorkflowUtil {
|
||||
@Resource
|
||||
private ChatServiceFactory chatServiceFactory;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String renderTemplate(String template, List<NodeIOData> values) {
|
||||
// 🔒 关键修复:如果 template 为 null,直接返回 null 或空字符串
|
||||
if (template == null) {
|
||||
return null; // 或 return ""; 根据业务需求
|
||||
}
|
||||
|
||||
String result = template;
|
||||
|
||||
// 防御 values 为 null
|
||||
if (values == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (NodeIOData next : values) {
|
||||
if (next == null || next.getName() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = next.getName();
|
||||
NodeIODataContent<?> dataContent = next.getContent();
|
||||
if (dataContent == null || dataContent.getValue() == null) {
|
||||
// 变量值为 null,替换为空字符串
|
||||
result = result.replace("{" + name + "}", "");
|
||||
continue;
|
||||
}
|
||||
|
||||
String replacement;
|
||||
if (dataContent.getType().equals(WfIODataTypeEnum.FILES.getValue())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> value = (List<String>) dataContent.getValue();
|
||||
result = result.replace("{" + name + "}", String.join(",", value));
|
||||
replacement = String.join(",", value);
|
||||
} else if (dataContent.getType().equals(WfIODataTypeEnum.OPTIONS.getValue())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> value = (Map<String, Object>) dataContent.getValue();
|
||||
result = result.replace("{" + name + "}", value.toString());
|
||||
replacement = value.toString();
|
||||
} else {
|
||||
result = result.replace("{" + name + "}", dataContent.getValue().toString());
|
||||
replacement = dataContent.getValue().toString();
|
||||
}
|
||||
|
||||
result = result.replace("{" + name + "}", replacement);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -81,8 +105,15 @@ public class WorkflowUtil {
|
||||
.mapResult(response -> {
|
||||
String responseTxt = response.aiMessage().text();
|
||||
log.info("llm response:{}", responseTxt);
|
||||
|
||||
// 传递所有输入数据 + 添加 LLM 输出
|
||||
wfState.getNodeStateByNodeUuid(node.getUuid()).ifPresent(item -> {
|
||||
List<NodeIOData> outputs = new ArrayList<>(item.getInputs());
|
||||
NodeIOData output = NodeIOData.createByText(DEFAULT_OUTPUT_PARAM_NAME, "", responseTxt);
|
||||
wfState.getNodeStateByNodeUuid(node.getUuid()).ifPresent(item -> item.getOutputs().add(output));
|
||||
outputs.add(output);
|
||||
item.setOutputs(outputs);
|
||||
});
|
||||
|
||||
return Map.of("completeResult", response.aiMessage().text());
|
||||
})
|
||||
.startingNode(node.getUuid())
|
||||
@@ -141,9 +172,10 @@ public class WorkflowUtil {
|
||||
* @return
|
||||
*/
|
||||
private Message getMessage(String role, Object value) {
|
||||
log.info("Creating message with role: {}, content: {}", role, value); // 🔥
|
||||
Message message = new Message();
|
||||
message.setContent(String.valueOf(value));
|
||||
message.setRole(role);
|
||||
message.setContent(value);
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -154,9 +186,13 @@ public class WorkflowUtil {
|
||||
* @param messages
|
||||
*/
|
||||
private void addSystemMessage(List<UserMessage> systemMessage, List<Message> messages) {
|
||||
log.info("addSystemMessage received: {}", systemMessage); // 🔥 加这一行
|
||||
|
||||
if (CollUtil.isEmpty(systemMessage)) {
|
||||
return;
|
||||
}
|
||||
systemMessage.stream().map(userMsg -> getMessage("system", userMsg.singleText())).forEach(messages::add);
|
||||
systemMessage.stream()
|
||||
.map(userMsg -> getMessage("system", userMsg.singleText()))
|
||||
.forEach(messages::add);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,17 +166,40 @@ public abstract class AbstractWfNode {
|
||||
protected abstract NodeProcessResult onProcess();
|
||||
|
||||
protected String getFirstInputText() {
|
||||
// 检查输入是否为空
|
||||
if (state.getInputs() == null || state.getInputs().isEmpty()) {
|
||||
log.warn("No inputs available for node: {}", state.getUuid());
|
||||
return "";
|
||||
}
|
||||
|
||||
// 优先查找 output 参数(LLM 节点的输出)
|
||||
Optional<String> outputParam = state.getInputs()
|
||||
.stream()
|
||||
.filter(item -> DEFAULT_OUTPUT_PARAM_NAME.equals(item.getName()))
|
||||
.map(NodeIOData::valueToString)
|
||||
.findFirst();
|
||||
|
||||
if (outputParam.isPresent()) {
|
||||
log.debug("Found output parameter for node: {}", state.getUuid());
|
||||
return outputParam.get();
|
||||
}
|
||||
|
||||
// 如果没有 output,查找其他文本类型参数(排除 input)
|
||||
String firstInputText;
|
||||
if (state.getInputs().size() > 1) {
|
||||
firstInputText = state.getInputs()
|
||||
.stream()
|
||||
.filter(item -> WfIODataTypeEnum.TEXT.getValue().equals(item.getContent().getType()) && !DEFAULT_INPUT_PARAM_NAME.equals(item.getName()))
|
||||
.filter(item -> WfIODataTypeEnum.TEXT.getValue().equals(item.getContent().getType())
|
||||
&& !DEFAULT_INPUT_PARAM_NAME.equals(item.getName()))
|
||||
.map(NodeIOData::valueToString)
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
} else {
|
||||
firstInputText = state.getInputs().get(0).valueToString();
|
||||
}
|
||||
|
||||
log.debug("Using first input text for node: {}, value: {}", state.getUuid(),
|
||||
firstInputText.length() > 50 ? firstInputText.substring(0, 50) + "..." : firstInputText);
|
||||
return firstInputText;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user