diff --git a/service-ai/service-ai-web/pom.xml b/service-ai/service-ai-web/pom.xml
index ce3546c..300d3e9 100644
--- a/service-ai/service-ai-web/pom.xml
+++ b/service-ai/service-ai-web/pom.xml
@@ -89,7 +89,10 @@
com.yomahub
liteflow-script-graaljs
- ${liteflow.version}
+
+
+ com.yomahub
+ liteflow-script-python
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/task/TaskTemplateController.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/task/TaskTemplateController.java
index 12dbf00..372e252 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/task/TaskTemplateController.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/task/TaskTemplateController.java
@@ -1,5 +1,6 @@
package com.lanyuanxiaoyao.service.ai.web.controller.task;
+import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -41,6 +42,12 @@ public class TaskTemplateController extends SimpleControllerSupport getFlowGraph(@PathVariable("id") Long id) throws JsonProcessingException {
+ var template = flowTaskTemplateService.detailOrThrow(id);
+ return AmisResponse.responseSuccess(mapper.readValue(template.getFlowGraph(), Map.class));
+ }
+
@PostMapping("update_flow_graph")
public AmisResponse> updateFlowGraph(@RequestBody UpdateGraphItem item) throws JsonProcessingException {
flowTaskTemplateService.updateFlowGraph(item.getId(), mapper.writeValueAsString(item.getGraph()));
@@ -49,8 +56,7 @@ public class TaskTemplateController extends SimpleControllerSupport saveItemMapper() {
- var map = Mappers.getMapper(SaveItem.Mapper.class);
- return item -> map.from(item, mapper);
+ return Mappers.getMapper(SaveItem.Mapper.class);
}
@Override
@@ -69,15 +75,9 @@ public class TaskTemplateController extends SimpleControllerSupport inputSchema;
@org.mapstruct.Mapper
- public static abstract class Mapper {
- public abstract FlowTaskTemplate from(SaveItem saveItem, @Context ObjectMapper mapper) throws Exception;
-
- protected String mapInputSchema(Map inputSchema, @Context ObjectMapper mapper) throws JsonProcessingException {
- return mapper.writeValueAsString(inputSchema);
- }
+ public interface Mapper extends SaveItemMapper {
}
}
@@ -105,6 +105,9 @@ public class TaskTemplateController extends SimpleControllerSupport mapJson(String source, @Context ObjectMapper mapper) throws Exception {
+ if (ObjectUtil.isNull(source)) {
+ return null;
+ }
return mapper.readValue(source, new TypeReference<>() {
});
}
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/FlowHelper.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/FlowHelper.java
index 24b914f..6fe87f0 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/FlowHelper.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/FlowHelper.java
@@ -47,11 +47,6 @@ public class FlowHelper {
throw new RuntimeException(StrUtil.format("Target node variable not found: {}.{}", targetNodeId, targetVariableName));
}
return targetNodeData.get(targetVariableName);
- } else if (context.getInput().containsKey(expression)) {
- if (!context.getInput().containsKey(expression)) {
- throw new RuntimeException(StrUtil.format("Target variable not found in input {}", expression));
- }
- return context.getInput().get(expression);
}
return null;
}
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/entity/FlowContext.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/entity/FlowContext.java
index 2f6182e..e0cc7e7 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/entity/FlowContext.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/entity/FlowContext.java
@@ -2,12 +2,10 @@ package com.lanyuanxiaoyao.service.ai.web.engine.entity;
import lombok.Data;
import org.eclipse.collections.api.factory.Maps;
-import org.eclipse.collections.api.map.ImmutableMap;
import org.eclipse.collections.api.map.MutableMap;
@Data
public class FlowContext {
- private ImmutableMap input = Maps.immutable.empty();
private MutableMap> data = Maps.mutable.>empty().asSynchronized();
public MutableMap get(String key) {
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/node/InputNode.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/node/InputNode.java
new file mode 100644
index 0000000..f0e1da5
--- /dev/null
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/engine/node/InputNode.java
@@ -0,0 +1,16 @@
+package com.lanyuanxiaoyao.service.ai.web.engine.node;
+
+import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeRunner;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author lanyuanxiaoyao
+ * @version 20250711
+ */
+@Slf4j
+public class InputNode extends FlowNodeRunner {
+ @Override
+ public void run() {
+ // 入参相关的内容在启动流程的时候已经注入了
+ }
+}
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/entity/vo/FlowGraphVo.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/entity/vo/FlowGraphVo.java
new file mode 100644
index 0000000..c9fb7d3
--- /dev/null
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/entity/vo/FlowGraphVo.java
@@ -0,0 +1,14 @@
+package com.lanyuanxiaoyao.service.ai.web.entity.vo;
+
+import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowEdge;
+import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowNode;
+import lombok.Data;
+import org.eclipse.collections.api.map.MutableMap;
+import org.eclipse.collections.api.set.ImmutableSet;
+
+@Data
+public class FlowGraphVo {
+ private ImmutableSet nodes;
+ private ImmutableSet edges;
+ private MutableMap> data;
+}
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java
index 05c2fff..b223cee 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java
@@ -7,9 +7,7 @@ import com.lanyuanxiaoyao.service.ai.web.entity.context.FeedbackContext;
import com.lanyuanxiaoyao.service.ai.web.repository.FeedbackRepository;
import com.yomahub.liteflow.core.FlowExecutor;
import java.util.List;
-import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -24,7 +22,7 @@ import org.springframework.transaction.annotation.Transactional;
this.executor = executor;
}
- @Scheduled(initialDelay = 1, fixedDelay = 1, timeUnit = TimeUnit.MINUTES)
+ // @Scheduled(initialDelay = 1, fixedDelay = 1, timeUnit = TimeUnit.MINUTES)
public void analysis() {
List feedbacks = repository.findAll(
builder -> builder
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskService.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskService.java
index ad4927f..71901e1 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskService.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskService.java
@@ -1,30 +1,29 @@
package com.lanyuanxiaoyao.service.ai.web.service.task;
import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.ai.web.base.service.SimpleServiceSupport;
import com.lanyuanxiaoyao.service.ai.web.engine.FlowExecutor;
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowContext;
-import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowEdge;
import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowGraph;
-import com.lanyuanxiaoyao.service.ai.web.engine.entity.FlowNode;
import com.lanyuanxiaoyao.service.ai.web.engine.node.CodeNode;
+import com.lanyuanxiaoyao.service.ai.web.engine.node.InputNode;
import com.lanyuanxiaoyao.service.ai.web.engine.node.LlmNode;
import com.lanyuanxiaoyao.service.ai.web.engine.node.LoopNode;
import com.lanyuanxiaoyao.service.ai.web.engine.node.OutputNode;
import com.lanyuanxiaoyao.service.ai.web.engine.node.SwitchNode;
import com.lanyuanxiaoyao.service.ai.web.engine.store.InMemoryFlowStore;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
+import com.lanyuanxiaoyao.service.ai.web.entity.vo.FlowGraphVo;
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskRepository;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
-import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.collections.api.factory.Maps;
-import org.eclipse.collections.api.map.MutableMap;
-import org.eclipse.collections.api.set.ImmutableSet;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;
@@ -42,7 +41,6 @@ public class FlowTaskService extends SimpleServiceSupport {
var flowTask = detailOrThrow(id);
var graphVo = mapper.readValue(flowTask.getTemplateFlowGraph(), FlowGraphVo.class);
var flowGraph = new FlowGraph(IdUtil.fastUUID(), graphVo.getNodes(), graphVo.getEdges());
- log.info("Graph: {}", flowGraph);
var store = new InMemoryFlowStore();
var executor = new FlowExecutor(
@@ -52,19 +50,25 @@ public class FlowTaskService extends SimpleServiceSupport {
"switch-node", SwitchNode.class,
"code-node", CodeNode.class,
"llm-node", LlmNode.class,
+ "input-node", InputNode.class,
"output-node", OutputNode.class
))
);
FlowContext context = new FlowContext();
- context.setInput(mapper.readValue(flowTask.getInput(), new TypeReference<>() {}));
context.setData(graphVo.getData());
+
+ // 如果发现输入节点,将相关数据注入到对应节点的上下文中
+ var inputNode = flowGraph.nodes()
+ .detectOptional(node -> StrUtil.equals(node.type(), "input-node") && ObjectUtil.isEmpty(node.parentId()))
+ .orElse(null);
+ if (ObjectUtil.isNotNull(inputNode)) {
+ if (!context.getData().containsKey(inputNode.id())) {
+ context.getData().put(inputNode.id(), Maps.mutable.empty());
+ }
+ context.getData().get(inputNode.id()).putAll(mapper.readValue(flowTask.getInput(), new TypeReference<>() {
+ }));
+ }
+
executor.execute(flowGraph, context);
}
-
- @Data
- public static final class FlowGraphVo {
- private ImmutableSet nodes;
- private ImmutableSet edges;
- private MutableMap> data;
- }
}
diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskTemplateService.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskTemplateService.java
index 41f6ab1..8711bc8 100644
--- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskTemplateService.java
+++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/task/FlowTaskTemplateService.java
@@ -1,22 +1,47 @@
package com.lanyuanxiaoyao.service.ai.web.service.task;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.ai.web.base.service.SimpleServiceSupport;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTaskTemplate;
+import com.lanyuanxiaoyao.service.ai.web.entity.vo.FlowGraphVo;
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskTemplateRepository;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
public class FlowTaskTemplateService extends SimpleServiceSupport {
- public FlowTaskTemplateService(FlowTaskTemplateRepository flowTaskTemplateRepository) {
+ private final ObjectMapper mapper;
+
+ public FlowTaskTemplateService(FlowTaskTemplateRepository flowTaskTemplateRepository, Jackson2ObjectMapperBuilder builder) {
super(flowTaskTemplateRepository);
+ this.mapper = builder.build();
}
@Transactional(rollbackFor = Exception.class)
- public void updateFlowGraph(Long id, String flowGraph) {
+ public void updateFlowGraph(Long id, String flowGraph) throws JsonProcessingException {
var template = detailOrThrow(id);
+
+ var graph = mapper.readValue(flowGraph, FlowGraphVo.class);
+ // 如果发现输入节点,就单独提取出来
+ var inputNode = graph.getNodes()
+ .detectOptional(node -> StrUtil.equals(node.type(), "input-node") && ObjectUtil.isEmpty(node.parentId()))
+ .orElse(null);
+ if (ObjectUtil.isNotNull(inputNode)) {
+ var nodeId = inputNode.id();
+ var nodeData = graph.getData().getOrDefault(nodeId, null);
+ if (ObjectUtil.isNotNull(nodeData) && nodeData.containsKey("inputs")) {
+ template.setInputSchema(mapper.writeValueAsString(nodeData.get("inputs")));
+ }
+ } else {
+ template.setInputSchema("{}");
+ }
+
template.setFlowGraph(flowGraph);
save(template);
}
diff --git a/service-web/client/src/components/flow/FlowChecker.tsx b/service-web/client/src/components/flow/FlowChecker.tsx
index 601d791..2681033 100644
--- a/service-web/client/src/components/flow/FlowChecker.tsx
+++ b/service-web/client/src/components/flow/FlowChecker.tsx
@@ -30,7 +30,7 @@ export const checkAddNode: (type: string, parentId: string | undefined, nodes: N
throw typeNotFound(type)
}
for (const checker of nodeDefine.checkers.add) {
- let checkResult = checker(type, parentId, {}, nodes, edges, undefined)
+ let checkResult = checker(type, parentId, nodes, edges, undefined)
if (checkResult.error) {
throw addNodeError(checkResult.message)
}
@@ -86,7 +86,7 @@ export const nodeTypeNotFound = () => new CheckError(302, '节点类型不存在
export const saveNodeError = (nodeId: string, reason?: string) => new CheckError(303, reason ?? `节点配置存在错误:${nodeId}`)
// @ts-ignore
-export const checkSave: (inputSchema: Record>, nodes: Node[], edges: Edge[], data: any) => void = (inputSchema, nodes, edges, data) => {
+export const checkSave: (nodes: Node[], edges: Edge[], data: any) => void = (nodes, edges, data) => {
if (isEmpty(nodes)) {
throw atLeastOneNode()
}
@@ -102,7 +102,7 @@ export const checkSave: (inputSchema: Record>, nodes
let nodeType = node.type!
let nodeDefine = NodeRegistryMap[nodeType]
for (let checker of nodeDefine.checkers.save) {
- let checkResult = checker(node.id, node.parentId, inputSchema, nodes, edges, data)
+ let checkResult = checker(node.id, node.parentId, nodes, edges, data)
if (checkResult.error) {
throw saveNodeError(node.id, checkResult.message)
}
diff --git a/service-web/client/src/components/flow/FlowEditor.tsx b/service-web/client/src/components/flow/FlowEditor.tsx
index c7db2fd..b12ee36 100644
--- a/service-web/client/src/components/flow/FlowEditor.tsx
+++ b/service-web/client/src/components/flow/FlowEditor.tsx
@@ -11,7 +11,6 @@ import AddNodeButton from './component/AddNodeButton.tsx'
import {checkAddConnection, checkSave} from './FlowChecker.tsx'
import {useNodeDrag} from './Helper.tsx'
import {NodeRegistryMap} from './NodeRegistry.tsx'
-import {useContextStore} from './store/ContextStore.ts'
import {useDataStore} from './store/DataStore.ts'
import {useFlowStore} from './store/FlowStore.ts'
import {flowDotColor, type FlowEditorProps} from './types.ts'
@@ -58,8 +57,6 @@ function FlowEditor(props: FlowEditorProps) {
onConnect,
} = useFlowStore()
- const {inputSchema, setInputSchema} = useContextStore()
-
useEffect(() => {
// language=JSON
// let initialData = JSON.parse('{"nodes":[{"id":"TCxPixrdkI","type":"start-node","position":{"x":-256,"y":109.5},"data":{},"measured":{"width":256,"height":83},"selected":false,"dragging":false},{"id":"tGs78_ietp","type":"llm-node","position":{"x":108,"y":-2.5},"data":{},"measured":{"width":256,"height":105},"selected":false,"dragging":false},{"id":"OeZdaU7LpY","type":"llm-node","position":{"x":111,"y":196},"data":{},"measured":{"width":256,"height":105},"selected":false,"dragging":false},{"id":"LjfoCYZo-E","type":"knowledge-node","position":{"x":497.62196259607214,"y":-10.792497317791003},"data":{},"measured":{"width":256,"height":75},"selected":false,"dragging":false},{"id":"sQM_22GYB5","type":"end-node","position":{"x":874.3164534765615,"y":151.70316541496913},"data":{},"measured":{"width":256,"height":75},"selected":false,"dragging":false},{"id":"KpMH_xc3ZZ","type":"llm-node","position":{"x":529.6286840434341,"y":150.4721376669937},"data":{},"measured":{"width":256,"height":75},"selected":false,"dragging":false},{"id":"pOrR6EMVbe","type":"switch-node","position":{"x":110.33793030183864,"y":373.9551529987239},"data":{},"measured":{"width":256,"height":157},"selected":false,"dragging":false}],"edges":[{"source":"TCxPixrdkI","sourceHandle":"source","target":"tGs78_ietp","targetHandle":"target","id":"xy-edge__TCxPixrdkIsource-tGs78_ietptarget"},{"source":"TCxPixrdkI","sourceHandle":"source","target":"OeZdaU7LpY","targetHandle":"target","id":"xy-edge__TCxPixrdkIsource-OeZdaU7LpYtarget"},{"source":"tGs78_ietp","sourceHandle":"source","target":"LjfoCYZo-E","targetHandle":"target","id":"xy-edge__tGs78_ietpsource-LjfoCYZo-Etarget"},{"source":"LjfoCYZo-E","sourceHandle":"source","target":"KpMH_xc3ZZ","targetHandle":"target","id":"xy-edge__LjfoCYZo-Esource-KpMH_xc3ZZtarget"},{"source":"OeZdaU7LpY","sourceHandle":"source","target":"KpMH_xc3ZZ","targetHandle":"target","id":"xy-edge__OeZdaU7LpYsource-KpMH_xc3ZZtarget"},{"source":"KpMH_xc3ZZ","sourceHandle":"source","target":"sQM_22GYB5","targetHandle":"target","id":"xy-edge__KpMH_xc3ZZsource-sQM_22GYB5target"},{"source":"TCxPixrdkI","sourceHandle":"source","target":"pOrR6EMVbe","id":"xy-edge__TCxPixrdkIsource-pOrR6EMVbe"},{"source":"pOrR6EMVbe","sourceHandle":"3","target":"sQM_22GYB5","targetHandle":"target","id":"xy-edge__pOrR6EMVbe3-sQM_22GYB5target"},{"source":"pOrR6EMVbe","sourceHandle":"1","target":"KpMH_xc3ZZ","targetHandle":"target","id":"xy-edge__pOrR6EMVbe1-KpMH_xc3ZZtarget"}],"data":{"tGs78_ietp":{"model":"qwen3","outputs":{"text":{"type":"string"}},"systemPrompt":"你是个聪明人"},"OeZdaU7LpY":{"model":"qwen3","outputs":{"text":{"type":"string"}},"systemPrompt":"你也是个聪明人"}}}')
@@ -72,7 +69,6 @@ function FlowEditor(props: FlowEditorProps) {
setNodes(initialNodes)
setEdges(initialEdges)
- setInputSchema(props.inputSchema)
}, [props.graphData])
const {
@@ -127,7 +123,7 @@ function FlowEditor(props: FlowEditorProps) {
if (commonInfo.debug) {
console.info('Save', JSON.stringify({nodes, edges, data}))
}
- checkSave(inputSchema, nodes, edges, data)
+ checkSave(nodes, edges, data)
props.onGraphDataChange({nodes, edges, data})
} catch (e) {
// @ts-ignore
diff --git a/service-web/client/src/components/flow/Helper.tsx b/service-web/client/src/components/flow/Helper.tsx
index f8bd614..4e0caef 100644
--- a/service-web/client/src/components/flow/Helper.tsx
+++ b/service-web/client/src/components/flow/Helper.tsx
@@ -3,7 +3,6 @@ import type {Option} from 'amis/lib/Schema'
import {contain, find, has, isEqual, max, min, unique} from 'licia'
import {type DependencyList, type MouseEvent as ReactMouseEvent, useCallback, useRef} from 'react'
import Queue from 'yocto-queue'
-import {originTypeMap} from '../../pages/ai/task/InputSchema.tsx'
import {useFlowStore} from './store/FlowStore.ts'
import {type OutputVariable, type OutputVariableType} from './types.ts'
@@ -21,17 +20,10 @@ export const getAllIncomerNodeById: (id: string, nodes: Node[], edges: Edge[]) =
return unique(result, (a, b) => isEqual(a, b))
}
-export const getAllIncomerNodeOutputVariables: (id: string, inputSchema: Record>, nodes: Node[], edges: Edge[], data: any) => OutputVariable[] = (id, inputSchema, nodes, edges, data) => {
- let inputSchemaVariables: OutputVariable[] = Object.keys(inputSchema).map(key => ({
- group: '流程入参',
- name: `${key}${inputSchema[key]?.label ? ` (${inputSchema[key].label})` : ''}`,
- type: originTypeMap[inputSchema[key]?.type ?? ''],
- variable: key,
- }))
-
+export const getAllIncomerNodeOutputVariables: (id: string, nodes: Node[], edges: Edge[], data: any) => OutputVariable[] = (id, nodes, edges, data) => {
let currentNode = find(nodes, n => isEqual(id, n.id))
if (!currentNode) {
- return inputSchemaVariables
+ return []
}
let incomerIds = getAllIncomerNodeById(id, nodes, edges)
@@ -63,7 +55,6 @@ export const getAllIncomerNodeOutputVariables: (id: string, inputSchema: Record<
}
return [
- ...inputSchemaVariables,
...(currentNode.parentId ? [
{
group: '循环入参',
@@ -82,9 +73,9 @@ export const getAllIncomerNodeOutputVariables: (id: string, inputSchema: Record<
]
}
-export const generateAllIncomerOutputVariablesFormOptions: (id: string, inputSchema: Record>, nodes: Node[], edges: Edge[], data: any, targetTypes?: OutputVariableType[]) => Option[] = (id, inputSchema, nodes, edges, data, targetTypes) => {
+export const generateAllIncomerOutputVariablesFormOptions: (id: string, nodes: Node[], edges: Edge[], data: any, targetTypes?: OutputVariableType[]) => Option[] = (id, nodes, edges, data, targetTypes) => {
let optionMap: Record = {}
- for (const item of getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data)) {
+ for (const item of getAllIncomerNodeOutputVariables(id, nodes, edges, data)) {
if (targetTypes && !contain(targetTypes, item.type)) {
continue
}
@@ -120,9 +111,9 @@ const numberDefaultOperator: string = 'equal'
const arrayOperators: ConditionOperator[] = ['is_empty', 'is_not_empty']
const arrayDefaultOperator: string = 'is_empty'
-export const generateAllIncomerOutputVariablesConditions: (id: string, inputSchema: Record>, nodes: Node[], edges: Edge[], data: any) => Option[] = (id, inputSchema, nodes, edges, data) => {
+export const generateAllIncomerOutputVariablesConditions: (id: string, nodes: Node[], edges: Edge[], data: any) => Option[] = (id, nodes, edges, data) => {
let optionMap: Record = {}
- for (const item of getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data)) {
+ for (const item of getAllIncomerNodeOutputVariables(id, nodes, edges, data)) {
if (!optionMap[item.group]) {
optionMap[item.group] = []
}
diff --git a/service-web/client/src/components/flow/NodeRegistry.tsx b/service-web/client/src/components/flow/NodeRegistry.tsx
index f0d71c1..b9b0025 100644
--- a/service-web/client/src/components/flow/NodeRegistry.tsx
+++ b/service-web/client/src/components/flow/NodeRegistry.tsx
@@ -11,12 +11,12 @@ import type {AddNodeChecker, NodeDefine, SaveNodeChecker} from './types.ts'
import InputNode from './node/InputNode.tsx'
const inputSingleVariableChecker: (field: string) => SaveNodeChecker = field => {
- return (id, _parentId, inputSchema, nodes, edges, data) => {
+ return (id, _parentId, nodes, edges, data) => {
let nodeData = data[id] ?? {}
if (has(nodeData, field)) {
let expression = nodeData?.[field] ?? ''
if (!isEmpty(expression)) {
- let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data).map(i => i.variable))
+ let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => i.variable))
if (!outputVariables.has(expression)) {
return {
error: true,
@@ -29,12 +29,12 @@ const inputSingleVariableChecker: (field: string) => SaveNodeChecker = field =>
}
}
-const inputMultiVariableChecker: SaveNodeChecker = (id, _parentId, inputSchema, nodes, edges, data) => {
+const inputMultiVariableChecker: SaveNodeChecker = (id, _parentId, nodes, edges, data) => {
let nodeData = data[id] ?? {}
if (has(nodeData, 'inputs')) {
let inputs = nodeData?.inputs ?? {}
if (!isEmpty(inputs)) {
- let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, inputSchema, nodes, edges, data).map(i => i.variable))
+ let outputVariables = new Set(getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => i.variable))
for (const key of Object.keys(inputs)) {
let variable = inputs[key]?.variable ?? ''
if (!outputVariables.has(variable)) {
@@ -49,7 +49,7 @@ const inputMultiVariableChecker: SaveNodeChecker = (id, _parentId, inputSchema,
return {error: false}
}
-const noMoreThanOneNodeType: AddNodeChecker = (type, parentId, _inputSchema, nodes) => {
+const noMoreThanOneNodeType: AddNodeChecker = (type, parentId, nodes) => {
return {
error: nodes.filter(n => isEqual(n.parentId, parentId) && isEqual(n.type, type)).length > 0,
message: `同一个流程(子流程)中类型为 ${type} 的节点至多有一个`
diff --git a/service-web/client/src/components/flow/node/AmisNode.tsx b/service-web/client/src/components/flow/node/AmisNode.tsx
index d3a44f5..0d49894 100644
--- a/service-web/client/src/components/flow/node/AmisNode.tsx
+++ b/service-web/client/src/components/flow/node/AmisNode.tsx
@@ -12,7 +12,6 @@ import {type FormSchema, OutputVariableTypeMap} from '../types.ts'
export function inputsFormColumns(
nodeId: string,
- inputSchema: Record>,
nodes: Node[],
edges: Edge[],
data: any,
@@ -38,7 +37,6 @@ export function inputsFormColumns(
selectMode: 'group',
options: generateAllIncomerOutputVariablesFormOptions(
nodeId,
- inputSchema,
nodes,
edges,
data,
diff --git a/service-web/client/src/components/flow/node/CodeNode.tsx b/service-web/client/src/components/flow/node/CodeNode.tsx
index 028b37f..051501a 100644
--- a/service-web/client/src/components/flow/node/CodeNode.tsx
+++ b/service-web/client/src/components/flow/node/CodeNode.tsx
@@ -1,7 +1,6 @@
import type {NodeProps} from '@xyflow/react'
import {Tag} from 'antd'
import React, {useCallback, useMemo} from 'react'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {inputsFormColumns, nodeClassName, NormalNodeHandler, outputsFormColumns} from './AmisNode.tsx'
@@ -16,13 +15,12 @@ const languageMap: Record = {
const CodeNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData, getDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
const nodeData = getDataById(props.id)
const formSchema: () => FormSchema = useCallback(() => ({
columns: [
- ...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
+ ...inputsFormColumns(props.id, getNodes(), getEdges(), getData()),
{
type: 'divider',
},
diff --git a/service-web/client/src/components/flow/node/KnowledgeNode.tsx b/service-web/client/src/components/flow/node/KnowledgeNode.tsx
index c0d1d04..16d276a 100644
--- a/service-web/client/src/components/flow/node/KnowledgeNode.tsx
+++ b/service-web/client/src/components/flow/node/KnowledgeNode.tsx
@@ -1,7 +1,6 @@
import type {NodeProps} from '@xyflow/react'
import React, {useCallback, useEffect} from 'react'
import {commonInfo} from '../../../util/amis.tsx'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {inputsFormColumns, nodeClassName, NormalNodeHandler, outputsFormColumns} from './AmisNode.tsx'
@@ -10,7 +9,6 @@ import type {FormSchema} from '../types.ts'
const KnowledgeNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData, mergeDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
useEffect(() => {
mergeDataById(
@@ -27,7 +25,7 @@ const KnowledgeNode = (props: NodeProps) => {
const formSchema: () => FormSchema = useCallback(() => ({
columns: [
- ...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
+ ...inputsFormColumns(props.id, getNodes(), getEdges(), getData()),
{
type: 'divider',
},
diff --git a/service-web/client/src/components/flow/node/LlmNode.tsx b/service-web/client/src/components/flow/node/LlmNode.tsx
index 343dfd2..0807a62 100644
--- a/service-web/client/src/components/flow/node/LlmNode.tsx
+++ b/service-web/client/src/components/flow/node/LlmNode.tsx
@@ -1,7 +1,6 @@
import type {NodeProps} from '@xyflow/react'
import {Tag} from 'antd'
import React, {useCallback, useEffect, useMemo} from 'react'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {inputsFormColumns, nodeClassName, NormalNodeHandler, outputsFormColumns} from './AmisNode.tsx'
@@ -15,7 +14,6 @@ const modelMap: Record = {
const LlmNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData, mergeDataById, getDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
const nodeData = getDataById(props.id)
@@ -34,7 +32,7 @@ const LlmNode = (props: NodeProps) => {
const formSchema: () => FormSchema = useCallback(() => ({
columns: [
- ...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
+ ...inputsFormColumns(props.id, getNodes(), getEdges(), getData()),
{
type: 'divider',
},
diff --git a/service-web/client/src/components/flow/node/LoopNode.tsx b/service-web/client/src/components/flow/node/LoopNode.tsx
index 4b3d7fd..6b2b22a 100644
--- a/service-web/client/src/components/flow/node/LoopNode.tsx
+++ b/service-web/client/src/components/flow/node/LoopNode.tsx
@@ -3,7 +3,6 @@ import {classnames} from 'amis'
import React, {useCallback, useEffect, useMemo} from 'react'
import AddNodeButton from '../component/AddNodeButton.tsx'
import {generateAllIncomerOutputVariablesFormOptions} from '../Helper.tsx'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import {flowBackgroundColor, flowDotColor, type FormSchema} from '../types.ts'
@@ -12,7 +11,6 @@ import AmisNode, {nodeClassName, NormalNodeHandler, outputsFormColumns} from './
const LoopNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData, mergeDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
useEffect(() => {
mergeDataById(
@@ -85,7 +83,6 @@ const LoopNode = (props: NodeProps) => {
selectMode: 'group',
options: generateAllIncomerOutputVariablesFormOptions(
props.id,
- getInputSchema(),
getNodes(),
getEdges(),
getData(),
@@ -101,7 +98,6 @@ const LoopNode = (props: NodeProps) => {
selectMode: 'group',
options: generateAllIncomerOutputVariablesFormOptions(
props.id,
- getInputSchema(),
getNodes(),
getEdges(),
getData(),
diff --git a/service-web/client/src/components/flow/node/OutputNode.tsx b/service-web/client/src/components/flow/node/OutputNode.tsx
index 179073d..c1c1965 100644
--- a/service-web/client/src/components/flow/node/OutputNode.tsx
+++ b/service-web/client/src/components/flow/node/OutputNode.tsx
@@ -1,7 +1,6 @@
import type {NodeProps} from '@xyflow/react'
import React, {useCallback} from 'react'
import {generateAllIncomerOutputVariablesFormOptions} from '../Helper.tsx'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {EndNodeHandler, nodeClassName} from './AmisNode.tsx'
@@ -10,7 +9,6 @@ import type {FormSchema} from '../types.ts'
const OutputNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData} = useDataStore()
- const {getInputSchema} = useContextStore()
const formSchema: () => FormSchema = useCallback(() => ({
columns: [
@@ -22,7 +20,6 @@ const OutputNode = (props: NodeProps) => {
selectMode: 'group',
options: generateAllIncomerOutputVariablesFormOptions(
props.id,
- getInputSchema(),
getNodes(),
getEdges(),
getData(),
diff --git a/service-web/client/src/components/flow/node/SwitchNode.tsx b/service-web/client/src/components/flow/node/SwitchNode.tsx
index a037e35..b2cabd3 100644
--- a/service-web/client/src/components/flow/node/SwitchNode.tsx
+++ b/service-web/client/src/components/flow/node/SwitchNode.tsx
@@ -4,7 +4,6 @@ import {Tag} from 'antd'
import {contain, isEqual} from 'licia'
import React, {useCallback, useMemo} from 'react'
import {generateAllIncomerOutputVariablesConditions} from '../Helper.tsx'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {nodeClassName} from './AmisNode.tsx'
@@ -13,7 +12,6 @@ import type {FormSchema} from '../types.ts'
const SwitchNode = (props: NodeProps) => {
const {getNodes, getEdges, removeEdges} = useFlowStore()
const {getData, getDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
const nodeData = getDataById(props.id)
// @ts-ignore
@@ -37,7 +35,6 @@ const SwitchNode = (props: NodeProps) => {
showANDOR: true,
fields: generateAllIncomerOutputVariablesConditions(
props.id,
- getInputSchema(),
getNodes(),
getEdges(),
getData(),
diff --git a/service-web/client/src/components/flow/node/TemplateNode.tsx b/service-web/client/src/components/flow/node/TemplateNode.tsx
index d8005bb..661b34c 100644
--- a/service-web/client/src/components/flow/node/TemplateNode.tsx
+++ b/service-web/client/src/components/flow/node/TemplateNode.tsx
@@ -1,7 +1,6 @@
import type {NodeProps} from '@xyflow/react'
import {Tag} from 'antd'
import React, {useCallback, useEffect, useMemo} from 'react'
-import {useContextStore} from '../store/ContextStore.ts'
import {useDataStore} from '../store/DataStore.ts'
import {useFlowStore} from '../store/FlowStore.ts'
import AmisNode, {inputsFormColumns, nodeClassName, NormalNodeHandler, outputsFormColumns} from './AmisNode.tsx'
@@ -17,7 +16,6 @@ const typeMap: Record = {
const TemplateNode = (props: NodeProps) => {
const {getNodes, getEdges} = useFlowStore()
const {getData, getDataById, mergeDataById} = useDataStore()
- const {getInputSchema} = useContextStore()
const nodeData = getDataById(props.id)
@@ -36,7 +34,7 @@ const TemplateNode = (props: NodeProps) => {
const formSchema: () => FormSchema = useCallback(() => ({
columns: [
- ...inputsFormColumns(props.id, getInputSchema(), getNodes(), getEdges(), getData()),
+ ...inputsFormColumns(props.id, getNodes(), getEdges(), getData()),
{
type: 'divider',
},
diff --git a/service-web/client/src/components/flow/store/ContextStore.ts b/service-web/client/src/components/flow/store/ContextStore.ts
deleted file mode 100644
index 2cd3319..0000000
--- a/service-web/client/src/components/flow/store/ContextStore.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import {create} from 'zustand/react'
-
-export const useContextStore = create<{
- inputSchema: Record>,
- getInputSchema: () => Record>,
- setInputSchema: (inputSchema: Record>) => void,
-}>((set, get) => ({
- inputSchema: {},
- getInputSchema: () => get().inputSchema,
- setInputSchema: (inputSchema: Record>) => set({inputSchema}),
-}))
\ No newline at end of file
diff --git a/service-web/client/src/components/flow/types.ts b/service-web/client/src/components/flow/types.ts
index 5d3279b..20845eb 100644
--- a/service-web/client/src/components/flow/types.ts
+++ b/service-web/client/src/components/flow/types.ts
@@ -20,13 +20,12 @@ export type NodeError = {
message?: string,
}
-export type AddNodeChecker = (type: string, parentId: string | undefined, inputSchema: Record>, nodes: Node[], edges: Edge[], data: any) => NodeError
-export type SaveNodeChecker = (id: string, parentId: string | undefined, inputSchema: Record>, nodes: Node[], edges: Edge[], data: any) => NodeError
+export type AddNodeChecker = (type: string, parentId: string | undefined, nodes: Node[], edges: Edge[], data: any) => NodeError
+export type SaveNodeChecker = (id: string, parentId: string | undefined, nodes: Node[], edges: Edge[], data: any) => NodeError
export type GraphData = { nodes: Node[], edges: Edge[], data: any }
export type FlowEditorProps = {
- inputSchema: Record>,
graphData: GraphData,
onGraphDataChange: (graphData: GraphData) => void,
}
diff --git a/service-web/client/src/pages/ai/task/InputSchema.tsx b/service-web/client/src/pages/ai/task/InputSchema.tsx
index 37c51f3..4c7092c 100644
--- a/service-web/client/src/pages/ai/task/InputSchema.tsx
+++ b/service-web/client/src/pages/ai/task/InputSchema.tsx
@@ -1,5 +1,4 @@
import type {Schema} from 'amis'
-import type {OutputVariableType} from '../../../components/flow/types.ts'
import {commonInfo, formInputFileStaticColumns} from '../../../util/amis.tsx'
export const typeMap: Record = {
@@ -9,13 +8,6 @@ export const typeMap: Record = {
files: '文件',
}
-export const originTypeMap: Record = {
- text: 'text',
- textarea: 'text',
- number: 'number',
- files: 'array-text',
-}
-
export type InputField = {
type: string
label: string
diff --git a/service-web/client/src/pages/ai/task/template/FlowTaskTemplateEdit.tsx b/service-web/client/src/pages/ai/task/template/FlowTaskTemplateEdit.tsx
index 7cfe7cb..a3412dc 100644
--- a/service-web/client/src/pages/ai/task/template/FlowTaskTemplateEdit.tsx
+++ b/service-web/client/src/pages/ai/task/template/FlowTaskTemplateEdit.tsx
@@ -1,9 +1,8 @@
-import {isEmpty, isEqual} from 'licia'
+import {isEqual} from 'licia'
import React from 'react'
import {useNavigate, useParams} from 'react-router'
import styled from 'styled-components'
import {amisRender, commonInfo, horizontalFormOptions} from '../../../../util/amis.tsx'
-import {generateInputForm, typeMap} from '../InputSchema.tsx'
const TemplateEditDiv = styled.div`
.antd-EditorControl {
@@ -39,31 +38,6 @@ const FlowTaskTemplateEdit: React.FC = () => {
wrapWithPanel: false,
...horizontalFormOptions(),
onEvent: {
- change: {
- actions: [
- {
- actionType: 'validate',
- },
- {
- actionType: 'custom',
- // @ts-ignore
- script: (context, doAction, event) => {
- let data = event?.data ?? {}
- let inputSchema = data.inputSchema ?? []
- if (!isEmpty(inputSchema) && isEmpty(data?.validateResult?.error ?? undefined)) {
- doAction({
- actionType: 'setValue',
- args: {
- value: {
- inputPreview: generateInputForm(inputSchema, '入参表单预览'),
- },
- },
- })
- }
- },
- },
- ],
- },
submitSucc: {
actions: [
{
@@ -99,71 +73,6 @@ const FlowTaskTemplateEdit: React.FC = () => {
maxLength: 500,
showCounter: true,
},
- {
- type: 'group',
- body: [
- {
- type: 'wrapper',
- size: 'none',
- body: [
- {
- type: 'input-kvs',
- name: 'inputSchema',
- label: '输入变量',
- addButtonText: '新增入参',
- draggable: false,
- keyItem: {
- label: '参数名称',
- ...horizontalFormOptions(),
- validations: {
- isAlphanumeric: true,
- },
- },
- valueItems: [
- {
- ...horizontalFormOptions(),
- type: 'input-text',
- name: 'label',
- required: true,
- label: '中文名称',
- clearValueOnEmpty: true,
- clearable: true,
- },
- {
- ...horizontalFormOptions(),
- type: 'input-text',
- name: 'description',
- label: '参数描述',
- clearValueOnEmpty: true,
- clearable: true,
- },
- {
- ...horizontalFormOptions(),
- type: 'select',
- name: 'type',
- label: '参数类型',
- required: true,
- selectFirst: true,
- options: Object.keys(typeMap).map(key => ({label: typeMap[key], value: key})),
- },
- {
- ...horizontalFormOptions(),
- type: 'switch',
- name: 'required',
- label: '是否必填',
- required: true,
- value: true,
- },
- ],
- },
- ],
- },
- {
- type: 'amis',
- name: 'inputPreview',
- },
- ],
- },
{
type: 'button-toolbar',
buttons: [
diff --git a/service-web/client/src/pages/ai/task/template/FlowTaskTemplateFlowEdit.tsx b/service-web/client/src/pages/ai/task/template/FlowTaskTemplateFlowEdit.tsx
index 6f6c147..6edf7de 100644
--- a/service-web/client/src/pages/ai/task/template/FlowTaskTemplateFlowEdit.tsx
+++ b/service-web/client/src/pages/ai/task/template/FlowTaskTemplateFlowEdit.tsx
@@ -13,7 +13,6 @@ const FlowTaskTemplateFlowEditDiv = styled.div`
const FlowTaskTemplateFlowEdit: React.FC = () => {
const navigate = useNavigate()
const {template_id} = useParams()
- const [inputSchema, setInputSchema] = useState>>({})
const [graphData, setGraphData] = useState({nodes: [], edges: [], data: {}})
useMount(async () => {
@@ -23,14 +22,12 @@ const FlowTaskTemplateFlowEdit: React.FC = () => {
headers: commonInfo.authorizationHeaders,
},
)
- setInputSchema(data?.data?.inputSchema)
setGraphData(data?.data?.flowGraph)
})
return (
{
await axios.post(