You've already forked DataMate
refactor: rename artifactId and application name to 'datamate'; add model configuration and related services (#26)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.datamate.common.models.domain.entity;
|
||||
|
||||
/**
|
||||
* 模型类型枚举类
|
||||
*
|
||||
* @author dallas
|
||||
* @since 2025-10-27
|
||||
*/
|
||||
public enum ModelType {
|
||||
/**
|
||||
* 语言模型
|
||||
*/
|
||||
CHAT,
|
||||
/**
|
||||
* 嵌入模型
|
||||
*/
|
||||
EMBEDDING
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user