feat(ai-web): 增加任务和任务模板

This commit is contained in:
2025-06-28 21:08:31 +08:00
parent 9a3375bd03
commit d08a6babbe
16 changed files with 720 additions and 22 deletions

View File

@@ -0,0 +1,93 @@
package com.lanyuanxiaoyao.service.ai.web.controller.task;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.ai.web.base.controller.SimpleControllerSupport;
import com.lanyuanxiaoyao.service.ai.web.base.entity.SimpleItem;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTaskTemplate;
import com.lanyuanxiaoyao.service.ai.web.service.task.FlowTaskService;
import com.lanyuanxiaoyao.service.ai.web.service.task.FlowTaskTemplateService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.Context;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("flow_task")
public class TaskController extends SimpleControllerSupport<FlowTask, TaskController.SaveItem, TaskController.ListItem, TaskController.DetailItem> {
private final FlowTaskTemplateService flowTaskTemplateService;
private final ObjectMapper mapper;
public TaskController(FlowTaskService flowTaskService, FlowTaskTemplateService flowTaskTemplateService, Jackson2ObjectMapperBuilder builder) {
super(flowTaskService);
this.flowTaskTemplateService = flowTaskTemplateService;
this.mapper = builder.build();
}
@Override
protected SaveItemMapper<FlowTask, SaveItem> saveItemMapper() {
return item -> {
FlowTask task = new FlowTask();
FlowTaskTemplate template = flowTaskTemplateService.detailOrThrow(item.getTemplateId());
task.setTemplate(template);
task.setInput(mapper.writeValueAsString(item.getInput()));
return task;
};
}
@Override
protected ListItemMapper<FlowTask, ListItem> listItemMapper() {
ListItem.Mapper map = Mappers.getMapper(ListItem.Mapper.class);
return task -> map.from(task, mapper);
}
@Override
protected DetailItemMapper<FlowTask, DetailItem> detailItemMapper() {
DetailItem.Mapper map = Mappers.getMapper(DetailItem.Mapper.class);
return task -> map.from(task, mapper);
}
@Data
public static final class SaveItem {
private Long templateId;
private Object input;
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class ListItem extends SimpleItem {
private Long templateId;
private Object input;
private FlowTask.Status status;
@org.mapstruct.Mapper
public static abstract class Mapper {
@Mapping(target = "templateId", source = "task.template.id")
public abstract ListItem from(FlowTask task, @Context ObjectMapper mapper) throws JsonProcessingException;
protected Object mapInput(String input, @Context ObjectMapper mapper) throws JsonProcessingException {
return mapper.readValue(input, Object.class);
}
}
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class DetailItem extends ListItem {
private String error;
private String result;
@org.mapstruct.Mapper
public static abstract class Mapper extends ListItem.Mapper {
@Mapping(target = "templateId", source = "task.template.id")
public abstract DetailItem from(FlowTask task, @Context ObjectMapper mapper) throws JsonProcessingException;
}
}
}

View File

@@ -0,0 +1,72 @@
package com.lanyuanxiaoyao.service.ai.web.controller.task;
import com.lanyuanxiaoyao.service.ai.web.base.controller.SimpleControllerSupport;
import com.lanyuanxiaoyao.service.ai.web.base.entity.SimpleItem;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTaskTemplate;
import com.lanyuanxiaoyao.service.ai.web.service.task.FlowTaskTemplateService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.mapstruct.factory.Mappers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("flow_task/template")
public class TaskTemplateController extends SimpleControllerSupport<FlowTaskTemplate, TaskTemplateController.SaveItem, TaskTemplateController.ListItem, TaskTemplateController.DetailItem> {
public TaskTemplateController(FlowTaskTemplateService flowTaskTemplateService) {
super(flowTaskTemplateService);
}
@Override
protected SaveItemMapper<FlowTaskTemplate, SaveItem> saveItemMapper() {
return Mappers.getMapper(SaveItem.Mapper.class);
}
@Override
protected ListItemMapper<FlowTaskTemplate, ListItem> listItemMapper() {
return Mappers.getMapper(ListItem.Mapper.class);
}
@Override
protected DetailItemMapper<FlowTaskTemplate, DetailItem> detailItemMapper() {
return Mappers.getMapper(DetailItem.Mapper.class);
}
@Data
public static final class SaveItem {
private String name;
private String description;
private String inputSchema;
private String flow;
@org.mapstruct.Mapper
public interface Mapper extends SaveItemMapper<FlowTaskTemplate, SaveItem> {
}
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class ListItem extends SimpleItem {
private String name;
private String description;
@org.mapstruct.Mapper
public interface Mapper extends ListItemMapper<FlowTaskTemplate, ListItem> {
}
}
@Data
@EqualsAndHashCode(callSuper = true)
public static class DetailItem extends SimpleItem {
private String name;
private String description;
private String inputSchema;
private String flow;
@org.mapstruct.Mapper
public interface Mapper extends DetailItemMapper<FlowTaskTemplate, DetailItem> {
}
}
}

View File

@@ -0,0 +1,44 @@
package com.lanyuanxiaoyao.service.ai.web.entity;
import com.lanyuanxiaoyao.service.ai.web.base.entity.SimpleEntity;
import com.lanyuanxiaoyao.service.common.Constants;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Getter
@Setter
@ToString
@Entity
@DynamicUpdate
@EntityListeners(AuditingEntityListener.class)
@Table(catalog = Constants.DATABASE_NAME, name = "service_ai_flow_task")
public class FlowTask extends SimpleEntity {
@ManyToOne
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private FlowTaskTemplate template;
@Column(columnDefinition = "longtext")
private String input;
@Column(nullable = false)
private Status status = Status.RUNNING;
@Column(columnDefinition = "longtext")
private String error;
@Column(columnDefinition = "longtext")
private String result;
public enum Status {
RUNNING,
ERROR,
FINISHED,
}
}

View File

@@ -0,0 +1,32 @@
package com.lanyuanxiaoyao.service.ai.web.entity;
import com.lanyuanxiaoyao.service.ai.web.base.entity.SimpleEntity;
import com.lanyuanxiaoyao.service.common.Constants;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.DynamicUpdate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Getter
@Setter
@ToString
@Entity
@DynamicUpdate
@EntityListeners(AuditingEntityListener.class)
@Table(catalog = Constants.DATABASE_NAME, name = "service_ai_flow_task_template")
public class FlowTaskTemplate extends SimpleEntity {
@Column(nullable = false)
private String name;
private String description;
@Column(nullable = false, columnDefinition = "longtext")
private String inputSchema;
@Column(nullable = false, columnDefinition = "text")
private String flow;
@Column(columnDefinition = "longtext")
private String flowGraph;
}

View File

@@ -0,0 +1,9 @@
package com.lanyuanxiaoyao.service.ai.web.repository;
import com.lanyuanxiaoyao.service.ai.web.base.repository.SimpleRepository;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
import org.springframework.stereotype.Repository;
@Repository
public interface FlowTaskRepository extends SimpleRepository<FlowTask, Long> {
}

View File

@@ -0,0 +1,9 @@
package com.lanyuanxiaoyao.service.ai.web.repository;
import com.lanyuanxiaoyao.service.ai.web.base.repository.SimpleRepository;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTaskTemplate;
import org.springframework.stereotype.Repository;
@Repository
public interface FlowTaskTemplateRepository extends SimpleRepository<FlowTaskTemplate, Long> {
}

View File

@@ -15,7 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
public class FeedbackService extends SimpleServiceSupport<Feedback> {
public class FeedbackService extends SimpleServiceSupport<Feedback> {
private final FlowExecutor executor;
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")

View File

@@ -0,0 +1,15 @@
package com.lanyuanxiaoyao.service.ai.web.service.task;
import com.lanyuanxiaoyao.service.ai.web.base.service.SimpleServiceSupport;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTask;
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class FlowTaskService extends SimpleServiceSupport<FlowTask> {
public FlowTaskService(FlowTaskRepository flowTaskRepository) {
super(flowTaskRepository);
}
}

View File

@@ -0,0 +1,15 @@
package com.lanyuanxiaoyao.service.ai.web.service.task;
import com.lanyuanxiaoyao.service.ai.web.base.service.SimpleServiceSupport;
import com.lanyuanxiaoyao.service.ai.web.entity.FlowTaskTemplate;
import com.lanyuanxiaoyao.service.ai.web.repository.FlowTaskTemplateRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class FlowTaskTemplateService extends SimpleServiceSupport<FlowTaskTemplate> {
public FlowTaskTemplateService(FlowTaskTemplateRepository flowTaskTemplateRepository) {
super(flowTaskTemplateRepository);
}
}

View File

@@ -1,11 +1,8 @@
server:
port: 8080
compression:
enabled: true
spring:
application:
name: service-ai-web
profiles:
include: random-port,common,discovery,metrics,forest
mvc:
async:
request-timeout: 3600000
@@ -21,27 +18,44 @@ spring:
ai:
vectorstore:
qdrant:
host: 132.121.206.65
port: 29463
api-key: ENC(0/0UkIKeAvyV17yNqSU3v04wmm8CdWKe4BYSSJa2FuBtK12TcZRJPdwk+ZpYnpISv+KmVTUrrmFBzAYrDR3ysA==)
host: 192.168.100.140
port: 6334
llm:
base-url: http://132.121.206.65:10086
api-key: ENC(K+Hff9QGC+fcyi510VIDd9CaeK/IN5WBJ9rlkUsHEdDgIidW+stHHJlsK0lLPUXXREha+ToQZqqDXJrqSE+GUKCXklFhelD8bRHFXBIeP/ZzT2cxhzgKUXgjw3S0Qw2R)
base-url: https://api.siliconflow.cn
api-key: sk-xrguybusoqndpqvgzgvllddzgjamksuecyqdaygdwnrnqfwo
chat:
base-url: ${spring.llm.base-url}/v1
model: 'Qwen3/qwen3-1.7b'
model: 'Qwen/Qwen3-8B'
visual:
model: 'Qwen2.5/qwen2.5-vl-7b-q4km'
base-url: https://open.bigmodel.cn/api/paas/v4
endpoint: /chat/completions
model: 'glm-4v-flash'
embedding:
model: 'Qwen3/qwen3-embedding-4b'
model: 'BAAI/bge-m3'
reranker:
model: 'BGE/beg-reranker-v2'
model: 'BAAI/bge-reranker-v2-m3'
cloud:
discovery:
enabled: false
zookeeper:
enabled: false
datasource:
url: jdbc:mysql://192.168.100.140:3306/hudi_collect_build_b12?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: rootless
driver-class-name: com.mysql.cj.jdbc.Driver
security:
meta:
authority: ENC(GXKnbq1LS11U2HaONspvH+D/TkIx13aWTaokdkzaF7HSvq6Z0Rv1+JUWFnYopVXu)
username: ENC(moIO5mO39V1Z+RDwROK9JXY4GfM8ZjDgM6Si7wRZ1MPVjbhTpmLz3lz28rAiw7c2LeCmizfJzHkEXIwGlB280g==)
darkcode: ENC(0jzpQ7T6S+P7bZrENgYsUoLhlqGvw7DA2MN3BRqEOwq7plhtg72vuuiPQNnr3DaYz0CpyTvxInhpx11W3VZ1trD6NINh7O3LN70ZqO5pWXk=)
jpa:
show-sql: true
generate-ddl: false
generate-ddl: true
jasypt:
encryptor:
password: 'r#(R,P"Dp^A47>WSn:Wn].gs/+"v:q_Q*An~zF*g-@j@jtSTv5H/,S-3:R?r9R}.'
fenix:
print-banner: false
liteflow:
rule-source: liteflow.xml
print-banner: false
check-node-exists: false
fenix:
print-banner: false