refactor: rename artifactId and application name to 'datamate'; add model configuration and related services (#26)

This commit is contained in:
Dallas98
2025-10-28 10:39:26 +08:00
committed by GitHub
parent 7f819563db
commit f54afddbeb
32 changed files with 520 additions and 20 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@@ -6,11 +6,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>DataMatePlatform</name>
<name>DataMate</name>
<description>一站式数据工作平台,面向模型微调与RAG检索</description>
<properties>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -1,7 +1,7 @@
# 数据引擎平台 - 主应用配置
spring:
application:
name: data-mate-platform
name: datamate
# 暂时排除Spring Security自动配置(开发阶段使用)
autoconfigure:

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@@ -33,5 +33,10 @@
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,23 @@
package com.datamate.common.infrastructure.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 知识库错误码
*
* @author dallas
* @since 2025-10-24
*/
@Getter
@AllArgsConstructor
public enum KnowledgeBaseErrorCode implements ErrorCode {
/**
* 知识库不存在
*/
KNOWLEDGE_BASE_NOT_FOUND("knowledge.0001", "知识库不存在");
private final String code;
private final String message;
}

View File

@@ -0,0 +1,85 @@
package com.datamate.common.models.application;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.datamate.common.infrastructure.exception.BusinessAssert;
import com.datamate.common.interfaces.PagedResponse;
import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.domain.repository.ModelConfigRepository;
import com.datamate.common.models.infrastructure.client.ModelClient;
import com.datamate.common.models.infrastructure.exception.ModelsErrorCode;
import com.datamate.common.models.interfaces.rest.dto.CreateModelRequest;
import com.datamate.common.models.interfaces.rest.dto.QueryModelRequest;
import dev.langchain4j.model.chat.ChatModel;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 模型配置应用服务类
*
* @author dallas
* @since 2025-10-27
*/
@Service
@RequiredArgsConstructor
public class ModelConfigApplicationService {
private final ModelConfigRepository modelConfigRepository;
public List<ModelConfig> getProviders() {
List<ModelConfig> providers = new ArrayList<>();
providers.add(ModelConfig.builder().provider("ModelEngine").baseUrl("http://localhost:9981").build());
providers.add(ModelConfig.builder().provider("Ollama").baseUrl("http://localhost:11434").build());
providers.add(ModelConfig.builder().provider("OpenAI").baseUrl("https://api.openai.com/v1").build());
providers.add(ModelConfig.builder().provider("DeepSeek").baseUrl("https://api.deepseek.cn/v1").build());
providers.add(ModelConfig.builder().provider("火山方舟").baseUrl("https://ark.cn-beijing.volces.com/api/v3").build());
providers.add(ModelConfig.builder().provider("阿里云百炼").baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1").build());
providers.add(ModelConfig.builder().provider("硅基流动").baseUrl("https://api.siliconflow.cn/v1").build());
providers.add(ModelConfig.builder().provider("智谱AI").baseUrl("https://open.bigmodel.cn/api/paas/v4").build());
return providers;
}
public PagedResponse<ModelConfig> getModels(QueryModelRequest queryModelRequest) {
// 从数据库查询模型配置
IPage<ModelConfig> page = modelConfigRepository.page(queryModelRequest);
return PagedResponse.of(page.getRecords(), page.getCurrent(), page.getTotal(), page.getPages());
}
public ModelConfig getModelDetail(String modelId) {
return modelConfigRepository.getById(modelId);
}
public ModelConfig createModel(CreateModelRequest modelConfig) {
ModelConfig newConfig = ModelConfig.builder()
.provider(modelConfig.getProvider())
.modelName(modelConfig.getModelName())
.type(modelConfig.getType())
.baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey())
.isEnabled(true)
.build();
ModelClient.checkHealth(newConfig);
modelConfigRepository.save(newConfig);
return newConfig;
}
public ModelConfig updateModel(String modelId, @Valid CreateModelRequest updateModelRequest) {
ModelConfig modelConfig = modelConfigRepository.getById(modelId);
BusinessAssert.notNull(modelConfig, ModelsErrorCode.MODEL_CONFIG_NOT_FOUND);
modelConfig.setProvider(updateModelRequest.getProvider());
modelConfig.setModelName(updateModelRequest.getModelName());
modelConfig.setType(updateModelRequest.getType());
modelConfig.setBaseUrl(updateModelRequest.getBaseUrl());
modelConfig.setApiKey(updateModelRequest.getApiKey());
modelConfig.setIsEnabled(true);
ModelClient.checkHealth(modelConfig);
modelConfigRepository.updateById(modelConfig);
return modelConfig;
}
public void deleteModel(String modelId) {
modelConfigRepository.removeById(modelId);
}
}

View File

@@ -0,0 +1,44 @@
package com.datamate.common.models.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.datamate.common.domain.model.base.BaseEntity;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
/**
* 模型配置实体类
*
* @author dallas
* @since 2025-10-27
*/
@Getter
@Setter
@TableName("t_model_config")
@Builder
public class ModelConfig extends BaseEntity<String> {
/**
* 模型名称(如 qwen2)
*/
private String modelName;
/**
* 模型提供商(如 Ollama、OpenAI、DeepSeek)
*/
private String provider;
/**
* API 基础地址
*/
private String baseUrl;
/**
* API 密钥(无密钥则为空)
*/
private String apiKey;
/**
* 模型类型(如 chat、embedding)
*/
private ModelType type;
/**
* 是否启用:1-启用,0-禁用
*/
private Boolean isEnabled;
}

View File

@@ -0,0 +1,18 @@
package com.datamate.common.models.domain.entity;
/**
* 模型类型枚举类
*
* @author dallas
* @since 2025-10-27
*/
public enum ModelType {
/**
* 语言模型
*/
CHAT,
/**
* 嵌入模型
*/
EMBEDDING
}

View File

@@ -0,0 +1,22 @@
package com.datamate.common.models.domain.repository;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.repository.IRepository;
import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.interfaces.rest.dto.QueryModelRequest;
/**
* 模型配置仓库接口
*
* @author dallas
* @since 2025-10-27
*/
public interface ModelConfigRepository extends IRepository<ModelConfig> {
/**
* 分页查询模型配置
*
* @param queryModelRequest 分页查询参数
* @return 模型配置列表
*/
IPage<ModelConfig> page(QueryModelRequest queryModelRequest);
}

View File

@@ -0,0 +1,44 @@
package com.datamate.common.models.infrastructure.client;
import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.domain.entity.ModelType;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import java.util.function.Consumer;
/**
* 模型客户端接口
*
* @author dallas
* @since 2025-10-27
*/
public class ModelClient {
public static <T> T invokeModel(ModelConfig modelConfig, Class<T> modelInterface) {
return switch (modelConfig.getType()) {
case CHAT -> modelInterface.cast(invokeChatModel(modelConfig));
case EMBEDDING -> modelInterface.cast(invokeEmbeddingModel(modelConfig));
};
}
private static EmbeddingModel invokeEmbeddingModel(ModelConfig modelConfig) {
return OpenAiEmbeddingModel.builder()
.baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey())
.modelName(modelConfig.getModelName())
.build();
}
private static ChatModel invokeChatModel(ModelConfig modelConfig) {
return OpenAiChatModel.builder()
.baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey())
.modelName(modelConfig.getModelName())
.build();
}
public static void checkHealth(ModelConfig modelConfig) {
}
}

View File

@@ -0,0 +1,27 @@
package com.datamate.common.models.infrastructure.exception;
import com.datamate.common.infrastructure.exception.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 模型配置错误码枚举类
*
* @author dallas
* @since 2025-10-27
*/
@Getter
@AllArgsConstructor
public enum ModelsErrorCode implements ErrorCode {
/**
* 模型配置不存在
*/
MODEL_CONFIG_NOT_FOUND("model.0001", "模型配置不存在"),
/**
* 模型配置已存在
*/
MODEL_CONFIG_ALREADY_EXISTS("model.0002", "模型配置已存在");
private final String code;
private final String message;
}

View File

@@ -0,0 +1,37 @@
package com.datamate.common.models.infrastructure.persistence.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.repository.CrudRepository;
import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.domain.repository.ModelConfigRepository;
import com.datamate.common.models.infrastructure.persistence.mapper.ModelConfigMapper;
import com.datamate.common.models.interfaces.rest.dto.QueryModelRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import java.util.Objects;
/**
* 模型配置仓库实现类
*
* @author dallas
* @since 2025-10-27
*/
@Repository
@RequiredArgsConstructor
public class ModelConfigRepositoryImpl extends CrudRepository<ModelConfigMapper, ModelConfig> implements ModelConfigRepository {
private final ModelConfigMapper modelConfigMapper;
@Override
public IPage<ModelConfig> page(QueryModelRequest queryModelRequest) {
IPage<ModelConfig> page = new Page<>(queryModelRequest.getPage(), queryModelRequest.getSize());
return this.page(page, new LambdaQueryWrapper<ModelConfig>()
.eq(StringUtils.hasText(queryModelRequest.getProvider()), ModelConfig::getProvider, queryModelRequest.getProvider())
.eq(Objects.nonNull(queryModelRequest.getType()), ModelConfig::getType, queryModelRequest.getType())
.eq(Objects.nonNull(queryModelRequest.getIsEnabled()), ModelConfig::getIsEnabled, queryModelRequest.getIsEnabled()));
}
}

View File

@@ -0,0 +1,15 @@
package com.datamate.common.models.infrastructure.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.datamate.common.models.domain.entity.ModelConfig;
import org.apache.ibatis.annotations.Mapper;
/**
* 模型配置映射器接口
*
* @author dallas
* @since 2025-10-27
*/
@Mapper
public interface ModelConfigMapper extends BaseMapper<ModelConfig> {
}

View File

@@ -0,0 +1,90 @@
package com.datamate.common.models.interfaces.rest;
import com.datamate.common.interfaces.PagedResponse;
import com.datamate.common.models.application.ModelConfigApplicationService;
import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.interfaces.rest.dto.CreateModelRequest;
import com.datamate.common.models.interfaces.rest.dto.QueryModelRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 模型配置控制器类
*
* @author dallas
* @since 2025-10-27
*/
@RestController
@RequestMapping("/api/models")
@RequiredArgsConstructor
public class ModelConfigController {
private final ModelConfigApplicationService modelConfigApplicationService;
/**
* 获取厂商列表
*
* @return 厂商列表
*/
@GetMapping("/providers")
public List<ModelConfig> getProviders() {
return modelConfigApplicationService.getProviders();
}
/**
* 获取模型列表
*
* @return 模型列表
*/
@GetMapping("/list")
public PagedResponse<ModelConfig> getModels(@RequestParam QueryModelRequest queryModelRequest) {
return modelConfigApplicationService.getModels(queryModelRequest);
}
/**
* 获取模型详情
*
* @param modelId 模型 ID
* @return 模型详情
*/
@GetMapping("/{modelId}")
public ModelConfig getModelDetail(@PathVariable String modelId) {
return modelConfigApplicationService.getModelDetail(modelId);
}
/**
* 创建模型配置
*
* @param createModelRequest 创建模型配置请求
* @return 创建的模型配置
*/
@PostMapping("/create")
public ModelConfig createModel(@RequestBody @Valid CreateModelRequest createModelRequest) {
return modelConfigApplicationService.createModel(createModelRequest);
}
/**
* 更新模型配置
*
* @param modelId 模型 ID
* @param updateModelRequest 更新模型配置请求
* @return 更新后的模型配置
*/
@PutMapping("/{modelId}")
public ModelConfig updateModel(@PathVariable String modelId, @RequestBody @Valid CreateModelRequest updateModelRequest) {
return modelConfigApplicationService.updateModel(modelId, updateModelRequest);
}
/**
* 删除模型配置
*
* @param modelId 模型 ID
*/
@DeleteMapping("/{modelId}")
public void deleteModel(@PathVariable String modelId) {
modelConfigApplicationService.deleteModel(modelId);
}
}

View File

@@ -0,0 +1,46 @@
package com.datamate.common.models.interfaces.rest.dto;
import com.datamate.common.models.domain.entity.ModelType;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
/**
* 创建模型配置请求类
*
* @author dallas
* @since 2025-10-27
*/
@Setter
@Getter
public class CreateModelRequest {
/**
* 模型名称(如 qwen2)
*/
@NotEmpty(message = "模型名称不能为空")
private String modelName;
/**
* 模型提供商(如 Ollama、OpenAI、DeepSeek)
*/
@NotEmpty(message = "模型提供商不能为空")
private String provider;
/**
* API 基础地址
*/
@NotEmpty(message = "API 基础地址不能为空")
private String baseUrl;
/**
* API 密钥(无密钥则为空)
*/
private String apiKey;
/**
* 模型类型(如 chat、embedding)
*/
@NotNull(message = "模型类型不能为空")
private ModelType type;
/**
* 是否启用:1-启用,0-禁用
*/
private Boolean isEnabled;
}

View File

@@ -0,0 +1,27 @@
package com.datamate.common.models.interfaces.rest.dto;
import com.datamate.common.interfaces.PagingQuery;
import com.datamate.common.models.domain.entity.ModelType;
import lombok.Getter;
import lombok.Setter;
/**
* 模型查询请求 DTO
*
* @author dallas
* @since 2025-10-27
*/
@Getter
@Setter
public class QueryModelRequest extends PagingQuery {
/**
* 模型提供商(如 Ollama、OpenAI、DeepSeek)
*/
private String provider;
/**
* 模型类型(如 chat、embedding)
*/
private ModelType type;
private Boolean isEnabled;
}

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>com.datamate</groupId>
<artifactId>data-mate-platform</artifactId>
<artifactId>datamate</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@@ -1,7 +1,7 @@
# 数据引擎平台 - 主应用配置
spring:
application:
name: data-mate-platform
name: datamate
# 暂时排除Spring Security自动配置(开发阶段使用)
autoconfigure:

View File

@@ -1,7 +1,7 @@
# 数据引擎平台 - 主应用配置
spring:
application:
name: data-mate-platform
name: datamate
# 暂时排除Spring Security自动配置(开发阶段使用)
autoconfigure:

View File

@@ -0,0 +1,17 @@
CREATE TABLE t_model_config
(
id VARCHAR(36) AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
model_name VARCHAR(100) NOT NULL COMMENT '模型名称(如 qwen2)',
provider VARCHAR(50) NOT NULL COMMENT '模型提供商(如 Ollama、OpenAI、DeepSeek)',
base_url VARCHAR(255) NOT NULL COMMENT 'API 基础地址',
api_key VARCHAR(255) DEFAULT '' COMMENT 'API 密钥(无密钥则为空)',
type VARCHAR(50) NOT NULL COMMENT '模型类型(如 chat、embedding)',
is_enabled TINYINT DEFAULT 1 COMMENT '是否启用:1-启用,0-禁用',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
created_by VARCHAR(255) COMMENT '创建者',
updated_by VARCHAR(255) COMMENT '更新者',
UNIQUE KEY uk_model_provider (model_name, provider) COMMENT '避免同一提供商下模型名称重复'
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='模型配置表';