Compare commits
3 Commits
267eecbf45
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2a8c39145 | ||
|
|
82ad3e7854 | ||
| 1e3e14c590 |
@@ -45,7 +45,7 @@ create table hudi_collect_build_b12.service_ai_flow_task
|
|||||||
status enum ('ERROR','FINISHED','RUNNING') not null comment '任务运行状态',
|
status enum ('ERROR','FINISHED','RUNNING') not null comment '任务运行状态',
|
||||||
template_description varchar(255) comment '任务对应的模板功能、内容说明',
|
template_description varchar(255) comment '任务对应的模板功能、内容说明',
|
||||||
template_flow_graph longtext not null comment '任务对应的模板前端流程图数据',
|
template_flow_graph longtext not null comment '任务对应的模板前端流程图数据',
|
||||||
template_input_schema longtext not null comment '任务对应的模板入参Schema',
|
template_input_schema longtext comment '任务对应的模板入参Schema',
|
||||||
template_name varchar(255) not null comment '任务对应的模板名称',
|
template_name varchar(255) not null comment '任务对应的模板名称',
|
||||||
primary key (id)
|
primary key (id)
|
||||||
) comment ='流程任务记录' charset = utf8mb4;
|
) comment ='流程任务记录' charset = utf8mb4;
|
||||||
@@ -57,7 +57,7 @@ create table hudi_collect_build_b12.service_ai_flow_task_template
|
|||||||
modified_time datetime(6) comment '记录更新时间',
|
modified_time datetime(6) comment '记录更新时间',
|
||||||
description varchar(255) comment '模板功能、内容说明',
|
description varchar(255) comment '模板功能、内容说明',
|
||||||
flow_graph longtext not null comment '前端流程图数据',
|
flow_graph longtext not null comment '前端流程图数据',
|
||||||
input_schema longtext not null comment '模板入参Schema',
|
input_schema longtext comment '模板入参Schema',
|
||||||
name varchar(255) not null comment '模板名称',
|
name varchar(255) not null comment '模板名称',
|
||||||
primary key (id)
|
primary key (id)
|
||||||
) comment ='流程任务模板' charset = utf8mb4;
|
) comment ='流程任务模板' charset = utf8mb4;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.controller.task;
|
package com.lanyuanxiaoyao.service.ai.web.controller.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
||||||
@@ -14,6 +16,7 @@ import java.util.Map;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -39,12 +42,18 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
|
|||||||
@GetMapping("input_data/{id}")
|
@GetMapping("input_data/{id}")
|
||||||
public AmisResponse<?> getInputData(@PathVariable("id") Long id) throws JsonProcessingException {
|
public AmisResponse<?> getInputData(@PathVariable("id") Long id) throws JsonProcessingException {
|
||||||
var task = flowTaskService.detailOrThrow(id);
|
var task = flowTaskService.detailOrThrow(id);
|
||||||
|
if (ObjectUtil.isEmpty(task.getInput())) {
|
||||||
|
return AmisResponse.responseSuccess();
|
||||||
|
}
|
||||||
return AmisResponse.responseSuccess(mapper.readValue(task.getInput(), Map.class));
|
return AmisResponse.responseSuccess(mapper.readValue(task.getInput(), Map.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("input_schema/{id}")
|
@GetMapping("input_schema/{id}")
|
||||||
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
|
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
|
||||||
var task = flowTaskService.detailOrThrow(id);
|
var task = flowTaskService.detailOrThrow(id);
|
||||||
|
if (ObjectUtil.isEmpty(task.getTemplateInputSchema())) {
|
||||||
|
return AmisResponse.responseSuccess();
|
||||||
|
}
|
||||||
return AmisResponse.responseSuccess(mapper.readValue(task.getTemplateInputSchema(), Map.class));
|
return AmisResponse.responseSuccess(mapper.readValue(task.getTemplateInputSchema(), Map.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +72,7 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
|
|||||||
task.setTemplateDescription(template.getDescription());
|
task.setTemplateDescription(template.getDescription());
|
||||||
task.setTemplateInputSchema(template.getInputSchema());
|
task.setTemplateInputSchema(template.getInputSchema());
|
||||||
task.setTemplateFlowGraph(template.getFlowGraph());
|
task.setTemplateFlowGraph(template.getFlowGraph());
|
||||||
task.setInput(mapper.writeValueAsString(item.getInput()));
|
task.setInput(ObjectUtil.isEmpty(item.getInput()) ? null : mapper.writeValueAsString(item.getInput()));
|
||||||
return task;
|
return task;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -91,9 +100,13 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
|
|||||||
public static class ListItem extends SimpleItem {
|
public static class ListItem extends SimpleItem {
|
||||||
private String templateName;
|
private String templateName;
|
||||||
private FlowTask.Status status;
|
private FlowTask.Status status;
|
||||||
|
private Boolean hasInput;
|
||||||
|
|
||||||
@org.mapstruct.Mapper
|
@org.mapstruct.Mapper(imports = {
|
||||||
|
StrUtil.class
|
||||||
|
})
|
||||||
public static abstract class Mapper {
|
public static abstract class Mapper {
|
||||||
|
@Mapping(target = "hasInput", expression = "java(StrUtil.isNotBlank(task.getInput()))")
|
||||||
public abstract ListItem from(FlowTask task);
|
public abstract ListItem from(FlowTask task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,8 +117,11 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
|
|||||||
private String error;
|
private String error;
|
||||||
private String result;
|
private String result;
|
||||||
|
|
||||||
@org.mapstruct.Mapper
|
@org.mapstruct.Mapper(imports = {
|
||||||
|
StrUtil.class
|
||||||
|
})
|
||||||
public static abstract class Mapper extends ListItem.Mapper {
|
public static abstract class Mapper extends ListItem.Mapper {
|
||||||
|
@Mapping(target = "hasInput", expression = "java(StrUtil.isNotBlank(task.getInput()))")
|
||||||
public abstract DetailItem from(FlowTask task);
|
public abstract DetailItem from(FlowTask task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ public class TaskTemplateController extends SimpleControllerSupport<FlowTaskTemp
|
|||||||
@GetMapping("input_schema/{id}")
|
@GetMapping("input_schema/{id}")
|
||||||
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
|
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
|
||||||
var template = flowTaskTemplateService.detailOrThrow(id);
|
var template = flowTaskTemplateService.detailOrThrow(id);
|
||||||
|
if (ObjectUtil.isEmpty(template.getInputSchema())) {
|
||||||
|
return AmisResponse.responseSuccess();
|
||||||
|
}
|
||||||
return AmisResponse.responseSuccess(mapper.readValue(template.getInputSchema(), Map.class));
|
return AmisResponse.responseSuccess(mapper.readValue(template.getInputSchema(), Map.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.engine.node;
|
package com.lanyuanxiaoyao.service.ai.web.engine.node;
|
||||||
|
|
||||||
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeRunner;
|
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeRunner;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,8 +10,16 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class InputNode extends FlowNodeRunner {
|
public class InputNode extends FlowNodeRunner {
|
||||||
|
public static final String KEY = "flow_inputs";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// 入参相关的内容在启动流程的时候已经注入了
|
var inputData = getContext().getData().get(KEY);
|
||||||
|
var inputs = this.<Map<String, Object>>getData("inputs");
|
||||||
|
for (String variable : inputs.keySet()) {
|
||||||
|
if (inputData.containsKey(variable)) {
|
||||||
|
setData(variable, inputData.get(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public class LlmNode extends FlowNodeRunner {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
var variableMap = FlowHelper.generateInputVariablesMap(getNodeId(), getContext());
|
var variableMap = FlowHelper.generateInputVariablesMap(getNodeId(), getContext());
|
||||||
log.info("Variable map: {}", variableMap);
|
|
||||||
var sourcePrompt = (String) getData("systemPrompt");
|
var sourcePrompt = (String) getData("systemPrompt");
|
||||||
if (StrUtil.isNotBlank(sourcePrompt)) {
|
if (StrUtil.isNotBlank(sourcePrompt)) {
|
||||||
var prompt = FlowHelper.renderTemplateText(sourcePrompt, variableMap.toMap());
|
var prompt = FlowHelper.renderTemplateText(sourcePrompt, variableMap.toMap());
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class OutputNode extends FlowNodeRunner {
|
public class OutputNode extends FlowNodeRunner {
|
||||||
|
private static final String KEY = "flow_outputs";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String expression = getData("output");
|
var variableMap = FlowHelper.generateInputVariablesMap(getNodeId(), getContext());
|
||||||
var targetVariable = FlowHelper.generateVariable(expression, getContext());
|
getContext().getData().put(KEY, variableMap.toMap());
|
||||||
log.info("Target: {}", targetVariable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class FlowTask extends SimpleEntity {
|
|||||||
@Comment("任务对应的模板功能、内容说明")
|
@Comment("任务对应的模板功能、内容说明")
|
||||||
private String templateDescription;
|
private String templateDescription;
|
||||||
@Comment("任务对应的模板入参Schema")
|
@Comment("任务对应的模板入参Schema")
|
||||||
@Column(nullable = false, columnDefinition = "longtext")
|
@Column(columnDefinition = "longtext")
|
||||||
private String templateInputSchema;
|
private String templateInputSchema;
|
||||||
@Comment("任务对应的模板前端流程图数据")
|
@Comment("任务对应的模板前端流程图数据")
|
||||||
@Column(nullable = false, columnDefinition = "longtext")
|
@Column(nullable = false, columnDefinition = "longtext")
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class FlowTaskTemplate extends SimpleEntity {
|
|||||||
@Comment("模板功能、内容说明")
|
@Comment("模板功能、内容说明")
|
||||||
private String description;
|
private String description;
|
||||||
@Comment("模板入参Schema")
|
@Comment("模板入参Schema")
|
||||||
@Column(nullable = false, columnDefinition = "longtext")
|
@Column(columnDefinition = "longtext")
|
||||||
private String inputSchema;
|
private String inputSchema;
|
||||||
@Comment("前端流程图数据")
|
@Comment("前端流程图数据")
|
||||||
@Column(nullable = false, columnDefinition = "longtext")
|
@Column(nullable = false, columnDefinition = "longtext")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.lanyuanxiaoyao.service.ai.web.service.task;
|
|||||||
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -57,15 +56,8 @@ public class FlowTaskService extends SimpleServiceSupport<FlowTask> {
|
|||||||
FlowContext context = new FlowContext();
|
FlowContext context = new FlowContext();
|
||||||
context.setData(graphVo.getData());
|
context.setData(graphVo.getData());
|
||||||
|
|
||||||
// 如果发现输入节点,将相关数据注入到对应节点的上下文中
|
if (ObjectUtil.isNotEmpty(flowTask.getInput())) {
|
||||||
var inputNode = flowGraph.nodes()
|
context.getData().put(InputNode.KEY, mapper.readValue(flowTask.getInput(), new TypeReference<>() {
|
||||||
.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<>() {
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ public class FlowTaskTemplateService extends SimpleServiceSupport<FlowTaskTempla
|
|||||||
if (ObjectUtil.isNotNull(nodeData) && nodeData.containsKey("inputs")) {
|
if (ObjectUtil.isNotNull(nodeData) && nodeData.containsKey("inputs")) {
|
||||||
template.setInputSchema(mapper.writeValueAsString(nodeData.get("inputs")));
|
template.setInputSchema(mapper.writeValueAsString(nodeData.get("inputs")));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
template.setInputSchema("{}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template.setFlowGraph(flowGraph);
|
template.setFlowGraph(flowGraph);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ function FlowEditor(props: FlowEditorProps) {
|
|||||||
onConnect(connection)
|
onConnect(connection)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
messageApi.error(e.toString())
|
message.error(e.toString())
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -1,31 +1,16 @@
|
|||||||
import type {NodeProps} from '@xyflow/react'
|
import type {NodeProps} from '@xyflow/react'
|
||||||
import React, {useCallback} from 'react'
|
import React, {useCallback} from 'react'
|
||||||
import {generateAllIncomerOutputVariablesFormOptions} from '../Helper.tsx'
|
|
||||||
import {useDataStore} from '../store/DataStore.ts'
|
import {useDataStore} from '../store/DataStore.ts'
|
||||||
import {useFlowStore} from '../store/FlowStore.ts'
|
import {useFlowStore} from '../store/FlowStore.ts'
|
||||||
import AmisNode, {EndNodeHandler, nodeClassName} from './AmisNode.tsx'
|
|
||||||
import type {FormSchema} from '../types.ts'
|
import type {FormSchema} from '../types.ts'
|
||||||
|
import AmisNode, {EndNodeHandler, inputsFormColumns, nodeClassName} from './AmisNode.tsx'
|
||||||
|
|
||||||
const OutputNode = (props: NodeProps) => {
|
const OutputNode = (props: NodeProps) => {
|
||||||
const {getNodes, getEdges} = useFlowStore()
|
const {getNodes, getEdges} = useFlowStore()
|
||||||
const {getData} = useDataStore()
|
const {getData} = useDataStore()
|
||||||
|
|
||||||
const formSchema: () => FormSchema = useCallback(() => ({
|
const formSchema: () => FormSchema = useCallback(() => ({
|
||||||
columns: [
|
columns: inputsFormColumns(props.id, getNodes(), getEdges(), getData()),
|
||||||
{
|
|
||||||
type: 'select',
|
|
||||||
name: 'output',
|
|
||||||
label: '输出变量',
|
|
||||||
required: true,
|
|
||||||
selectMode: 'group',
|
|
||||||
options: generateAllIncomerOutputVariablesFormOptions(
|
|
||||||
props.id,
|
|
||||||
getNodes(),
|
|
||||||
getEdges(),
|
|
||||||
getData(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}), [props.id])
|
}), [props.id])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -87,6 +87,7 @@ const FlowTask: React.FC = () => {
|
|||||||
width: 200,
|
width: 200,
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
visibleOn: 'hasInput',
|
||||||
type: 'action',
|
type: 'action',
|
||||||
label: '查看',
|
label: '查看',
|
||||||
level: 'link',
|
level: 'link',
|
||||||
@@ -107,17 +108,18 @@ const FlowTask: React.FC = () => {
|
|||||||
return {
|
return {
|
||||||
...payload,
|
...payload,
|
||||||
data: {
|
data: {
|
||||||
...generateInputForm(payload.data, undefined, false, true),
|
...generateInputForm(payload.data ?? {}, undefined, false, true),
|
||||||
id: 'db8a4d10-0c47-4e27-b1a4-d0f2e1c15992',
|
id: 'db8a4d10-0c47-4e27-b1a4-d0f2e1c15992',
|
||||||
initApi: {
|
initApi: {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: `${commonInfo.baseAiUrl}/flow_task/input_data/\${id}`,
|
url: `${commonInfo.baseAiUrl}/flow_task/input_data/\${id}`,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
adaptor: (payload, response, api, context) => {
|
adaptor: (payload, response, api, context) => {
|
||||||
|
console.log(payload)
|
||||||
return {
|
return {
|
||||||
...payload,
|
...payload,
|
||||||
data: {
|
data: {
|
||||||
inputData: payload.data,
|
inputData: payload.data ?? {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ const FlowTaskAdd: React.FC = () => {
|
|||||||
input: '${inputData|default:undefined}',
|
input: '${inputData|default:undefined}',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
...generateInputForm(payload.data, undefined, false),
|
...generateInputForm(payload.data ?? {}, undefined, false),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user