Commit b4014bf2df7825a867da97662165a738b1f926e1

Authored by YunaiV
1 parent b8a443fb

【代码评审】AI:写作部分的建议

yudao-module-ai/yudao-module-ai-api/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java
... ... @@ -7,7 +7,7 @@ import lombok.Getter;
7 7 import java.util.Arrays;
8 8  
9 9 /**
10   - * AI 写作类型的枚举
  10 + * AI 内置聊天角色的枚举
11 11 *
12 12 * @author xiaoxin
13 13 */
... ... @@ -21,6 +21,7 @@ public enum AiChatRoleEnum implements IntArrayValuable {
21 21 2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。
22 22 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。
23 23 """),
  24 +
24 25 AI_MIND_MAP_ROLE(2, "脑图助手", """
25 26 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子:
26 27 # Geek-AI 助手
... ... @@ -38,7 +39,6 @@ public enum AiChatRoleEnum implements IntArrayValuable {
38 39 除此之外不要任何解释性语句。
39 40 """);
40 41  
41   -
42 42 /**
43 43 * 角色
44 44 */
... ... @@ -51,7 +51,7 @@ public enum AiChatRoleEnum implements IntArrayValuable {
51 51 /**
52 52 * 角色设定
53 53 */
54   - private final String prompt;
  54 + private final String systemMessage;
55 55  
56 56 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiChatRoleEnum::getRole).toArray();
57 57  
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java
... ... @@ -7,7 +7,9 @@ import lombok.Data;
7 7 @Schema(description = "管理后台 - AI 思维导图生成 Request VO")
8 8 @Data
9 9 public class AiMindMapGenerateReqVO {
  10 +
10 11 @Schema(description = "思维导图内容提示", example = "Java 学习路线")
11 12 @NotBlank(message = "思维导图内容提示不能为空")
12 13 private String prompt;
  14 +
13 15 }
14 16 \ No newline at end of file
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java
... ... @@ -12,6 +12,7 @@ import lombok.Data;
12 12 *
13 13 * @author xiaoxin
14 14 */
  15 +// TODO @xin:如果没 typehandler 的需求,autoResultMap 可以去掉哈
15 16 @TableName(value = "ai_mind_map", autoResultMap = true)
16 17 @Data
17 18 public class AiMindMapDO extends BaseDO {
... ... @@ -24,20 +25,21 @@ public class AiMindMapDO extends BaseDO {
24 25  
25 26 /**
26 27 * 用户编号
  28 + *
  29 + * 关联 AdminUserDO 的 userId 字段
27 30 */
28 31 private Long userId;
29 32  
30 33 /**
31   - * 模型
32   - */
33   - private String model;
34   -
35   - /**
36 34 * 平台
37 35 * <p>
38 36 * 枚举 {@link AiPlatformEnum}
39 37 */
40 38 private String platform;
  39 + /**
  40 + * 模型
  41 + */
  42 + private String model;
41 43  
42 44 /**
43 45 * 生成内容提示
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java
... ... @@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.ai.dal.dataobject.write;
2 2  
3 3 import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
4 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum;
5 6 import com.baomidou.mybatisplus.annotation.IdType;
6 7 import com.baomidou.mybatisplus.annotation.TableId;
7 8 import com.baomidou.mybatisplus.annotation.TableName;
8 9 import lombok.Data;
9   -import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum;
10 10  
11 11 /**
12 12 * AI 写作 DO
13 13 *
14 14 * @author xiaoxin
15 15 */
16   -@TableName(value = "ai_write", autoResultMap = true)
  16 +@TableName("ai_write")
17 17 @Data
18 18 public class AiWriteDO extends BaseDO {
19 19  
... ... @@ -25,6 +25,8 @@ public class AiWriteDO extends BaseDO {
25 25  
26 26 /**
27 27 * 用户编号
  28 + *
  29 + * 关联 AdminUserDO 的 userId 字段
28 30 */
29 31 private Long userId;
30 32  
... ... @@ -36,16 +38,15 @@ public class AiWriteDO extends BaseDO {
36 38 private Integer type;
37 39  
38 40 /**
39   - * 模型
40   - */
41   - private String model;
42   -
43   - /**
44 41 * 平台
45 42 *
46 43 * 枚举 {@link AiPlatformEnum}
47 44 */
48 45 private String platform;
  46 + /**
  47 + * 模型
  48 + */
  49 + private String model;
49 50  
50 51 /**
51 52 * 生成内容提示
... ... @@ -56,7 +57,6 @@ public class AiWriteDO extends BaseDO {
56 57 * 生成的内容
57 58 */
58 59 private String generatedContent;
59   -
60 60 /**
61 61 * 原文
62 62 */
... ... @@ -64,21 +64,26 @@ public class AiWriteDO extends BaseDO {
64 64  
65 65 /**
66 66 * 长度提示词
  67 + *
  68 + * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_LENGTH}
67 69 */
68 70 private Integer length;
69   -
70 71 /**
71 72 * 格式提示词
  73 + *
  74 + * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_FORMAT}
72 75 */
73 76 private Integer format;
74   -
75 77 /**
76 78 * 语气提示词
  79 + *
  80 + * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_TONE}
77 81 */
78 82 private Integer tone;
79   -
80 83 /**
81 84 * 语言提示词
  85 + *
  86 + * 字典:{@link cn.iocoder.yudao.module.ai.enums.DictTypeConstants#AI_WRITE_LANGUAGE}
82 87 */
83 88 private Integer language;
84 89  
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
... ... @@ -66,7 +66,7 @@ public class AiMindMapServiceImpl implements AiMindMapService {
66 66 systemMessage = mindMapRole.getSystemMessage();
67 67 } else {
68 68 model = chatModalService.getRequiredDefaultChatModel();
69   - systemMessage = AiChatRoleEnum.AI_MIND_MAP_ROLE.getPrompt();
  69 + systemMessage = AiChatRoleEnum.AI_MIND_MAP_ROLE.getSystemMessage();
70 70 }
71 71  
72 72 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiChatRoleService.java
... ... @@ -120,6 +120,7 @@ public interface AiChatRoleService {
120 120  
121 121 /**
122 122 * 根据名字获得聊天角色
  123 + *
123 124 * @param name 名字
124 125 * @return 聊天角色列表
125 126 */
... ...
yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
... ... @@ -65,6 +65,7 @@ public class AiWriteServiceImpl implements AiWriteService {
65 65 public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) {
66 66 // 1.1 获取写作模型 尝试获取写作助手角色,如果没有则使用默认模型
67 67 AiChatRoleDO writeRole = CollUtil.getFirst(chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName()));
  68 + // TODO @xin:如果有 writeRole,但是没 modeId,是不是也可以用 systemMessage 哈?建议的写法是:先通过 modelId 获取 model。如果 model == null,则 chatModalService.getRequiredDefaultChatModel();如果还是 null,则抛出异常;。。。。。。。。。。。。。。然后,systemMessage = writeRole != null && writeRole.systemPrompt != "" 这样处理。
68 69 AiChatModelDO model;
69 70 String systemMessage;
70 71 if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) {
... ... @@ -72,18 +73,21 @@ public class AiWriteServiceImpl implements AiWriteService {
72 73 systemMessage = writeRole.getSystemMessage();
73 74 } else {
74 75 model = chatModalService.getRequiredDefaultChatModel();
75   - systemMessage = AiChatRoleEnum.AI_WRITE_ROLE.getPrompt();
  76 + systemMessage = AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage();
76 77 }
77 78 // 1.2 校验平台
78 79 AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
79 80 StreamingChatModel chatModel = apiKeyService.getChatModel(model.getKeyId());
80 81  
81 82 // 2. 插入写作信息
82   - AiWriteDO writeDO = BeanUtils.toBean(generateReqVO, AiWriteDO.class, e -> e.setUserId(userId).setModel(model.getModel()).setPlatform(platform.getPlatform()));
  83 + AiWriteDO writeDO = BeanUtils.toBean(generateReqVO, AiWriteDO.class,
  84 + write -> write.setUserId(userId).setPlatform(platform.getPlatform()).setModel(model.getModel()));
83 85 writeMapper.insert(writeDO);
84 86  
  87 + // 3. 调用大模型,写作生成
85 88 ChatOptions chatOptions = AiUtils.buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens());
86 89 // 3.1 角色设定
  90 + // TODO @xin:要不把 90 到 97 这部分,合并到一个方法里。目的是:让这个方法的主干更明确
87 91 List<Message> chatMessages = new ArrayList<>();
88 92 if (StrUtil.isNotBlank(systemMessage)) {
89 93 chatMessages.add(new SystemMessage(systemMessage));
... ... @@ -94,7 +98,7 @@ public class AiWriteServiceImpl implements AiWriteService {
94 98 Prompt prompt = new Prompt(chatMessages, chatOptions);
95 99 Flux<ChatResponse> streamResponse = chatModel.stream(prompt);
96 100  
97   - // 3.2 流式返回
  101 + // 4. 流式返回
98 102 StringBuffer contentBuffer = new StringBuffer();
99 103 return streamResponse.map(chunk -> {
100 104 String newContent = chunk.getResult() != null ? chunk.getResult().getOutput().getContent() : null;
... ... @@ -115,13 +119,13 @@ public class AiWriteServiceImpl implements AiWriteService {
115 119 }
116 120  
117 121 private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) {
118   - Integer type = generateReqVO.getType();
119 122 String format = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat());
120 123 String tone = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getTone());
121 124 String language = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getLanguage());
122 125 String length = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LENGTH, generateReqVO.getLength());
  126 + // 格式化 prompt
123 127 String prompt = generateReqVO.getPrompt();
124   - if (Objects.equals(type, AiWriteTypeEnum.WRITING.getType())) {
  128 + if (Objects.equals(generateReqVO.getType(), AiWriteTypeEnum.WRITING.getType())) {
125 129 return StrUtil.format(AiWriteTypeEnum.WRITING.getPrompt(), prompt, format, tone, language, length);
126 130 } else {
127 131 return StrUtil.format(AiWriteTypeEnum.REPLY.getPrompt(), generateReqVO.getOriginalContent(), prompt, format, tone, language, length);
... ...