You've already forked DataMate
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:
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 基础地址',
|
||||||
|
|||||||
Reference in New Issue
Block a user