refactor(ai-web): 优化inputSchema可以为空,方便各处判断流程是否有入参

This commit is contained in:
2025-07-21 00:05:28 +08:00
parent 267eecbf45
commit 1e3e14c590
11 changed files with 43 additions and 24 deletions

View File

@@ -45,7 +45,7 @@ create table hudi_collect_build_b12.service_ai_flow_task
status enum ('ERROR','FINISHED','RUNNING') not null comment '任务运行状态',
template_description varchar(255) 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 '任务对应的模板名称',
primary key (id)
) comment ='流程任务记录' charset = utf8mb4;
@@ -57,7 +57,7 @@ create table hudi_collect_build_b12.service_ai_flow_task_template
modified_time datetime(6) comment '记录更新时间',
description varchar(255) 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 '模板名称',
primary key (id)
) comment ='流程任务模板' charset = utf8mb4;

View File

@@ -1,5 +1,7 @@
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.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
@@ -14,6 +16,7 @@ import java.util.Map;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.bind.annotation.GetMapping;
@@ -39,12 +42,18 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
@GetMapping("input_data/{id}")
public AmisResponse<?> getInputData(@PathVariable("id") Long id) throws JsonProcessingException {
var task = flowTaskService.detailOrThrow(id);
if (ObjectUtil.isEmpty(task.getInput())) {
return AmisResponse.responseSuccess();
}
return AmisResponse.responseSuccess(mapper.readValue(task.getInput(), Map.class));
}
@GetMapping("input_schema/{id}")
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
var task = flowTaskService.detailOrThrow(id);
if (ObjectUtil.isEmpty(task.getTemplateInputSchema())) {
return AmisResponse.responseSuccess();
}
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.setTemplateInputSchema(template.getInputSchema());
task.setTemplateFlowGraph(template.getFlowGraph());
task.setInput(mapper.writeValueAsString(item.getInput()));
task.setInput(ObjectUtil.isEmpty(item.getInput()) ? null : mapper.writeValueAsString(item.getInput()));
return task;
};
}
@@ -91,9 +100,13 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
public static class ListItem extends SimpleItem {
private String templateName;
private FlowTask.Status status;
private Boolean hasInput;
@org.mapstruct.Mapper
@org.mapstruct.Mapper(imports = {
StrUtil.class
})
public static abstract class Mapper {
@Mapping(target = "hasInput", expression = "java(StrUtil.isNotBlank(task.getInput()))")
public abstract ListItem from(FlowTask task);
}
}
@@ -104,8 +117,11 @@ public class TaskController extends SimpleControllerSupport<FlowTask, TaskContro
private String error;
private String result;
@org.mapstruct.Mapper
@org.mapstruct.Mapper(imports = {
StrUtil.class
})
public static abstract class Mapper extends ListItem.Mapper {
@Mapping(target = "hasInput", expression = "java(StrUtil.isNotBlank(task.getInput()))")
public abstract DetailItem from(FlowTask task);
}
}

View File

@@ -39,6 +39,9 @@ public class TaskTemplateController extends SimpleControllerSupport<FlowTaskTemp
@GetMapping("input_schema/{id}")
public AmisResponse<?> getInputSchema(@PathVariable("id") Long id) throws JsonProcessingException {
var template = flowTaskTemplateService.detailOrThrow(id);
if (ObjectUtil.isEmpty(template.getInputSchema())) {
return AmisResponse.responseSuccess();
}
return AmisResponse.responseSuccess(mapper.readValue(template.getInputSchema(), Map.class));
}

View File

@@ -1,6 +1,7 @@
package com.lanyuanxiaoyao.service.ai.web.engine.node;
import com.lanyuanxiaoyao.service.ai.web.engine.FlowNodeRunner;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
/**
@@ -9,8 +10,16 @@ import lombok.extern.slf4j.Slf4j;
*/
@Slf4j
public class InputNode extends FlowNodeRunner {
public static final String KEY = "flow_inputs";
@Override
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));
}
}
}
}

View File

@@ -16,7 +16,6 @@ public class LlmNode extends FlowNodeRunner {
@Override
public void run() {
var variableMap = FlowHelper.generateInputVariablesMap(getNodeId(), getContext());
log.info("Variable map: {}", variableMap);
var sourcePrompt = (String) getData("systemPrompt");
if (StrUtil.isNotBlank(sourcePrompt)) {
var prompt = FlowHelper.renderTemplateText(sourcePrompt, variableMap.toMap());

View File

@@ -32,7 +32,7 @@ public class FlowTask extends SimpleEntity {
@Comment("任务对应的模板功能、内容说明")
private String templateDescription;
@Comment("任务对应的模板入参Schema")
@Column(nullable = false, columnDefinition = "longtext")
@Column(columnDefinition = "longtext")
private String templateInputSchema;
@Comment("任务对应的模板前端流程图数据")
@Column(nullable = false, columnDefinition = "longtext")

View File

@@ -28,7 +28,7 @@ public class FlowTaskTemplate extends SimpleEntity {
@Comment("模板功能、内容说明")
private String description;
@Comment("模板入参Schema")
@Column(nullable = false, columnDefinition = "longtext")
@Column(columnDefinition = "longtext")
private String inputSchema;
@Comment("前端流程图数据")
@Column(nullable = false, columnDefinition = "longtext")

View File

@@ -2,7 +2,6 @@ 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;
@@ -57,15 +56,8 @@ public class FlowTaskService extends SimpleServiceSupport<FlowTask> {
FlowContext context = new FlowContext();
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<>() {
if (ObjectUtil.isNotEmpty(flowTask.getInput())) {
context.getData().put(InputNode.KEY, mapper.readValue(flowTask.getInput(), new TypeReference<>() {
}));
}

View File

@@ -38,8 +38,6 @@ public class FlowTaskTemplateService extends SimpleServiceSupport<FlowTaskTempla
if (ObjectUtil.isNotNull(nodeData) && nodeData.containsKey("inputs")) {
template.setInputSchema(mapper.writeValueAsString(nodeData.get("inputs")));
}
} else {
template.setInputSchema("{}");
}
template.setFlowGraph(flowGraph);

View File

@@ -87,6 +87,7 @@ const FlowTask: React.FC = () => {
width: 200,
buttons: [
{
visibleOn: 'hasInput',
type: 'action',
label: '查看',
level: 'link',
@@ -107,17 +108,18 @@ const FlowTask: React.FC = () => {
return {
...payload,
data: {
...generateInputForm(payload.data, undefined, false, true),
...generateInputForm(payload.data ?? {}, undefined, false, true),
id: 'db8a4d10-0c47-4e27-b1a4-d0f2e1c15992',
initApi: {
method: 'get',
url: `${commonInfo.baseAiUrl}/flow_task/input_data/\${id}`,
// @ts-ignore
adaptor: (payload, response, api, context) => {
console.log(payload)
return {
...payload,
data: {
inputData: payload.data,
inputData: payload.data ?? {},
},
}
},

View File

@@ -159,7 +159,7 @@ const FlowTaskAdd: React.FC = () => {
input: '${inputData|default:undefined}',
}
},
...generateInputForm(payload.data, undefined, false),
...generateInputForm(payload.data ?? {}, undefined, false),
},
}
},