mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	【增加】AI:写作模版构建
This commit is contained in:
		| @ -1,13 +1,16 @@ | |||||||
| package cn.iocoder.yudao.module.ai.controller.admin.write; | package cn.iocoder.yudao.module.ai.controller.admin.write; | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.service.write.AiWriteService; | import cn.iocoder.yudao.module.ai.service.write.AiWriteService; | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.annotation.security.PermitAll; | import jakarta.annotation.security.PermitAll; | ||||||
|  | import jakarta.validation.Valid; | ||||||
| import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||||
| import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.PostMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestBody; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||||
| import reactor.core.publisher.Flux; | import reactor.core.publisher.Flux; | ||||||
| @ -22,8 +25,8 @@ public class AiWriteController { | |||||||
|  |  | ||||||
|     @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) |     @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) | ||||||
|     @PermitAll |     @PermitAll | ||||||
|     @Operation(summary = "作文生产(流式)", description = "流式返回,响应较快") |     @Operation(summary = "写作生成(流式)", description = "流式返回,响应较快") | ||||||
|     public Flux<CommonResult<String>> generateComposition() { |     public Flux<CommonResult<String>> generateComposition(@RequestBody @Valid AiWriteGenerateReqVO generateReqVO) { | ||||||
|         return writeService.generateComposition(); |         return writeService.generateComposition(generateReqVO); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,39 @@ | |||||||
|  | package cn.iocoder.yudao.module.ai.controller.admin.write.vo; | ||||||
|  |  | ||||||
|  | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | @Schema(description = "管理后台 - AI 写作生成 Request VO") | ||||||
|  | @Data | ||||||
|  | public class AiWriteGenerateReqVO { | ||||||
|  |  | ||||||
|  |     @Schema(description = "写作内容", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "田忌赛马") | ||||||
|  |     private String content; | ||||||
|  |  | ||||||
|  |     @Schema(description = "原文", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "领导我要辞职") | ||||||
|  |     private String originalContent; | ||||||
|  |  | ||||||
|  |     @Schema(description = "回复内容", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "准了") | ||||||
|  |     private String replyContent; | ||||||
|  |  | ||||||
|  |     @Schema(description = "长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "中等") | ||||||
|  |     @NotBlank(message = "长度不能为空") | ||||||
|  |     private String length; | ||||||
|  |  | ||||||
|  |     @Schema(description = "格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "文章") | ||||||
|  |     @NotBlank(message = "格式不能为空") | ||||||
|  |     private String format; | ||||||
|  |  | ||||||
|  |     @Schema(description = "语气", requiredMode = Schema.RequiredMode.REQUIRED, example = "随意") | ||||||
|  |     @NotBlank(message = "语气不能为空") | ||||||
|  |     private String tone; | ||||||
|  |  | ||||||
|  |     @Schema(description = "语言", requiredMode = Schema.RequiredMode.REQUIRED, example = "中文") | ||||||
|  |     @NotBlank(message = "语言不能为空") | ||||||
|  |     private String language; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     @Schema(description = "写作类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||||
|  |     private Integer writeType; | ||||||
|  | } | ||||||
| @ -1,6 +1,7 @@ | |||||||
| package cn.iocoder.yudao.module.ai.service.write; | package cn.iocoder.yudao.module.ai.service.write; | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO; | ||||||
| import reactor.core.publisher.Flux; | import reactor.core.publisher.Flux; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @ -11,7 +12,7 @@ import reactor.core.publisher.Flux; | |||||||
| public interface AiWriteService { | public interface AiWriteService { | ||||||
|  |  | ||||||
|  |  | ||||||
|     Flux<CommonResult<String>> generateComposition(); |     Flux<CommonResult<String>> generateComposition(AiWriteGenerateReqVO generateReqVO); | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoChatModel; | |||||||
| import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; | import cn.iocoder.yudao.framework.ai.core.model.xinghuo.XingHuoOptions; | ||||||
| import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; | import cn.iocoder.yudao.framework.ai.core.model.yiyan.YiYanChatOptions; | ||||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||||
|  | import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO; | ||||||
| import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; | import cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants; | ||||||
| import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| @ -37,11 +38,11 @@ public class AiWriteServiceImpl implements AiWriteService { | |||||||
|  |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public Flux<CommonResult<String>> generateComposition() { |     public Flux<CommonResult<String>> generateComposition(AiWriteGenerateReqVO generateReqVO) { | ||||||
|         StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(6L); |         StreamingChatClient chatClient = apiKeyService.getStreamingChatClient(6L); | ||||||
|         AiPlatformEnum platform = AiPlatformEnum.validatePlatform("QianWen"); |         AiPlatformEnum platform = AiPlatformEnum.validatePlatform("QianWen"); | ||||||
|         ChatOptions chatOptions = buildChatOptions(platform, "qwen-72b-chat", 1.0, 1000); |         ChatOptions chatOptions = buildChatOptions(platform, "qwen-72b-chat", 1.0, 1000); | ||||||
|         Prompt prompt = new Prompt("请直接写一篇关于 气候变化 的文章,格式为自动,语气为自动,语言为自动,长度为自动。请确保涵盖主要观点,不需要标题,不需要任何额外的解释或道歉。", chatOptions); |         Prompt prompt = new Prompt(buildWritingPrompt(generateReqVO), chatOptions); | ||||||
|         Flux<ChatResponse> streamResponse = chatClient.stream(prompt); |         Flux<ChatResponse> streamResponse = chatClient.stream(prompt); | ||||||
|         // 3.3 流式返回 |         // 3.3 流式返回 | ||||||
|         StringBuffer contentBuffer = new StringBuffer(); |         StringBuffer contentBuffer = new StringBuffer(); | ||||||
| @ -54,11 +55,23 @@ public class AiWriteServiceImpl implements AiWriteService { | |||||||
|         }).doOnComplete(() -> { |         }).doOnComplete(() -> { | ||||||
|             log.info("generateComposition complete, content: {}", contentBuffer); |             log.info("generateComposition complete, content: {}", contentBuffer); | ||||||
|         }).onErrorResume(error -> { |         }).onErrorResume(error -> { | ||||||
|  |             log.error("[AI 写作] 发生异常", error); | ||||||
|             return Flux.just(error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); |             return Flux.just(error(ErrorCodeConstants.AI_CHAT_STREAM_ERROR)); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     private String buildWritingPrompt(AiWriteGenerateReqVO generateReqVO) { | ||||||
|  |         String template = "请直接写一篇关于 [{}] 的文章,格式为:{},语气为:{},语言为:{},长度为:{}。请确保涵盖主要内容,不需要任何额外的解释或道歉。"; | ||||||
|  |         String content = generateReqVO.getContent(); | ||||||
|  |         String format = generateReqVO.getFormat(); | ||||||
|  |         String tone = generateReqVO.getTone(); | ||||||
|  |         String language = generateReqVO.getLanguage(); | ||||||
|  |         String length = generateReqVO.getLength(); | ||||||
|  |         return StrUtil.format(template, content, format, tone, language, length); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // TODO 芋艿:复用 | ||||||
|     private static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) { |     private static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens) { | ||||||
|         Float temperatureF = temperature != null ? temperature.floatValue() : null; |         Float temperatureF = temperature != null ? temperature.floatValue() : null; | ||||||
|         //noinspection EnhancedSwitchMigration |         //noinspection EnhancedSwitchMigration | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 xiaoxin
					xiaoxin