【新增】AI:聊天角色管理(50%)

This commit is contained in:
YunaiV 2024-05-13 20:46:37 +08:00
parent 6bc1f8d0f9
commit 1676f671d8
19 changed files with 355 additions and 574 deletions

View File

@ -18,8 +18,9 @@ public interface ErrorCodeConstants {
ErrorCode CHAT_MODAL_NOT_EXIST = new ErrorCode(1_040_001_000, "AI 模型不存在!");
ErrorCode CHAT_MODAL_DISABLE = new ErrorCode(1_040_001_001, "AI 模型({})已禁用!");
// ErrorCode AI_MODAL_CONFIG_PARAMS_INCORRECT = new ErrorCode(1_022_000_081, "AI 模型 config 参数不正确! {} ");
// ErrorCode AI_MODAL_PLATFORM_PARAMS_INCORRECT = new ErrorCode(1_022_000_083, "AI 平台参数不正确! {} ");
// ========== API 聊天模型 1-040-002-000 ==========
ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "AI 聊天角色不存在");
ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "AI 聊天角色({})已禁用!");
// conversation
@ -31,14 +32,7 @@ public interface ErrorCodeConstants {
ErrorCode AI_MIDJOURNEY_OPERATION_NOT_EXISTS = new ErrorCode(1_022_000_040, "midjourney 操作不存在!");
ErrorCode AI_MIDJOURNEY_MESSAGE_ID_INCORRECT = new ErrorCode(1_022_000_040, "midjourney message id 不正确!");
// role
ErrorCode AI_CHAT_ROLE_NOT_EXIST = new ErrorCode(1_022_000_060, "AI 角色不存在!");
ErrorCode AI_CHAT_ROLE_NOT_PUBLIC = new ErrorCode(1_022_000_060, "AI 角色未公开!");
// chat
ErrorCode AI_CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_022_000_100, "AI 提问的 MessageId 不存在!");
}

View File

@ -1,17 +1,30 @@
package cn.iocoder.yudao.module.ai.controller.admin.model;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*;
import cn.iocoder.yudao.module.ai.service.AiChatRoleService;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - AI 聊天角色")
@RestController
@RequestMapping("/ai/chat-role")
@ -21,42 +34,55 @@ public class AiChatRoleController {
@Resource
private AiChatRoleService chatRoleService;
@Operation(summary = "chat角色 - 角色列表")
@GetMapping("/list")
public PageResult<AiChatRoleListRespVO> list(@Validated @ModelAttribute AiChatRoleListReqVO req) {
return chatRoleService.list(req);
}
// TODO 芋艿我的分页
@Operation(summary = "chat角色 - 添加")
@PutMapping("/add")
public CommonResult<Void> add(@Validated @RequestBody AiChatRoleAddReqVO req) {
chatRoleService.add(req);
return CommonResult.success(null);
}
// TODO 芋艿我的新增
@Operation(summary = "chat角色 - 修改")
@PostMapping("/update")
public CommonResult<Void> update(@Validated @RequestBody AiChatRoleUpdateReqVO req) {
chatRoleService.update(req);
return CommonResult.success(null);
}
// TODO 芋艿我的修改
@Operation(summary = "chat角色 - 修改可见性")
@PostMapping("/update-public-status")
public CommonResult<Void> updatePublicStatus(@Validated @RequestBody AiChatRoleUpdatePublicStatusReqVO req) {
chatRoleService.updatePublicStatus(req);
return CommonResult.success(null);
}
@Operation(summary = "chat角色 - 删除")
@DeleteMapping("/delete")
public CommonResult<Void> delete(@RequestParam("id") Long id) {
chatRoleService.delete(id);
return CommonResult.success(null);
}
// TODO 芋艿我的删除
// ========== 角色管理 ==========
@PostMapping("/create")
@Operation(summary = "创建聊天角色")
@PreAuthorize("@ss.hasPermission('ai:chat-role:create')")
public CommonResult<Long> createChatRole(@Valid @RequestBody AiChatRoleSaveReqVO createReqVO) {
return success(chatRoleService.createChatRole(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新聊天角色")
@PreAuthorize("@ss.hasPermission('ai:chat-role:update')")
public CommonResult<Boolean> updateChatRole(@Valid @RequestBody AiChatRoleSaveReqVO updateReqVO) {
chatRoleService.updateChatRole(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除聊天角色")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('ai:chat-role:delete')")
public CommonResult<Boolean> deleteChatRole(@RequestParam("id") Long id) {
chatRoleService.deleteChatRole(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得聊天角色")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('ai:chat-role:query')")
public CommonResult<AiChatRoleRespVO> getChatRole(@RequestParam("id") Long id) {
AiChatRoleDO chatRole = chatRoleService.getChatRole(id);
return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得聊天角色分页")
@PreAuthorize("@ss.hasPermission('ai:chat-role:query')")
public CommonResult<PageResult<AiChatRoleRespVO>> getChatRolePage(@Valid AiChatRolePageReqVO pageReqVO) {
PageResult<AiChatRoleDO> pageResult = chatRoleService.getChatRolePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class));
}
}

View File

@ -1,52 +0,0 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色列表
*
* @fansili
* @since v1.0
*/
@Data
@Accessors(chain = true)
public class AiChatRoleAddReqVO {
@NotNull
@Schema(description = "角色名,角色的显示名称")
private String name;
@Schema(description = "头像")
private String avatar;
@NotNull
@Schema(description = "分类,角色所属的类别,如娱乐、创作等")
private String category;
@NotNull
@Schema(description = "角色描述")
private String description;
@Schema(description = "角色欢迎语")
private String welcomeMessage;
@NotNull
@Schema(description = "角色设定(消息)")
private String systemMessage;
@NotNull
@Schema(description = "模型编号")
private Long modelId;
@NotNull
@Schema(description = "开启状态 0、open 1、close")
private Boolean publicStatus;
@NotNull
@Schema(description = "排序")
private Integer sort;
}

View File

@ -1,20 +0,0 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色列表
*
* @fansili
* @since v1.0
*/
@Data
@Accessors(chain = true)
public class AiChatRoleListReqVO extends PageParam {
@Schema(description = "查询")
private String search;
}

View File

@ -1,52 +0,0 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色列表
*
* @fansili
* @since v1.0
*/
@Data
@Accessors(chain = true)
public class AiChatRoleListRespVO {
@Schema(description = "编号", example = "1")
private Long id;
@Schema(description = "角色名称", example = "小红书写作")
private String name;
@Schema(description = "角色头像", example = "http://...")
private String avatar;
@Schema(description = "角色分类", example = "writing")
private String category;
@Schema(description = "角色描述", example = "角色描述")
private String description;
@Schema(description = "角色欢迎语", example = "欢迎...")
private String welcomeMessage;
@Schema(description = "角色设定(消息)", example = "你是拥有丰富的小红书写作经验作者xxxx")
private String systemMessage;
@Schema(description = "用户编号", example = "1")
private Long userId;
@Schema(description = "模型编号", example = "1")
private Long modelId;
@Schema(description = "是否公开 true - 公开false - 私有", example = "true")
private Boolean publicStatus;
@Schema(description = "排序值 asc", example = "1")
private Integer sort;
@Schema(description = "状态 0、开启 1、关闭", example = "1")
private Integer status;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - AI 聊天角色分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AiChatRolePageReqVO extends PageParam {
@Schema(description = "角色名称", example = "李四")
private String name;
@Schema(description = "角色类别", example = "创作")
private String category;
@Schema(description = "是否公开", example = "1")
private Boolean publicStatus;
}

View File

@ -2,36 +2,50 @@ package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色
*
* @fansili
* @since v1.0
*/
import java.time.LocalDateTime;
@Schema(description = "管理后台 - AI 聊天角色 Response VO")
@Data
@Accessors(chain = true)
public class AiChatRoleRespVO {
@Schema(description = "id")
@Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32746")
private Long id;
@Schema(description = "用户id")
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9442")
private Long userId;
@Schema(description = "角色名字")
@Schema(description = "模型编号", example = "17640")
private Long modelId;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String name;
@Schema(description = "角色介绍,详细描述角色的功能或用途")
private String introduce;
@Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
private String avatar;
@Schema(description = "分类,角色所属的类别,如娱乐、创作等")
private String classify;
@Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作")
private String category;
@Schema(description = "状态 open、close")
private String enable;
@Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sort;
@Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
private String description;
@Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED)
private String welcomeMessage;
@Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED)
private String systemMessage;
@Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Boolean publicStatus;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "角色的使用次数统计")
private Integer useCount;
}

View File

@ -0,0 +1,57 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import jakarta.validation.constraints.*;
@Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO")
@Data
public class AiChatRoleSaveReqVO {
@Schema(description = "角色编号", example = "32746")
private Long id;
@Schema(description = "模型编号", example = "17640")
private Long modelId;
@Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotEmpty(message = "角色名称不能为空")
private String name;
@Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
@NotEmpty(message = "角色头像不能为空")
private String avatar;
@Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作")
@NotEmpty(message = "角色类别不能为空")
private String category;
@Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "角色排序不能为空")
private Integer sort;
@Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对")
@NotEmpty(message = "角色描述不能为空")
private String description;
@Schema(description = "角色欢迎语", requiredMode = Schema.RequiredMode.REQUIRED, example = "Talk is cheap, i will show code")
@NotEmpty(message = "角色欢迎语不能为空")
private String welcomeMessage;
@Schema(description = "角色上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题")
@NotEmpty(message = "角色上下文不能为空")
private String systemMessage;
@Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "是否公开不能为空")
private Boolean publicStatus;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色 - 修改可见性
*
* @fansili
* @since v1.0
*/
@Data
@Accessors(chain = true)
public class AiChatRoleUpdatePublicStatusReqVO extends PageParam {
@NotNull(message = "角色编号不能为空")
@Schema(description = "角色编号")
private Long id;
@NotNull(message = "开启状态不能为空")
@Schema(description = "开启状态 open、close")
private Boolean publicStatus;
}

View File

@ -1,62 +0,0 @@
package cn.iocoder.yudao.module.ai.controller.admin.model.vo.role;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* chat 角色 - 更新
*
* @fansili
* @since v1.0
*/
@Data
@Accessors(chain = true)
public class AiChatRoleUpdateReqVO extends PageParam {
@NotNull(message = "角色编号不能为空")
@Schema(description = "角色编号")
private Long id;
@NotNull
@Schema(description = "角色名,角色的显示名称")
private String name;
@Schema(description = "头像")
private String avatar;
@NotNull
@Schema(description = "分类,角色所属的类别,如娱乐、创作等")
private String category;
@NotNull
@Schema(description = "角色描述")
private String description;
@Schema(description = "角色欢迎语")
private String welcomeMessage;
@NotNull
@Schema(description = "角色设定(消息)")
private String systemMessage;
@NotNull
@Schema(description = "模型编号")
private Long modelId;
@NotNull
@Schema(description = "开启状态 open、close")
private Boolean publicStatus;
@NotNull
@Schema(description = "排序")
private Integer sort;
@NotNull
@Schema(description = "状态")
private Integer status;
}

View File

@ -1,56 +0,0 @@
package cn.iocoder.yudao.module.ai.convert;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleAddReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleListRespVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 聊天 对话 convert
*
* @author fansili
* @time 2024/4/18 16:39
* @since 1.0
*/
@Mapper
public interface AiChatRoleConvert {
AiChatRoleConvert INSTANCE = Mappers.getMapper(AiChatRoleConvert.class);
/**
* 转换 - ChatRoleListRes
*
* @param roleList
* @return
*/
List<AiChatRoleListRespVO> convertChatRoleListRes(List<AiChatRoleDO> roleList);
/**
* 转换 - AiChatRoleDO
*
* @param req
* @return
*/
AiChatRoleDO convertAiChatRoleDO(AiChatRoleAddReqVO req);
/**
* 转换 - AiChatRoleDO
*
* @param req
* @return
*/
AiChatRoleDO convertAiChatRoleDO(AiChatRoleUpdateReqVO req);
/**
* 转换 - AiChatRoleRes
*
* @param aiChatRoleDO
* @return
*/
AiChatRoleRespVO convertAiChatRoleRes(AiChatRoleDO aiChatRoleDO);
}

View File

@ -46,7 +46,7 @@ public class AiChatRoleDO extends BaseDO {
*/
private String welcomeMessage;
/**
* 角色设定消息
* 角色上下文
*/
private String systemMessage;
@ -65,9 +65,10 @@ public class AiChatRoleDO extends BaseDO {
private Long modelId;
/**
* 是否公开 true - 公开false - 私有
* 是否公开
*
* true - 公开false - 私有
* 1. true - 公开由管理员在角色管理所创建
* 2. false - 私有由个人在我的角色所创建
*/
private Boolean publicStatus;

View File

@ -1,17 +1,27 @@
package cn.iocoder.yudao.module.ai.dal.mysql;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* role mapper
* AI 聊天角色 Mapper
*
* @fansili
* @since v1.0
* @author fansili
*/
@Repository
@Mapper
public interface AiChatRoleMapper extends BaseMapperX<AiChatRoleDO> {
default PageResult<AiChatRoleDO> selectPage(AiChatRolePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<AiChatRoleDO>()
.likeIfPresent(AiChatRoleDO::getName, reqVO.getName())
.eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory())
.eqIfPresent(AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus())
.orderByDesc(AiChatRoleDO::getId));
}
}

View File

@ -1,76 +0,0 @@
package cn.iocoder.yudao.module.ai.service;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
/**
* chat 角色
*
* @fansili
* @since v1.0
*/
public interface AiChatRoleService {
/**
* 获取聊天角色列表
*
* @param req
* @return
*/
PageResult<AiChatRoleListRespVO> list(AiChatRoleListReqVO req);
/**
* chat角色 - 添加
*
* @param req
* @return
*/
void add(AiChatRoleAddReqVO req);
/**
* chat角色 - 修改
*
* @param req
*/
void update(AiChatRoleUpdateReqVO req);
/**
* chat角色 - 修改可见性
*
* @param req
*/
void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req);
/**
* chat角色 - 删除
*
* @param chatRoleId
*/
void delete(Long chatRoleId);
/**
* 获取角色
*
* @param roleId
* @return
*/
AiChatRoleRespVO getChatRole(Long roleId);
/**
* 校验 - 角色是否存在
*
* @param id
* @return
*/
AiChatRoleDO validateExists(Long id);
/**
* 校验 - 角色是否公开
*
* @param aiChatRoleDO
*/
void validateIsPublic(AiChatRoleDO aiChatRoleDO);
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.ai.service.model;
package cn.iocoder.yudao.module.ai.service.impl;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
@ -7,14 +7,15 @@ import cn.iocoder.yudao.module.ai.ErrorCodeConstants;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleRespVO;
import cn.iocoder.yudao.module.ai.convert.AiChatConversationConvert;
import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatModelMapper;
import cn.iocoder.yudao.module.ai.service.AiChatConversationService;
import cn.iocoder.yudao.module.ai.service.AiChatRoleService;
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
@ -45,10 +46,7 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
// 默认使用 sort 排序第一个模型
AiChatModelDO aiChatModalDO = aiChatModalMapper.selectFirstModal();
// 查询角色
AiChatRoleRespVO chatRoleRes = null;
if (req.getRoleId() != null) {
chatRoleRes = aiChatRoleService.getChatRole(req.getRoleId());
}
AiChatRoleDO chatRoleRes = req.getRoleId() != null ? aiChatRoleService.getChatRole(req.getRoleId()) : null;
Long chatRoleId = chatRoleRes != null ? chatRoleRes.getId() : null;
// 创建新的 Conversation
AiChatConversationDO insertConversation = saveConversation(AiCommonConstants.CONVERSATION_DEFAULT_TITLE,

View File

@ -1,129 +0,0 @@
package cn.iocoder.yudao.module.ai.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.ai.ErrorCodeConstants;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.*;
import cn.iocoder.yudao.module.ai.convert.AiChatRoleConvert;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper;
import cn.iocoder.yudao.module.ai.enums.AiChatRoleCategoryEnum;
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
import cn.iocoder.yudao.module.ai.service.AiChatRoleService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* chat 角色
*
* @fansili
* @since v1.0
*/
@Service
@AllArgsConstructor
@Slf4j
public class AiChatRoleServiceImpl implements AiChatRoleService {
private final AiChatRoleMapper aiChatRoleMapper;
private final AiChatModelService aiChatModalService;
@Override
public PageResult<AiChatRoleListRespVO> list(AiChatRoleListReqVO req) {
// 查询条件
LambdaQueryWrapperX<AiChatRoleDO> queryWrapperX = new LambdaQueryWrapperX<>();
// search 查询
if (!StrUtil.isBlank(req.getSearch())) {
queryWrapperX.eq(AiChatRoleDO::getName, req.getSearch());
}
// 默认排序id desc
queryWrapperX.orderByDesc(AiChatRoleDO::getId);
//
PageResult<AiChatRoleDO> aiChatRoleDOPageResult = aiChatRoleMapper.selectPage(req, queryWrapperX);
Long total = aiChatRoleDOPageResult.getTotal();
List<AiChatRoleDO> roleList = aiChatRoleDOPageResult.getList();
// 换货res
List<AiChatRoleListRespVO> chatRoleListResList = AiChatRoleConvert.INSTANCE.convertChatRoleListRes(roleList);
return new PageResult<>(chatRoleListResList, total);
}
@Override
public void add(AiChatRoleAddReqVO req) {
// 转换enum并校验enum
AiChatRoleCategoryEnum.valueOfCategory(req.getCategory());
// 校验模型是否存在 TODO
// aiChatModalService.validateExists(req.getModelId());
// 转换do
AiChatRoleDO insertAiChatRoleDO = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req);
insertAiChatRoleDO.setUserId(SecurityFrameworkUtils.getLoginUserId());
insertAiChatRoleDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
// 保存
aiChatRoleMapper.insert(insertAiChatRoleDO);
}
@Override
public void update(AiChatRoleUpdateReqVO req) {
// 检查角色是否存在
validateExists(req.getId());
// 转换enum并校验enum
AiChatRoleCategoryEnum.valueOfCategory(req.getCategory());
// 校验模型是否存在 TODO
// aiChatModalService.validateExists(req.getModelId());
// 转换do
AiChatRoleDO updateChatRole = AiChatRoleConvert.INSTANCE.convertAiChatRoleDO(req);
updateChatRole.setId(req.getId());
aiChatRoleMapper.updateById(updateChatRole);
}
@Override
public void updatePublicStatus(AiChatRoleUpdatePublicStatusReqVO req) {
// 检查角色是否存在
validateExists(req.getId());
// 更新
aiChatRoleMapper.updateById(
new AiChatRoleDO()
.setId(req.getId())
.setPublicStatus(req.getPublicStatus())
);
}
@Override
public void delete(Long chatRoleId) {
// 检查角色是否存在
validateExists(chatRoleId);
// 删除
aiChatRoleMapper.deleteById(chatRoleId);
}
@Override
public AiChatRoleRespVO getChatRole(Long roleId) {
// 检查角色是否存在
AiChatRoleDO aiChatRoleDO = validateExists(roleId);
return AiChatRoleConvert.INSTANCE.convertAiChatRoleRes(aiChatRoleDO);
}
public AiChatRoleDO validateExists(Long id) {
AiChatRoleDO aiChatRoleDO = aiChatRoleMapper.selectById(id);
if (aiChatRoleDO == null) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_EXIST);
}
return aiChatRoleDO;
}
public void validateIsPublic(AiChatRoleDO aiChatRoleDO) {
if (aiChatRoleDO == null) {
return;
}
if (!aiChatRoleDO.getPublicStatus()) {
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AI_CHAT_ROLE_NOT_PUBLIC);
}
}
}

View File

@ -23,12 +23,11 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatConversationMapper;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatMessageMapper;
import cn.iocoder.yudao.module.ai.service.AiChatConversationService;
import cn.iocoder.yudao.module.ai.service.AiChatRoleService;
import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
import cn.iocoder.yudao.module.ai.service.AiChatService;
import cn.iocoder.yudao.module.ai.service.model.AiChatModelService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
@ -53,12 +52,12 @@ import java.util.stream.Collectors;
public class AiChatServiceImpl implements AiChatService {
private final AiChatClientFactory aiChatClientFactory;
private final AiChatMessageMapper aiChatMessageMapper;
private final AiChatConversationMapper aiChatConversationMapper;
private final AiChatConversationService chatConversationService;
private final AiChatModelService aiChatModalService;
private final AiChatRoleService aiChatRoleService;
private final HttpMessageConverters messageConverters;
private final AiChatRoleService chatRoleService;
@Transactional(rollbackFor = Exception.class)
public AiChatMessageRespVO chat(AiChatMessageSendReqVO req) {
@ -68,12 +67,7 @@ public class AiChatServiceImpl implements AiChatService {
// 获取对话模型
AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId());
// 获取角色信息
AiChatRoleDO aiChatRoleDO = null;
if (conversation.getRoleId() != null) {
aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId());
}
// 校验角色是否公开
aiChatRoleService.validateIsPublic(aiChatRoleDO);
AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null;
// 获取 client 类型
AiPlatformEnum platformEnum = AiPlatformEnum.validatePlatform(chatModel.getPlatform());
// 保存 chat message
@ -142,12 +136,7 @@ public class AiChatServiceImpl implements AiChatService {
// 获取对话模型
AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId());
// 获取角色信息
AiChatRoleDO aiChatRoleDO = null;
if (conversation.getRoleId() != null) {
aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId());
}
// 校验角色是否公开
aiChatRoleService.validateIsPublic(aiChatRoleDO);
AiChatRoleDO chatRoleDO = conversation.getRoleId() != null ? chatRoleService.validateChatRole(conversation.getRoleId()) : null;
// 创建 chat 需要的 Prompt
Prompt prompt = new Prompt(aiChatMessageDO.getContent());
// 提前创建一个 system message
@ -204,13 +193,6 @@ public class AiChatServiceImpl implements AiChatService {
AiChatConversationRespVO conversation = chatConversationService.getConversationOfValidate(req.getConversationId());
// 获取对话模型
AiChatModelDO chatModel = aiChatModalService.validateChatModel(conversation.getModelId());
// 获取角色信息
AiChatRoleDO aiChatRoleDO = null;
if (conversation.getRoleId() != null) {
aiChatRoleDO = aiChatRoleService.validateExists(conversation.getRoleId());
}
// 校验角色是否公开
aiChatRoleService.validateIsPublic(aiChatRoleDO);
AiChatMessageDO userMessage = insertChatMessage(conversation.getId(), MessageType.USER, loginUserId, conversation.getRoleId(),
chatModel.getModel(), chatModel.getId(), req.getContent(),
null, conversation.getTemperature(), conversation.getMaxTokens(), conversation.getMaxContexts());

View File

@ -0,0 +1,61 @@
package cn.iocoder.yudao.module.ai.service.model;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import jakarta.validation.Valid;
/**
* AI 聊天角色 Service 接口
*
* @author fansili
*/
public interface AiChatRoleService {
/**
* 创建聊天角色
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createChatRole(@Valid AiChatRoleSaveReqVO createReqVO);
/**
* 更新聊天角色
*
* @param updateReqVO 更新信息
*/
void updateChatRole(@Valid AiChatRoleSaveReqVO updateReqVO);
/**
* 删除聊天角色
*
* @param id 编号
*/
void deleteChatRole(Long id);
/**
* 获得聊天角色
*
* @param id 编号
* @return AI 聊天角色
*/
AiChatRoleDO getChatRole(Long id);
/**
* 校验角色是否存在
*
* @param id 角色编号
*/
AiChatRoleDO validateChatRole(Long id);
/**
* 获得AI 聊天角色分页
*
* @param pageReqVO 分页查询
* @return AI 聊天角色分页
*/
PageResult<AiChatRoleDO> getChatRolePage(AiChatRolePageReqVO pageReqVO);
}

View File

@ -0,0 +1,85 @@
package cn.iocoder.yudao.module.ai.service.model;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRolePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.model.vo.role.AiChatRoleSaveReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
import cn.iocoder.yudao.module.ai.dal.mysql.AiChatRoleMapper;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_DISABLE;
import static cn.iocoder.yudao.module.ai.ErrorCodeConstants.CHAT_ROLE_NOT_EXISTS;
/**
* AI 聊天角色 Service 实现类
*
* @author fansili
*/
@Service
@AllArgsConstructor
@Slf4j
public class AiChatRoleServiceImpl implements AiChatRoleService {
@Resource
private AiChatRoleMapper chatRoleMapper;
@Override
public Long createChatRole(AiChatRoleSaveReqVO createReqVO) {
AiChatRoleDO chatRole = BeanUtils.toBean(createReqVO, AiChatRoleDO.class);
chatRoleMapper.insert(chatRole);
return chatRole.getId();
}
@Override
public void updateChatRole(AiChatRoleSaveReqVO updateReqVO) {
// 校验存在
validateChatRoleExists(updateReqVO.getId());
// 更新
AiChatRoleDO updateObj = BeanUtils.toBean(updateReqVO, AiChatRoleDO.class);
chatRoleMapper.updateById(updateObj);
}
@Override
public void deleteChatRole(Long id) {
// 校验存在
validateChatRoleExists(id);
// 删除
chatRoleMapper.deleteById(id);
}
private AiChatRoleDO validateChatRoleExists(Long id) {
AiChatRoleDO chatRole = chatRoleMapper.selectById(id);
if (chatRole == null) {
throw exception(CHAT_ROLE_NOT_EXISTS);
}
return chatRole;
}
@Override
public AiChatRoleDO getChatRole(Long id) {
return chatRoleMapper.selectById(id);
}
@Override
public AiChatRoleDO validateChatRole(Long id) {
AiChatRoleDO chatRole = validateChatRoleExists(id);
if (CommonStatusEnum.isDisable(chatRole.getStatus())) {
throw exception(CHAT_ROLE_DISABLE, chatRole.getName());
}
return chatRole;
}
@Override
public PageResult<AiChatRoleDO> getChatRolePage(AiChatRolePageReqVO pageReqVO) {
return chatRoleMapper.selectPage(pageReqVO);
}
}