mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	【解决todo】AI 写作:语言、语气等改为字典
This commit is contained in:
		| @@ -0,0 +1,16 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.enums; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * AI 字典类型的枚举类 | ||||||
|  |  * | ||||||
|  |  * @author xiaoxin | ||||||
|  |  */ | ||||||
|  | public interface DictTypeConstants { | ||||||
|  |  | ||||||
|  |     // ========== AI Write ========== | ||||||
|  |     String AI_WRITE_FORMAT = "ai_write_format"; // 写作格式 | ||||||
|  |     String AI_WRITE_LENGTH = "ai_write_length"; // 写作长度 | ||||||
|  |     String AI_WRITE_LANGUAGE = "ai_write_language"; // 写作语言 | ||||||
|  |     String AI_WRITE_TONE = "ai_write_tone"; // 写作语气 | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.enums.write; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| import java.util.Arrays; |  | ||||||
|  |  | ||||||
| // TODO @xin:写作的几个,不用枚举类哈。直接搞字段就好了。AiWriteTypeEnum 还是需要的哈 |  | ||||||
| @AllArgsConstructor |  | ||||||
| @Getter |  | ||||||
| public enum AiLanguageEnum implements IntArrayValuable { |  | ||||||
|  |  | ||||||
|     AUTO(1, "自动"), |  | ||||||
|     CHINESE(2, "中文"), |  | ||||||
|     ENGLISH(3, "英文"), |  | ||||||
|     KOREAN(4, "韩语"), |  | ||||||
|     JAPANESE(5, "日语"); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Language code |  | ||||||
|      */ |  | ||||||
|     private final Integer language; |  | ||||||
|     /** |  | ||||||
|      * Language name |  | ||||||
|      */ |  | ||||||
|     private final String name; |  | ||||||
|  |  | ||||||
|     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiLanguageEnum::getLanguage).toArray(); |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int[] array() { |  | ||||||
|         return ARRAYS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static AiLanguageEnum valueOfLanguage(Integer language) { |  | ||||||
|         for (AiLanguageEnum languageEnum : AiLanguageEnum.values()) { |  | ||||||
|             if (languageEnum.getLanguage().equals(language)) { |  | ||||||
|                 return languageEnum; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         throw new IllegalArgumentException("未知语言: " + language); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,53 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.enums.write; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| import java.util.Arrays; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * AI 写作类型的枚举 |  | ||||||
|  * |  | ||||||
|  * @author xiaoxin |  | ||||||
|  */ |  | ||||||
| @AllArgsConstructor |  | ||||||
| @Getter |  | ||||||
| public enum AiWriteFormatEnum implements IntArrayValuable { |  | ||||||
|  |  | ||||||
|     AUTO(1, "自动"), |  | ||||||
|     EMAIL(2, "电子邮件"), |  | ||||||
|     MESSAGE(3, "消息"), |  | ||||||
|     COMMENT(4, "评论"), |  | ||||||
|     PARAGRAPH(5, "段落"), |  | ||||||
|     ARTICLE(6, "文章"), |  | ||||||
|     BLOG_POST(7, "博客文章"), |  | ||||||
|     IDEA(8, "想法"), |  | ||||||
|     OUTLINE(9, "大纲"); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 格式 |  | ||||||
|      */ |  | ||||||
|     private final Integer format; |  | ||||||
|     /** |  | ||||||
|      * 格式名 |  | ||||||
|      */ |  | ||||||
|     private final String name; |  | ||||||
|  |  | ||||||
|     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiWriteFormatEnum::getFormat).toArray(); |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int[] array() { |  | ||||||
|         return ARRAYS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static AiWriteFormatEnum valueOfFormat(Integer format) { |  | ||||||
|         for (AiWriteFormatEnum formatEnum : AiWriteFormatEnum.values()) { |  | ||||||
|             if (formatEnum.getFormat().equals(format)) { |  | ||||||
|                 return formatEnum; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         throw new IllegalArgumentException("未知格式: " + format); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,47 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.enums.write; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| import java.util.Arrays; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * AI 写作类型的枚举 |  | ||||||
|  * |  | ||||||
|  * @author xiaoxin |  | ||||||
|  */ |  | ||||||
| @AllArgsConstructor |  | ||||||
| @Getter |  | ||||||
| public enum AiWriteLengthEnum implements IntArrayValuable { |  | ||||||
|  |  | ||||||
|     AUTO(1, "自动"), |  | ||||||
|     SHORT(2, "短"), |  | ||||||
|     MEDIUM(3, "中"), |  | ||||||
|     LONG(4, "长"); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 长度 |  | ||||||
|      */ |  | ||||||
|     private final Integer length; |  | ||||||
|     /** |  | ||||||
|      * 长度名 |  | ||||||
|      */ |  | ||||||
|     private final String name; |  | ||||||
|  |  | ||||||
|     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiWriteLengthEnum::getLength).toArray(); |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int[] array() { |  | ||||||
|         return ARRAYS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static AiWriteLengthEnum valueOfLength(Integer length) { |  | ||||||
|         for (AiWriteLengthEnum lengthEnum : AiWriteLengthEnum.values()) { |  | ||||||
|             if (lengthEnum.getLength().equals(length)) { |  | ||||||
|                 return lengthEnum; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         throw new IllegalArgumentException("未知长度: " + length); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,46 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.ai.enums.write; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |  | ||||||
| import lombok.AllArgsConstructor; |  | ||||||
| import lombok.Getter; |  | ||||||
|  |  | ||||||
| import java.util.Arrays; |  | ||||||
|  |  | ||||||
| @AllArgsConstructor |  | ||||||
| @Getter |  | ||||||
| public enum AiWriteToneEnum implements IntArrayValuable { |  | ||||||
|  |  | ||||||
|     AUTO(1, "自动"), |  | ||||||
|     FRIENDLY(2, "友善"), |  | ||||||
|     CASUAL(3, "随意"), |  | ||||||
|     KIND(4, "友好"), |  | ||||||
|     PROFESSIONAL(5, "专业"), |  | ||||||
|     HUMOROUS(6, "谈谐"), |  | ||||||
|     INTERESTING(7, "有趣"), |  | ||||||
|     FORMAL(8, "正式"); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 语气 |  | ||||||
|      */ |  | ||||||
|     private final Integer tone; |  | ||||||
|     /** |  | ||||||
|      * 语气名 |  | ||||||
|      */ |  | ||||||
|     private final String name; |  | ||||||
|  |  | ||||||
|     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(AiWriteToneEnum::getTone).toArray(); |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int[] array() { |  | ||||||
|         return ARRAYS; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static AiWriteToneEnum valueOfTone(Integer tone) { |  | ||||||
|         for (AiWriteToneEnum toneEnum : AiWriteToneEnum.values()) { |  | ||||||
|             if (toneEnum.getTone().equals(tone)) { |  | ||||||
|                 return toneEnum; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         throw new IllegalArgumentException("未知语气: " + tone); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -14,11 +14,10 @@ public class AiWriteGenerateReqVO { | |||||||
|     @InEnum(AiWriteTypeEnum.class) |     @InEnum(AiWriteTypeEnum.class) | ||||||
|     private Integer type; |     private Integer type; | ||||||
|  |  | ||||||
|     // TODO @xin:如果非必填,可以不用写 requiredMode |     @Schema(description = "写作内容提示", example = "1.撰写:田忌赛马;2.回复:不批") | ||||||
|     @Schema(description = "写作内容提示", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1.撰写:田忌赛马;2.回复:不批") |  | ||||||
|     private String prompt; |     private String prompt; | ||||||
|  |  | ||||||
|     @Schema(description = "原文", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "领导我要辞职") |     @Schema(description = "原文", example = "领导我要辞职") | ||||||
|     private String originalContent; |     private String originalContent; | ||||||
|  |  | ||||||
|     @Schema(description = "长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |     @Schema(description = "长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||||
|   | |||||||
| @@ -54,7 +54,6 @@ public class AiMusicServiceImpl implements AiMusicService { | |||||||
|     public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) { |     public List<Long> generateMusic(Long userId, AiSunoGenerateReqVO reqVO) { | ||||||
|         // 1. 调用 Suno 生成音乐 |         // 1. 调用 Suno 生成音乐 | ||||||
|         SunoApi sunoApi = apiKeyService.getSunoApi(); |         SunoApi sunoApi = apiKeyService.getSunoApi(); | ||||||
|         // TODO 芋艿:这两个貌似一直没跑成功,你那可以么?用的请求是 AiMusicController.http 的  --xin:大部分ok的,补充了error_message |  | ||||||
|         List<SunoApi.MusicData> musicDataList; |         List<SunoApi.MusicData> musicDataList; | ||||||
|         if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { |         if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { | ||||||
|             // 1.1 描述模式 |             // 1.1 描述模式 | ||||||
|   | |||||||
| @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO | |||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; | import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; | ||||||
| import cn.iocoder.yudao.module.ai.dal.mysql.write.AiWriteMapper; | import cn.iocoder.yudao.module.ai.dal.mysql.write.AiWriteMapper; | ||||||
|  | import cn.iocoder.yudao.module.ai.enums.DictTypeConstants; | ||||||
| import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; | import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; | ||||||
| import cn.iocoder.yudao.module.ai.enums.write.*; | import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; | ||||||
| import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | ||||||
| import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | import cn.iocoder.yudao.module.ai.service.model.AiChatModelService; | ||||||
|  | import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||||||
| import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; | import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| @@ -45,14 +47,17 @@ public class AiWriteServiceImpl implements AiWriteService { | |||||||
|     private AiApiKeyService apiKeyService; |     private AiApiKeyService apiKeyService; | ||||||
|     @Resource |     @Resource | ||||||
|     private AiChatModelService chatModalService; |     private AiChatModelService chatModalService; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private AiWriteMapper writeMapper; // TODO @xin:上面空一行;因为同类之间不要空行,非同类空行; |     private DictDataApi dictDataApi; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AiWriteMapper writeMapper; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { |     public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { | ||||||
|         // 1.1 校验模型 |         // 1.1 校验模型 TODO 芋艿 是不是取默认的模型也ok? | ||||||
|         // TODO @xin:可以约定大于配置先,查询某个名字。例如说,写作助手!然后写作助手,上面是有个 model 的,可以使用它。 |         AiChatModelDO model = chatModalService.getRequiredDefaultChatModel(); | ||||||
|         AiChatModelDO model = chatModalService.validateChatModel(14L); |  | ||||||
|         StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); |         StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); | ||||||
|         AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); |         AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | ||||||
|         ChatOptions chatOptions = buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); |         ChatOptions chatOptions = buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||||||
| @@ -83,10 +88,10 @@ public class AiWriteServiceImpl implements AiWriteService { | |||||||
|     private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) { |     private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) { | ||||||
|         String template; |         String template; | ||||||
|         Integer writeType = generateReqVO.getType(); |         Integer writeType = generateReqVO.getType(); | ||||||
|         String format = AiWriteFormatEnum.valueOfFormat(generateReqVO.getFormat()).getName(); |         String format = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat()); | ||||||
|         String tone = AiWriteToneEnum.valueOfTone(generateReqVO.getTone()).getName(); |         String tone = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getFormat()); | ||||||
|         String language = AiLanguageEnum.valueOfLanguage(generateReqVO.getLanguage()).getName(); |         String language = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getFormat()); | ||||||
|         String length = AiWriteLengthEnum.valueOfLength(generateReqVO.getLength()).getName(); |         String length = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LENGTH, generateReqVO.getFormat()); | ||||||
|         if (Objects.equals(writeType, AiWriteTypeEnum.WRITING.getType())) { |         if (Objects.equals(writeType, AiWriteTypeEnum.WRITING.getType())) { | ||||||
|             template = "请撰写一篇关于 [{}] 的文章。文章的内容格式为:[{}],语气为:[{}],语言为:[{}],长度为:[{}]。请确保涵盖主要内容,不需要除了正文内容外的其他回复,如标题、额外的解释或道歉。"; |             template = "请撰写一篇关于 [{}] 的文章。文章的内容格式为:[{}],语气为:[{}],语言为:[{}],长度为:[{}]。请确保涵盖主要内容,不需要除了正文内容外的其他回复,如标题、额外的解释或道歉。"; | ||||||
|             return StrUtil.format(template, generateReqVO.getPrompt(), format, tone, language, length); |             return StrUtil.format(template, generateReqVO.getPrompt(), format, tone, language, length); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 xiaoxin
					xiaoxin