feat(modelprovider): 补齐模型工作台聚合与转换分层
This commit is contained in:
@@ -3,36 +3,33 @@ package com.bruce.modelprovider.controller;
|
|||||||
import com.bruce.common.domain.model.RequestResult;
|
import com.bruce.common.domain.model.RequestResult;
|
||||||
import com.bruce.modelprovider.dto.request.ModelCallLogQueryRequest;
|
import com.bruce.modelprovider.dto.request.ModelCallLogQueryRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
|
import com.bruce.modelprovider.factory.ModelCallLogFactory;
|
||||||
import com.bruce.modelprovider.service.IModelCallLogService;
|
import com.bruce.modelprovider.service.IModelCallLogService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/model/call-logs")
|
@RequestMapping("/api/model/call-logs")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelCallLogController {
|
public class ModelCallLogController {
|
||||||
|
|
||||||
private final IModelCallLogService modelCallLogService;
|
private final IModelCallLogService modelCallLogService;
|
||||||
|
private final ModelCallLogFactory modelCallLogFactory;
|
||||||
|
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
/**
|
|
||||||
* 方法 query,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<List<ModelCallLogResponse>> query(@RequestBody(required = false) ModelCallLogQueryRequest request) {
|
public RequestResult<List<ModelCallLogResponse>> query(@RequestBody(required = false) ModelCallLogQueryRequest request) {
|
||||||
|
log.info("ModelCallLogController.query start, request={}", request);
|
||||||
return RequestResult.success(modelCallLogService.query(request));
|
return RequestResult.success(modelCallLogService.query(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
/**
|
|
||||||
* 方法 detail,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<ModelCallLogResponse> detail(@RequestParam("id") Long id) {
|
public RequestResult<ModelCallLogResponse> detail(@RequestParam("id") Long id) {
|
||||||
return RequestResult.success(ModelCallLogResponse.fromEntity(modelCallLogService.getById(id)));
|
log.info("ModelCallLogController.detail start, id={}", id);
|
||||||
|
return RequestResult.success(modelCallLogFactory.toResponse(modelCallLogService.getById(id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,50 +4,43 @@ import com.bruce.common.domain.model.RequestResult;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
import com.bruce.modelprovider.service.IModelConfigService;
|
import com.bruce.modelprovider.service.IModelConfigService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/model/configs")
|
@RequestMapping("/api/model/configs")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelConfigController {
|
public class ModelConfigController {
|
||||||
|
|
||||||
private final IModelConfigService modelConfigService;
|
private final IModelConfigService modelConfigService;
|
||||||
|
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
/**
|
|
||||||
* 方法 query,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<List<ModelConfigResponse>> query() {
|
public RequestResult<List<ModelConfigResponse>> query() {
|
||||||
|
log.info("ModelConfigController.query start");
|
||||||
return RequestResult.success(modelConfigService.listResponses());
|
return RequestResult.success(modelConfigService.listResponses());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
/**
|
|
||||||
* 方法 detail,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<ModelConfigResponse> detail(@RequestParam("id") Long id) {
|
public RequestResult<ModelConfigResponse> detail(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelConfigController.detail start, id={}", id);
|
||||||
return RequestResult.success(modelConfigService.getResponseById(id));
|
return RequestResult.success(modelConfigService.getResponseById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
/**
|
|
||||||
* 方法 save,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> save(@RequestBody ModelConfigSaveRequest request) {
|
public RequestResult<Boolean> save(@RequestBody ModelConfigSaveRequest request) {
|
||||||
|
log.info("ModelConfigController.save start, id={}, modelCode={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getModelCode());
|
||||||
return RequestResult.success(modelConfigService.saveOrUpdate(request));
|
return RequestResult.success(modelConfigService.saveOrUpdate(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
/**
|
|
||||||
* 方法 delete,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelConfigController.delete start, id={}", id);
|
||||||
return RequestResult.success(modelConfigService.removeById(id));
|
return RequestResult.success(modelConfigService.removeById(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,58 +4,49 @@ import com.bruce.common.domain.model.RequestResult;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelProviderSaveRequest;
|
import com.bruce.modelprovider.dto.request.ModelProviderSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
import com.bruce.modelprovider.service.IModelProviderService;
|
import com.bruce.modelprovider.service.IModelProviderService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/model/providers")
|
@RequestMapping("/api/model/providers")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelProviderController {
|
public class ModelProviderController {
|
||||||
|
|
||||||
private final IModelProviderService modelProviderService;
|
private final IModelProviderService modelProviderService;
|
||||||
|
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
/**
|
|
||||||
* 方法 query,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<List<ModelProviderResponse>> query() {
|
public RequestResult<List<ModelProviderResponse>> query() {
|
||||||
|
log.info("ModelProviderController.query start");
|
||||||
return RequestResult.success(modelProviderService.listResponses());
|
return RequestResult.success(modelProviderService.listResponses());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
/**
|
|
||||||
* 方法 detail,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<ModelProviderResponse> detail(@RequestParam("id") Long id) {
|
public RequestResult<ModelProviderResponse> detail(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelProviderController.detail start, id={}", id);
|
||||||
return RequestResult.success(modelProviderService.getResponseById(id));
|
return RequestResult.success(modelProviderService.getResponseById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
/**
|
|
||||||
* 方法 save,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> save(@RequestBody ModelProviderSaveRequest request) {
|
public RequestResult<Boolean> save(@RequestBody ModelProviderSaveRequest request) {
|
||||||
|
log.info("ModelProviderController.save start, id={}, providerCode={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getProviderCode());
|
||||||
return RequestResult.success(modelProviderService.saveOrUpdate(request));
|
return RequestResult.success(modelProviderService.saveOrUpdate(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
/**
|
|
||||||
* 方法 delete,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelProviderController.delete start, id={}", id);
|
||||||
return RequestResult.success(modelProviderService.removeById(id));
|
return RequestResult.success(modelProviderService.removeById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/checkHealth")
|
@PostMapping("/checkHealth")
|
||||||
/**
|
|
||||||
* 方法 checkHealth,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> checkHealth(@RequestParam("id") Long id) {
|
public RequestResult<Boolean> checkHealth(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelProviderController.checkHealth start, id={}", id);
|
||||||
return RequestResult.success(modelProviderService.checkHealth(id));
|
return RequestResult.success(modelProviderService.checkHealth(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,50 +4,43 @@ import com.bruce.common.domain.model.RequestResult;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/model/routes")
|
@RequestMapping("/api/model/routes")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelRouteRuleController {
|
public class ModelRouteRuleController {
|
||||||
|
|
||||||
private final IModelRouteRuleService modelRouteRuleService;
|
private final IModelRouteRuleService modelRouteRuleService;
|
||||||
|
|
||||||
@PostMapping("/query")
|
@PostMapping("/query")
|
||||||
/**
|
|
||||||
* 方法 query,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<List<ModelRouteRuleResponse>> query() {
|
public RequestResult<List<ModelRouteRuleResponse>> query() {
|
||||||
|
log.info("ModelRouteRuleController.query start");
|
||||||
return RequestResult.success(modelRouteRuleService.listResponses());
|
return RequestResult.success(modelRouteRuleService.listResponses());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/detail")
|
@GetMapping("/detail")
|
||||||
/**
|
|
||||||
* 方法 detail,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<ModelRouteRuleResponse> detail(@RequestParam("id") Long id) {
|
public RequestResult<ModelRouteRuleResponse> detail(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelRouteRuleController.detail start, id={}", id);
|
||||||
return RequestResult.success(modelRouteRuleService.getResponseById(id));
|
return RequestResult.success(modelRouteRuleService.getResponseById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/save")
|
@PostMapping("/save")
|
||||||
/**
|
|
||||||
* 方法 save,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> save(@RequestBody ModelRouteRuleSaveRequest request) {
|
public RequestResult<Boolean> save(@RequestBody ModelRouteRuleSaveRequest request) {
|
||||||
|
log.info("ModelRouteRuleController.save start, id={}, routeCode={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getRouteCode());
|
||||||
return RequestResult.success(modelRouteRuleService.saveOrUpdate(request));
|
return RequestResult.success(modelRouteRuleService.saveOrUpdate(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/delete")
|
@PostMapping("/delete")
|
||||||
/**
|
|
||||||
* 方法 delete,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
public RequestResult<Boolean> delete(@RequestParam("id") Long id) {
|
||||||
|
log.info("ModelRouteRuleController.delete start, id={}", id);
|
||||||
return RequestResult.success(modelRouteRuleService.removeById(id));
|
return RequestResult.success(modelRouteRuleService.removeById(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.bruce.modelprovider.controller;
|
||||||
|
|
||||||
|
import com.bruce.common.domain.model.RequestResult;
|
||||||
|
import com.bruce.modelprovider.service.IModelWorkspaceService;
|
||||||
|
import com.bruce.modelprovider.vo.ModelWorkspaceVO;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型工作台聚合接口。
|
||||||
|
*/
|
||||||
|
@Tag(name = "模型工作台")
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/api/model/workspace")
|
||||||
|
public class ModelWorkspaceController {
|
||||||
|
|
||||||
|
private final IModelWorkspaceService modelWorkspaceService;
|
||||||
|
|
||||||
|
@Operation(summary = "查询模型与路由工作台聚合视图")
|
||||||
|
@GetMapping
|
||||||
|
public RequestResult<ModelWorkspaceVO> getWorkspace() {
|
||||||
|
log.info("ModelWorkspaceController.getWorkspace start");
|
||||||
|
ModelWorkspaceVO workspace = modelWorkspaceService.getWorkspace();
|
||||||
|
log.info("ModelWorkspaceController.getWorkspace success, providerCount={}, modelCount={}, routeRuleCount={}",
|
||||||
|
workspace.getProviderCount(), workspace.getModelCount(), workspace.getRouteRuleCount());
|
||||||
|
return RequestResult.success(workspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,40 +4,35 @@ import com.bruce.common.domain.model.RequestResult;
|
|||||||
import com.bruce.modelprovider.dto.request.RagStoreModelConfigSaveRequest;
|
import com.bruce.modelprovider.dto.request.RagStoreModelConfigSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse;
|
import com.bruce.modelprovider.dto.response.RagStoreModelConfigResponse;
|
||||||
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/rag/store")
|
@RequestMapping("/api/rag/store")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class RagStoreModelConfigController {
|
public class RagStoreModelConfigController {
|
||||||
|
|
||||||
private final IRagStoreModelConfigService ragStoreModelConfigService;
|
private final IRagStoreModelConfigService ragStoreModelConfigService;
|
||||||
|
|
||||||
@GetMapping("/modelConfig")
|
@GetMapping("/modelConfig")
|
||||||
/**
|
|
||||||
* 方法 modelConfig,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<RagStoreModelConfigResponse> modelConfig(@RequestParam("storeId") Long storeId) {
|
public RequestResult<RagStoreModelConfigResponse> modelConfig(@RequestParam("storeId") Long storeId) {
|
||||||
|
log.info("RagStoreModelConfigController.modelConfig start, storeId={}", storeId);
|
||||||
return RequestResult.success(ragStoreModelConfigService.getByStoreId(storeId));
|
return RequestResult.success(ragStoreModelConfigService.getByStoreId(storeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/modelConfig/save")
|
@PostMapping("/modelConfig/save")
|
||||||
/**
|
|
||||||
* 方法 save,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> save(@RequestBody RagStoreModelConfigSaveRequest request) {
|
public RequestResult<Boolean> save(@RequestBody RagStoreModelConfigSaveRequest request) {
|
||||||
|
log.info("RagStoreModelConfigController.save start, storeId={}, embeddingModelId={}",
|
||||||
|
request == null ? null : request.getStoreId(),
|
||||||
|
request == null ? null : request.getEmbeddingModelId());
|
||||||
return RequestResult.success(ragStoreModelConfigService.saveOrUpdate(request));
|
return RequestResult.success(ragStoreModelConfigService.saveOrUpdate(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/rebuildIndex")
|
@PostMapping("/rebuildIndex")
|
||||||
/**
|
|
||||||
* 方法 rebuildIndex,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RequestResult<Boolean> rebuildIndex(@RequestParam("storeId") Long storeId) {
|
public RequestResult<Boolean> rebuildIndex(@RequestParam("storeId") Long storeId) {
|
||||||
|
log.info("RagStoreModelConfigController.rebuildIndex start, storeId={}", storeId);
|
||||||
return RequestResult.success(storeId != null);
|
return RequestResult.success(storeId != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.bruce.modelprovider.factory;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
|
import com.bruce.modelprovider.entity.ModelCallLog;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型调用日志工厂。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ModelCallLogFactory {
|
||||||
|
|
||||||
|
public ModelCallLogResponse toResponse(ModelCallLog entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelCallLogResponse response = new ModelCallLogResponse();
|
||||||
|
BeanUtils.copyProperties(entity, response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModelCallLogResponse> toResponses(List<ModelCallLog> entities) {
|
||||||
|
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.bruce.modelprovider.factory;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
|
import com.bruce.modelprovider.entity.ModelConfig;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型配置工厂,统一转换模型配置请求、实体和返回对象。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ModelConfigFactory {
|
||||||
|
|
||||||
|
public ModelConfig toEntity(ModelConfigSaveRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelConfig entity = new ModelConfig();
|
||||||
|
entity.setId(request.getId());
|
||||||
|
entity.setProviderId(request.getProviderId());
|
||||||
|
entity.setModelCode(trimToNull(request.getModelCode()));
|
||||||
|
entity.setModelName(trimToNull(request.getModelName()));
|
||||||
|
entity.setUpstreamModel(trimToNull(request.getUpstreamModel()));
|
||||||
|
entity.setModelType(trimToNull(request.getModelType()));
|
||||||
|
entity.setEmbeddingDimension(request.getEmbeddingDimension());
|
||||||
|
entity.setLocalModel(request.getLocalModel());
|
||||||
|
entity.setDefaultModel(request.getDefaultModel());
|
||||||
|
entity.setOptionsJson(trimToNull(request.getOptionsJson()));
|
||||||
|
entity.setEnabled(request.getEnabled());
|
||||||
|
entity.setRemark(trimToNull(request.getRemark()));
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelConfigResponse toResponse(ModelConfig entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelConfigResponse response = new ModelConfigResponse();
|
||||||
|
BeanUtils.copyProperties(entity, response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModelConfigResponse> toResponses(List<ModelConfig> entities) {
|
||||||
|
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (!StringUtils.hasText(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.bruce.modelprovider.factory;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelProviderSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
|
import com.bruce.modelprovider.entity.ModelProvider;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型服务商工厂,统一负责服务商 DTO、Entity、VO 的转换。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ModelProviderFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将保存请求转换为实体,统一处理字符串裁剪逻辑。
|
||||||
|
*/
|
||||||
|
public ModelProvider toEntity(ModelProviderSaveRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelProvider entity = new ModelProvider();
|
||||||
|
entity.setId(request.getId());
|
||||||
|
entity.setProviderCode(trimToNull(request.getProviderCode()));
|
||||||
|
entity.setProviderName(trimToNull(request.getProviderName()));
|
||||||
|
entity.setProviderType(trimToNull(request.getProviderType()));
|
||||||
|
entity.setProtocolType(trimToNull(request.getProtocolType()));
|
||||||
|
entity.setBaseUrl(trimToNull(request.getBaseUrl()));
|
||||||
|
entity.setAuthType(trimToNull(request.getAuthType()));
|
||||||
|
entity.setSecretRef(trimToNull(request.getSecretRef()));
|
||||||
|
entity.setApiKeyCipher(trimToNull(request.getApiKeyCipher()));
|
||||||
|
entity.setTimeoutMs(request.getTimeoutMs());
|
||||||
|
entity.setPriority(request.getPriority());
|
||||||
|
entity.setEnabled(request.getEnabled());
|
||||||
|
entity.setRemark(trimToNull(request.getRemark()));
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将实体转换为前端返回对象,并隐藏密文字段,只返回是否已配置密钥。
|
||||||
|
*/
|
||||||
|
public ModelProviderResponse toResponse(ModelProvider entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelProviderResponse response = new ModelProviderResponse();
|
||||||
|
BeanUtils.copyProperties(entity, response);
|
||||||
|
response.setHasApiKey(StringUtils.hasText(entity.getApiKeyCipher()));
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModelProviderResponse> toResponses(List<ModelProvider> entities) {
|
||||||
|
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (!StringUtils.hasText(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.bruce.modelprovider.factory;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
|
import com.bruce.modelprovider.entity.ModelRouteRule;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型路由规则工厂。
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class ModelRouteRuleFactory {
|
||||||
|
|
||||||
|
public ModelRouteRule toEntity(ModelRouteRuleSaveRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelRouteRule entity = new ModelRouteRule();
|
||||||
|
entity.setId(request.getId());
|
||||||
|
entity.setRouteCode(trimToNull(request.getRouteCode()));
|
||||||
|
entity.setRouteName(trimToNull(request.getRouteName()));
|
||||||
|
entity.setTaskType(trimToNull(request.getTaskType()));
|
||||||
|
entity.setMatchScope(trimToNull(request.getMatchScope()));
|
||||||
|
entity.setScopeId(request.getScopeId());
|
||||||
|
entity.setPrimaryModelId(request.getPrimaryModelId());
|
||||||
|
entity.setFallbackModelIdsJson(trimToNull(request.getFallbackModelIdsJson()));
|
||||||
|
entity.setRouteStrategy(trimToNull(request.getRouteStrategy()));
|
||||||
|
entity.setMaxLatencyMs(request.getMaxLatencyMs());
|
||||||
|
entity.setEnabled(request.getEnabled());
|
||||||
|
entity.setRemark(trimToNull(request.getRemark()));
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelRouteRuleResponse toResponse(ModelRouteRule entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelRouteRuleResponse response = new ModelRouteRuleResponse();
|
||||||
|
BeanUtils.copyProperties(entity, response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ModelRouteRuleResponse> toResponses(List<ModelRouteRule> entities) {
|
||||||
|
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToNull(String value) {
|
||||||
|
if (!StringUtils.hasText(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.bruce.modelprovider.service;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.vo.ModelWorkspaceVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型工作台聚合服务。
|
||||||
|
*/
|
||||||
|
public interface IModelWorkspaceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 聚合模型服务商、模型、路由和最近失败调用摘要。
|
||||||
|
*/
|
||||||
|
ModelWorkspaceVO getWorkspace();
|
||||||
|
}
|
||||||
@@ -4,37 +4,38 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelCallLogQueryRequest;
|
import com.bruce.modelprovider.dto.request.ModelCallLogQueryRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
import com.bruce.modelprovider.entity.ModelCallLog;
|
import com.bruce.modelprovider.entity.ModelCallLog;
|
||||||
|
import com.bruce.modelprovider.factory.ModelCallLogFactory;
|
||||||
import com.bruce.modelprovider.mapper.ModelCallLogMapper;
|
import com.bruce.modelprovider.mapper.ModelCallLogMapper;
|
||||||
import com.bruce.modelprovider.service.IModelCallLogService;
|
import com.bruce.modelprovider.service.IModelCallLogService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
/**
|
@RequiredArgsConstructor
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelCallLogServiceImpl extends ServiceImpl<ModelCallLogMapper, ModelCallLog>
|
public class ModelCallLogServiceImpl extends ServiceImpl<ModelCallLogMapper, ModelCallLog>
|
||||||
implements IModelCallLogService {
|
implements IModelCallLogService {
|
||||||
|
|
||||||
|
private final ModelCallLogFactory modelCallLogFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 query,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public List<ModelCallLogResponse> query(ModelCallLogQueryRequest request) {
|
public List<ModelCallLogResponse> query(ModelCallLogQueryRequest request) {
|
||||||
|
log.info("查询模型调用日志开始,request={}", request);
|
||||||
ModelCallLogQueryRequest q = request == null ? new ModelCallLogQueryRequest() : request;
|
ModelCallLogQueryRequest q = request == null ? new ModelCallLogQueryRequest() : request;
|
||||||
return lambdaQuery()
|
List<ModelCallLogResponse> responses = modelCallLogFactory.toResponses(lambdaQuery()
|
||||||
.eq(StringUtils.hasText(q.getTaskType()), ModelCallLog::getTaskType, q.getTaskType())
|
.eq(StringUtils.hasText(q.getTaskType()), ModelCallLog::getTaskType, q.getTaskType())
|
||||||
.eq(q.getProviderId() != null, ModelCallLog::getProviderId, q.getProviderId())
|
.eq(q.getProviderId() != null, ModelCallLog::getProviderId, q.getProviderId())
|
||||||
.eq(q.getModelId() != null, ModelCallLog::getModelId, q.getModelId())
|
.eq(q.getModelId() != null, ModelCallLog::getModelId, q.getModelId())
|
||||||
.eq(StringUtils.hasText(q.getStatus()), ModelCallLog::getStatus, q.getStatus())
|
.eq(StringUtils.hasText(q.getStatus()), ModelCallLog::getStatus, q.getStatus())
|
||||||
.eq(StringUtils.hasText(q.getBizType()), ModelCallLog::getBizType, q.getBizType())
|
.eq(StringUtils.hasText(q.getBizType()), ModelCallLog::getBizType, q.getBizType())
|
||||||
.orderByDesc(ModelCallLog::getId)
|
.orderByDesc(ModelCallLog::getId)
|
||||||
.list()
|
.list());
|
||||||
.stream()
|
log.info("查询模型调用日志结束,count={}", responses.size());
|
||||||
.map(ModelCallLogResponse::fromEntity)
|
return responses;
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,43 +4,45 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
import com.bruce.modelprovider.entity.ModelConfig;
|
import com.bruce.modelprovider.entity.ModelConfig;
|
||||||
|
import com.bruce.modelprovider.factory.ModelConfigFactory;
|
||||||
import com.bruce.modelprovider.mapper.ModelConfigMapper;
|
import com.bruce.modelprovider.mapper.ModelConfigMapper;
|
||||||
import com.bruce.modelprovider.service.IModelConfigService;
|
import com.bruce.modelprovider.service.IModelConfigService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
/**
|
@RequiredArgsConstructor
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelConfigServiceImpl extends ServiceImpl<ModelConfigMapper, ModelConfig> implements IModelConfigService {
|
public class ModelConfigServiceImpl extends ServiceImpl<ModelConfigMapper, ModelConfig> implements IModelConfigService {
|
||||||
|
|
||||||
|
private final ModelConfigFactory modelConfigFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 listResponses,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public List<ModelConfigResponse> listResponses() {
|
public List<ModelConfigResponse> listResponses() {
|
||||||
/**
|
log.info("查询模型配置列表开始");
|
||||||
* 方法 list,用于定义接口能力契约。
|
List<ModelConfigResponse> responses = modelConfigFactory.toResponses(list());
|
||||||
*/
|
log.info("查询模型配置列表结束,count={}", responses.size());
|
||||||
return list().stream().map(ModelConfigResponse::fromEntity).toList();
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getResponseById,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public ModelConfigResponse getResponseById(Long id) {
|
public ModelConfigResponse getResponseById(Long id) {
|
||||||
return ModelConfigResponse.fromEntity(getById(id));
|
log.info("查询模型配置详情开始,id={}", id);
|
||||||
|
ModelConfigResponse response = modelConfigFactory.toResponse(getById(id));
|
||||||
|
log.info("查询模型配置详情结束,id={}, found={}", id, response != null);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 saveOrUpdate,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public boolean saveOrUpdate(ModelConfigSaveRequest request) {
|
public boolean saveOrUpdate(ModelConfigSaveRequest request) {
|
||||||
|
log.info("保存模型配置开始,id={}, providerId={}, modelCode={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getProviderId(),
|
||||||
|
request == null ? null : request.getModelCode());
|
||||||
if (request == null) {
|
if (request == null) {
|
||||||
throw new IllegalArgumentException("模型保存请求不能为空");
|
throw new IllegalArgumentException("模型保存请求不能为空");
|
||||||
}
|
}
|
||||||
@@ -62,24 +64,25 @@ public class ModelConfigServiceImpl extends ServiceImpl<ModelConfigMapper, Model
|
|||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new IllegalArgumentException("模型不存在,ID: " + request.getId());
|
throw new IllegalArgumentException("模型不存在,ID: " + request.getId());
|
||||||
}
|
}
|
||||||
entity.setProviderId(request.getProviderId());
|
ModelConfig requestEntity = modelConfigFactory.toEntity(request);
|
||||||
entity.setModelCode(request.getModelCode().trim());
|
entity.setProviderId(requestEntity.getProviderId());
|
||||||
entity.setModelName(request.getModelName());
|
entity.setModelCode(requestEntity.getModelCode());
|
||||||
entity.setUpstreamModel(request.getUpstreamModel());
|
entity.setModelName(requestEntity.getModelName());
|
||||||
entity.setModelType(request.getModelType());
|
entity.setUpstreamModel(requestEntity.getUpstreamModel());
|
||||||
entity.setEmbeddingDimension(request.getEmbeddingDimension());
|
entity.setModelType(requestEntity.getModelType());
|
||||||
entity.setLocalModel(request.getLocalModel());
|
entity.setEmbeddingDimension(requestEntity.getEmbeddingDimension());
|
||||||
entity.setDefaultModel(request.getDefaultModel());
|
entity.setLocalModel(requestEntity.getLocalModel());
|
||||||
entity.setOptionsJson(request.getOptionsJson());
|
entity.setDefaultModel(requestEntity.getDefaultModel());
|
||||||
|
entity.setOptionsJson(requestEntity.getOptionsJson());
|
||||||
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
||||||
entity.setRemark(request.getRemark());
|
entity.setRemark(requestEntity.getRemark());
|
||||||
return request.getId() == null ? save(entity) : updateById(entity);
|
boolean result = request.getId() == null ? save(entity) : updateById(entity);
|
||||||
|
log.info("保存模型配置结束,id={}, providerId={}, modelCode={}, result={}",
|
||||||
|
entity.getId(), entity.getProviderId(), entity.getModelCode(), result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getEnabledModel,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public ModelConfig getEnabledModel(Long modelId) {
|
public ModelConfig getEnabledModel(Long modelId) {
|
||||||
ModelConfig model = getById(modelId);
|
ModelConfig model = getById(modelId);
|
||||||
if (model == null || !Boolean.TRUE.equals(model.getEnabled())) {
|
if (model == null || !Boolean.TRUE.equals(model.getEnabled())) {
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import com.bruce.modelprovider.dto.request.ModelProviderSaveRequest;
|
|||||||
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
import com.bruce.modelprovider.entity.ModelProvider;
|
import com.bruce.modelprovider.entity.ModelProvider;
|
||||||
import com.bruce.modelprovider.enums.ModelHealthStatusEnum;
|
import com.bruce.modelprovider.enums.ModelHealthStatusEnum;
|
||||||
|
import com.bruce.modelprovider.factory.ModelProviderFactory;
|
||||||
import com.bruce.modelprovider.mapper.ModelProviderMapper;
|
import com.bruce.modelprovider.mapper.ModelProviderMapper;
|
||||||
import com.bruce.modelprovider.service.IModelProviderService;
|
import com.bruce.modelprovider.service.IModelProviderService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -24,39 +26,35 @@ import java.util.List;
|
|||||||
* 3. 默认健康状态初始化;
|
* 3. 默认健康状态初始化;
|
||||||
* 4. 对接上游健康检查并回写检查结果。
|
* 4. 对接上游健康检查并回写检查结果。
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* ModelProviderServiceImpl,负责模型平台对应层的职责。
|
|
||||||
*/
|
|
||||||
public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, ModelProvider>
|
public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, ModelProvider>
|
||||||
implements IModelProviderService {
|
implements IModelProviderService {
|
||||||
|
|
||||||
private final OpenAiCompatibleModelClient openAiCompatibleModelClient;
|
private final OpenAiCompatibleModelClient openAiCompatibleModelClient;
|
||||||
|
private final ModelProviderFactory modelProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询全部服务商并转换为响应对象。
|
* 查询全部服务商并转换为响应对象。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 listResponses,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public List<ModelProviderResponse> listResponses() {
|
public List<ModelProviderResponse> listResponses() {
|
||||||
/**
|
log.info("查询模型服务商列表开始");
|
||||||
* 方法 list,用于定义接口能力契约。
|
List<ModelProviderResponse> responses = modelProviderFactory.toResponses(list());
|
||||||
*/
|
log.info("查询模型服务商列表结束,count={}", responses.size());
|
||||||
return list().stream().map(ModelProviderResponse::fromEntity).toList();
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按ID查询服务商详情(响应对象已脱敏,不返回明文密钥)。
|
* 按ID查询服务商详情(响应对象已脱敏,不返回明文密钥)。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getResponseById,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public ModelProviderResponse getResponseById(Long id) {
|
public ModelProviderResponse getResponseById(Long id) {
|
||||||
return ModelProviderResponse.fromEntity(getById(id));
|
log.info("查询模型服务商详情开始,id={}", id);
|
||||||
|
ModelProviderResponse response = modelProviderFactory.toResponse(getById(id));
|
||||||
|
log.info("查询模型服务商详情结束,id={}, found={}", id, response != null);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,10 +62,10 @@ public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, M
|
|||||||
* 会执行必要校验:请求非空、编码/名称非空、编码唯一。
|
* 会执行必要校验:请求非空、编码/名称非空、编码唯一。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 saveOrUpdate,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public boolean saveOrUpdate(ModelProviderSaveRequest request) {
|
public boolean saveOrUpdate(ModelProviderSaveRequest request) {
|
||||||
|
log.info("保存模型服务商开始,id={}, providerCode={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getProviderCode());
|
||||||
if (request == null) {
|
if (request == null) {
|
||||||
throw new IllegalArgumentException("服务商保存请求不能为空");
|
throw new IllegalArgumentException("服务商保存请求不能为空");
|
||||||
}
|
}
|
||||||
@@ -88,32 +86,33 @@ public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, M
|
|||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new IllegalArgumentException("服务商不存在,ID: " + request.getId());
|
throw new IllegalArgumentException("服务商不存在,ID: " + request.getId());
|
||||||
}
|
}
|
||||||
entity.setProviderCode(request.getProviderCode().trim());
|
ModelProvider requestEntity = modelProviderFactory.toEntity(request);
|
||||||
entity.setProviderName(request.getProviderName().trim());
|
entity.setProviderCode(requestEntity.getProviderCode());
|
||||||
entity.setProviderType(request.getProviderType());
|
entity.setProviderName(requestEntity.getProviderName());
|
||||||
entity.setProtocolType(request.getProtocolType());
|
entity.setProviderType(requestEntity.getProviderType());
|
||||||
entity.setBaseUrl(request.getBaseUrl());
|
entity.setProtocolType(requestEntity.getProtocolType());
|
||||||
entity.setAuthType(request.getAuthType());
|
entity.setBaseUrl(requestEntity.getBaseUrl());
|
||||||
entity.setSecretRef(request.getSecretRef());
|
entity.setAuthType(requestEntity.getAuthType());
|
||||||
entity.setApiKeyCipher(request.getApiKeyCipher());
|
entity.setSecretRef(requestEntity.getSecretRef());
|
||||||
entity.setTimeoutMs(request.getTimeoutMs());
|
entity.setApiKeyCipher(requestEntity.getApiKeyCipher());
|
||||||
entity.setPriority(request.getPriority());
|
entity.setTimeoutMs(requestEntity.getTimeoutMs());
|
||||||
|
entity.setPriority(requestEntity.getPriority());
|
||||||
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
||||||
entity.setRemark(request.getRemark());
|
entity.setRemark(requestEntity.getRemark());
|
||||||
if (!StringUtils.hasText(entity.getHealthStatus())) {
|
if (!StringUtils.hasText(entity.getHealthStatus())) {
|
||||||
entity.setHealthStatus(ModelHealthStatusEnum.UNKNOWN.name());
|
entity.setHealthStatus(ModelHealthStatusEnum.UNKNOWN.name());
|
||||||
}
|
}
|
||||||
return request.getId() == null ? save(entity) : updateById(entity);
|
boolean result = request.getId() == null ? save(entity) : updateById(entity);
|
||||||
|
log.info("保存模型服务商结束,id={}, providerCode={}, result={}", entity.getId(), entity.getProviderCode(), result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主动健康检查并回写健康状态与检查时间。
|
* 主动健康检查并回写健康状态与检查时间。
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 checkHealth,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public boolean checkHealth(Long id) {
|
public boolean checkHealth(Long id) {
|
||||||
|
log.info("模型服务商健康检查开始,id={}", id);
|
||||||
ModelProvider provider = getById(id);
|
ModelProvider provider = getById(id);
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
throw new IllegalArgumentException("服务商不存在,ID: " + id);
|
throw new IllegalArgumentException("服务商不存在,ID: " + id);
|
||||||
@@ -121,10 +120,9 @@ public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, M
|
|||||||
boolean healthy = openAiCompatibleModelClient.health(provider);
|
boolean healthy = openAiCompatibleModelClient.health(provider);
|
||||||
provider.setHealthStatus(healthy ? ModelHealthStatusEnum.HEALTHY.name() : ModelHealthStatusEnum.UNHEALTHY.name());
|
provider.setHealthStatus(healthy ? ModelHealthStatusEnum.HEALTHY.name() : ModelHealthStatusEnum.UNHEALTHY.name());
|
||||||
provider.setLastHealthCheckTime(new Date());
|
provider.setLastHealthCheckTime(new Date());
|
||||||
/**
|
boolean result = updateById(provider);
|
||||||
* 方法 updateById,用于定义接口能力契约。
|
log.info("模型服务商健康检查结束,id={}, healthStatus={}, result={}", id, provider.getHealthStatus(), result);
|
||||||
*/
|
return result;
|
||||||
return updateById(provider);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,44 +4,46 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
||||||
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
import com.bruce.modelprovider.entity.ModelRouteRule;
|
import com.bruce.modelprovider.entity.ModelRouteRule;
|
||||||
|
import com.bruce.modelprovider.factory.ModelRouteRuleFactory;
|
||||||
import com.bruce.modelprovider.mapper.ModelRouteRuleMapper;
|
import com.bruce.modelprovider.mapper.ModelRouteRuleMapper;
|
||||||
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
/**
|
@RequiredArgsConstructor
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class ModelRouteRuleServiceImpl extends ServiceImpl<ModelRouteRuleMapper, ModelRouteRule>
|
public class ModelRouteRuleServiceImpl extends ServiceImpl<ModelRouteRuleMapper, ModelRouteRule>
|
||||||
implements IModelRouteRuleService {
|
implements IModelRouteRuleService {
|
||||||
|
|
||||||
|
private final ModelRouteRuleFactory modelRouteRuleFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 listResponses,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public List<ModelRouteRuleResponse> listResponses() {
|
public List<ModelRouteRuleResponse> listResponses() {
|
||||||
/**
|
log.info("查询模型路由规则列表开始");
|
||||||
* 方法 list,用于定义接口能力契约。
|
List<ModelRouteRuleResponse> responses = modelRouteRuleFactory.toResponses(list());
|
||||||
*/
|
log.info("查询模型路由规则列表结束,count={}", responses.size());
|
||||||
return list().stream().map(ModelRouteRuleResponse::fromEntity).toList();
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getResponseById,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public ModelRouteRuleResponse getResponseById(Long id) {
|
public ModelRouteRuleResponse getResponseById(Long id) {
|
||||||
return ModelRouteRuleResponse.fromEntity(getById(id));
|
log.info("查询模型路由规则详情开始,id={}", id);
|
||||||
|
ModelRouteRuleResponse response = modelRouteRuleFactory.toResponse(getById(id));
|
||||||
|
log.info("查询模型路由规则详情结束,id={}, found={}", id, response != null);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 saveOrUpdate,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public boolean saveOrUpdate(ModelRouteRuleSaveRequest request) {
|
public boolean saveOrUpdate(ModelRouteRuleSaveRequest request) {
|
||||||
|
log.info("保存模型路由规则开始,id={}, routeCode={}, taskType={}",
|
||||||
|
request == null ? null : request.getId(),
|
||||||
|
request == null ? null : request.getRouteCode(),
|
||||||
|
request == null ? null : request.getTaskType());
|
||||||
if (request == null || !StringUtils.hasText(request.getRouteCode())) {
|
if (request == null || !StringUtils.hasText(request.getRouteCode())) {
|
||||||
throw new IllegalArgumentException("路由编码不能为空");
|
throw new IllegalArgumentException("路由编码不能为空");
|
||||||
}
|
}
|
||||||
@@ -56,18 +58,21 @@ public class ModelRouteRuleServiceImpl extends ServiceImpl<ModelRouteRuleMapper,
|
|||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
throw new IllegalArgumentException("路由不存在,ID: " + request.getId());
|
throw new IllegalArgumentException("路由不存在,ID: " + request.getId());
|
||||||
}
|
}
|
||||||
entity.setRouteCode(request.getRouteCode().trim());
|
ModelRouteRule requestEntity = modelRouteRuleFactory.toEntity(request);
|
||||||
entity.setRouteName(request.getRouteName());
|
entity.setRouteCode(requestEntity.getRouteCode());
|
||||||
entity.setTaskType(request.getTaskType());
|
entity.setRouteName(requestEntity.getRouteName());
|
||||||
entity.setMatchScope(request.getMatchScope());
|
entity.setTaskType(requestEntity.getTaskType());
|
||||||
entity.setScopeId(request.getScopeId());
|
entity.setMatchScope(requestEntity.getMatchScope());
|
||||||
entity.setPrimaryModelId(request.getPrimaryModelId());
|
entity.setScopeId(requestEntity.getScopeId());
|
||||||
entity.setFallbackModelIdsJson(request.getFallbackModelIdsJson());
|
entity.setPrimaryModelId(requestEntity.getPrimaryModelId());
|
||||||
entity.setRouteStrategy(request.getRouteStrategy());
|
entity.setFallbackModelIdsJson(requestEntity.getFallbackModelIdsJson());
|
||||||
entity.setMaxLatencyMs(request.getMaxLatencyMs());
|
entity.setRouteStrategy(requestEntity.getRouteStrategy());
|
||||||
|
entity.setMaxLatencyMs(requestEntity.getMaxLatencyMs());
|
||||||
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
entity.setEnabled(request.getEnabled() == null ? Boolean.TRUE : request.getEnabled());
|
||||||
entity.setRemark(request.getRemark());
|
entity.setRemark(requestEntity.getRemark());
|
||||||
return request.getId() == null ? save(entity) : updateById(entity);
|
boolean result = request.getId() == null ? save(entity) : updateById(entity);
|
||||||
|
log.info("保存模型路由规则结束,id={}, routeCode={}, result={}", entity.getId(), entity.getRouteCode(), result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.bruce.modelprovider.service.impl;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelCallLogQueryRequest;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
|
import com.bruce.modelprovider.service.IModelCallLogService;
|
||||||
|
import com.bruce.modelprovider.service.IModelConfigService;
|
||||||
|
import com.bruce.modelprovider.service.IModelProviderService;
|
||||||
|
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
||||||
|
import com.bruce.modelprovider.service.IModelWorkspaceService;
|
||||||
|
import com.bruce.modelprovider.vo.ModelWorkspaceFailureVO;
|
||||||
|
import com.bruce.modelprovider.vo.ModelWorkspaceVO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型工作台聚合服务实现。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ModelWorkspaceServiceImpl implements IModelWorkspaceService {
|
||||||
|
|
||||||
|
private static final String HEALTHY = "HEALTHY";
|
||||||
|
private static final String UNHEALTHY = "UNHEALTHY";
|
||||||
|
private static final String FAILED = "FAILED";
|
||||||
|
|
||||||
|
private final IModelProviderService modelProviderService;
|
||||||
|
private final IModelConfigService modelConfigService;
|
||||||
|
private final IModelRouteRuleService modelRouteRuleService;
|
||||||
|
private final IModelCallLogService modelCallLogService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelWorkspaceVO getWorkspace() {
|
||||||
|
log.info("模型工作台查询开始");
|
||||||
|
List<ModelProviderResponse> providers = modelProviderService.listResponses();
|
||||||
|
List<ModelConfigResponse> models = modelConfigService.listResponses();
|
||||||
|
List<ModelRouteRuleResponse> routes = modelRouteRuleService.listResponses();
|
||||||
|
List<ModelCallLogResponse> logs = modelCallLogService.query(new ModelCallLogQueryRequest());
|
||||||
|
|
||||||
|
List<ModelCallLogResponse> failedLogs = logs.stream()
|
||||||
|
.filter(log -> FAILED.equals(log.getStatus()))
|
||||||
|
.limit(5)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
ModelWorkspaceVO workspace = new ModelWorkspaceVO();
|
||||||
|
workspace.setProviderCount(providers.size());
|
||||||
|
workspace.setHealthyProviderCount((int) providers.stream().filter(provider -> HEALTHY.equals(provider.getHealthStatus())).count());
|
||||||
|
workspace.setUnhealthyProviderCount((int) providers.stream().filter(provider -> UNHEALTHY.equals(provider.getHealthStatus())).count());
|
||||||
|
workspace.setModelCount(models.size());
|
||||||
|
workspace.setEnabledModelCount((int) models.stream().filter(model -> Boolean.TRUE.equals(model.getEnabled())).count());
|
||||||
|
workspace.setRouteRuleCount(routes.size());
|
||||||
|
workspace.setEnabledRouteRuleCount((int) routes.stream().filter(route -> Boolean.TRUE.equals(route.getEnabled())).count());
|
||||||
|
workspace.setRecentFailedCallCount(failedLogs.size());
|
||||||
|
workspace.setProviders(providers);
|
||||||
|
workspace.setModels(models);
|
||||||
|
workspace.setRoutes(routes);
|
||||||
|
workspace.setFailedCallSummaries(failedLogs.stream().map(this::toFailureVO).toList());
|
||||||
|
log.info("模型工作台查询结束,providerCount={}, modelCount={}, routeRuleCount={}, failedCallCount={}",
|
||||||
|
workspace.getProviderCount(), workspace.getModelCount(), workspace.getRouteRuleCount(), workspace.getRecentFailedCallCount());
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelWorkspaceFailureVO toFailureVO(ModelCallLogResponse log) {
|
||||||
|
ModelWorkspaceFailureVO vo = new ModelWorkspaceFailureVO();
|
||||||
|
vo.setRequestId(log.getRequestId());
|
||||||
|
vo.setStatus(log.getStatus());
|
||||||
|
vo.setErrorCode(log.getErrorCode());
|
||||||
|
vo.setErrorMessage(log.getErrorMessage());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,31 +9,28 @@ import com.bruce.modelprovider.mapper.RagStoreModelConfigMapper;
|
|||||||
import com.bruce.modelprovider.service.IModelConfigService;
|
import com.bruce.modelprovider.service.IModelConfigService;
|
||||||
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
import com.bruce.modelprovider.service.IRagStoreModelConfigService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
/**
|
|
||||||
* 该类属于模型平台模块,用于承载对应分层职责。
|
|
||||||
*/
|
|
||||||
public class RagStoreModelConfigServiceImpl extends ServiceImpl<RagStoreModelConfigMapper, RagStoreModelConfig>
|
public class RagStoreModelConfigServiceImpl extends ServiceImpl<RagStoreModelConfigMapper, RagStoreModelConfig>
|
||||||
implements IRagStoreModelConfigService {
|
implements IRagStoreModelConfigService {
|
||||||
|
|
||||||
private final IModelConfigService modelConfigService;
|
private final IModelConfigService modelConfigService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getByStoreId,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RagStoreModelConfigResponse getByStoreId(Long storeId) {
|
public RagStoreModelConfigResponse getByStoreId(Long storeId) {
|
||||||
|
log.info("查询知识库模型配置开始,storeId={}", storeId);
|
||||||
return RagStoreModelConfigResponse.fromEntity(getActiveEntity(storeId));
|
return RagStoreModelConfigResponse.fromEntity(getActiveEntity(storeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 saveOrUpdate,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public boolean saveOrUpdate(RagStoreModelConfigSaveRequest request) {
|
public boolean saveOrUpdate(RagStoreModelConfigSaveRequest request) {
|
||||||
|
log.info("保存知识库模型配置开始,storeId={}, embeddingModelId={}",
|
||||||
|
request == null ? null : request.getStoreId(),
|
||||||
|
request == null ? null : request.getEmbeddingModelId());
|
||||||
if (request == null || request.getStoreId() == null) {
|
if (request == null || request.getStoreId() == null) {
|
||||||
throw new IllegalArgumentException("知识库模型配置请求不能为空");
|
throw new IllegalArgumentException("知识库模型配置请求不能为空");
|
||||||
}
|
}
|
||||||
@@ -57,26 +54,23 @@ public class RagStoreModelConfigServiceImpl extends ServiceImpl<RagStoreModelCon
|
|||||||
entity.setRemark(request.getRemark());
|
entity.setRemark(request.getRemark());
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
entity.setIndexVersion(1);
|
entity.setIndexVersion(1);
|
||||||
/**
|
boolean result = save(entity);
|
||||||
* 方法 save,用于定义接口能力契约。
|
log.info("保存知识库模型配置结束,storeId={}, indexVersion={}, result={}",
|
||||||
*/
|
entity.getStoreId(), entity.getIndexVersion(), result);
|
||||||
return save(entity);
|
return result;
|
||||||
}
|
}
|
||||||
boolean changed = !current.getEmbeddingModelId().equals(request.getEmbeddingModelId())
|
boolean changed = !current.getEmbeddingModelId().equals(request.getEmbeddingModelId())
|
||||||
|| !current.getEmbeddingDimension().equals(request.getEmbeddingDimension());
|
|| !current.getEmbeddingDimension().equals(request.getEmbeddingDimension());
|
||||||
if (changed) {
|
if (changed) {
|
||||||
entity.setIndexVersion(current.getIndexVersion() == null ? 2 : current.getIndexVersion() + 1);
|
entity.setIndexVersion(current.getIndexVersion() == null ? 2 : current.getIndexVersion() + 1);
|
||||||
}
|
}
|
||||||
/**
|
boolean result = updateById(entity);
|
||||||
* 方法 updateById,用于定义接口能力契约。
|
log.info("保存知识库模型配置结束,storeId={}, indexVersion={}, result={}",
|
||||||
*/
|
entity.getStoreId(), entity.getIndexVersion(), result);
|
||||||
return updateById(entity);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
|
||||||
* 方法 getActiveEntity,用于执行业务逻辑处理。
|
|
||||||
*/
|
|
||||||
public RagStoreModelConfig getActiveEntity(Long storeId) {
|
public RagStoreModelConfig getActiveEntity(Long storeId) {
|
||||||
return lambdaQuery().eq(RagStoreModelConfig::getStoreId, storeId)
|
return lambdaQuery().eq(RagStoreModelConfig::getStoreId, storeId)
|
||||||
.eq(RagStoreModelConfig::getActive, true)
|
.eq(RagStoreModelConfig::getActive, true)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.bruce.modelprovider.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近失败调用摘要。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "模型调用失败摘要")
|
||||||
|
public class ModelWorkspaceFailureVO {
|
||||||
|
|
||||||
|
@Schema(description = "请求ID")
|
||||||
|
private String requestId;
|
||||||
|
|
||||||
|
@Schema(description = "调用状态")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "错误码")
|
||||||
|
private String errorCode;
|
||||||
|
|
||||||
|
@Schema(description = "错误摘要")
|
||||||
|
private String errorMessage;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.bruce.modelprovider.vo;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模型工作台聚合视图。
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "模型与路由工作台聚合视图")
|
||||||
|
public class ModelWorkspaceVO {
|
||||||
|
|
||||||
|
@Schema(description = "服务商总数")
|
||||||
|
private Integer providerCount;
|
||||||
|
|
||||||
|
@Schema(description = "健康服务商数量")
|
||||||
|
private Integer healthyProviderCount;
|
||||||
|
|
||||||
|
@Schema(description = "异常服务商数量")
|
||||||
|
private Integer unhealthyProviderCount;
|
||||||
|
|
||||||
|
@Schema(description = "模型总数")
|
||||||
|
private Integer modelCount;
|
||||||
|
|
||||||
|
@Schema(description = "启用模型数量")
|
||||||
|
private Integer enabledModelCount;
|
||||||
|
|
||||||
|
@Schema(description = "路由规则总数")
|
||||||
|
private Integer routeRuleCount;
|
||||||
|
|
||||||
|
@Schema(description = "启用路由规则数量")
|
||||||
|
private Integer enabledRouteRuleCount;
|
||||||
|
|
||||||
|
@Schema(description = "最近失败调用数量")
|
||||||
|
private Integer recentFailedCallCount;
|
||||||
|
|
||||||
|
@Schema(description = "服务商列表")
|
||||||
|
private List<ModelProviderResponse> providers = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "模型列表")
|
||||||
|
private List<ModelConfigResponse> models = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "路由规则列表")
|
||||||
|
private List<ModelRouteRuleResponse> routes = new ArrayList<>();
|
||||||
|
|
||||||
|
@Schema(description = "最近失败调用摘要")
|
||||||
|
private List<ModelWorkspaceFailureVO> failedCallSummaries = new ArrayList<>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
package com.bruce.modelprovider.factory;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelConfigSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelProviderSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.request.ModelRouteRuleSaveRequest;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
|
import com.bruce.modelprovider.entity.ModelCallLog;
|
||||||
|
import com.bruce.modelprovider.entity.ModelConfig;
|
||||||
|
import com.bruce.modelprovider.entity.ModelProvider;
|
||||||
|
import com.bruce.modelprovider.entity.ModelRouteRule;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class ModelProviderFactoryTests {
|
||||||
|
|
||||||
|
private final ModelProviderFactory modelProviderFactory = new ModelProviderFactory();
|
||||||
|
private final ModelConfigFactory modelConfigFactory = new ModelConfigFactory();
|
||||||
|
private final ModelRouteRuleFactory modelRouteRuleFactory = new ModelRouteRuleFactory();
|
||||||
|
private final ModelCallLogFactory modelCallLogFactory = new ModelCallLogFactory();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void modelProviderFactoryShouldTrimRequestAndHideCipherInResponse() {
|
||||||
|
ModelProviderSaveRequest request = new ModelProviderSaveRequest();
|
||||||
|
request.setId(1L);
|
||||||
|
request.setProviderCode(" OPENAI_MAIN ");
|
||||||
|
request.setProviderName(" OpenAI 主服务 ");
|
||||||
|
request.setProviderType(" OPENAI ");
|
||||||
|
request.setProtocolType(" OPENAI_COMPATIBLE ");
|
||||||
|
request.setBaseUrl(" https://api.openai.com/v1 ");
|
||||||
|
request.setAuthType(" BEARER_TOKEN ");
|
||||||
|
request.setSecretRef(" OPENAI_KEY ");
|
||||||
|
request.setTimeoutMs(60000);
|
||||||
|
request.setPriority(100);
|
||||||
|
request.setEnabled(true);
|
||||||
|
request.setRemark(" 主路由服务商 ");
|
||||||
|
|
||||||
|
ModelProvider entity = modelProviderFactory.toEntity(request);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertEquals("OPENAI_MAIN", entity.getProviderCode());
|
||||||
|
assertEquals("OpenAI 主服务", entity.getProviderName());
|
||||||
|
assertEquals("OPENAI", entity.getProviderType());
|
||||||
|
assertEquals("OPENAI_COMPATIBLE", entity.getProtocolType());
|
||||||
|
assertEquals("https://api.openai.com/v1", entity.getBaseUrl());
|
||||||
|
assertEquals("BEARER_TOKEN", entity.getAuthType());
|
||||||
|
assertEquals("OPENAI_KEY", entity.getSecretRef());
|
||||||
|
assertEquals("主路由服务商", entity.getRemark());
|
||||||
|
|
||||||
|
ModelProviderResponse response = modelProviderFactory.toResponse(entity);
|
||||||
|
assertFalse(Boolean.TRUE.equals(response.getHasApiKey()));
|
||||||
|
|
||||||
|
entity.setApiKeyCipher("cipher");
|
||||||
|
response = modelProviderFactory.toResponse(entity);
|
||||||
|
assertTrue(Boolean.TRUE.equals(response.getHasApiKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void modelConfigFactoryShouldMapFullConfigFields() {
|
||||||
|
ModelConfigSaveRequest request = new ModelConfigSaveRequest();
|
||||||
|
request.setId(2L);
|
||||||
|
request.setProviderId(1L);
|
||||||
|
request.setModelCode(" EMB_1024 ");
|
||||||
|
request.setModelName(" text-embedding-3-large ");
|
||||||
|
request.setUpstreamModel(" text-embedding-3-large ");
|
||||||
|
request.setModelType(" EMBEDDING ");
|
||||||
|
request.setEmbeddingDimension(1024);
|
||||||
|
request.setLocalModel(false);
|
||||||
|
request.setDefaultModel(true);
|
||||||
|
request.setOptionsJson(" {\"dimensions\":1024} ");
|
||||||
|
request.setEnabled(true);
|
||||||
|
request.setRemark(" 默认向量模型 ");
|
||||||
|
|
||||||
|
ModelConfig entity = modelConfigFactory.toEntity(request);
|
||||||
|
assertEquals("EMB_1024", entity.getModelCode());
|
||||||
|
assertEquals("text-embedding-3-large", entity.getModelName());
|
||||||
|
assertEquals("text-embedding-3-large", entity.getUpstreamModel());
|
||||||
|
assertEquals("EMBEDDING", entity.getModelType());
|
||||||
|
assertEquals("{\"dimensions\":1024}", entity.getOptionsJson());
|
||||||
|
assertEquals("默认向量模型", entity.getRemark());
|
||||||
|
|
||||||
|
ModelConfigResponse response = modelConfigFactory.toResponse(entity);
|
||||||
|
assertEquals(1024, response.getEmbeddingDimension());
|
||||||
|
assertTrue(Boolean.TRUE.equals(response.getDefaultModel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void modelRouteRuleFactoryShouldMapRouteFields() {
|
||||||
|
ModelRouteRuleSaveRequest request = new ModelRouteRuleSaveRequest();
|
||||||
|
request.setId(3L);
|
||||||
|
request.setRouteCode(" RAG_GLOBAL ");
|
||||||
|
request.setRouteName(" 全局检索路由 ");
|
||||||
|
request.setTaskType(" RAG_RETRIEVAL ");
|
||||||
|
request.setMatchScope(" GLOBAL ");
|
||||||
|
request.setScopeId(1001L);
|
||||||
|
request.setPrimaryModelId(2L);
|
||||||
|
request.setFallbackModelIdsJson(" [3,4] ");
|
||||||
|
request.setRouteStrategy(" MANUAL ");
|
||||||
|
request.setMaxLatencyMs(3000);
|
||||||
|
request.setEnabled(true);
|
||||||
|
request.setRemark(" 全局默认规则 ");
|
||||||
|
|
||||||
|
ModelRouteRule entity = modelRouteRuleFactory.toEntity(request);
|
||||||
|
assertEquals("RAG_GLOBAL", entity.getRouteCode());
|
||||||
|
assertEquals("全局检索路由", entity.getRouteName());
|
||||||
|
assertEquals("RAG_RETRIEVAL", entity.getTaskType());
|
||||||
|
assertEquals("[3,4]", entity.getFallbackModelIdsJson());
|
||||||
|
assertEquals("全局默认规则", entity.getRemark());
|
||||||
|
|
||||||
|
ModelRouteRuleResponse response = modelRouteRuleFactory.toResponse(entity);
|
||||||
|
assertEquals(2L, response.getPrimaryModelId());
|
||||||
|
assertEquals("MANUAL", response.getRouteStrategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void modelCallLogFactoryShouldExposeReadonlyView() {
|
||||||
|
ModelCallLog entity = new ModelCallLog();
|
||||||
|
entity.setId(10L);
|
||||||
|
entity.setRequestId("req-001");
|
||||||
|
entity.setProviderId(1L);
|
||||||
|
entity.setModelId(2L);
|
||||||
|
entity.setTaskType("RAG_EMBEDDING");
|
||||||
|
entity.setBizType("RAG_DOCUMENT_INDEX");
|
||||||
|
entity.setBizId("doc-1");
|
||||||
|
entity.setCallType("EMBEDDING");
|
||||||
|
entity.setStatus("FAILED");
|
||||||
|
entity.setDurationMs(2200);
|
||||||
|
entity.setErrorCode("TIMEOUT");
|
||||||
|
entity.setErrorMessage("上游超时");
|
||||||
|
entity.setEstimatedCost(new BigDecimal("0.00250000"));
|
||||||
|
|
||||||
|
ModelCallLogResponse response = modelCallLogFactory.toResponse(entity);
|
||||||
|
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals("req-001", response.getRequestId());
|
||||||
|
assertEquals("RAG_EMBEDDING", response.getTaskType());
|
||||||
|
assertEquals("RAG_DOCUMENT_INDEX", response.getBizType());
|
||||||
|
assertEquals("FAILED", response.getStatus());
|
||||||
|
assertEquals("TIMEOUT", response.getErrorCode());
|
||||||
|
assertEquals("上游超时", response.getErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package com.bruce.modelprovider.workspace;
|
||||||
|
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelCallLogResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelConfigResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelProviderResponse;
|
||||||
|
import com.bruce.modelprovider.dto.response.ModelRouteRuleResponse;
|
||||||
|
import com.bruce.modelprovider.service.IModelCallLogService;
|
||||||
|
import com.bruce.modelprovider.service.IModelConfigService;
|
||||||
|
import com.bruce.modelprovider.service.IModelProviderService;
|
||||||
|
import com.bruce.modelprovider.service.IModelRouteRuleService;
|
||||||
|
import com.bruce.modelprovider.service.impl.ModelWorkspaceServiceImpl;
|
||||||
|
import com.bruce.modelprovider.vo.ModelWorkspaceVO;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class ModelWorkspaceServiceTests {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IModelProviderService modelProviderService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IModelConfigService modelConfigService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IModelRouteRuleService modelRouteRuleService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private IModelCallLogService modelCallLogService;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private ModelWorkspaceServiceImpl modelWorkspaceService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWorkspaceShouldAggregateHealthRoutesAndFailureSummary() {
|
||||||
|
when(modelProviderService.listResponses()).thenReturn(List.of(
|
||||||
|
provider(1L, "OPENAI_MAIN", "HEALTHY", true),
|
||||||
|
provider(2L, "LOCAL_OLLAMA", "UNHEALTHY", true),
|
||||||
|
provider(3L, "TEST_PROVIDER", "UNKNOWN", false)
|
||||||
|
));
|
||||||
|
when(modelConfigService.listResponses()).thenReturn(List.of(
|
||||||
|
model(11L, 1L, "CHAT_MAIN", "CHAT", true),
|
||||||
|
model(12L, 1L, "EMB_1024", "EMBEDDING", true),
|
||||||
|
model(13L, 2L, "CHAT_FALLBACK", "CHAT", false)
|
||||||
|
));
|
||||||
|
when(modelRouteRuleService.listResponses()).thenReturn(List.of(
|
||||||
|
route(21L, "RAG_GLOBAL", "RAG_RETRIEVAL", 11L, "[13]", true),
|
||||||
|
route(22L, "CHAT_GLOBAL", "AGENT_CHAT", 11L, "[]", false)
|
||||||
|
));
|
||||||
|
when(modelCallLogService.query(org.mockito.ArgumentMatchers.any())).thenReturn(List.of(
|
||||||
|
log("req-001", "FAILED", "TIMEOUT", "上游超时"),
|
||||||
|
log("req-002", "FAILED", "AUTH_ERROR", "鉴权失败"),
|
||||||
|
log("req-003", "SUCCESS", null, null)
|
||||||
|
));
|
||||||
|
|
||||||
|
ModelWorkspaceVO workspace = modelWorkspaceService.getWorkspace();
|
||||||
|
|
||||||
|
assertNotNull(workspace);
|
||||||
|
assertEquals(3, workspace.getProviderCount());
|
||||||
|
assertEquals(1, workspace.getHealthyProviderCount());
|
||||||
|
assertEquals(1, workspace.getUnhealthyProviderCount());
|
||||||
|
assertEquals(3, workspace.getModelCount());
|
||||||
|
assertEquals(2, workspace.getEnabledModelCount());
|
||||||
|
assertEquals(2, workspace.getRouteRuleCount());
|
||||||
|
assertEquals(1, workspace.getEnabledRouteRuleCount());
|
||||||
|
assertEquals(2, workspace.getRecentFailedCallCount());
|
||||||
|
assertEquals(2, workspace.getFailedCallSummaries().size());
|
||||||
|
assertEquals(3, workspace.getProviders().size());
|
||||||
|
assertEquals(3, workspace.getModels().size());
|
||||||
|
assertEquals(2, workspace.getRoutes().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelProviderResponse provider(Long id, String code, String healthStatus, boolean enabled) {
|
||||||
|
ModelProviderResponse response = new ModelProviderResponse();
|
||||||
|
response.setId(id);
|
||||||
|
response.setProviderCode(code);
|
||||||
|
response.setProviderName(code);
|
||||||
|
response.setHealthStatus(healthStatus);
|
||||||
|
response.setEnabled(enabled);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelConfigResponse model(Long id, Long providerId, String code, String modelType, boolean enabled) {
|
||||||
|
ModelConfigResponse response = new ModelConfigResponse();
|
||||||
|
response.setId(id);
|
||||||
|
response.setProviderId(providerId);
|
||||||
|
response.setModelCode(code);
|
||||||
|
response.setModelName(code);
|
||||||
|
response.setModelType(modelType);
|
||||||
|
response.setEnabled(enabled);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelRouteRuleResponse route(Long id, String code, String taskType, Long primaryModelId, String fallbackJson, boolean enabled) {
|
||||||
|
ModelRouteRuleResponse response = new ModelRouteRuleResponse();
|
||||||
|
response.setId(id);
|
||||||
|
response.setRouteCode(code);
|
||||||
|
response.setRouteName(code);
|
||||||
|
response.setTaskType(taskType);
|
||||||
|
response.setPrimaryModelId(primaryModelId);
|
||||||
|
response.setFallbackModelIdsJson(fallbackJson);
|
||||||
|
response.setEnabled(enabled);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ModelCallLogResponse log(String requestId, String status, String errorCode, String errorMessage) {
|
||||||
|
ModelCallLogResponse response = new ModelCallLogResponse();
|
||||||
|
response.setRequestId(requestId);
|
||||||
|
response.setStatus(status);
|
||||||
|
response.setErrorCode(errorCode);
|
||||||
|
response.setErrorMessage(errorMessage);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
frontend/src/api/__tests__/modelWorkspace.spec.ts
Normal file
20
frontend/src/api/__tests__/modelWorkspace.spec.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
|
import { getModelWorkspace } from '../modelWorkspace';
|
||||||
|
import { get } from '../request';
|
||||||
|
|
||||||
|
vi.mock('../request', () => ({
|
||||||
|
get: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('model workspace api', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads model workspace aggregate endpoint', () => {
|
||||||
|
getModelWorkspace();
|
||||||
|
|
||||||
|
expect(get).toHaveBeenCalledWith('/model/workspace');
|
||||||
|
});
|
||||||
|
});
|
||||||
28
frontend/src/api/modelWorkspace.ts
Normal file
28
frontend/src/api/modelWorkspace.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { get } from './request';
|
||||||
|
import type { ModelConfig, ModelProvider, ModelRouteRule } from './modelProvider';
|
||||||
|
|
||||||
|
export interface ModelWorkspaceFailure {
|
||||||
|
requestId: string;
|
||||||
|
status?: string | null;
|
||||||
|
errorCode?: string | null;
|
||||||
|
errorMessage?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModelWorkspace {
|
||||||
|
providerCount: number;
|
||||||
|
healthyProviderCount: number;
|
||||||
|
unhealthyProviderCount: number;
|
||||||
|
modelCount: number;
|
||||||
|
enabledModelCount: number;
|
||||||
|
routeRuleCount: number;
|
||||||
|
enabledRouteRuleCount: number;
|
||||||
|
recentFailedCallCount: number;
|
||||||
|
providers: ModelProvider[];
|
||||||
|
models: ModelConfig[];
|
||||||
|
routes: ModelRouteRule[];
|
||||||
|
failedCallSummaries: ModelWorkspaceFailure[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getModelWorkspace() {
|
||||||
|
return get<ModelWorkspace>('/model/workspace');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user