feat: add model health check functionality and improve model configuration (#30)

* refactor: rename artifactId and application name to 'datamate'; add model configuration and related services

* refactor: simplify package scanning by using wildcard for mapper packages

* feat: add model health check functionality and improve model configuration
This commit is contained in:
Dallas98
2025-10-28 16:06:53 +08:00
committed by GitHub
parent acafe70d90
commit 1a6e25758e
6 changed files with 52 additions and 10 deletions

View File

@@ -207,6 +207,19 @@
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version> <version>${spring-boot.version}</version>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<parameters>true</parameters>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@@ -5,6 +5,7 @@ import com.datamate.common.domain.model.base.BaseEntity;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
/** /**
* 模型配置实体类 * 模型配置实体类
@@ -16,6 +17,7 @@ import lombok.Setter;
@Setter @Setter
@TableName("t_model_config") @TableName("t_model_config")
@Builder @Builder
@ToString
public class ModelConfig extends BaseEntity<String> { public class ModelConfig extends BaseEntity<String> {
/** /**
* 模型名称(如 qwen2) * 模型名称(如 qwen2)

View File

@@ -1,13 +1,13 @@
package com.datamate.common.models.infrastructure.client; package com.datamate.common.models.infrastructure.client;
import com.datamate.common.infrastructure.exception.BusinessException;
import com.datamate.common.models.domain.entity.ModelConfig; import com.datamate.common.models.domain.entity.ModelConfig;
import com.datamate.common.models.domain.entity.ModelType; import com.datamate.common.models.infrastructure.exception.ModelsErrorCode;
import dev.langchain4j.model.chat.ChatModel; import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel; import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
/** /**
* 模型客户端接口 * 模型客户端接口
@@ -15,6 +15,7 @@ import java.util.function.Consumer;
* @author dallas * @author dallas
* @since 2025-10-27 * @since 2025-10-27
*/ */
@Slf4j
public class ModelClient { public class ModelClient {
public static <T> T invokeModel(ModelConfig modelConfig, Class<T> modelInterface) { public static <T> T invokeModel(ModelConfig modelConfig, Class<T> modelInterface) {
return switch (modelConfig.getType()) { return switch (modelConfig.getType()) {
@@ -23,7 +24,7 @@ public class ModelClient {
}; };
} }
private static EmbeddingModel invokeEmbeddingModel(ModelConfig modelConfig) { public static EmbeddingModel invokeEmbeddingModel(ModelConfig modelConfig) {
return OpenAiEmbeddingModel.builder() return OpenAiEmbeddingModel.builder()
.baseUrl(modelConfig.getBaseUrl()) .baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey()) .apiKey(modelConfig.getApiKey())
@@ -31,7 +32,7 @@ public class ModelClient {
.build(); .build();
} }
private static ChatModel invokeChatModel(ModelConfig modelConfig) { public static ChatModel invokeChatModel(ModelConfig modelConfig) {
return OpenAiChatModel.builder() return OpenAiChatModel.builder()
.baseUrl(modelConfig.getBaseUrl()) .baseUrl(modelConfig.getBaseUrl())
.apiKey(modelConfig.getApiKey()) .apiKey(modelConfig.getApiKey())
@@ -40,5 +41,24 @@ public class ModelClient {
} }
public static void checkHealth(ModelConfig modelConfig) { public static void checkHealth(ModelConfig modelConfig) {
try {
switch (modelConfig.getType()) {
case CHAT -> checkChatModelHealth(modelConfig);
case EMBEDDING -> checkEmbeddingModelHealth(modelConfig);
}
} catch (Exception e) {
log.error("Model health check failed for modelConfig: {}", modelConfig, e);
throw BusinessException.of(ModelsErrorCode.MODEL_HEALTH_CHECK_FAILED);
}
}
private static void checkEmbeddingModelHealth(ModelConfig modelConfig) {
EmbeddingModel embeddingModel = invokeEmbeddingModel(modelConfig);
embeddingModel.embed("text");
}
private static void checkChatModelHealth(ModelConfig modelConfig) {
ChatModel chatModel = invokeChatModel(modelConfig);
chatModel.chat("hello");
} }
} }

View File

@@ -20,7 +20,12 @@ public enum ModelsErrorCode implements ErrorCode {
/** /**
* 模型配置已存在 * 模型配置已存在
*/ */
MODEL_CONFIG_ALREADY_EXISTS("model.0002", "模型配置已存在"); MODEL_CONFIG_ALREADY_EXISTS("model.0002", "模型配置已存在"),
/**
* 模型健康检查失败
*/
MODEL_HEALTH_CHECK_FAILED("model.0003", "模型健康检查失败");
private final String code; private final String code;
private final String message; private final String message;

View File

@@ -19,7 +19,7 @@ import java.util.List;
* @since 2025-10-27 * @since 2025-10-27
*/ */
@RestController @RestController
@RequestMapping("/api/models") @RequestMapping("/models")
@RequiredArgsConstructor @RequiredArgsConstructor
public class ModelConfigController { public class ModelConfigController {
private final ModelConfigApplicationService modelConfigApplicationService; private final ModelConfigApplicationService modelConfigApplicationService;
@@ -40,7 +40,7 @@ public class ModelConfigController {
* @return 模型列表 * @return 模型列表
*/ */
@GetMapping("/list") @GetMapping("/list")
public PagedResponse<ModelConfig> getModels(@RequestParam QueryModelRequest queryModelRequest) { public PagedResponse<ModelConfig> getModels(QueryModelRequest queryModelRequest) {
return modelConfigApplicationService.getModels(queryModelRequest); return modelConfigApplicationService.getModels(queryModelRequest);
} }
@@ -51,7 +51,7 @@ public class ModelConfigController {
* @return 模型详情 * @return 模型详情
*/ */
@GetMapping("/{modelId}") @GetMapping("/{modelId}")
public ModelConfig getModelDetail(@PathVariable String modelId) { public ModelConfig getModelDetail(@PathVariable("modelId") String modelId) {
return modelConfigApplicationService.getModelDetail(modelId); return modelConfigApplicationService.getModelDetail(modelId);
} }

View File

@@ -1,6 +1,8 @@
USE datamate;
CREATE TABLE t_model_config CREATE TABLE t_model_config
( (
id VARCHAR(36) AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID', id VARCHAR(36) PRIMARY KEY COMMENT '主键ID',
model_name VARCHAR(100) NOT NULL COMMENT '模型名称(如 qwen2)', model_name VARCHAR(100) NOT NULL COMMENT '模型名称(如 qwen2)',
provider VARCHAR(50) NOT NULL COMMENT '模型提供商(如 Ollama、OpenAI、DeepSeek)', provider VARCHAR(50) NOT NULL COMMENT '模型提供商(如 Ollama、OpenAI、DeepSeek)',
base_url VARCHAR(255) NOT NULL COMMENT 'API 基础地址', base_url VARCHAR(255) NOT NULL COMMENT 'API 基础地址',