diff --git a/metis-starter/src/main/java/com/metis/config/DateFormatterEnum.java b/metis-starter/src/main/java/com/metis/config/DateFormatterEnum.java new file mode 100644 index 0000000..1d76534 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/config/DateFormatterEnum.java @@ -0,0 +1,43 @@ +package com.metis.config; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.stream.Stream; + +@Getter +@AllArgsConstructor +public enum DateFormatterEnum { + + /** + * 时间格式 + */ + COMMON_DATE_TIME(0, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault())), + COMMON_SHORT_DATE(1, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneId.systemDefault())), + COMMON_MONTH_DAY(2, DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault())), + COMMON_MONTH(3, DateTimeFormatter.ofPattern("yyyy-MM").withZone(ZoneId.systemDefault())), + YEAR(4, DateTimeFormatter.ofPattern("yyyy").withZone(ZoneId.systemDefault())), + COLON_DELIMITED_TIME(5, DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault())), + COLON_DELIMITED_SHORT_TIME(6, DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault())), + CHINESE_DATE_TIME(7, DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒").withZone(ZoneId.systemDefault())), + CHINESE_SHORT_DATE(8, DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分").withZone(ZoneId.systemDefault())), + CHINESE_DATE(9, DateTimeFormatter.ofPattern("yyyy年MM月dd日").withZone(ZoneId.systemDefault())), + CHINESE_MONTH(10, DateTimeFormatter.ofPattern("yyyy年MM月").withZone(ZoneId.systemDefault())), + CHINESE_YEAR(11, DateTimeFormatter.ofPattern("yyyy年").withZone(ZoneId.systemDefault())), + CHINESE_TIME(12, DateTimeFormatter.ofPattern("HH时mm分ss秒").withZone(ZoneId.systemDefault())), + CHINESE_SHORT_TIME(13, DateTimeFormatter.ofPattern("HH时mm分").withZone(ZoneId.systemDefault())); + + private final Integer code; + private final DateTimeFormatter dateTimeFormatter; + + + public static DateFormatterEnum findByCode(int code){ + return Stream.of(values()) + .filter(e -> e.getCode().equals(code)) + .findAny() + .orElse(null); + } + +} \ No newline at end of file diff --git a/metis-starter/src/main/java/com/metis/config/JacksonAutoConfiguration.java b/metis-starter/src/main/java/com/metis/config/JacksonAutoConfiguration.java new file mode 100644 index 0000000..ec172d9 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/config/JacksonAutoConfiguration.java @@ -0,0 +1,144 @@ +package com.metis.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.json.JsonReadFeature; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; +import lombok.AllArgsConstructor; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.core.annotation.Order; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.Locale; +import java.util.TimeZone; + +/** + * 杰克逊自动配置 + * + * @author clay + * @date 2025/04/26 + */ +@Order(Integer.MIN_VALUE) +@AutoConfiguration +@AllArgsConstructor +@ConditionalOnClass(ObjectMapper.class) +@AutoConfigureBefore(org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class) +public class JacksonAutoConfiguration { + + /** + * Jackson2ObjectMapperBuilder + * + * @return {@link Jackson2ObjectMapperBuilder} + */ + @Bean + @Primary + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); + builder.locale(Locale.CHINA); + builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault())); + + //时间类型支持 + JavaTimeModule javaTimeModule = buildJavaTimeModule(); + //其他类型支持 + SimpleModule simpleModule = buildSimpleModule(); + + builder.modules(javaTimeModule,simpleModule); + return builder; + } + + /** + * ObjectMapper + * + * @param builder 建设者 + * @return {@link ObjectMapper} + */ + @Bean + @Primary + public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { + ObjectMapper objectMapper = builder.createXmlMapper(false).build(); + objectMapper.findAndRegisterModules(); + + // 其他配置 +// objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true); + objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + objectMapper.configure(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature(), true); + objectMapper.configure(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION, true); + //开启整数反序列化时使用长整型(long)的选项。确保处理的数据不会因类型限制丢失信息 + objectMapper.configure(DeserializationFeature.USE_LONG_FOR_INTS, true); + //开启输出缩进功能。这通常用于美化JSON格式输出,使结构更清晰易读 + objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); + //禁用报错 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + + return objectMapper; + } + + /** + * 构建简单模块 + * + * @return {@link SimpleModule} + */ + private SimpleModule buildSimpleModule() { + SimpleModule simpleModule = new SimpleModule(); + + //BigInteger + simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + simpleModule.addDeserializer(BigInteger.class, new NumberDeserializers.BigIntegerDeserializer()); + + //Long + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + simpleModule.addDeserializer(Long.class, new NumberDeserializers.LongDeserializer(Long.class, null)); + + //BigDecimal + simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + simpleModule.addDeserializer(BigDecimal.class, new NumberDeserializers.BigDecimalDeserializer()); + + return simpleModule; + } + + /** + * 构建Java时间模块 + * + * @return {@link JavaTimeModule} + */ + private JavaTimeModule buildJavaTimeModule() { + // 添加自定义序列化和反序列化器 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateFormatterEnum.COMMON_DATE_TIME.getDateTimeFormatter())); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateFormatterEnum.COMMON_DATE_TIME.getDateTimeFormatter())); + + javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateFormatterEnum.COMMON_MONTH_DAY.getDateTimeFormatter())); + javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateFormatterEnum.COLON_DELIMITED_TIME.getDateTimeFormatter())); + javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateFormatterEnum.COMMON_MONTH_DAY.getDateTimeFormatter())); + javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateFormatterEnum.COLON_DELIMITED_TIME.getDateTimeFormatter())); + + //不提供 java.util.Date 的序列化处理,全项目禁用 java.util.Date 类 + return javaTimeModule; + } + + +} diff --git a/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java b/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java new file mode 100644 index 0000000..e2f1480 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/convert/ModelPlatformConvert.java @@ -0,0 +1,16 @@ +package com.metis.convert; + +import com.metis.domain.entity.ModelPlatform; +import com.metis.domain.entity.ModelPlatformInfo; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface ModelPlatformConvert { + + ModelPlatformConvert INSTANCE = Mappers.getMapper(ModelPlatformConvert.class); + + ModelPlatformInfo toInfo(ModelPlatform modelPlatform); + + +} diff --git a/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java new file mode 100644 index 0000000..9a86841 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatform.java @@ -0,0 +1,64 @@ +package com.metis.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.metis.domain.SimpleBaseEntity; +import com.metis.enums.ModelTypeEnum; +import com.metis.enums.YesOrNoEnum; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * llm model平台 + * + * @author clay + * @date 2025/04/26 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("model_platform") +public class ModelPlatform extends SimpleBaseEntity { + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.ASSIGN_ID) + private Long id; + + /** + * 名字 + */ + private String name; + + /** + * 类型 + */ + private ModelTypeEnum type; + + /** + * 自定义类型 + */ + private String customType; + + /** + * 请求地址 + */ + private String url; + + /** + * api密匙 + */ + private String apiKey; + + /** + * 状态 + */ + private YesOrNoEnum state; + + /** + * 描述 + */ + private String description; + +} diff --git a/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatformInfo.java b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatformInfo.java new file mode 100644 index 0000000..37c424a --- /dev/null +++ b/metis-starter/src/main/java/com/metis/domain/entity/ModelPlatformInfo.java @@ -0,0 +1,28 @@ +package com.metis.domain.entity; + +import com.metis.enums.ModelTypeEnum; +import lombok.Data; + +@Data +public class ModelPlatformInfo { + + /** + * 名字 + */ + private String name; + + /** + * 类型 + */ + private ModelTypeEnum type; + + /** + * 请求地址 + */ + private String url; + + /** + * api密匙 + */ + private String apiKey; +} diff --git a/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java b/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java new file mode 100644 index 0000000..ee0f8cd --- /dev/null +++ b/metis-starter/src/main/java/com/metis/domain/entity/base/Model.java @@ -0,0 +1,12 @@ +package com.metis.domain.entity.base; + +import lombok.Data; + +@Data +public class Model { + + + private String name; + + +} diff --git a/metis-starter/src/main/java/com/metis/enums/ModelTypeEnum.java b/metis-starter/src/main/java/com/metis/enums/ModelTypeEnum.java new file mode 100644 index 0000000..b449fa1 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/enums/ModelTypeEnum.java @@ -0,0 +1,51 @@ +package com.metis.enums; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Optional; + +/** + * llm 类型 枚举 + * + * @author clay + * @date 2025/04/26 + */ +@Getter +@AllArgsConstructor +public enum ModelTypeEnum implements BaseEnum { + CUSTOM(0, "自定义"), + OPEN_AI(1, "OpenAI"), + OLLAMA(2, "Ollama"), + + ; + + + @JsonValue + private final Integer code; + private final String name; + + /** + * 根据 code 转换枚举 + * + * @param code 编码 + * @return 枚举 + */ + public static Optional of(Integer code) { + return Optional.ofNullable(BaseEnum.parseByCode(ModelTypeEnum.class, code)); + } + + /** + * 枚举序列化器(前端传code时自动转换为对应枚举) + * + * @param code 编码 + * @return 枚举 + */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ModelTypeEnum get(Integer code) { + return BaseEnum.parseByCode(ModelTypeEnum.class, code); + } + +} diff --git a/metis-starter/src/main/java/com/metis/llm/ModelService.java b/metis-starter/src/main/java/com/metis/llm/ModelService.java new file mode 100644 index 0000000..879d943 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/llm/ModelService.java @@ -0,0 +1,19 @@ +package com.metis.llm; + +import com.metis.domain.entity.base.Model; + +import java.util.List; + +public interface ModelService { + + + /** + * 列表 + * + * @param modelId llm id + * @return {@link List }<{@link Model }> + */ + List listModel(Long modelId); + + +} diff --git a/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java b/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java new file mode 100644 index 0000000..e7dbf54 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/llm/PlatformModeList.java @@ -0,0 +1,23 @@ +package com.metis.llm; + +import com.metis.domain.entity.ModelPlatform; +import com.metis.domain.entity.base.Model; +import com.metis.enums.ModelTypeEnum; + +import java.util.List; + +public interface PlatformModeList { + + + List modelList(ModelPlatform modelPlatform); + + + /** + * 得到类型 + * + * @return {@link ModelTypeEnum } + */ + ModelTypeEnum getType(); + + +} diff --git a/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java b/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java new file mode 100644 index 0000000..9224ace --- /dev/null +++ b/metis-starter/src/main/java/com/metis/llm/impl/ModelServiceImpl.java @@ -0,0 +1,31 @@ +package com.metis.llm.impl; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import com.metis.domain.entity.ModelPlatform; +import com.metis.domain.entity.base.Model; +import com.metis.llm.ModelService; +import com.metis.service.ModelPlatformService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ModelServiceImpl implements ModelService { + + private final ModelPlatformService modelPlatformService; + + + @Override + public List listModel(Long modelId) { + Assert.isTrue(ObjectUtil.isNotNull(modelId), "模型平台ID不能为空"); + ModelPlatform modelPlatform = modelPlatformService.getById(modelId); + Assert.isTrue(ObjectUtil.isNotNull(modelPlatform), "模型平台不存在"); + + return List.of(); + } +} diff --git a/metis-starter/src/main/java/com/metis/mapper/ModelPlatformMapper.java b/metis-starter/src/main/java/com/metis/mapper/ModelPlatformMapper.java new file mode 100644 index 0000000..260d311 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/mapper/ModelPlatformMapper.java @@ -0,0 +1,18 @@ +package com.metis.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.metis.domain.entity.ModelPlatform; + +/** + * LLM模型平台映射器 + * + * @author clay + * @date 2025/04/26 + */ +public interface ModelPlatformMapper extends BaseMapper { + +} + + + + diff --git a/metis-starter/src/main/java/com/metis/service/ModelPlatformService.java b/metis-starter/src/main/java/com/metis/service/ModelPlatformService.java new file mode 100644 index 0000000..e1ad1f6 --- /dev/null +++ b/metis-starter/src/main/java/com/metis/service/ModelPlatformService.java @@ -0,0 +1,14 @@ +package com.metis.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.metis.domain.entity.ModelPlatform; + +/** + * LLM模型平台服务 + * + * @author clay + * @date 2025/04/26 + */ +public interface ModelPlatformService extends IService { + +} diff --git a/metis-starter/src/main/java/com/metis/service/impl/ModelPlatformServiceImpl.java b/metis-starter/src/main/java/com/metis/service/impl/ModelPlatformServiceImpl.java new file mode 100644 index 0000000..2e8cb6c --- /dev/null +++ b/metis-starter/src/main/java/com/metis/service/impl/ModelPlatformServiceImpl.java @@ -0,0 +1,25 @@ +package com.metis.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.metis.domain.entity.ModelPlatform; +import com.metis.mapper.ModelPlatformMapper; +import com.metis.service.ModelPlatformService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * LLM模型平台服务实现 + * + * @author clay + * @date 2025/04/26 + */ +@Slf4j +@Service +public class ModelPlatformServiceImpl extends ServiceImpl + implements ModelPlatformService { + +} + + + +