package com.vincent.rsf.server.ai.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.vincent.rsf.framework.exception.CoolException;
|
import com.vincent.rsf.server.ai.config.AiDefaults;
|
import com.vincent.rsf.server.ai.entity.AiParam;
|
import com.vincent.rsf.server.ai.mapper.AiParamMapper;
|
import com.vincent.rsf.server.ai.service.AiParamService;
|
import com.vincent.rsf.server.system.enums.StatusType;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
|
@Service("aiParamService")
|
public class AiParamServiceImpl extends ServiceImpl<AiParamMapper, AiParam> implements AiParamService {
|
|
@Override
|
public AiParam getActiveParam(Long tenantId) {
|
ensureTenantId(tenantId);
|
AiParam aiParam = this.getOne(new LambdaQueryWrapper<AiParam>()
|
.eq(AiParam::getTenantId, tenantId)
|
.eq(AiParam::getStatus, StatusType.ENABLE.val)
|
.eq(AiParam::getDeleted, 0)
|
.last("limit 1"));
|
if (aiParam == null) {
|
throw new CoolException("未找到启用中的 AI 参数配置");
|
}
|
return aiParam;
|
}
|
|
@Override
|
public void validateBeforeSave(AiParam aiParam, Long tenantId) {
|
ensureTenantId(tenantId);
|
aiParam.setTenantId(tenantId);
|
fillDefaults(aiParam);
|
ensureBaseFields(aiParam);
|
ensureSingleActive(tenantId, null, aiParam.getStatus());
|
}
|
|
@Override
|
public void validateBeforeUpdate(AiParam aiParam, Long tenantId) {
|
ensureTenantId(tenantId);
|
fillDefaults(aiParam);
|
if (aiParam.getId() == null) {
|
throw new CoolException("AI 参数 ID 不能为空");
|
}
|
AiParam current = requireOwnedRecord(aiParam.getId(), tenantId);
|
aiParam.setTenantId(current.getTenantId());
|
ensureBaseFields(aiParam);
|
ensureSingleActive(tenantId, aiParam.getId(), aiParam.getStatus());
|
}
|
|
private void ensureBaseFields(AiParam aiParam) {
|
if (!StringUtils.hasText(aiParam.getName())) {
|
throw new CoolException("AI 参数名称不能为空");
|
}
|
if (!StringUtils.hasText(aiParam.getProviderType())) {
|
aiParam.setProviderType(AiDefaults.PROVIDER_OPENAI_COMPATIBLE);
|
}
|
if (!StringUtils.hasText(aiParam.getBaseUrl())) {
|
throw new CoolException("AI Base URL 不能为空");
|
}
|
if (!StringUtils.hasText(aiParam.getApiKey())) {
|
throw new CoolException("AI API Key 不能为空");
|
}
|
if (!StringUtils.hasText(aiParam.getModel())) {
|
throw new CoolException("AI 模型不能为空");
|
}
|
}
|
|
private void ensureSingleActive(Long tenantId, Long selfId, Integer status) {
|
if (status == null || status != StatusType.ENABLE.val) {
|
return;
|
}
|
LambdaQueryWrapper<AiParam> wrapper = new LambdaQueryWrapper<AiParam>()
|
.eq(AiParam::getTenantId, tenantId)
|
.eq(AiParam::getStatus, StatusType.ENABLE.val)
|
.eq(AiParam::getDeleted, 0);
|
if (selfId != null) {
|
wrapper.ne(AiParam::getId, selfId);
|
}
|
if (this.count(wrapper) > 0) {
|
throw new CoolException("同一租户仅允许一条启用中的 AI 参数配置");
|
}
|
}
|
|
private AiParam requireOwnedRecord(Long id, Long tenantId) {
|
AiParam aiParam = this.getOne(new LambdaQueryWrapper<AiParam>()
|
.eq(AiParam::getId, id)
|
.eq(AiParam::getTenantId, tenantId)
|
.eq(AiParam::getDeleted, 0)
|
.last("limit 1"));
|
if (aiParam == null) {
|
throw new CoolException("AI 参数不存在或无权访问");
|
}
|
return aiParam;
|
}
|
|
private void ensureTenantId(Long tenantId) {
|
if (tenantId == null) {
|
throw new CoolException("当前租户不存在");
|
}
|
}
|
|
private void fillDefaults(AiParam aiParam) {
|
if (!StringUtils.hasText(aiParam.getProviderType())) {
|
aiParam.setProviderType(AiDefaults.PROVIDER_OPENAI_COMPATIBLE);
|
}
|
if (aiParam.getTemperature() == null) {
|
aiParam.setTemperature(AiDefaults.DEFAULT_TEMPERATURE);
|
}
|
if (aiParam.getTopP() == null) {
|
aiParam.setTopP(AiDefaults.DEFAULT_TOP_P);
|
}
|
if (aiParam.getTimeoutMs() == null) {
|
aiParam.setTimeoutMs(AiDefaults.DEFAULT_TIMEOUT_MS);
|
}
|
if (aiParam.getStreamingEnabled() == null) {
|
aiParam.setStreamingEnabled(Boolean.TRUE);
|
}
|
if (aiParam.getStatus() == null) {
|
aiParam.setStatus(StatusType.ENABLE.val);
|
}
|
}
|
}
|