【调整】根据接口设计调整,ai model

This commit is contained in:
cherishsince 2024-05-06 16:32:47 +08:00
parent 118158424b
commit c21b5f7679
16 changed files with 392 additions and 66 deletions

View File

@ -11,24 +11,27 @@ public interface ErrorCodeConstants {
// ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ========== // ========== 模块 ai 错误码区间 [1-022-000-000 ~ 1-023-000-000) ==========
// TODO @fansili1类注释不太对2中英文之间有个空格例如说 AI 模型 // chat
ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI模型暂不支持!");
ErrorCode AI_MODULE_NOT_SUPPORTED = new ErrorCode(1_022_000_000, "AI 模型暂不支持!");
ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");; ErrorCode AI_CHAT_ROLE_NOT_EXISTENT = new ErrorCode(1_022_000_001, "AI Role 不存在!");;
ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话,对话 id 不能为空!");;
ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat 对话不存在!");
ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条 chat 对话不是你的!");
// midjourney
ErrorCode AI_CHAT_CONTINUE_CONVERSATION_ID_NOT_NULL = new ErrorCode(1_022_000_002, "chat 继续对话对话id不能为空!");;
ErrorCode AI_CHAT_CONTINUE_NOT_EXIST = new ErrorCode(1_022_000_020, "chat对话不存在!");
ErrorCode AI_CHAT_CONVERSATION_NOT_YOURS = new ErrorCode(1_022_000_021, "这条chat对话不是你的!");
ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!"); ErrorCode AI_MIDJOURNEY_IMAGINE_FAIL = new ErrorCode(1_022_000_040, "midjourney imagine 操作失败!");
ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole不存在!"); // role
ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "ai模型不存在!"); ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "chatRole 不存在!");
// modal
ErrorCode AI_MODAL_NOT_EXIST = new ErrorCode(1_022_000_080, "AI 模型不存在!");
ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} ");
ErrorCode AI_MODAL_NOT_SUPPORTED_MODAL = new ErrorCode(1_022_000_082, "AI 模型不支持的 modal! {} ");
ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} ");
} }

View File

@ -0,0 +1,11 @@
package cn.iocoder.yudao.module.ai.enums;
/**
* 枚举
*
* @author fansili
* @time 2024/5/6 11:48
* @since 1.0
*/
public enum AiChatModalTypeEnum {
}

View File

@ -30,7 +30,7 @@ public class AiChatModalController {
private final AiChatModalService aiChatModalService; private final AiChatModalService aiChatModalService;
@Operation(summary = "ai模型 - 模型照片上传") @Operation(summary = "ai模型 - 模型列表")
@GetMapping("/modal/list") @GetMapping("/modal/list")
public PageResult<AiChatModalListRes> list(@ModelAttribute AiChatModalListReq req) { public PageResult<AiChatModalListRes> list(@ModelAttribute AiChatModalListReq req) {
return aiChatModalService.list(req); return aiChatModalService.list(req);

View File

@ -22,27 +22,23 @@ public class AiChatModalDO extends BaseDO {
*/ */
private Long id; private Long id;
/** /**
* 模型key * 名字
*/ */
private String modelKey; private String name;
/** /**
* 模型类型 参考{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum} * 类型
*/
private String modelPlatform;
/**
* 模型类型
* {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel} * {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel}
* {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel} * {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel}
*/ */
private String modelType; private String modal;
/** /**
* 模型名字 * 平台 参考{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum}
*/ */
private String modelName; private String platform;
/** /**
* 模型照片 * 图片地址
*/ */
private String modalImage; private String imageUrl;
/** /**
* 禁用 0正常 1禁用 * 禁用 0正常 1禁用
*/ */

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.ai.dal.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat config
*
* @author fansili
* @time 2024/5/6 15:06
* @since 1.0
*/
@Data
@Accessors(chain = true)
public class AiChatModalChatConfigVO extends AiChatModalConfigVO {
@NotNull
@Schema(description = "在生成消息时采用的Top-K采样大小")
private Double topK;
@NotNull
@Schema(description = "Top-P核采样方法的概率阈值")
private Double topP;
@NotNull
@Schema(description = "温度参数,用于调整生成回复的随机性和多样性程度")
private Double temperature;
@NotNull
@Schema(description = "最大 tokens")
private Integer maxTokens;
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.ai.dal.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* modal config
*
* @author fansili
* @time 2024/5/6 15:06
* @since 1.0
*/
@Data
@Accessors(chain = true)
public class AiChatModalConfigVO {
/**
* 模型平台 (冗余方便类型转换)
* 参考{@link cn.iocoder.yudao.framework.ai.AiPlatformEnum}
*/
private String platform;
/**
* 模型类型(冗余方便类型转换)
* {@link cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel}
* {@link cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel}
*/
private String type;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.ai.dal.vo;
import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* dall
*
* @author fansili
* @time 2024/5/6 15:06
* @since 1.0
*/
@Data
@Accessors(chain = true)
public class AiChatModalDallConfigVO extends AiChatModalConfigVO {
// 可选字段默认为1
// 生成图像的数量必须在1到10之间对于dall-e-3模型目前仅支持n=1
private Integer n = 1;
// 可选字段默认为standard
// 设置生成图像的质量hd质量将创建细节更丰富图像整体一致性更高的图片该参数仅对dall-e-3模型有效
private String quality = "standard";
// 可选字段默认为url
// 返回生成图像的格式必须是url或b64_json中的一种URL链接的有效期是从生成图像后开始计算的60分钟内有效
private String responseFormat = "url";
// 可选字段默认为1024x1024
// 生成图像的尺寸大小对于dall-e-2模型尺寸可为256x256, 512x512, 1024x1024对于dall-e-3模型尺寸可为1024x1024, 1792x1024, 1024x1792
private String size = "1024x1024";
// 可选字段默认为vivid
// 图像生成的风格可为vivid生动或natural自然vivid会使模型偏向生成超现实和戏剧性的图像而natural则会让模型产出更自然不那么超现实的图像该参数仅对dall-e-3模型有效
private OpenAiImageStyleEnum style = OpenAiImageStyleEnum.VIVID;
// 可选字段
// 代表您的终端用户的唯一标识符有助于OpenAI监控并检测滥用行为了解更多信息请参考官方文档
private String endUserId = "UID123456";
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.ai.dal.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Midjourney Config
*
* @author fansili
* @time 2024/5/6 15:07
* @since 1.0
*/
@Data
@Accessors(chain = true)
public class AiChatModalMidjourneyConfigVO extends AiChatModalConfigVO {
}

View File

@ -0,0 +1,75 @@
//package cn.iocoder.yudao.module.ai.mapper.typeHandler;
//
//import cn.hutool.core.util.StrUtil;
//import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
//import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
//import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO;
//import org.apache.ibatis.type.BaseTypeHandler;
//import org.apache.ibatis.type.JdbcType;
//import org.apache.ibatis.type.MappedTypes;
//
//import java.sql.CallableStatement;
//import java.sql.PreparedStatement;
//import java.sql.ResultSet;
//import java.sql.SQLException;
//
///**
// * chat modal config
// *
// * @author fansili
// * @time 2024/5/6 11:18
// * @since 1.0
// */
//@MappedTypes(value = AiChatModalDO.Config.class)
//public class AiChatModelConfigTypeHandler extends BaseTypeHandler<AiChatModalDO.Config> {
//
// @Override
// public void setNonNullParameter(PreparedStatement ps, int i, AiChatModalDO.Config parameter, JdbcType jdbcType) throws SQLException {
// // MyCustomType 转换为数据库类型并设置到 PreparedStatement
// if (parameter == null) {
// ps.setString(i, "");
// } else {
// ps.setString(i, JsonUtils.toJsonString(parameter));
// }
// }
//
// @Override
// public AiChatModalDO.Config getNullableResult(ResultSet rs, String columnName) throws SQLException {
// // ResultSet 中获取数据库类型并转换为 MyCustomType
// String str = rs.getString(columnName);
// if (StrUtil.isBlank(str)) {
// return null;
// }
// AiChatModalDO.Config config = JsonUtils.parseObject(str, AiChatModalDO.Config.class);
// // 获取平台
// AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(config.getModelPlatform());
// if (AiPlatformEnum.CHAT_PLATFORM_LIST.contains(platformEnum)) {
// return JsonUtils.parseObject(str, AiChatModalDO.ChatConfig.class);
// } else if (AiPlatformEnum.OPEN_AI_DALL == platformEnum) {
// return JsonUtils.parseObject(str, AiChatModalDO.OpenAiImageConfig.class);
// } else if (AiPlatformEnum.MIDJOURNEY == platformEnum) {
// return JsonUtils.parseObject(str, AiChatModalDO.MidjourneyConfig.class);
// }
// throw new IllegalArgumentException("ai模型中config不能转换! json: " + str);
// }
//
// @Override
// public AiChatModalDO.Config getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// // ResultSet 中获取数据库类型并转换为 MyCustomType
// String str = rs.getString(columnIndex);
// if (StrUtil.isBlank(str)) {
// return null;
// }
// return JsonUtils.parseObject(str, AiChatModalDO.Config.class);
// }
//
// @Override
// public AiChatModalDO.Config getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
// // CallableStatement 中获取数据库类型并转换为 MyCustomType
// String str = cs.getString(columnIndex);
// if (StrUtil.isBlank(str)) {
// return null;
// }
// return JsonUtils.parseObject(str, AiChatModalDO.Config.class);
// }
//}

View File

@ -1,23 +1,34 @@
package cn.iocoder.yudao.module.ai.service.impl; package cn.iocoder.yudao.module.ai.service.impl;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.validation.ValidationUtil;
import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatModal;
import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel;
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.ai.ErrorCodeConstants; import cn.iocoder.yudao.module.ai.ErrorCodeConstants;
import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert; import cn.iocoder.yudao.module.ai.convert.AiChatModalConvert;
import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO; import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO;
import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalChatConfigVO;
import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalConfigVO;
import cn.iocoder.yudao.module.ai.dal.vo.AiChatModalDallConfigVO;
import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum; import cn.iocoder.yudao.module.ai.enums.AiChatModalDisableEnum;
import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper; import cn.iocoder.yudao.module.ai.mapper.AiChatModalMapper;
import cn.iocoder.yudao.module.ai.service.AiChatModalService; import cn.iocoder.yudao.module.ai.service.AiChatModalService;
import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalAddReq;
import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq; import cn.iocoder.yudao.module.ai.vo.AiChatModalListReq;
import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes; import cn.iocoder.yudao.module.ai.vo.AiChatModalListRes;
import jakarta.validation.ConstraintViolation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* ai 模型 * ai 模型
@ -40,7 +51,7 @@ public class AiChatModalServiceImpl implements AiChatModalService {
queryWrapperX.eq(AiChatModalDO::getDisable, AiChatModalDisableEnum.NO.getValue()); queryWrapperX.eq(AiChatModalDO::getDisable, AiChatModalDisableEnum.NO.getValue());
// search // search
if (!StrUtil.isBlank(req.getSearch())) { if (!StrUtil.isBlank(req.getSearch())) {
queryWrapperX.like(AiChatModalDO::getModelName, req.getSearch().trim()); queryWrapperX.like(AiChatModalDO::getName, req.getSearch().trim());
} }
// 默认排序 // 默认排序
queryWrapperX.orderByDesc(AiChatModalDO::getId); queryWrapperX.orderByDesc(AiChatModalDO::getId);
@ -53,21 +64,38 @@ public class AiChatModalServiceImpl implements AiChatModalService {
@Override @Override
public void add(AiChatModalAddReq req) { public void add(AiChatModalAddReq req) {
// 校验 platformtype
validatePlatform(req.getPlatform());
validateModal(req.getPlatform(), req.getModal());
// 转换config
AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req);
// 校验 modal config
validateModalConfig(aiChatModalConfigVO);
// 转换 do // 转换 do
AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); AiChatModalDO insertChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req);
// // 设置默认属性
insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue()); insertChatModalDO.setDisable(AiChatModalDisableEnum.NO.getValue());
insertChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO));
// 保存数据库 // 保存数据库
aiChatModalMapper.insert(insertChatModalDO); aiChatModalMapper.insert(insertChatModalDO);
} }
@Override @Override
public void update(Long id, AiChatModalAddReq req) { public void update(Long id, AiChatModalAddReq req) {
// 校验 platformtype
validatePlatform(req.getPlatform());
validateModal(req.getPlatform(), req.getModal());
// 转换config
AiChatModalConfigVO aiChatModalConfigVO = convertConfig(req);
// 校验 modal config
validateModalConfig(aiChatModalConfigVO);
// 校验模型是否存在 // 校验模型是否存在
validateChatModalExists(id); validateChatModalExists(id);
// 转换 updateChatModalDO // 转换 updateChatModalDO
AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req); AiChatModalDO updateChatModalDO = AiChatModalConvert.INSTANCE.convertAiChatModalDO(req);
updateChatModalDO.setId(id); updateChatModalDO.setId(id);
updateChatModalDO.setConfig(JsonUtils.toJsonString(aiChatModalConfigVO));
// 更新数据库 // 更新数据库
aiChatModalMapper.updateById(updateChatModalDO); aiChatModalMapper.updateById(updateChatModalDO);
} }
@ -86,4 +114,52 @@ public class AiChatModalServiceImpl implements AiChatModalService {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST); throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_EXIST);
} }
} }
private void validateModal(String platform, String modal) {
AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(platform);
try {
if (AiPlatformEnum.QIAN_WEN == platformEnum) {
QianWenChatModal.valueOfModel(modal);
} else if (AiPlatformEnum.XING_HUO == platformEnum) {
XingHuoChatModel.valueOfModel(modal);
} else if (AiPlatformEnum.YI_YAN == platformEnum) {
YiYanChatModel.valueOfModel(modal);
} else {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_NOT_SUPPORTED_MODAL, platform);
}
} catch (IllegalArgumentException e) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, e.getMessage());
}
}
private void validatePlatform(String platform) {
try {
AiPlatformEnum.valueOfPlatform(platform);
} catch (IllegalArgumentException e) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_PLATFORM_PARAMS_INCORRECT, e.getMessage());
}
}
private void validateModalConfig(AiChatModalConfigVO aiChatModalConfigVO) {
Set<ConstraintViolation<AiChatModalConfigVO>> validate = ValidationUtil.validate(aiChatModalConfigVO);
for (ConstraintViolation<AiChatModalConfigVO> constraintViolation : validate) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_MODAL_CONFIG_PARAMS_INCORRECT, constraintViolation.getMessage());
}
}
private static AiChatModalConfigVO convertConfig(AiChatModalAddReq req) {
AiPlatformEnum platformEnum = AiPlatformEnum.valueOfPlatform(req.getPlatform());
AiChatModalConfigVO resVo = null;
if (AiPlatformEnum.CHAT_PLATFORM_LIST.contains(platformEnum)) {
resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalChatConfigVO.class);
} else if (AiPlatformEnum.OPEN_AI_DALL == platformEnum) {
resVo = JsonUtils.parseObject(JsonUtils.toJsonString(req.getConfig()), AiChatModalDallConfigVO.class);
}
if (resVo == null) {
throw new IllegalArgumentException("ai模型中config不能转换! json: " + req.getConfig());
}
resVo.setType(req.getModal());
resVo.setPlatform(req.getPlatform());
return resVo;
}
} }

View File

@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.ai.image.ImageGeneration;
import cn.iocoder.yudao.framework.ai.image.ImagePrompt; import cn.iocoder.yudao.framework.ai.image.ImagePrompt;
import cn.iocoder.yudao.framework.ai.image.ImageResponse; import cn.iocoder.yudao.framework.ai.image.ImageResponse;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageClient;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions; import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageOptions;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum;
import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi; import cn.iocoder.yudao.framework.ai.midjourney.api.MidjourneyInteractionsApi;
import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.MidjourneyWebSocketStarter;
import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify; import cn.iocoder.yudao.framework.ai.midjourney.webSocket.WssNotify;
@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.ai.mapper.AiImageMapper;
import cn.iocoder.yudao.module.ai.service.AiImageService; import cn.iocoder.yudao.module.ai.service.AiImageService;
import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq; import cn.iocoder.yudao.module.ai.vo.AiImageDallDrawingReq;
import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq; import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyReq;
import cn.iocoder.yudao.module.ai.vo.AiImageMidjourneyRes;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;

View File

@ -6,6 +6,8 @@ import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.Map;
/** /**
* ai chat modal * ai chat modal
* *
@ -19,18 +21,24 @@ public class AiChatModalAddReq {
@NotNull @NotNull
@Schema(description = "模型名字") @Schema(description = "模型名字")
@Size(max = 60, message = "模型名字最大60") @Size(max = 60, message = "模型名字最大60个字符")
private String modelName; private String name;
@NotNull
@Size(max = 32, message = "模型平台最大32个字符")
@Schema(description = "模型平台 参考 AiPlatformEnum")
private String platform;
@NotNull @NotNull
@Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)") @Schema(description = "模型类型(qianwen、yiyan、xinghuo、openai)")
@Size(max = 32, message = "模型类型最大32") @Size(max = 32, message = "模型类型最大32个字符")
private String modelType; private String modal;
@Schema(description = "模型照片") @Schema(description = "模型照片")
private String modalImage; @Size(max = 256, message = "模型照片地址最大256个字符")
private String imageUrl;
@Schema(description = "模型配置JSON") @Schema(description = "模型配置JSON")
private String modelConfig; // @Size(max = 1024, message = "模型配置最大1024个字符")
private Map<String, Object> config;
} }

View File

@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.ai.vo; package cn.iocoder.yudao.module.ai.vo;
import cn.iocoder.yudao.module.ai.dal.dataobject.AiChatModalDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -13,29 +15,25 @@ import lombok.experimental.Accessors;
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class AiChatModalListRes { public class AiChatModalListRes {
/**
* 编号 @Schema(description = "id")
*/
private Long id; private Long id;
/**
* 模型名字 @Schema(description = "模型平台 参考 AiPlatformEnum")
*/ private String platform;
private String modelName;
/** @Schema(description = "模型类型 参考 YiYanChatModel、XingHuoChatModel")
* 模型类型(qianwenyiyanxinghuoopenai) private String modal;
*/
private String modelType; @Schema(description = "模型名字")
/** private String name;
* 模型照片
*/ @Schema(description = "模型照片")
private String modalImage; private String image;
/**
* 模型配置JSON @Schema(description = "禁用 0、正常 1、禁用")
*/
private String modelConfig;
/**
* 禁用 0正常 1禁用
*/
private Integer disable; private Integer disable;
@Schema(description = "modal 配置")
private String config;
} }

View File

@ -1,19 +1,41 @@
### chat call ### chat call
GET {{baseUrl}}/ai/chat/modal/list GET {{baseUrl}}/ai/chat/modal/list
Authorization: {{token}} Authorization: {{token}}
### chat call ### chat call
PUT {{baseUrl}}/ai/chat/modal PUT {{baseUrl}}/ai/chat/modal
Content-Type: application/json Content-Type: application/json
Authorization: {{token}} Authorization: {{token}}
{ {
"modelName": "小红书Ai写作大模型", "name": "小红书Ai写作大模型-plus",
"modelType": "yiyan", "modal": "ERNIE-3.5-8K",
"modalImage": "", "platform": "yiyan",
"modelConfig": "" "imageUrl": "",
"config": {
"topK": 0.6,
"topP": 0.6,
"temperature": 0.86,
"maxTokens": 2048
}
}
### chat call
POST {{baseUrl}}/ai/chat/modal/7
Content-Type: application/json
Authorization: {{token}}
{
"name": "小红书Ai写作大模型-plus",
"modal": "ERNIE-3.5-8K",
"platform": "yiyan",
"imageUrl": "",
"config": {
"topK": 0.6,
"topP": 0.6,
"temperature": 0.86,
"maxTokens": 2048
}
} }

View File

@ -1,8 +1,11 @@
package cn.iocoder.yudao.framework.ai; package cn.iocoder.yudao.framework.ai;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import java.util.List;
/** /**
* ai 模型平台 * ai 模型平台
* *
@ -17,12 +20,27 @@ public enum AiPlatformEnum {
YI_YAN("yiyan", "一言"), YI_YAN("yiyan", "一言"),
QIAN_WEN("qianwen", "千问"), QIAN_WEN("qianwen", "千问"),
XING_HUO("xinghuo", "星火"), XING_HUO("xinghuo", "星火"),
OPEN_AI("openai", "openAi"),
OPEN_AI_DALL("dall", "dall"),
MIDJOURNEY("midjourney", "midjourney"),
; ;
private String platform; private String platform;
private String name; private String name;
public static List<AiPlatformEnum> CHAT_PLATFORM_LIST = Lists.newArrayList(
AiPlatformEnum.YI_YAN,
AiPlatformEnum.QIAN_WEN,
AiPlatformEnum.XING_HUO,
AiPlatformEnum.OPEN_AI
);
public static List<AiPlatformEnum> IMAGE_PLATFORM_LIST = Lists.newArrayList(
AiPlatformEnum.OPEN_AI_DALL,
AiPlatformEnum.MIDJOURNEY
);
public static AiPlatformEnum valueOfPlatform(String platform) { public static AiPlatformEnum valueOfPlatform(String platform) {
for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) { for (AiPlatformEnum itemEnum : AiPlatformEnum.values()) {
if (itemEnum.getPlatform().equals(platform)) { if (itemEnum.getPlatform().equals(platform)) {

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.ai.config;
import cn.iocoder.yudao.framework.ai.AiPlatformEnum; import cn.iocoder.yudao.framework.ai.AiPlatformEnum;
import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel; import cn.iocoder.yudao.framework.ai.chatxinghuo.XingHuoChatModel;
import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel; import cn.iocoder.yudao.framework.ai.chatyiyan.YiYanChatModel;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageModelEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageModelEnum;
import cn.iocoder.yudao.framework.ai.imageopenai.OpenAiImageStyleEnum; import cn.iocoder.yudao.framework.ai.imageopenai.enums.OpenAiImageStyleEnum;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;