mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 02:08: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) | ||||
|     private Integer type; | ||||
|  | ||||
|     // TODO @xin:如果非必填,可以不用写 requiredMode | ||||
|     @Schema(description = "写作内容提示", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1.撰写:田忌赛马;2.回复:不批") | ||||
|     @Schema(description = "写作内容提示", example = "1.撰写:田忌赛马;2.回复:不批") | ||||
|     private String prompt; | ||||
|  | ||||
|     @Schema(description = "原文", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "领导我要辞职") | ||||
|     @Schema(description = "原文", example = "领导我要辞职") | ||||
|     private String originalContent; | ||||
|  | ||||
|     @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) { | ||||
|         // 1. 调用 Suno 生成音乐 | ||||
|         SunoApi sunoApi = apiKeyService.getSunoApi(); | ||||
|         // TODO 芋艿:这两个貌似一直没跑成功,你那可以么?用的请求是 AiMusicController.http 的  --xin:大部分ok的,补充了error_message | ||||
|         List<SunoApi.MusicData> musicDataList; | ||||
|         if (Objects.equals(AiMusicGenerateModeEnum.DESCRIPTION.getMode(), reqVO.getGenerateMode())) { | ||||
|             // 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.write.AiWriteDO; | ||||
| 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.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.AiChatModelService; | ||||
| import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | ||||
| import com.alibaba.cloud.ai.tongyi.chat.TongYiChatOptions; | ||||
| import jakarta.annotation.Resource; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| @@ -45,14 +47,17 @@ public class AiWriteServiceImpl implements AiWriteService { | ||||
|     private AiApiKeyService apiKeyService; | ||||
|     @Resource | ||||
|     private AiChatModelService chatModalService; | ||||
|  | ||||
|     @Resource | ||||
|     private AiWriteMapper writeMapper; // TODO @xin:上面空一行;因为同类之间不要空行,非同类空行; | ||||
|     private DictDataApi dictDataApi; | ||||
|  | ||||
|     @Resource | ||||
|     private AiWriteMapper writeMapper; | ||||
|  | ||||
|     @Override | ||||
|     public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) { | ||||
|         // 1.1 校验模型 | ||||
|         // TODO @xin:可以约定大于配置先,查询某个名字。例如说,写作助手!然后写作助手,上面是有个 model 的,可以使用它。 | ||||
|         AiChatModelDO model = chatModalService.validateChatModel(14L); | ||||
|         // 1.1 校验模型 TODO 芋艿 是不是取默认的模型也ok? | ||||
|         AiChatModelDO model = chatModalService.getRequiredDefaultChatModel(); | ||||
|         StreamingChatModel chatClient = apiKeyService.getChatClient(model.getKeyId()); | ||||
|         AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform()); | ||||
|         ChatOptions chatOptions = buildChatOptions(platform, model.getModel(), model.getTemperature(), model.getMaxTokens()); | ||||
| @@ -83,10 +88,10 @@ public class AiWriteServiceImpl implements AiWriteService { | ||||
|     private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) { | ||||
|         String template; | ||||
|         Integer writeType = generateReqVO.getType(); | ||||
|         String format = AiWriteFormatEnum.valueOfFormat(generateReqVO.getFormat()).getName(); | ||||
|         String tone = AiWriteToneEnum.valueOfTone(generateReqVO.getTone()).getName(); | ||||
|         String language = AiLanguageEnum.valueOfLanguage(generateReqVO.getLanguage()).getName(); | ||||
|         String length = AiWriteLengthEnum.valueOfLength(generateReqVO.getLength()).getName(); | ||||
|         String format = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat()); | ||||
|         String tone = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getFormat()); | ||||
|         String language = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getFormat()); | ||||
|         String length = dictDataApi.getDictDataLabel(DictTypeConstants.AI_WRITE_LENGTH, generateReqVO.getFormat()); | ||||
|         if (Objects.equals(writeType, AiWriteTypeEnum.WRITING.getType())) { | ||||
|             template = "请撰写一篇关于 [{}] 的文章。文章的内容格式为:[{}],语气为:[{}],语言为:[{}],长度为:[{}]。请确保涵盖主要内容,不需要除了正文内容外的其他回复,如标题、额外的解释或道歉。"; | ||||
|             return StrUtil.format(template, generateReqVO.getPrompt(), format, tone, language, length); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 xiaoxin
					xiaoxin