├── .gitattributes ├── .gitignore ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── CHANGELOG.md ├── LICENSE ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src └── main ├── java └── space │ └── wenliang │ └── ai │ └── aigcplatformserver │ ├── AigcPlatformServerApplication.java │ ├── ai │ ├── audio │ │ ├── AudioContext.java │ │ ├── AudioCreator.java │ │ ├── IAudioCreator.java │ │ └── creator │ │ │ ├── AbsAudioCreator.java │ │ │ ├── ChatTtsCreator.java │ │ │ ├── CosyVoiceCreator.java │ │ │ ├── EdgeTtsCreator.java │ │ │ ├── FishSpeechCreator.java │ │ │ └── GptSovitsCreator.java │ └── chat │ │ ├── AiService.java │ │ ├── IAiService.java │ │ ├── openAi │ │ ├── OpenAiResponseBody.java │ │ └── OpenAiService.java │ │ ├── qwen │ │ └── QwenAiService.java │ │ └── spark │ │ ├── SparkAiService.java │ │ └── SparkResponseBody.java │ ├── bean │ ├── AiResult.java │ ├── AppInfoData.java │ ├── AudioCombine.java │ ├── AudioSegment.java │ ├── ChapterAdd.java │ ├── ChapterBatchOperator.java │ ├── ChapterExpose.java │ ├── ChapterSummary.java │ ├── ControlsUpdate.java │ ├── EdgeTtsSetting.java │ ├── EdgeTtsVoice.java │ ├── FormatTextProject.java │ ├── GlobalSetting.java │ ├── GroupCount.java │ ├── LangDict.java │ ├── OpenFolder.java │ ├── PolyphonicInfo.java │ ├── PolyphonicParams.java │ ├── ProjectQuery.java │ ├── PromptAudio.java │ ├── PromptAudioSort.java │ ├── RoleInferenceData.java │ ├── RoleInferenceParam.java │ ├── Subtitle.java │ ├── TextMarkupInfo.java │ ├── TextProject.java │ ├── TextRoleChange.java │ └── UpdateModelInfo.java │ ├── common │ ├── AudioTaskStateConstants.java │ ├── CacheConstants.java │ ├── CacheEnum.java │ ├── CommonConstants.java │ ├── ModelTypeEnum.java │ ├── Page.java │ ├── PageReq.java │ ├── Result.java │ └── ResultEnum.java │ ├── config │ ├── ApiPrefixFilter.java │ ├── EnvConfig.java │ ├── LiquibaseConfig.java │ ├── MybatisPlusConfig.java │ ├── WebMvcConfig.java │ └── WebSocketConfig.java │ ├── controller │ ├── AmModelConfigController.java │ ├── AmModelFileController.java │ ├── AmPromptAudioController.java │ ├── AmServerController.java │ ├── AppController.java │ ├── DictController.java │ ├── FilesController.java │ ├── GlobalSettingController.java │ ├── PinyinController.java │ ├── SseController.java │ ├── TextChapterController.java │ ├── TextProjectController.java │ ├── TmPromptTemplateController.java │ └── TmServerController.java │ ├── entity │ ├── AmModelConfigEntity.java │ ├── AmModelFileEntity.java │ ├── AmPromptAudioEntity.java │ ├── AmServerEntity.java │ ├── AudioModelInfo.java │ ├── AudioModelInfoKey.java │ ├── AudioRoleInfo.java │ ├── ChapterInfoEntity.java │ ├── TextChapterEntity.java │ ├── TextCommonRoleEntity.java │ ├── TextProjectEntity.java │ ├── TextRoleEntity.java │ ├── TextRoleInferenceEntity.java │ ├── TmPromptTemplateEntity.java │ └── TmServerEntity.java │ ├── exception │ ├── BizException.java │ └── GlobalExceptionHandler.java │ ├── hooks │ ├── ShutdownHook.java │ ├── StartHook.java │ └── start │ │ ├── CacheLoad.java │ │ └── StartupInfoPrinter.java │ ├── mapper │ ├── AmModelConfigMapper.java │ ├── AmModelFileMapper.java │ ├── AmPromptAudioMapper.java │ ├── AmServerMapper.java │ ├── ChapterInfoMapper.java │ ├── TextChapterMapper.java │ ├── TextCommonRoleMapper.java │ ├── TextProjectMapper.java │ ├── TextRoleInferenceMapper.java │ ├── TextRoleMapper.java │ ├── TmPromptTemplateMapper.java │ └── TmServerMapper.java │ ├── service │ ├── AmModelConfigService.java │ ├── AmModelFileService.java │ ├── AmPromptAudioService.java │ ├── AmServerService.java │ ├── ChapterInfoService.java │ ├── TextChapterService.java │ ├── TextCommonRoleService.java │ ├── TextProjectService.java │ ├── TextRoleInferenceService.java │ ├── TextRoleService.java │ ├── TmPromptTemplateService.java │ ├── TmServerService.java │ ├── business │ │ ├── BChapterInfoService.java │ │ ├── BTextChapterService.java │ │ ├── BTextProjectService.java │ │ └── impl │ │ │ ├── BChapterInfoServiceImpl.java │ │ │ ├── BTextChapterServiceImpl.java │ │ │ └── BTextProjectServiceImpl.java │ ├── cache │ │ ├── DictService.java │ │ ├── GlobalSettingService.java │ │ └── PinyinCacheService.java │ └── impl │ │ ├── AmModelConfigServiceImpl.java │ │ ├── AmModelFileServiceImpl.java │ │ ├── AmPromptAudioServiceImpl.java │ │ ├── AmServerServiceImpl.java │ │ ├── ChapterInfoServiceImpl.java │ │ ├── TextChapterServiceImpl.java │ │ ├── TextCommonRoleServiceImpl.java │ │ ├── TextProjectServiceImpl.java │ │ ├── TextRoleInferenceServiceImpl.java │ │ ├── TextRoleServiceImpl.java │ │ ├── TmPromptTemplateServiceImpl.java │ │ └── TmServerServiceImpl.java │ ├── socket │ ├── GlobalWebSocketHandler.java │ └── TextProjectWebSocketHandler.java │ ├── spring │ ├── annotation │ │ └── SingleValueParam.java │ └── resolver │ │ └── SingleValueParamHandlerMethodArgumentResolver.java │ ├── test │ └── OpenFolder.java │ └── util │ ├── AudioUtils.java │ ├── ChapterUtils.java │ ├── FileUtils.java │ ├── IdUtils.java │ ├── KeyUtils.java │ ├── PathWrapperUtils.java │ ├── SubtitleUtils.java │ └── UnicodeUtils.java └── resources ├── application-prod.yaml ├── application.yaml ├── liquibase ├── mysql │ ├── changelogs │ │ ├── changelog-1.0.0.sql │ │ ├── changelog-1.1.0.sql │ │ ├── changelog-2.5.0.sql │ │ ├── changelog-2.6.4.sql │ │ └── changelog-2.6.5.sql │ └── master.xml └── sqlite │ ├── changelogs │ ├── changelog-1.0.0.sql │ ├── changelog-1.1.0.sql │ ├── changelog-2.5.0.sql │ ├── changelog-2.6.4.sql │ └── changelog-2.6.5.sql │ └── master.xml ├── pinyin ├── pinyin-unihan.txt └── unihan-pinyin.txt └── static └── favicon.ico /.gitattributes: -------------------------------------------------------------------------------- 1 | /mvnw text eol=lf 2 | *.cmd text eol=crlf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | 35 | ### project ### 36 | /model/** 37 | /project/** 38 | /config/** 39 | *.db -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.6.5 (2024-10-24) 2 | 3 | ### Features 4 | 5 | - 角色推理功能优化 6 | - 新增文本合并功能 7 | - UI布局优化 8 | 9 | ### Bug Fixes 10 | 11 | - 修复一些表单校验问题 12 | - 修复角色推理界面文本大模型选择不生效问题 13 | - 修复特定情况下UI失效问题 14 | 15 | ## 2.6.4 (2024-10-14) 16 | 17 | ### Features 18 | 19 | - 角色推理功能优化 20 | - 增加文本大模型提示词模板 21 | - 接入CosyVoice 22 | 23 | ## 2.6.3 (2024-09-21) 24 | 25 | ### Features 26 | 27 | - 依赖组件升级 28 | 29 | ### Bug Fixes 30 | 31 | - 修复选中生成语音不生效问题 32 | 33 | ## 2.6.2 (2024-09-20) 34 | 35 | ### Features 36 | 37 | - 适配fish-speech 1.4 38 | 39 | ### Bug Fixes 40 | 41 | - 修复UI布局失效问题 42 | 43 | ## 2.6.1 (2024-08-26) 44 | 45 | ### Features 46 | 47 | - 新增文本批量标记、批量删除功能 48 | 49 | ### Bug Fixes 50 | 51 | - 修复单条文本编辑时更新失效问题 52 | 53 | ## 2.6.0 (2024-08-25) 54 | 55 | ### Features 56 | 57 | - 页面性能优化 58 | 59 | ## 2.5.2 (2024-08-14) 60 | 61 | ### Features 62 | 63 | - 优化Kimi max_tokens 计算 64 | 65 | ## 2.5.1 (2024-08-13) 66 | 67 | ### Bug Fixes 68 | 69 | - 修复预置角色配置不生效问题 70 | 71 | ## 2.5.0 (2024-08-12) 72 | 73 | ### Features 74 | 75 | - 界面优化 76 | - 优化角色推理功能 77 | - 新增排序功能,新增指定添加文本功能 78 | - 新增多音字拼音标记功能(谐音) 79 | - 新增批量操作功能 80 | - 新增合并后音频播放功能 81 | - 新增CosyVoice 82 | 83 | ## 2.4.1 (2024-07-11) 84 | 85 | ### Bug Fixes 86 | 87 | - 修复改变音量等操作时,音频不能播放问题 88 | 89 | ## 2.4.0 (2024-07-10) 90 | 91 | ### Features 92 | 93 | - 新增sqlite版本管理 94 | - 新增增加、删除章节,章节排序功能 95 | - 新增单条文本删除功能 96 | 97 | ## 2.3.0 (2024-07-05) 98 | 99 | ### Bug Fixes 100 | 101 | - 修复使用有语言标签的参考音频时生成音频失败问题 102 | 103 | ## 2.2.0 (2024-07-02) 104 | 105 | ### Features 106 | 107 | - 优化文本切分,优化字幕超长问题 108 | - 新增模型配置自定义功能 109 | - 新增模型配置编辑页面,选择时预览功能 110 | - 新增各模型音频生成页面 111 | 112 | ## 2.1.1 (2024-06-17) 113 | 114 | ### Bug Fixes 115 | 116 | - 修复音频合并时,内存溢出问题 117 | 118 | ## 2.1.0 (2024-06-16) 119 | 120 | ### Features 121 | 122 | - 项目结构优化,引入数据库存储数据 123 | 124 | ## 2.0.0 (2024-06-09) 125 | 126 | ### Features 127 | 128 | - 新UI新交互,项目重构 129 | 130 | ## 1.7.0 (2024-05-21) 131 | 132 | ## 1.6.0 (2024-05-19) 133 | 134 | ## 1.5.0 (2024-05-17) 135 | 136 | ## 1.4.0 (2024-05-14) 137 | 138 | ## 1.3.0 (2024-05-13) 139 | 140 | ## 1.2.0 (2024-05-12) 141 | 142 | ## 1.1.0 (2024-05-07) 143 | 144 | ## 1.0.0 (2024-04-26) 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 🚀 简介 2 | 3 | 本项目旨在集成主流开源大模型,实现不同类型大模型以及同类型大模型之间的协调合作,从而提供全面而灵活的AI生成内容服务。 4 | 5 | ## 📚 文档 6 | 7 | [文档](https://doc.aigc.wenliang.space) 8 | 9 | ## 🛠️ 技术栈 10 | 11 | ### 后端 12 | 13 | Java SpringBoot3 MySQL 14 | 15 | ### 前端 16 | 17 | Vue3 18 | 19 | ## 📅 开发计划 20 | 21 | ### 📑 页面功能 22 | 23 | - 文本 24 | - ✅文本转音频 25 | - ❎文本生图像 26 | - ❎文本生视频 27 | - 音频 28 | - ❎音频换声音 29 | - ❎音频换文字 30 | - 图像 31 | - ❎··· 32 | - 视频 33 | - ❎视频换文字 34 | - ❎视频换声音 35 | 36 | ### 🔧 基础功能 37 | 38 | - ❎启动管理器(主服务与集成大模型的更新) 39 | - ❎多平台 40 | 41 | ## 📚 参考资料 42 | 43 | - [GPT-SoVITS GitHub](https://github.com/RVC-Boss/GPT-SoVITS) 44 | - [Fish-Speech GitHub](https://github.com/fishaudio/fish-speech) 45 | - [ChatTTS GitHub](https://github.com/2noise/ChatTTS) 46 | - [Edge-TTS GitHub](https://github.com/rany2/edge-tts) 47 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/AigcPlatformServerApplication.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AigcPlatformServerApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AigcPlatformServerApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/AudioContext.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.bean.TextMarkupInfo; 5 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 6 | import space.wenliang.ai.aigcplatformserver.entity.AudioModelInfo; 7 | 8 | @Data 9 | public class AudioContext extends AudioModelInfo { 10 | 11 | private String text; 12 | private String textLang; 13 | private TextMarkupInfo textMarkupInfo; 14 | 15 | private Integer textPartIndexStart; 16 | private Integer textPartIndexEnd; 17 | private String markupText; 18 | 19 | private String mediaType = "wav"; 20 | private String outputDir; 21 | private String outputName; 22 | 23 | private AmServerEntity amServer; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/AudioCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.stereotype.Service; 7 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 8 | import space.wenliang.ai.aigcplatformserver.exception.BizException; 9 | import space.wenliang.ai.aigcplatformserver.service.AmServerService; 10 | 11 | import java.util.Map; 12 | 13 | @Service 14 | @RequiredArgsConstructor 15 | public class AudioCreator { 16 | 17 | private final AmServerService amServerService; 18 | private final Map audioCreatorMap; 19 | 20 | public ResponseEntity createAudio(AudioContext context) { 21 | if (audioCreatorMap.containsKey(context.getAmType())) { 22 | addAudioServer(context); 23 | return audioCreatorMap.get(context.getAmType()).createAudio(context); 24 | } else { 25 | throw new BizException("audio creater not exist, type: " + context.getAmType()); 26 | } 27 | } 28 | 29 | public void createFile(AudioContext context) { 30 | if (audioCreatorMap.containsKey(context.getAmType())) { 31 | addAudioServer(context); 32 | audioCreatorMap.get(context.getAmType()).createFile(context); 33 | } else { 34 | throw new BizException("audio creater not exist, type: " + context.getAmType()); 35 | } 36 | } 37 | 38 | private void addAudioServer(AudioContext context) { 39 | AmServerEntity amServer = amServerService.getOne(new LambdaQueryWrapper() 40 | .eq(AmServerEntity::getName, context.getAmType())); 41 | context.setAmServer(amServer); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/IAudioCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | 5 | public interface IAudioCreator { 6 | 7 | void preCheck(AudioContext context); 8 | 9 | void pre(AudioContext context) throws Exception; 10 | 11 | ResponseEntity createAudio(AudioContext context); 12 | 13 | void createFile(AudioContext context); 14 | 15 | void post(AudioContext context) throws Exception; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/AbsAudioCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.http.MediaType; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.client.ResourceAccessException; 7 | import org.springframework.web.client.RestClient; 8 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 9 | import space.wenliang.ai.aigcplatformserver.ai.audio.IAudioCreator; 10 | import space.wenliang.ai.aigcplatformserver.bean.PolyphonicInfo; 11 | import space.wenliang.ai.aigcplatformserver.exception.BizException; 12 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 13 | import space.wenliang.ai.aigcplatformserver.util.AudioUtils; 14 | 15 | import java.nio.file.Files; 16 | import java.nio.file.Path; 17 | import java.util.List; 18 | import java.util.Map; 19 | import java.util.Objects; 20 | 21 | @Slf4j 22 | public abstract class AbsAudioCreator implements IAudioCreator { 23 | 24 | public final RestClient restClient; 25 | public final PinyinCacheService pinyinCacheService; 26 | 27 | protected AbsAudioCreator(RestClient restClient, 28 | PinyinCacheService pinyinCacheService) { 29 | this.restClient = restClient; 30 | this.pinyinCacheService = pinyinCacheService; 31 | } 32 | 33 | public void textMarkup(AudioContext context) { 34 | StringBuilder markupText = new StringBuilder(context.getText()); 35 | if (Objects.nonNull(context.getTextMarkupInfo())) { 36 | List polyphonicInfos = context.getTextMarkupInfo().getPolyphonicInfos(); 37 | for (PolyphonicInfo polyphonicInfo : polyphonicInfos) { 38 | if (Objects.nonNull(polyphonicInfo.getIndex()) 39 | && Objects.nonNull(polyphonicInfo.getMarkup()) 40 | && polyphonicInfo.getIndex() >= context.getTextPartIndexStart() 41 | && polyphonicInfo.getIndex() <= context.getTextPartIndexEnd()) { 42 | String uniHan = pinyinCacheService.getUniHanByPinyin(polyphonicInfo.getMarkup()); 43 | if (Objects.nonNull(uniHan)) { 44 | markupText.setCharAt(polyphonicInfo.getIndex() - context.getTextPartIndexStart(), uniHan.charAt(0)); 45 | } 46 | } 47 | } 48 | 49 | } 50 | context.setMarkupText(markupText.toString()); 51 | } 52 | 53 | public Map buildParams(AudioContext context) { 54 | return Map.of(); 55 | } 56 | 57 | @Override 58 | public void preCheck(AudioContext context) { 59 | if (Objects.isNull(context.getAmServer())) { 60 | throw new BizException("[" + context.getAmType() + "]类型的api服务没有配置"); 61 | } 62 | } 63 | 64 | @Override 65 | public void pre(AudioContext context) { 66 | 67 | } 68 | 69 | public ResponseEntity createAudio(AudioContext context) { 70 | 71 | preCheck(context); 72 | 73 | pre(context); 74 | 75 | try { 76 | log.info("Creating audio file..."); 77 | ResponseEntity response = creator(context); 78 | log.info("Creating audio file done."); 79 | 80 | if (response.getStatusCode().is2xxSuccessful() && Objects.nonNull(response.getBody())) { 81 | return response; 82 | } 83 | } catch (ResourceAccessException e) { 84 | log.error("write exception, context: {}", context, e); 85 | throw new BizException("音频生成服务连接异常,服务类型:" + context.getAmType()); 86 | } catch (Exception e) { 87 | log.error("write exception, context: {}", context, e); 88 | throw new BizException(e.getMessage()); 89 | } 90 | return null; 91 | } 92 | 93 | public void createFile(AudioContext context) { 94 | 95 | preCheck(context); 96 | 97 | pre(context); 98 | 99 | try { 100 | ResponseEntity response = creator(context); 101 | 102 | if (response.getStatusCode().is2xxSuccessful() && Objects.nonNull(response.getBody())) { 103 | 104 | Path path = Path.of(context.getOutputDir(), context.getOutputName() + "." + context.getMediaType()); 105 | if (Files.notExists(path.getParent())) { 106 | Files.createDirectories(path.getParent()); 107 | } 108 | if (Files.exists(path)) { 109 | Files.delete(path); 110 | } 111 | byte[] bytes = AudioUtils.audioFormat(response.getBody()); 112 | Files.write(path, bytes); 113 | log.info("write file, context: {}", context); 114 | } 115 | 116 | } catch (ResourceAccessException e) { 117 | log.error("write exception, context: {}", context, e); 118 | throw new BizException("音频生成服务连接异常,服务类型:" + context.getAmType()); 119 | } catch (Exception e) { 120 | log.error("write exception, context: {}", context, e); 121 | throw new BizException(e.getMessage()); 122 | } 123 | 124 | } 125 | 126 | @Override 127 | public void post(AudioContext context) { 128 | 129 | } 130 | 131 | public ResponseEntity creator(AudioContext context) { 132 | 133 | textMarkup(context); 134 | 135 | Map params = buildParams(context); 136 | 137 | return restClient 138 | .post() 139 | .uri(context.getAmServer().getUri()) 140 | .contentType(MediaType.APPLICATION_JSON) 141 | .body(params) 142 | .retrieve() 143 | .toEntity(byte[].class); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/ChatTtsCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONObject; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.web.client.RestClient; 7 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 8 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Objects; 13 | import java.util.stream.Collectors; 14 | 15 | @Service("chat-tts") 16 | public class ChatTtsCreator extends AbsAudioCreator { 17 | 18 | public ChatTtsCreator(RestClient restClient, 19 | PinyinCacheService pinyinCacheService) { 20 | super(restClient, pinyinCacheService); 21 | } 22 | 23 | 24 | @Override 25 | public Map buildParams(AudioContext context) { 26 | context.setMediaType("wav"); 27 | 28 | Map params = new HashMap<>(); 29 | 30 | params.put("text", context.getMarkupText()); 31 | 32 | JSONObject config = JSON.parseObject(context.getAmMcParamsJson()); 33 | 34 | if (Objects.nonNull(config)) { 35 | Map filterConfig = config.entrySet().stream() 36 | .filter((e) -> e.getValue() != null) 37 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 38 | 39 | params.putAll(filterConfig); 40 | } 41 | return params; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/CosyVoiceCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONObject; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.core.io.FileSystemResource; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.http.client.MultipartBodyBuilder; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.web.client.RestClient; 13 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 14 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 15 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 16 | 17 | import java.nio.file.Path; 18 | import java.util.Map; 19 | import java.util.Optional; 20 | 21 | import static space.wenliang.ai.aigcplatformserver.common.CommonConstants.prompt_audio; 22 | 23 | @Slf4j 24 | @Service("cosy-voice") 25 | public class CosyVoiceCreator extends AbsAudioCreator { 26 | 27 | private final EnvConfig envConfig; 28 | 29 | public CosyVoiceCreator(EnvConfig envConfig, 30 | RestClient restClient, 31 | PinyinCacheService pinyinCacheService) { 32 | super(restClient, pinyinCacheService); 33 | this.envConfig = envConfig; 34 | } 35 | 36 | @Override 37 | public Map buildParams(AudioContext context) { 38 | context.setMediaType("wav"); 39 | return Map.of(); 40 | } 41 | 42 | @Override 43 | public ResponseEntity creator(AudioContext context) { 44 | 45 | super.textMarkup(context); 46 | 47 | JSONObject config = JSON.parseObject(context.getAmMcParamsJson()); 48 | 49 | String mode = config.getString("mode"); 50 | 51 | MultipartBodyBuilder builder = new MultipartBodyBuilder(); 52 | builder.part("tts_text", context.getMarkupText()); 53 | builder.part("spk_id", config.getString("role")); 54 | builder.part("seed", Optional.ofNullable(config.getInteger("seed")).orElse(0)); 55 | 56 | String path = ""; 57 | if (StringUtils.equals(mode, "preset")) { 58 | path = "/inference_sft"; 59 | } 60 | 61 | if (StringUtils.equals(mode, "custom")) { 62 | path = "/inference_zero_shot"; 63 | 64 | Path audioPath = envConfig.buildModelPath( 65 | prompt_audio, context.getAmPaGroup(), context.getAmPaRole(), context.getAmPaMood(), context.getAmPaAudio()); 66 | builder.part("prompt_text", context.getAmPaAudioText()); 67 | builder.part("prompt_wav", new FileSystemResource(audioPath)); 68 | } 69 | 70 | if (StringUtils.equals(mode, "advanced")) { 71 | path = "/inference_instruct"; 72 | 73 | builder.part("instruct_text", config.getString("instruct")); 74 | } 75 | 76 | return restClient 77 | .post() 78 | .uri(context.getAmServer().getHost() + path) 79 | .contentType(MediaType.MULTIPART_FORM_DATA) 80 | .body(builder.build()) 81 | .retrieve() 82 | .toEntity(byte[].class); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/EdgeTtsCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.web.client.RestClient; 7 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 8 | import space.wenliang.ai.aigcplatformserver.bean.EdgeTtsVoice; 9 | import space.wenliang.ai.aigcplatformserver.common.ModelTypeEnum; 10 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 11 | import space.wenliang.ai.aigcplatformserver.exception.BizException; 12 | import space.wenliang.ai.aigcplatformserver.service.AmServerService; 13 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 14 | 15 | import java.util.HashMap; 16 | import java.util.List; 17 | import java.util.Map; 18 | import java.util.Objects; 19 | 20 | @Service("edge-tts") 21 | public class EdgeTtsCreator extends AbsAudioCreator { 22 | 23 | private final AmServerService amServerService; 24 | 25 | public EdgeTtsCreator(RestClient restClient, 26 | AmServerService amServerService, 27 | PinyinCacheService pinyinCacheService) { 28 | super(restClient, pinyinCacheService); 29 | this.amServerService = amServerService; 30 | } 31 | 32 | @Override 33 | public Map buildParams(AudioContext context) { 34 | context.setMediaType("wav"); 35 | 36 | Map params = new HashMap<>(); 37 | 38 | params.put("text", context.getMarkupText()); 39 | 40 | params.put("voice", JSON.parseObject(context.getAmMcParamsJson()).getString("shortName")); 41 | 42 | return params; 43 | } 44 | 45 | public List getVoices() { 46 | AmServerEntity amServer = amServerService.getOne(new LambdaQueryWrapper() 47 | .eq(AmServerEntity::getName, ModelTypeEnum.edge_tts.getName())); 48 | 49 | if (Objects.isNull(amServer)) { 50 | throw new BizException("没有找到edge-tts音频服务配置"); 51 | } 52 | 53 | String body = super.restClient 54 | .post() 55 | .uri(amServer.getHost() + "/voices") 56 | .retrieve() 57 | .body(String.class); 58 | return JSON.parseArray(body, EdgeTtsVoice.class); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/FishSpeechCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONObject; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.web.client.RestClient; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 13 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 14 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 15 | 16 | import java.io.IOException; 17 | import java.nio.file.Files; 18 | import java.nio.file.Path; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Objects; 23 | import java.util.stream.Collectors; 24 | 25 | import static space.wenliang.ai.aigcplatformserver.common.CommonConstants.prompt_audio; 26 | 27 | @Slf4j 28 | @Service("fish-speech") 29 | public class FishSpeechCreator extends AbsAudioCreator { 30 | 31 | private final EnvConfig envConfig; 32 | 33 | private final WebClient msgpackWebClient; 34 | 35 | public FishSpeechCreator(EnvConfig envConfig, 36 | RestClient restClient, 37 | PinyinCacheService pinyinCacheService, 38 | WebClient msgpackWebClient) { 39 | super(restClient, pinyinCacheService); 40 | this.envConfig = envConfig; 41 | this.msgpackWebClient = msgpackWebClient; 42 | } 43 | 44 | @Override 45 | public Map buildParams(AudioContext context) { 46 | context.setMediaType("wav"); 47 | 48 | Path audioPath = envConfig.buildModelPath( 49 | prompt_audio, context.getAmPaGroup(), context.getAmPaRole(), context.getAmPaMood(), context.getAmPaAudio()); 50 | 51 | Map params = new HashMap<>(); 52 | 53 | params.put("text", context.getMarkupText()); 54 | 55 | try { 56 | params.put("references", List.of(Map.of( 57 | "audio", Files.readAllBytes(audioPath), 58 | "text", context.getAmPaAudioText() 59 | ))); 60 | } catch (IOException e) { 61 | throw new RuntimeException(e); 62 | } 63 | 64 | params.put("format", "wav"); 65 | 66 | JSONObject config = JSON.parseObject(context.getAmMcParamsJson()); 67 | 68 | if (Objects.nonNull(config) && !StringUtils.equals(context.getAmMcId(), "-1")) { 69 | 70 | Map filterConfig = config.entrySet().stream() 71 | .filter((e) -> e.getValue() != null) 72 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 73 | 74 | params.putAll(filterConfig); 75 | } 76 | 77 | return params; 78 | } 79 | 80 | public ResponseEntity creator(AudioContext context) { 81 | 82 | textMarkup(context); 83 | 84 | Map params = buildParams(context); 85 | 86 | return msgpackWebClient 87 | .post() 88 | .uri(context.getAmServer().getUri()) 89 | .contentType(MediaType.parseMediaType("application/msgpack")) 90 | .bodyValue(params) 91 | .retrieve() 92 | .toEntity(byte[].class).block(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/audio/creator/GptSovitsCreator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.audio.creator; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONObject; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.web.client.ResourceAccessException; 11 | import org.springframework.web.client.RestClient; 12 | import space.wenliang.ai.aigcplatformserver.ai.audio.AudioContext; 13 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 14 | import space.wenliang.ai.aigcplatformserver.exception.BizException; 15 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 16 | 17 | import java.nio.file.Path; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | import java.util.Objects; 21 | import java.util.Optional; 22 | import java.util.stream.Collectors; 23 | 24 | import static space.wenliang.ai.aigcplatformserver.common.CommonConstants.prompt_audio; 25 | 26 | @Slf4j 27 | @Service("gpt-sovits") 28 | public class GptSovitsCreator extends AbsAudioCreator { 29 | 30 | private final EnvConfig envConfig; 31 | 32 | public GptSovitsCreator(EnvConfig envConfig, 33 | RestClient restClient, 34 | PinyinCacheService pinyinCacheService) { 35 | super(restClient, pinyinCacheService); 36 | this.envConfig = envConfig; 37 | } 38 | 39 | @Override 40 | public Map buildParams(AudioContext context) { 41 | context.setMediaType("wav"); 42 | 43 | Path audioPath = envConfig.buildModelPath( 44 | prompt_audio, context.getAmPaGroup(), context.getAmPaRole(), context.getAmPaMood(), context.getAmPaAudio()); 45 | 46 | String refAudioPathStr = audioPath.toAbsolutePath().toString(); 47 | 48 | Map params = new HashMap<>(); 49 | 50 | params.put("text", context.getMarkupText()); 51 | params.put("text_language", Optional.ofNullable(context.getTextLang()).orElse("zh")); 52 | 53 | params.put("refer_wav_path", refAudioPathStr); 54 | params.put("prompt_text", context.getAmPaAudioText()); 55 | params.put("prompt_language", Optional.ofNullable(context.getAmPaAudioLang()).orElse("zh")); 56 | 57 | JSONObject config = JSON.parseObject(context.getAmMcParamsJson()); 58 | 59 | if (Objects.nonNull(config) && !StringUtils.equals(context.getAmMcId(), "-1")) { 60 | 61 | Map filterConfig = config.entrySet().stream() 62 | .filter((e) -> e.getValue() != null) 63 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 64 | 65 | params.putAll(filterConfig); 66 | } 67 | 68 | return params; 69 | } 70 | 71 | @Override 72 | public void pre(AudioContext context) { 73 | 74 | try { 75 | 76 | String host = context.getAmServer().getHost(); 77 | 78 | String gpt_weights = null; 79 | String sovits_weights = null; 80 | for (JSONObject jsonObject : JSON.parseArray(context.getAmMfJson(), JSONObject.class)) { 81 | String fileType = jsonObject.getString("fileType"); 82 | String fileName = jsonObject.getString("fileName"); 83 | if (StringUtils.equals(fileType, "ckpt")) { 84 | gpt_weights = envConfig.buildModelPath("gpt-sovits", context.getAmMfGroup(), context.getAmMfRole(), fileName).toAbsolutePath().toString(); 85 | } 86 | if (StringUtils.equals(fileType, "pth")) { 87 | sovits_weights = envConfig.buildModelPath("gpt-sovits", context.getAmMfGroup(), context.getAmMfRole(), fileName).toAbsolutePath().toString(); 88 | } 89 | } 90 | 91 | if (StringUtils.isNotBlank(gpt_weights) && StringUtils.isNotBlank(sovits_weights)) { 92 | Map params = Map.of("gpt_model_path", gpt_weights, "sovits_model_path", sovits_weights); 93 | 94 | log.info("开始切换GPT-SoVITS模型, {}", gpt_weights); 95 | 96 | ResponseEntity response = restClient 97 | .post() 98 | .uri(host + "/set_model") 99 | .contentType(MediaType.APPLICATION_JSON) 100 | .body(params) 101 | .retrieve() 102 | .toEntity(String.class); 103 | 104 | log.info("切换GPT-SoVITS模型成功, {}", response.getBody()); 105 | } 106 | } catch (ResourceAccessException e) { 107 | log.error("切换GPT-SoVITS模型失败", e); 108 | throw new BizException("音频生成服务连接异常,服务类型:" + context.getAmType()); 109 | } catch (Exception e) { 110 | log.error("切换GPT-SoVITS模型失败", e); 111 | throw new BizException("切换GPT-SoVITS模型失败"); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/AiService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.stereotype.Service; 5 | import reactor.core.publisher.Flux; 6 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 7 | import space.wenliang.ai.aigcplatformserver.service.TmServerService; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Objects; 12 | import java.util.Optional; 13 | 14 | @Service 15 | @RequiredArgsConstructor 16 | public class AiService { 17 | 18 | private final Map aiServiceMap; 19 | private final TmServerService aChatModelConfigService; 20 | 21 | public Flux stream(Integer tmServerId, String systemMessage, String userMessage) { 22 | List services = aChatModelConfigService.list(); 23 | Optional first = services.stream() 24 | .filter(chatModelParam -> Objects.equals(chatModelParam.getId(), tmServerId)).findFirst(); 25 | if (first.isEmpty()) { 26 | return Flux.error(new RuntimeException("需要有一个文本大模型配置!")); 27 | } 28 | return aiServiceMap.get(first.get().getInterfaceType()).stream(first.get(), systemMessage, userMessage); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/IAiService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat; 2 | 3 | import reactor.core.publisher.Flux; 4 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 5 | 6 | public interface IAiService { 7 | 8 | Flux call(TmServerEntity config, String systemMessage, String userMessage); 9 | 10 | Flux stream(TmServerEntity config, String systemMessage, String userMessage); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/openAi/OpenAiResponseBody.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat.openAi; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class OpenAiResponseBody { 9 | 10 | private String id; 11 | private Long created; 12 | private List choices; 13 | 14 | @Data 15 | public static class Choice { 16 | private Integer index; 17 | private String finish_reason; 18 | private Delta delta; 19 | } 20 | 21 | @Data 22 | public static class Delta { 23 | private String role; 24 | private String content; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/openAi/OpenAiService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat.openAi; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONArray; 5 | import com.alibaba.fastjson2.JSONObject; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.http.HttpHeaders; 9 | import org.springframework.http.HttpStatusCode; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.web.reactive.function.client.WebClient; 13 | import reactor.core.publisher.Flux; 14 | import reactor.core.publisher.Mono; 15 | import space.wenliang.ai.aigcplatformserver.ai.chat.IAiService; 16 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 17 | import space.wenliang.ai.aigcplatformserver.socket.GlobalWebSocketHandler; 18 | 19 | import java.util.Map; 20 | import java.util.Objects; 21 | import java.util.Optional; 22 | 23 | @Slf4j 24 | @Service("OpenAi") 25 | public class OpenAiService implements IAiService { 26 | 27 | private final WebClient webClient; 28 | private final GlobalWebSocketHandler globalWebSocketHandler; 29 | 30 | public OpenAiService(WebClient webClient, GlobalWebSocketHandler globalWebSocketHandler) { 31 | this.webClient = webClient; 32 | this.globalWebSocketHandler = globalWebSocketHandler; 33 | } 34 | 35 | @Override 36 | public Flux call(TmServerEntity config, String systemMessage, String userMessage) { 37 | 38 | JSONObject request = new JSONObject(); 39 | request.put("model", config.getModel()); 40 | request.put("temperature", config.getTemperature()); 41 | 42 | JSONArray messages = new JSONArray(); 43 | messages.add(Map.of("role", "system", "content", systemMessage)); 44 | messages.add(Map.of("role", "user", "content", userMessage)); 45 | request.put("messages", messages); 46 | 47 | computedMaxTokens(config, request); 48 | 49 | return webClient.post() 50 | .uri(config.getHost() + config.getPath()) 51 | .header(HttpHeaders.AUTHORIZATION, "Bearer " + config.getApiKey()) 52 | .bodyValue(request) 53 | .retrieve() 54 | .bodyToFlux(String.class) 55 | .retry(0); 56 | } 57 | 58 | @Override 59 | public Flux stream(TmServerEntity config, String systemMessage, String userMessage) { 60 | 61 | JSONObject request = new JSONObject(); 62 | request.put("model", config.getModel()); 63 | request.put("stream", true); 64 | request.put("temperature", config.getTemperature()); 65 | 66 | JSONArray messages = new JSONArray(); 67 | messages.add(Map.of("role", "system", "content", systemMessage)); 68 | messages.add(Map.of("role", "user", "content", userMessage)); 69 | request.put("messages", messages); 70 | 71 | computedMaxTokens(config, request); 72 | 73 | return webClient.post() 74 | .uri(config.getHost() + config.getPath()) 75 | .header(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE) 76 | .header(HttpHeaders.AUTHORIZATION, "Bearer " + config.getApiKey()) 77 | .bodyValue(request) 78 | .retrieve() 79 | .onStatus( 80 | HttpStatusCode::isError, 81 | clientResponse -> clientResponse.bodyToMono(String.class) 82 | .flatMap(errorBody -> { 83 | globalWebSocketHandler.sendErrorMessage("文本大模型请求异常", errorBody); 84 | return Mono.error(new RuntimeException(errorBody)); 85 | }) 86 | ) 87 | .bodyToFlux(String.class) 88 | .filter(s -> Objects.nonNull(s) && !StringUtils.equals(s, "[DONE]")) 89 | .mapNotNull(s -> JSON.parseObject(s, OpenAiResponseBody.class)) 90 | .filter(openAiResponseBody -> Objects.isNull(openAiResponseBody.getChoices().getFirst().getFinish_reason())) 91 | .mapNotNull(openAiResponseBody -> openAiResponseBody.getChoices().getFirst().getDelta().getContent()) 92 | .retry(0) 93 | .doOnError(throwable -> log.error(throwable.getMessage(), throwable)); 94 | } 95 | 96 | public void computedMaxTokens(TmServerEntity config, JSONObject request) { 97 | 98 | if (config.getModel().startsWith("moonshot") && config.getMaxTokens() == 0) { 99 | Integer total_tokens = webClient.post() 100 | .uri(config.getHost() + "/v1/tokenizers/estimate-token-count") 101 | .header(HttpHeaders.AUTHORIZATION, "Bearer " + config.getApiKey()) 102 | .bodyValue(request) 103 | .retrieve() 104 | .onStatus( 105 | HttpStatusCode::isError, // 检查状态码是否为错误 106 | clientResponse -> clientResponse.bodyToMono(String.class) // 提取错误响应的body 107 | .flatMap(errorBody -> { 108 | globalWebSocketHandler.sendErrorMessage("文本大模型请求异常", errorBody); 109 | return Mono.error(new RuntimeException(errorBody)); 110 | }) 111 | ) 112 | .bodyToMono(String.class) 113 | .mapNotNull(JSON::parseObject) 114 | .mapNotNull(jsonObject -> jsonObject.getJSONObject("data").getInteger("total_tokens")) 115 | .block(); 116 | 117 | int modelSize = Integer.parseInt(config.getModel().substring(config.getModel().lastIndexOf("-") + 1).replace("k", "")); 118 | 119 | request.put("max_tokens", (modelSize * 1024) - Optional.ofNullable(total_tokens).orElse(0)); 120 | } else { 121 | request.put("max_tokens", config.getMaxTokens()); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/qwen/QwenAiService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat.qwen; 2 | 3 | import com.alibaba.dashscope.aigc.generation.Generation; 4 | import com.alibaba.dashscope.aigc.generation.GenerationParam; 5 | import com.alibaba.dashscope.aigc.generation.GenerationResult; 6 | import com.alibaba.dashscope.common.Message; 7 | import com.alibaba.dashscope.common.MessageManager; 8 | import com.alibaba.dashscope.common.Role; 9 | import io.reactivex.Flowable; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.stereotype.Service; 12 | import reactor.core.publisher.Flux; 13 | import space.wenliang.ai.aigcplatformserver.ai.chat.IAiService; 14 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 15 | 16 | @Slf4j 17 | @Service("Qwen") 18 | public class QwenAiService implements IAiService { 19 | 20 | @Override 21 | public Flux call(TmServerEntity config, String systemMessage, String userMessage) { 22 | try { 23 | Generation gen = new Generation(); 24 | GenerationParam generationParam = buildGenerationParam(config, systemMessage, userMessage, false); 25 | return Flux.just(gen.call(generationParam).getOutput().getChoices().getFirst().getMessage().getContent()); 26 | } catch (Exception e) { 27 | throw new RuntimeException(e); 28 | } 29 | } 30 | 31 | @Override 32 | public Flux stream(TmServerEntity config, String systemMessage, String userMessage) { 33 | try { 34 | Generation gen = new Generation(); 35 | GenerationParam generationParam = buildGenerationParam(config, systemMessage, userMessage, true); 36 | Flowable result = gen.streamCall(generationParam); 37 | return Flux.from(result).mapNotNull(generationResult -> generationResult.getOutput() 38 | .getChoices().getFirst().getMessage().getContent()); 39 | } catch (Exception e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | public GenerationParam buildGenerationParam(TmServerEntity config, String systemMessage, String userMessage, boolean stream) { 45 | MessageManager msgManager = new MessageManager(10); 46 | Message systemMsg = 47 | Message.builder().role(Role.SYSTEM.getValue()).content(systemMessage).build(); 48 | Message userMsg = Message.builder().role(Role.USER.getValue()).content(userMessage).build(); 49 | msgManager.add(systemMsg); 50 | msgManager.add(userMsg); 51 | return GenerationParam.builder() 52 | .apiKey(config.getApiKey()) 53 | .model(config.getModel()) 54 | .temperature(config.getTemperature()) 55 | .messages(msgManager.get()) 56 | .resultFormat(GenerationParam.ResultFormat.MESSAGE) 57 | .incrementalOutput(stream) 58 | .build(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/ai/chat/spark/SparkResponseBody.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.ai.chat.spark; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class SparkResponseBody { 9 | private Header header; 10 | private Payload payload; 11 | 12 | 13 | @Data 14 | public static class Header { 15 | private int code; 16 | private String message; 17 | private String sid; 18 | private int status; 19 | } 20 | 21 | @Data 22 | public static class Payload { 23 | private Choices choices; 24 | private Usage usage; 25 | 26 | @Data 27 | public static class Choices { 28 | private int status; 29 | private int seq; 30 | private List text; 31 | 32 | @Data 33 | public static class Text { 34 | private String content; 35 | private String role; 36 | private int index; 37 | 38 | } 39 | } 40 | 41 | @Data 42 | public static class Usage { 43 | private Text text; 44 | 45 | @Data 46 | public static class Text { 47 | private int question_tokens; 48 | private int prompt_tokens; 49 | private int completion_tokens; 50 | private int total_tokens; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/AiResult.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class AiResult { 14 | 15 | private List roles = new ArrayList<>(); 16 | 17 | private List linesMappings = new ArrayList<>(); 18 | 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public static class Role { 23 | private String role; 24 | private String gender; 25 | private String age; 26 | 27 | public Role(String role) { 28 | this.role = role; 29 | this.gender = "未知"; 30 | this.age = "未知"; 31 | } 32 | } 33 | 34 | @Data 35 | @NoArgsConstructor 36 | @AllArgsConstructor 37 | public static class LinesMapping { 38 | private String linesIndex; 39 | private String role; 40 | private String mood; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/AppInfoData.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | @Data 7 | @Builder 8 | public class AppInfoData { 9 | private String currentVersion; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/AudioCombine.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class AudioCombine { 9 | 10 | private Integer id; 11 | 12 | private AudioSegment audioSegment; 13 | 14 | private List audioSegments; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/AudioSegment.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class AudioSegment { 8 | 9 | private Integer id; 10 | private Integer part; 11 | private String audioName; 12 | 13 | private String text; 14 | 15 | private Double audioVolume; 16 | private Double audioSpeed; 17 | private Integer audioInterval; 18 | 19 | private Long audioLength; 20 | 21 | @JsonIgnore 22 | private String audioPath; 23 | @JsonIgnore 24 | private byte[] audioBytes; 25 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ChapterAdd.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class ChapterAdd { 10 | private TextChapterEntity textChapter; 11 | private List sortChapters; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ChapterBatchOperator.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class ChapterBatchOperator { 9 | private String projectId; 10 | private String chapterId; 11 | private List chapterInfoIds; 12 | private String operatorType; 13 | private Boolean booleanValue; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ChapterExpose.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class ChapterExpose { 9 | private String projectId; 10 | private String chapterId; 11 | private List chapterInfoIds; 12 | private Boolean combineAudio; 13 | private Boolean subtitle; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ChapterSummary.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class ChapterSummary { 7 | private String chapterId; 8 | private Integer wordCount; 9 | private Integer textCount; 10 | private Integer dialogueCount; 11 | private Integer maxTaskState; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ControlsUpdate.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.List; 7 | 8 | @Getter 9 | @Setter 10 | public class ControlsUpdate { 11 | private String projectId; 12 | private String chapterId; 13 | private List chapterInfoIds; 14 | 15 | private Boolean enableVolume; 16 | private Double volume; 17 | private Boolean enableSpeed; 18 | private Double speed; 19 | private Boolean enableInterval; 20 | private Integer interval; 21 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/EdgeTtsSetting.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class EdgeTtsSetting { 7 | private String enName; 8 | private String zhName; 9 | private Boolean showFlag; 10 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/EdgeTtsVoice.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class EdgeTtsVoice { 9 | private String Name; 10 | private String ShortName; 11 | private String Gender; 12 | private String Locale; 13 | private String SuggestedCodec; 14 | private String FriendlyName; 15 | private String Status; 16 | private List VoiceTag; 17 | 18 | @Data 19 | public static class VoiceTag { 20 | private List ContentCategories; 21 | private List VoicePersonalities; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/FormatTextProject.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.entity.ChapterInfoEntity; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class FormatTextProject { 10 | private String projectName; 11 | private String projectType; 12 | private List chapterInfos; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/GlobalSetting.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GlobalSetting { 7 | 8 | private Boolean subtitleOptimize = false; 9 | private Integer subAudioInterval = 300; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/GroupCount.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class GroupCount { 7 | private String group1; 8 | private Integer count1; 9 | private Boolean count2; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/LangDict.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class LangDict { 11 | private String enName; 12 | private String zhName; 13 | private String text; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/OpenFolder.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class OpenFolder { 7 | private String projectId; 8 | private String chapterId; 9 | private String op; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/PolyphonicInfo.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class PolyphonicInfo { 7 | private Integer index; 8 | private String markup; 9 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/PolyphonicParams.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class PolyphonicParams extends PolyphonicInfo { 7 | private Integer chapterInfoId; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/ProjectQuery.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.common.PageReq; 5 | 6 | @Data 7 | public class ProjectQuery extends PageReq { 8 | 9 | private String projectId; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/PromptAudio.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class PromptAudio { 9 | 10 | private String paGroup; 11 | private String paRole; 12 | private String paRoleGender; 13 | private String paRoleAge; 14 | private String paRoleLang; 15 | private List paRoleTags; 16 | private String paRoleAvatar; 17 | private List paMoods; 18 | 19 | @Data 20 | public static class PaMood { 21 | private String paMood; 22 | private String paMoodAvatar; 23 | private List PaAudios; 24 | } 25 | 26 | @Data 27 | public static class PaAudio { 28 | private Integer id; 29 | private String paId; 30 | private String paAudio; 31 | private String paAudioText; 32 | private String paAudioLang; 33 | private List paAudioTags; 34 | private String audioUrl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/PromptAudioSort.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class PromptAudioSort { 11 | private String group; 12 | private Integer sortOrder; 13 | private Boolean showFlag; 14 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/RoleInferenceData.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleInferenceEntity; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Data 10 | public class RoleInferenceData { 11 | private String content; 12 | private String lines; 13 | private List textRoleMoods = new ArrayList<>(); 14 | private List roles = new ArrayList<>(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/RoleInferenceParam.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleInferenceEntity; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class RoleInferenceParam { 10 | private String projectId; 11 | private String chapterId; 12 | private String inferenceType; 13 | private Integer tmServerId; 14 | private String systemPrompt; 15 | private String userPrompt; 16 | private List textRoleInferences; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/Subtitle.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class Subtitle { 11 | private double startTime; 12 | private double endTime; 13 | private String text; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/TextMarkupInfo.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Data 9 | public class TextMarkupInfo { 10 | 11 | private List polyphonicInfos = new ArrayList<>(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/TextProject.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 7 | 8 | @Getter 9 | @Setter 10 | public class TextProject extends TextProjectEntity { 11 | 12 | @TableField(exist = false) 13 | private Integer chapterCount; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/TextRoleChange.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | @Data 8 | public class TextRoleChange { 9 | private String projectId; 10 | private String chapterId; 11 | private List chapterInfoIds; 12 | private String formRoleName; 13 | private String fromRoleType; 14 | private Boolean changeModel; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/bean/UpdateModelInfo.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.bean; 2 | 3 | import lombok.Data; 4 | import space.wenliang.ai.aigcplatformserver.entity.AudioRoleInfo; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class UpdateModelInfo extends AudioRoleInfo { 10 | private String projectId; 11 | private String chapterId; 12 | private List ids; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/AudioTaskStateConstants.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | public class AudioTaskStateConstants { 4 | 5 | public static final int init = 0; 6 | public static final int process = 1; 7 | public static final int modified = 2; 8 | public static final int created = 3; 9 | public static final int combined = 4; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/CacheConstants.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | public class CacheConstants { 4 | 5 | public static final String PINYIN = "pinyin"; 6 | public static final String AM_MODEL_FILE = "am_model_file"; 7 | public static final String AM_MODEL_CONFIG = "am_model_config"; 8 | public static final String AM_PROMPT_AUDIO = "am_prompt_audio"; 9 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/CacheEnum.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CacheEnum { 7 | 8 | PINYIN(CacheConstants.PINYIN, Long.MAX_VALUE), 9 | 10 | AM_MODEL_FILE(CacheConstants.AM_MODEL_FILE, Long.MAX_VALUE), 11 | 12 | AM_MODEL_CONFIG(CacheConstants.AM_MODEL_CONFIG, Long.MAX_VALUE), 13 | 14 | AM_PROMPT_AUDIO(CacheConstants.AM_PROMPT_AUDIO, Long.MAX_VALUE), 15 | 16 | ; 17 | 18 | public final String name; 19 | 20 | public final Long expires; 21 | 22 | CacheEnum(String name, Long expires) { 23 | this.name = name; 24 | this.expires = expires; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/CommonConstants.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | public class CommonConstants { 4 | 5 | public static String prompt_audio = "ref-audio"; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/ModelTypeEnum.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum ModelTypeEnum { 7 | 8 | gpt_sovits("audio", "gpt-sovits"), 9 | fish_speech("audio", "fish-speech"), 10 | edge_tts("audio", "edge-tts"), 11 | chat_tts("audio", "chat-tts"), 12 | cosy_voice("audio", "cosy-voice"), 13 | ; 14 | 15 | private final String type; 16 | private final String name; 17 | 18 | ModelTypeEnum(String type, String name) { 19 | this.type = type; 20 | this.name = name; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/PageReq.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class PageReq { 9 | 10 | private Long current = 1L; 11 | 12 | private Long pageSize = 10L; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/Result.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.experimental.Accessors; 7 | 8 | @Data 9 | @Accessors(chain = true) 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class Result { 13 | 14 | public String code; 15 | 16 | public String msg; 17 | 18 | public T data; 19 | 20 | public static Result success() { 21 | return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), null); 22 | } 23 | 24 | public static Result success(T data) { 25 | return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMsg(), data); 26 | } 27 | 28 | public static Result failure() { 29 | return new Result<>(ResultEnum.FAILURE.getCode(), ResultEnum.FAILURE.getMsg(), null); 30 | } 31 | 32 | public static Result failure(String msg) { 33 | return new Result<>(ResultEnum.FAILURE.getCode(), msg, null); 34 | } 35 | 36 | public static Result failure(String code, String msg) { 37 | return new Result<>(code, msg, null); 38 | } 39 | 40 | public static Result failure(ResultEnum resultEnum) { 41 | return new Result<>(resultEnum.getCode(), resultEnum.getMsg(), null); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/common/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.common; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum ResultEnum { 7 | 8 | SUCCESS("0000", "搞定~"), 9 | FAILURE("9999", "处理遇到了问题~"), 10 | PARAMETER_ERROR("0001", "参数缺失~"), 11 | ; 12 | 13 | 14 | private final String code; 15 | 16 | private final String msg; 17 | 18 | ResultEnum(String code, String msg) { 19 | this.code = code; 20 | this.msg = msg; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/ApiPrefixFilter.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import jakarta.servlet.*; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import jakarta.servlet.http.HttpServletRequestWrapper; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.annotation.Profile; 8 | 9 | import java.io.IOException; 10 | 11 | @Configuration 12 | @Profile("integrated") 13 | public class ApiPrefixFilter implements Filter { 14 | 15 | private static final String API_PREFIX = "/api"; 16 | 17 | @Override 18 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 19 | throws IOException, ServletException { 20 | HttpServletRequest httpRequest = (HttpServletRequest) request; 21 | String requestURI = httpRequest.getRequestURI(); 22 | 23 | if (requestURI.startsWith(API_PREFIX)) { 24 | // 去掉 /api 前缀 25 | String newRequestURI = requestURI.substring(API_PREFIX.length()); 26 | HttpServletRequestWrapper wrapper = new IntegratedRequestWrapper(httpRequest, newRequestURI); 27 | chain.doFilter(wrapper, response); 28 | } else { 29 | chain.doFilter(request, response); 30 | } 31 | } 32 | 33 | public static class IntegratedRequestWrapper extends HttpServletRequestWrapper { 34 | 35 | private final String newRequestURI; 36 | 37 | public IntegratedRequestWrapper(HttpServletRequest request, String newRequestURI) { 38 | super(request); 39 | this.newRequestURI = newRequestURI; 40 | } 41 | 42 | @Override 43 | public String getRequestURI() { 44 | return newRequestURI; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/EnvConfig.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import lombok.Data; 4 | import lombok.RequiredArgsConstructor; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Configuration; 8 | import space.wenliang.ai.aigcplatformserver.hooks.StartHook; 9 | 10 | import java.io.File; 11 | import java.net.URLEncoder; 12 | import java.nio.charset.StandardCharsets; 13 | import java.nio.file.Path; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | @Data 19 | @Configuration 20 | @RequiredArgsConstructor 21 | public class EnvConfig implements StartHook.StartHookListener { 22 | 23 | @Value("${server.domain:}") 24 | private String domain; 25 | 26 | @Value("${server.port:}") 27 | private String port; 28 | 29 | @Value("${user.dir:}") 30 | private String userDir; 31 | 32 | @Value("${application.version:}") 33 | private String applicationVersion; 34 | 35 | private String modelDir; 36 | private String configDir; 37 | private String projectDir; 38 | 39 | private String modelUrl; 40 | private String projectUrl; 41 | 42 | public static String urlEncode(List path) { 43 | return path.stream() 44 | .map(s -> URLEncoder.encode(s, StandardCharsets.UTF_8)) 45 | .map(s -> s.replace("+", "%20")) 46 | .collect(Collectors.joining("/")); 47 | } 48 | 49 | @Override 50 | public void startHook() { 51 | 52 | if (StringUtils.isBlank(domain)) { 53 | String host = "127.0.0.1"; 54 | domain = "http://" + host + ":" + port; 55 | } 56 | 57 | modelUrl = STR."\{domain}/files/model/"; 58 | projectUrl = STR."\{domain}/files/project/"; 59 | 60 | if (StringUtils.isBlank(modelDir)) { 61 | modelDir = userDir + File.separator + "model"; 62 | } 63 | 64 | if (StringUtils.isBlank(configDir)) { 65 | configDir = userDir + File.separator + "config"; 66 | } 67 | 68 | if (StringUtils.isBlank(projectDir)) { 69 | projectDir = userDir + File.separator + "project"; 70 | } 71 | } 72 | 73 | public Path buildModelPath(String... path) { 74 | return Path.of(modelDir, path); 75 | } 76 | 77 | public Path buildConfigPath(String... names) { 78 | return Path.of(configDir, names); 79 | } 80 | 81 | public Path buildProjectPath(String... names) { 82 | return Path.of(projectDir, names); 83 | } 84 | 85 | public String buildModelUrl(String... path) { 86 | return modelUrl + urlEncode(Arrays.asList(path)); 87 | } 88 | 89 | public String buildProjectUrl(String... path) { 90 | return projectUrl + urlEncode(Arrays.asList(path)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/LiquibaseConfig.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import liquibase.integration.spring.SpringLiquibase; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.Profile; 7 | 8 | import javax.sql.DataSource; 9 | 10 | @Configuration 11 | public class LiquibaseConfig { 12 | 13 | @Bean 14 | @Profile("mysql") 15 | public SpringLiquibase mysqlLiquibase(DataSource dataSource) { 16 | SpringLiquibase liquibase = new SpringLiquibase(); 17 | liquibase.setDataSource(dataSource); 18 | liquibase.setChangeLog("classpath:liquibase/mysql/master.xml"); 19 | liquibase.setClearCheckSums(true); 20 | return liquibase; 21 | } 22 | 23 | @Bean 24 | @Profile("sqlite") 25 | public SpringLiquibase sqliteLiquibase(DataSource dataSource) { 26 | SpringLiquibase liquibase = new SpringLiquibase(); 27 | liquibase.setDataSource(dataSource); 28 | liquibase.setChangeLog("classpath:liquibase/sqlite/master.xml"); 29 | liquibase.setClearCheckSums(true); 30 | return liquibase; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | @MapperScan("space.wenliang.ai.aigcplatformserver.mapper") 12 | public class MybatisPlusConfig { 13 | 14 | @Bean 15 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 16 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 17 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 18 | return interceptor; 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.msgpack.jackson.dataformat.MessagePackFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.http.client.ClientHttpRequestFactory; 10 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 11 | import org.springframework.http.codec.json.Jackson2JsonDecoder; 12 | import org.springframework.http.codec.json.Jackson2JsonEncoder; 13 | import org.springframework.web.client.RestClient; 14 | import org.springframework.web.client.RestTemplate; 15 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 16 | import org.springframework.web.reactive.function.client.WebClient; 17 | import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; 18 | import org.springframework.web.reactive.socket.client.WebSocketClient; 19 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 20 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 21 | import space.wenliang.ai.aigcplatformserver.spring.resolver.SingleValueParamHandlerMethodArgumentResolver; 22 | 23 | import java.util.List; 24 | 25 | @Configuration 26 | public class WebMvcConfig implements WebMvcConfigurer { 27 | 28 | @Override 29 | public void addViewControllers(ViewControllerRegistry registry) { 30 | registry.addViewController("/webui/**") 31 | .setViewName("forward:/index.html"); 32 | } 33 | 34 | @Override 35 | public void addArgumentResolvers(List argumentResolvers) { 36 | argumentResolvers.add(new SingleValueParamHandlerMethodArgumentResolver()); 37 | WebMvcConfigurer.super.addArgumentResolvers(argumentResolvers); 38 | } 39 | 40 | 41 | @Bean 42 | public RestTemplate restTemplate(ClientHttpRequestFactory factory) { 43 | return new RestTemplate(factory); 44 | 45 | } 46 | 47 | @Bean 48 | public ClientHttpRequestFactory simpleClientHttpRequestFactory() { 49 | SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); 50 | factory.setReadTimeout(600000);//单位为ms 51 | factory.setConnectTimeout(30000);//单位为ms 52 | return factory; 53 | } 54 | 55 | @Bean 56 | public RestClient restClient(ClientHttpRequestFactory factory) { 57 | return RestClient.builder() 58 | .requestFactory(factory) 59 | .build(); 60 | } 61 | 62 | @Bean 63 | public WebClient webClient() { 64 | return WebClient.builder() 65 | .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 66 | .build(); 67 | } 68 | 69 | @Bean 70 | public WebClient msgpackWebClient() { 71 | ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); 72 | 73 | return WebClient.builder() 74 | .codecs(configurer -> { 75 | configurer.defaultCodecs().jackson2JsonEncoder( 76 | new Jackson2JsonEncoder(objectMapper, MediaType.parseMediaType("application/msgpack")) 77 | ); 78 | configurer.defaultCodecs().jackson2JsonDecoder( 79 | new Jackson2JsonDecoder(objectMapper, MediaType.parseMediaType("application/msgpack")) 80 | ); 81 | configurer.defaultCodecs().maxInMemorySize(10 * 1024 * 1024); // 设置最大缓冲区为 10MB 82 | }) 83 | .build(); 84 | 85 | } 86 | 87 | @Bean 88 | public WebSocketClient webSocketClient() { 89 | return new ReactorNettyWebSocketClient(); 90 | } 91 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 5 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 6 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 7 | import space.wenliang.ai.aigcplatformserver.socket.GlobalWebSocketHandler; 8 | import space.wenliang.ai.aigcplatformserver.socket.TextProjectWebSocketHandler; 9 | 10 | @Configuration 11 | @EnableWebSocket 12 | public class WebSocketConfig implements WebSocketConfigurer { 13 | 14 | private final GlobalWebSocketHandler globalWebSocketHandler; 15 | private final TextProjectWebSocketHandler textProjectWebSocketHandler; 16 | 17 | public WebSocketConfig(GlobalWebSocketHandler globalWebSocketHandler, 18 | TextProjectWebSocketHandler textProjectWebSocketHandler) { 19 | this.globalWebSocketHandler = globalWebSocketHandler; 20 | this.textProjectWebSocketHandler = textProjectWebSocketHandler; 21 | } 22 | 23 | @Override 24 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 25 | registry.addHandler(globalWebSocketHandler, "/ws/global").setAllowedOrigins("*"); 26 | registry.addHandler(textProjectWebSocketHandler, "/ws/text").setAllowedOrigins("*"); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/AmModelFileController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import space.wenliang.ai.aigcplatformserver.common.Result; 8 | import space.wenliang.ai.aigcplatformserver.entity.AmModelFileEntity; 9 | import space.wenliang.ai.aigcplatformserver.service.AmModelFileService; 10 | import space.wenliang.ai.aigcplatformserver.spring.annotation.SingleValueParam; 11 | 12 | import java.util.List; 13 | 14 | @RestController 15 | @RequestMapping("amModelFile") 16 | @RequiredArgsConstructor 17 | public class AmModelFileController { 18 | 19 | private final AmModelFileService amModelFileService; 20 | 21 | @PostMapping("refreshCache") 22 | public Result refreshCache(@SingleValueParam("modelType") String modelType) { 23 | amModelFileService.refreshCache(modelType); 24 | return Result.success(); 25 | } 26 | 27 | @PostMapping("getByModelType") 28 | public Result getByModelType(@SingleValueParam("modelType") String modelType) { 29 | List modelFiles = amModelFileService.getByModelType(modelType); 30 | return Result.success(modelFiles); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/AmPromptAudioController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import space.wenliang.ai.aigcplatformserver.bean.PromptAudio; 9 | import space.wenliang.ai.aigcplatformserver.bean.PromptAudioSort; 10 | import space.wenliang.ai.aigcplatformserver.common.Result; 11 | import space.wenliang.ai.aigcplatformserver.service.AmPromptAudioService; 12 | 13 | import java.util.List; 14 | 15 | @RestController 16 | @RequestMapping("amPromptAudio") 17 | @RequiredArgsConstructor 18 | public class AmPromptAudioController { 19 | 20 | private final AmPromptAudioService amPromptAudioService; 21 | 22 | @PostMapping("refreshCache") 23 | public Result refreshCache() { 24 | amPromptAudioService.refreshCache(); 25 | return Result.success(); 26 | } 27 | 28 | @PostMapping("queryPromptAudios") 29 | public Result queryPromptAudios() { 30 | List promptAudios = amPromptAudioService.promptAudios(); 31 | return Result.success(promptAudios); 32 | } 33 | 34 | @PostMapping("updatePromptAudio") 35 | public Result updatePromptAudio(@RequestBody PromptAudio promptAudio) { 36 | amPromptAudioService.updatePromptAudio(promptAudio); 37 | return Result.success(); 38 | } 39 | 40 | @PostMapping("queryPromptAudioSorts") 41 | public Result queryPromptAudioSorts() { 42 | List refAudioSorts = amPromptAudioService.queryPromptAudioSorts(); 43 | return Result.success(refAudioSorts); 44 | } 45 | 46 | @PostMapping("updatePromptAudioSorts") 47 | public Result updatePromptAudioSorts(@RequestBody List promptAudioSorts) { 48 | amPromptAudioService.updatePromptAudioSorts(promptAudioSorts); 49 | return Result.success(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/AmServerController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import space.wenliang.ai.aigcplatformserver.common.Result; 10 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 11 | import space.wenliang.ai.aigcplatformserver.service.AmServerService; 12 | 13 | import java.util.List; 14 | 15 | @Slf4j 16 | @RestController 17 | @RequestMapping("amServer") 18 | @RequiredArgsConstructor 19 | public class AmServerController { 20 | 21 | private final AmServerService amServerService; 22 | 23 | @PostMapping("list") 24 | public Result list() { 25 | List list = amServerService.list(); 26 | return Result.success(list); 27 | } 28 | 29 | @PostMapping("updateConfig") 30 | public Result updateConfig(@RequestBody AmServerEntity config) { 31 | amServerService.updateById(config); 32 | return Result.success(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/AppController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import space.wenliang.ai.aigcplatformserver.bean.AppInfoData; 8 | import space.wenliang.ai.aigcplatformserver.common.Result; 9 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 10 | 11 | @RestController 12 | @RequestMapping("app") 13 | @RequiredArgsConstructor 14 | public class AppController { 15 | 16 | private final EnvConfig envConfig; 17 | 18 | @PostMapping("appInfo") 19 | public Result getAppInfoData() { 20 | AppInfoData appInfoData = AppInfoData.builder() 21 | .currentVersion(envConfig.getApplicationVersion()) 22 | .build(); 23 | return Result.success(appInfoData); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/DictController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import space.wenliang.ai.aigcplatformserver.bean.LangDict; 9 | import space.wenliang.ai.aigcplatformserver.common.Result; 10 | import space.wenliang.ai.aigcplatformserver.service.cache.DictService; 11 | 12 | import java.util.List; 13 | 14 | @RestController 15 | @RequestMapping("dict") 16 | @RequiredArgsConstructor 17 | public class DictController { 18 | 19 | private final DictService dictService; 20 | 21 | @PostMapping("lang") 22 | public Result lang() { 23 | List langDicts = dictService.getLangDict(); 24 | return Result.success(langDicts); 25 | } 26 | 27 | @PostMapping("lang/edit") 28 | public Result editLangDict(@RequestBody LangDict langDict) { 29 | dictService.editLangDict(langDict); 30 | return Result.success(); 31 | } 32 | 33 | @PostMapping("lang/sort") 34 | public Result langDictSort(@RequestBody List langDicts) { 35 | dictService.langDictSort(langDicts); 36 | return Result.success(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/FilesController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import jakarta.servlet.ServletContext; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.core.io.Resource; 7 | import org.springframework.core.io.UrlResource; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.*; 11 | import space.wenliang.ai.aigcplatformserver.bean.OpenFolder; 12 | import space.wenliang.ai.aigcplatformserver.common.Result; 13 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 14 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 15 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 16 | import space.wenliang.ai.aigcplatformserver.service.TextChapterService; 17 | import space.wenliang.ai.aigcplatformserver.service.TextProjectService; 18 | import space.wenliang.ai.aigcplatformserver.util.FileUtils; 19 | 20 | import java.io.IOException; 21 | import java.net.URLDecoder; 22 | import java.nio.charset.StandardCharsets; 23 | import java.nio.file.Path; 24 | import java.nio.file.Paths; 25 | 26 | @RestController 27 | @RequestMapping("/files") 28 | @RequiredArgsConstructor 29 | public class FilesController { 30 | 31 | private final EnvConfig envConfig; 32 | private final ServletContext servletContext; 33 | private final TextProjectService textProjectService; 34 | private final TextChapterService textChapterService; 35 | 36 | @GetMapping("/model/**") 37 | public ResponseEntity getModelFile(HttpServletRequest request) { 38 | return getResourceFile(request, "/files/model/", envConfig.getModelDir()); 39 | } 40 | 41 | @GetMapping("/project/**") 42 | public ResponseEntity getProjectFile(HttpServletRequest request) { 43 | return getResourceFile(request, "/files/project/", envConfig.getProjectDir()); 44 | } 45 | 46 | @PostMapping("openFolder") 47 | public Result openFolder(@RequestBody OpenFolder openFolder) throws IOException { 48 | TextProjectEntity textProject = textProjectService.getByProjectId(openFolder.getProjectId()); 49 | TextChapterEntity textChapter = textChapterService.getByChapterId(openFolder.getChapterId()); 50 | 51 | Path srtPath = envConfig.buildProjectPath( 52 | "text", 53 | FileUtils.fileNameFormat(textProject.getProjectName()), 54 | FileUtils.fileNameFormat(textChapter.getChapterName())); 55 | FileUtils.openFolder(srtPath); 56 | return Result.success(); 57 | } 58 | 59 | public ResponseEntity getResourceFile(HttpServletRequest request, String subUrl, String dir) { 60 | try { 61 | 62 | String fullPath = URLDecoder.decode(request.getRequestURI().substring(subUrl.length()), StandardCharsets.UTF_8); 63 | Path filePath = Paths.get(dir).resolve(fullPath).normalize(); 64 | 65 | Resource resource = new UrlResource(filePath.toUri()); 66 | if (!resource.exists() || !resource.isReadable()) { 67 | return ResponseEntity.notFound().build(); 68 | } 69 | 70 | // 确定文件的MIME类型 71 | String contentType = servletContext.getMimeType(filePath.toString()); 72 | if (contentType == null) { 73 | contentType = "application/octet-stream"; 74 | } 75 | 76 | // 设置响应头并返回文件 77 | return ResponseEntity.ok() 78 | .contentType(MediaType.parseMediaType(contentType)) 79 | .body(resource); 80 | } catch (Exception e) { 81 | return ResponseEntity.badRequest().build(); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/GlobalSettingController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | import space.wenliang.ai.aigcplatformserver.bean.GlobalSetting; 9 | import space.wenliang.ai.aigcplatformserver.common.Result; 10 | import space.wenliang.ai.aigcplatformserver.service.cache.GlobalSettingService; 11 | 12 | @RestController 13 | @RequestMapping("globalSetting") 14 | @RequiredArgsConstructor 15 | public class GlobalSettingController { 16 | 17 | private final GlobalSettingService globalSettingService; 18 | 19 | @PostMapping("getGlobalSetting") 20 | public Result getGlobalSetting() { 21 | return Result.success(globalSettingService.getGlobalSetting()); 22 | } 23 | 24 | @PostMapping("updateGlobalSetting") 25 | public Result updateGlobalSetting(@RequestBody GlobalSetting globalSetting) { 26 | globalSettingService.updateGlobalSetting(globalSetting); 27 | return Result.success(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/PinyinController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import space.wenliang.ai.aigcplatformserver.common.Result; 8 | import space.wenliang.ai.aigcplatformserver.service.cache.PinyinCacheService; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | @RestController 14 | @RequestMapping("pinyin") 15 | @RequiredArgsConstructor 16 | public class PinyinController { 17 | 18 | private final PinyinCacheService pinyinCacheService; 19 | 20 | @PostMapping("getPinyinData") 21 | public Result getPinyinData() { 22 | Map> textPinyins = pinyinCacheService.getTextPinyins(); 23 | return Result.success(textPinyins); 24 | } 25 | 26 | @PostMapping("refreshCache") 27 | public Result refreshCache() { 28 | pinyinCacheService.refreshCache(); 29 | return Result.success(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/SseController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import org.springframework.web.bind.annotation.PostMapping; 4 | import org.springframework.web.bind.annotation.RequestBody; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import reactor.core.publisher.Flux; 8 | import space.wenliang.ai.aigcplatformserver.bean.RoleInferenceParam; 9 | import space.wenliang.ai.aigcplatformserver.service.business.BTextChapterService; 10 | 11 | @RestController 12 | @RequestMapping("sse") 13 | public class SseController { 14 | 15 | private final BTextChapterService bTextChapterService; 16 | 17 | public SseController(BTextChapterService bTextChapterService) { 18 | this.bTextChapterService = bTextChapterService; 19 | } 20 | 21 | @PostMapping("textChapter/roleInference") 22 | public Flux roleInference(@RequestBody RoleInferenceParam roleInferenceParam) { 23 | return bTextChapterService.roleInference(roleInferenceParam); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/TextProjectController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.springframework.web.bind.annotation.*; 6 | import org.springframework.web.multipart.MultipartFile; 7 | import space.wenliang.ai.aigcplatformserver.bean.FormatTextProject; 8 | import space.wenliang.ai.aigcplatformserver.bean.TextProject; 9 | import space.wenliang.ai.aigcplatformserver.common.Result; 10 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 11 | import space.wenliang.ai.aigcplatformserver.service.TextProjectService; 12 | import space.wenliang.ai.aigcplatformserver.service.business.BTextProjectService; 13 | import space.wenliang.ai.aigcplatformserver.spring.annotation.SingleValueParam; 14 | import space.wenliang.ai.aigcplatformserver.util.FileUtils; 15 | 16 | import java.io.BufferedReader; 17 | import java.io.IOException; 18 | import java.io.InputStreamReader; 19 | import java.nio.charset.Charset; 20 | import java.util.List; 21 | 22 | @RestController 23 | @RequestMapping("textProject") 24 | @RequiredArgsConstructor 25 | public class TextProjectController { 26 | 27 | private final TextProjectService textProjectService; 28 | private final BTextProjectService bTextProjectService; 29 | 30 | @PostMapping("projectList") 31 | public Result projectList() { 32 | List list = bTextProjectService.projectList(); 33 | return Result.success(list); 34 | } 35 | 36 | @PostMapping("getTextProject") 37 | public Result getTextProject(@SingleValueParam("projectId") String projectId) { 38 | TextProjectEntity textProject = bTextProjectService.getByProjectId(projectId); 39 | return Result.success(textProject); 40 | } 41 | 42 | @PostMapping("createProject") 43 | public Result createProject(@RequestParam("project") String project, 44 | @RequestParam("projectType") String projectType, 45 | @RequestParam("file") MultipartFile file) throws IOException { 46 | 47 | Charset charset = FileUtils.detectCharset(file.getBytes()); 48 | 49 | StringBuilder content = new StringBuilder(); 50 | 51 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream(), charset))) { 52 | String line; 53 | while ((line = reader.readLine()) != null) { 54 | if (StringUtils.isNotBlank(line)) { 55 | content.append(line.stripLeading()).append("\n"); 56 | } 57 | } 58 | } 59 | bTextProjectService.createProject(project, projectType, content.toString()); 60 | return Result.success(); 61 | } 62 | 63 | @PostMapping("createFormatTextProject") 64 | public Result createFormatTextProject(@RequestBody FormatTextProject project) { 65 | bTextProjectService.createFormatTextProject(project); 66 | return Result.success(); 67 | } 68 | 69 | @PostMapping("updateProject") 70 | public Result updateProject(@RequestBody TextProjectEntity textProjectEntity) throws IOException { 71 | bTextProjectService.updateProject(textProjectEntity); 72 | return Result.success(); 73 | } 74 | 75 | 76 | @PostMapping("deleteProject") 77 | public Result deleteProject(@RequestBody TextProjectEntity textProjectEntity) throws IOException { 78 | bTextProjectService.deleteProject(textProjectEntity); 79 | return Result.success(); 80 | } 81 | 82 | @PostMapping("tmpChapterSplit") 83 | public Result tmpChapterSplit(@SingleValueParam("projectId") String projectId, 84 | @SingleValueParam("chapterPattern") String chapterPattern, 85 | @SingleValueParam("dialoguePattern") String dialoguePattern) { 86 | List chapterTitles = bTextProjectService.tmpChapterSplit(projectId, chapterPattern, dialoguePattern); 87 | return Result.success(chapterTitles); 88 | } 89 | 90 | @PostMapping("chapterSplit") 91 | public Result chapterSplit(@SingleValueParam("projectId") String projectId, 92 | @SingleValueParam("chapterPattern") String chapterPattern, 93 | @SingleValueParam("dialoguePattern") String dialoguePattern) { 94 | bTextProjectService.chapterSplit(projectId, chapterPattern, dialoguePattern); 95 | return Result.success(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/TmPromptTemplateController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.util.CollectionUtils; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import space.wenliang.ai.aigcplatformserver.common.Result; 14 | import space.wenliang.ai.aigcplatformserver.entity.TmPromptTemplateEntity; 15 | import space.wenliang.ai.aigcplatformserver.service.TmPromptTemplateService; 16 | import space.wenliang.ai.aigcplatformserver.spring.annotation.SingleValueParam; 17 | 18 | import java.util.Comparator; 19 | import java.util.List; 20 | import java.util.Objects; 21 | 22 | @Slf4j 23 | @RestController 24 | @RequestMapping("tmPromptTemplate") 25 | @RequiredArgsConstructor 26 | public class TmPromptTemplateController { 27 | 28 | private final TmPromptTemplateService tmPromptTemplateService; 29 | 30 | @PostMapping("list") 31 | public Result list(@SingleValueParam("templateGroup") String templateGroup, 32 | @SingleValueParam("isDefault") Boolean isDefault) { 33 | List list = tmPromptTemplateService.list( 34 | new LambdaQueryWrapper() 35 | .eq(StringUtils.isNotBlank(templateGroup), TmPromptTemplateEntity::getTemplateGroup, templateGroup) 36 | .eq(Objects.nonNull(isDefault), TmPromptTemplateEntity::getIsDefault, isDefault)) 37 | .stream() 38 | .sorted(Comparator.comparing(TmPromptTemplateEntity::getTemplateGroup) 39 | .thenComparing(v -> !Objects.equals(v.getIsPreset(), Boolean.TRUE))) 40 | .toList(); 41 | return Result.success(list); 42 | } 43 | 44 | @PostMapping("edit") 45 | public Result edit(@RequestBody TmPromptTemplateEntity promptTemplateEntity) { 46 | List list = tmPromptTemplateService.list( 47 | new LambdaQueryWrapper() 48 | .eq(TmPromptTemplateEntity::getTemplateGroup, promptTemplateEntity.getTemplateGroup()) 49 | .eq(TmPromptTemplateEntity::getIsDefault, true)); 50 | 51 | if (Objects.isNull(promptTemplateEntity.getId())) { 52 | promptTemplateEntity.setIsDefault(CollectionUtils.isEmpty(list)); 53 | } 54 | promptTemplateEntity.setIsPreset(false); 55 | tmPromptTemplateService.saveOrUpdate(promptTemplateEntity); 56 | return Result.success(); 57 | } 58 | 59 | @PostMapping("delete") 60 | public Result delete(@RequestBody TmPromptTemplateEntity promptTemplateEntity) { 61 | if (tmPromptTemplateService.removeById(promptTemplateEntity) && Objects.equals(promptTemplateEntity.getIsDefault(), Boolean.TRUE)) { 62 | tmPromptTemplateService.update( 63 | new LambdaUpdateWrapper() 64 | .set(TmPromptTemplateEntity::getIsDefault, true) 65 | .eq(TmPromptTemplateEntity::getTemplateGroup, promptTemplateEntity.getTemplateGroup()) 66 | .eq(TmPromptTemplateEntity::getIsPreset, true)); 67 | } 68 | return Result.success(); 69 | } 70 | 71 | @PostMapping("setDefault") 72 | public Result setDefault(@RequestBody TmPromptTemplateEntity promptTemplateEntity) { 73 | List list = tmPromptTemplateService.list( 74 | new LambdaQueryWrapper() 75 | .eq(TmPromptTemplateEntity::getTemplateGroup, promptTemplateEntity.getTemplateGroup())); 76 | List customPromptTemplateIds = list.stream().map(TmPromptTemplateEntity::getId) 77 | .filter(id -> !Objects.equals(id, promptTemplateEntity.getId())) 78 | .toList(); 79 | if (!CollectionUtils.isEmpty(customPromptTemplateIds)) { 80 | tmPromptTemplateService.update( 81 | new LambdaUpdateWrapper() 82 | .set(TmPromptTemplateEntity::getIsDefault, false) 83 | .in(TmPromptTemplateEntity::getId, customPromptTemplateIds)); 84 | } 85 | tmPromptTemplateService.update( 86 | new LambdaUpdateWrapper() 87 | .set(TmPromptTemplateEntity::getIsDefault, true) 88 | .eq(TmPromptTemplateEntity::getId, promptTemplateEntity.getId())); 89 | return Result.success(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/controller/TmServerController.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.controller; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import space.wenliang.ai.aigcplatformserver.common.Result; 11 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 12 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 13 | import space.wenliang.ai.aigcplatformserver.service.TmServerService; 14 | import space.wenliang.ai.aigcplatformserver.util.FileUtils; 15 | 16 | import java.nio.file.Files; 17 | import java.nio.file.Path; 18 | import java.util.List; 19 | import java.util.Objects; 20 | 21 | @Slf4j 22 | @RestController 23 | @RequestMapping("tmServer") 24 | @RequiredArgsConstructor 25 | public class TmServerController { 26 | 27 | public static String textModelServerTemplateStr = """ 28 | [ 29 | { 30 | "templateName": "OpenAI", 31 | "interfaceType": "OpenAi", 32 | "host": "https://api.openai.com", 33 | "path": "/v1/chat/completions", 34 | "model": "gpt-3.5-turbo", 35 | "temperature": 0.3, 36 | "maxTokens": 4096 37 | }, 38 | { 39 | "templateName": "Kimi", 40 | "interfaceType": "OpenAi", 41 | "host": "https://api.moonshot.cn", 42 | "path": "/v1/chat/completions", 43 | "model": "moonshot-v1-32k", 44 | "temperature": 0.3, 45 | "maxTokens": 10000 46 | }, 47 | { 48 | "templateName": "DeepSeek", 49 | "interfaceType": "OpenAi", 50 | "host": "https://api.deepseek.com", 51 | "path": "/v1/chat/completions", 52 | "model": "deepseek-chat", 53 | "temperature": 0.3, 54 | "maxTokens": 4096 55 | }, 56 | { 57 | "templateName": "Ollama", 58 | "interfaceType": "OpenAi", 59 | "host": "http://127.0.0.1:11434", 60 | "path": "/v1/chat/completions", 61 | "model": "qwen2:7b", 62 | "temperature": 0.3, 63 | "maxTokens": 4096 64 | }, 65 | { 66 | "templateName": "Glm", 67 | "interfaceType": "OpenAi", 68 | "host": "https://open.bigmodel.cn", 69 | "path": "/api/paas/v4/chat/completions", 70 | "model": "glm-4", 71 | "temperature": 0.3, 72 | "maxTokens": 4096 73 | }, 74 | { 75 | "templateName": "Spark", 76 | "interfaceType": "Spark", 77 | "host": "https://spark-api.xf-yun.com", 78 | "path": "/v3.5/chat", 79 | "model": "generalv3.5", 80 | "temperature": 0.3, 81 | "maxTokens": 4096 82 | }, 83 | { 84 | "templateName": "Qwen", 85 | "interfaceType": "Qwen", 86 | "host": "https://dashscope.aliyuncs.com", 87 | "path": "/api/v1/services/aigc/text-generation/generation", 88 | "model": "qwen-turbo", 89 | "temperature": 0.3, 90 | "maxTokens": 2000 91 | } 92 | ] 93 | """; 94 | private final EnvConfig envConfig; 95 | private final TmServerService tmServerService; 96 | 97 | @PostMapping("list") 98 | public Result list() { 99 | return Result.success(tmServerService.list()); 100 | } 101 | 102 | @PostMapping("templateList") 103 | public Result templateList() { 104 | List tmServerEntities; 105 | 106 | Path path = envConfig.buildConfigPath("text-model-server-template.json"); 107 | 108 | if (Files.exists(path)) { 109 | try { 110 | tmServerEntities = FileUtils.getListFromFile(path, Object.class); 111 | } catch (Exception e) { 112 | log.error("读取文本大模型服务模板失败", e); 113 | throw new RuntimeException(e); 114 | } 115 | } else { 116 | tmServerEntities = JSON.parseArray(textModelServerTemplateStr); 117 | } 118 | return Result.success(tmServerEntities); 119 | } 120 | 121 | @PostMapping("updateModelChatConfig") 122 | public Result updateModelChatConfig(@RequestBody TmServerEntity tmServerEntity) { 123 | tmServerService.saveOrUpdate(tmServerEntity); 124 | 125 | return Result.success(); 126 | } 127 | 128 | @PostMapping("deleteModelChatConfig") 129 | public Result deleteModelChatConfig(@RequestBody TmServerEntity tmServerEntity) { 130 | tmServerService.removeById(tmServerEntity); 131 | 132 | return Result.success(); 133 | } 134 | 135 | @PostMapping("activeModelChatConfig") 136 | public Result activeModelChatConfig(@RequestBody TmServerEntity tmServerEntity) { 137 | List tmServerEntities = tmServerService.list(); 138 | 139 | for (TmServerEntity serverEntity : tmServerEntities) { 140 | serverEntity.setActive(Objects.equals(tmServerEntity.getId(), serverEntity.getId())); 141 | } 142 | 143 | tmServerService.updateBatchById(tmServerEntities); 144 | 145 | return Result.success(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AmModelConfigEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName am_model_config 13 | */ 14 | @TableName(value = "am_model_config") 15 | @Data 16 | public class AmModelConfigEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "mc_id") 28 | private String mcId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "mc_name") 33 | private String mcName; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "mc_params_json") 38 | private String mcParamsJson; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "am_type") 43 | private String amType; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "mf_id") 48 | private String mfId; 49 | /** 50 | * 51 | */ 52 | @TableField(value = "pa_id") 53 | private String paId; 54 | /** 55 | * 56 | */ 57 | @TableField(value = "text") 58 | private String text; 59 | /** 60 | * 61 | */ 62 | @TableField(value = "save_audio") 63 | private Boolean saveAudio; 64 | /** 65 | * 66 | */ 67 | @TableField(value = "show_flag") 68 | private Boolean showFlag; 69 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AmModelFileEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName am_model_file 13 | */ 14 | @TableName(value = "am_model_file") 15 | @Data 16 | public class AmModelFileEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "mf_id") 28 | private String mfId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "am_type") 33 | private String amType; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "mf_group") 38 | private String mfGroup; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "mf_role") 43 | private String mfRole; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "mf_json") 48 | private String mfJson; 49 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AmPromptAudioEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName am_prompt_audio 13 | */ 14 | @TableName(value = "am_prompt_audio") 15 | @Data 16 | public class AmPromptAudioEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "pa_id") 28 | private String paId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "pa_group") 33 | private String paGroup; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "pa_group_sort") 38 | private Integer paGroupSort; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "pa_group_show") 43 | private Boolean paGroupShow; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "pa_role") 48 | private String paRole; 49 | /** 50 | * 51 | */ 52 | @TableField(value = "pa_role_gender") 53 | private String paRoleGender; 54 | /** 55 | * 56 | */ 57 | @TableField(value = "pa_role_age") 58 | private String paRoleAge; 59 | /** 60 | * 61 | */ 62 | @TableField(value = "pa_role_lang") 63 | private String paRoleLang; 64 | /** 65 | * 66 | */ 67 | @TableField(value = "pa_role_tags") 68 | private String paRoleTags; 69 | /** 70 | * 71 | */ 72 | @TableField(value = "pa_role_avatar") 73 | private String paRoleAvatar; 74 | /** 75 | * 76 | */ 77 | @TableField(value = "pa_mood") 78 | private String paMood; 79 | /** 80 | * 81 | */ 82 | @TableField(value = "pa_mood_avatar") 83 | private String paMoodAvatar; 84 | /** 85 | * 86 | */ 87 | @TableField(value = "pa_audio") 88 | private String paAudio; 89 | /** 90 | * 91 | */ 92 | @TableField(value = "pa_audio_text") 93 | private String paAudioText; 94 | /** 95 | * 96 | */ 97 | @TableField(value = "pa_audio_lang") 98 | private String paAudioLang; 99 | /** 100 | * 101 | */ 102 | @TableField(value = "pa_audio_tags") 103 | private String paAudioTags; 104 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AmServerEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName am_server 13 | */ 14 | @TableName(value = "am_server") 15 | @Data 16 | public class AmServerEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "name") 28 | private String name; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "host") 33 | private String host; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "path") 38 | private String path; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "api_version") 43 | private String apiVersion; 44 | 45 | public String getUri() { 46 | return getHost().trim() + getPath().trim(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AudioModelInfo.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Data; 5 | 6 | import java.util.Objects; 7 | 8 | @Data 9 | public class AudioModelInfo extends AudioModelInfoKey { 10 | 11 | /** 12 | * 13 | */ 14 | @TableField(value = "am_pa_group") 15 | public String amPaGroup; 16 | 17 | /** 18 | * 19 | */ 20 | @TableField(value = "am_pa_role") 21 | public String amPaRole; 22 | 23 | /** 24 | * 25 | */ 26 | @TableField(value = "am_pa_mood") 27 | public String amPaMood; 28 | 29 | /** 30 | * 31 | */ 32 | @TableField(value = "am_pa_audio") 33 | public String amPaAudio; 34 | 35 | /** 36 | * 37 | */ 38 | @TableField(value = "am_pa_audio_text") 39 | public String amPaAudioText; 40 | 41 | /** 42 | * 43 | */ 44 | @TableField(value = "am_pa_audio_lang") 45 | public String amPaAudioLang; 46 | 47 | /** 48 | * 49 | */ 50 | @TableField(value = "am_mf_group") 51 | public String amMfGroup; 52 | 53 | /** 54 | * 55 | */ 56 | @TableField(value = "am_mf_role") 57 | public String amMfRole; 58 | 59 | /** 60 | * 61 | */ 62 | @TableField(value = "am_mf_json") 63 | public String amMfJson; 64 | 65 | /** 66 | * 67 | */ 68 | @TableField(value = "am_mc_name") 69 | public String amMcName; 70 | 71 | /** 72 | * 73 | */ 74 | @TableField(value = "am_mc_params_json") 75 | public String amMcParamsJson; 76 | 77 | 78 | public void setPromptAudio(AmPromptAudioEntity promptAudio) { 79 | if (Objects.nonNull(promptAudio)) { 80 | this.amPaId = promptAudio.getPaId(); 81 | this.amPaGroup = promptAudio.getPaGroup(); 82 | this.amPaRole = promptAudio.getPaRole(); 83 | this.amPaMood = promptAudio.getPaMood(); 84 | this.amPaAudio = promptAudio.getPaAudio(); 85 | this.amPaAudioText = promptAudio.getPaAudioText(); 86 | this.amPaAudioLang = promptAudio.getPaAudioLang(); 87 | } else { 88 | this.amPaId = "-1"; 89 | } 90 | } 91 | 92 | public void setModelFile(AmModelFileEntity modelFile) { 93 | if (Objects.nonNull(modelFile)) { 94 | this.amMfId = modelFile.getMfId(); 95 | this.amMfGroup = modelFile.getMfGroup(); 96 | this.amMfRole = modelFile.getMfRole(); 97 | this.amMfJson = modelFile.getMfJson(); 98 | } else { 99 | this.amMfId = "-1"; 100 | } 101 | } 102 | 103 | public void setModelConfig(AmModelConfigEntity modelConfig) { 104 | if (Objects.nonNull(modelConfig)) { 105 | this.amMcId = modelConfig.getMcId(); 106 | this.amMcName = modelConfig.getMcName(); 107 | this.amMcParamsJson = modelConfig.getMcParamsJson(); 108 | } else { 109 | this.amMcId = "-1"; 110 | } 111 | } 112 | 113 | public void setAudioModelInfo(AudioModelInfo audioModelInfo) { 114 | if (Objects.isNull(audioModelInfo)) { 115 | return; 116 | } 117 | 118 | this.setAmType(audioModelInfo.getAmType()); 119 | 120 | this.setAmPaId(audioModelInfo.getAmPaId()); 121 | this.setAmPaGroup(audioModelInfo.getAmPaGroup()); 122 | this.setAmPaRole(audioModelInfo.getAmPaRole()); 123 | this.setAmPaMood(audioModelInfo.getAmPaMood()); 124 | this.setAmPaAudio(audioModelInfo.getAmPaAudio()); 125 | this.setAmPaAudioText(audioModelInfo.getAmPaAudioText()); 126 | this.setAmPaAudioLang(audioModelInfo.getAmPaAudioLang()); 127 | 128 | this.setAmMfId(audioModelInfo.getAmMfId()); 129 | this.setAmMfGroup(audioModelInfo.getAmMfGroup()); 130 | this.setAmMfRole(audioModelInfo.getAmMfRole()); 131 | this.setAmMfJson(audioModelInfo.getAmMfJson()); 132 | 133 | this.setAmMcId(audioModelInfo.getAmMcId()); 134 | this.setAmMcName(audioModelInfo.getAmMcName()); 135 | this.setAmMcParamsJson(audioModelInfo.getAmMcParamsJson()); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AudioModelInfoKey.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class AudioModelInfoKey { 8 | 9 | /** 10 | * 11 | */ 12 | @TableField(value = "am_type") 13 | public String amType; 14 | 15 | /** 16 | * 17 | */ 18 | @TableField(value = "am_pa_id") 19 | public String amPaId; 20 | 21 | /** 22 | * 23 | */ 24 | @TableField(value = "am_mf_id") 25 | public String amMfId; 26 | 27 | /** 28 | * 29 | */ 30 | @TableField(value = "am_mc_id") 31 | public String amMcId; 32 | 33 | /** 34 | * 35 | */ 36 | @TableField(value = "am_mc_params_json") 37 | public String amMcParamsJson; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/AudioRoleInfo.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Data; 5 | 6 | @Data 7 | public class AudioRoleInfo extends AudioModelInfo { 8 | 9 | /** 10 | * 11 | */ 12 | @TableField(value = "role") 13 | public String role; 14 | 15 | /** 16 | * 17 | */ 18 | @TableField(value = "gender") 19 | public String gender; 20 | 21 | /** 22 | * 23 | */ 24 | @TableField(value = "age") 25 | public String age; 26 | 27 | public void setAudioRoleInfo(AudioRoleInfo audioRoleInfo) { 28 | this.setRole(audioRoleInfo.getRole()); 29 | this.setGender(audioRoleInfo.getGender()); 30 | this.setAge(audioRoleInfo.getAge()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/ChapterInfoEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.baomidou.mybatisplus.annotation.IdType; 5 | import com.baomidou.mybatisplus.annotation.TableField; 6 | import com.baomidou.mybatisplus.annotation.TableId; 7 | import com.baomidou.mybatisplus.annotation.TableName; 8 | import lombok.Data; 9 | import space.wenliang.ai.aigcplatformserver.bean.TextMarkupInfo; 10 | 11 | import java.io.Serializable; 12 | import java.util.Objects; 13 | 14 | /** 15 | * @TableName chapter_info 16 | */ 17 | @TableName(value = "chapter_info") 18 | @Data 19 | public class ChapterInfoEntity extends AudioRoleInfo implements Serializable { 20 | @TableField(exist = false) 21 | private static final long serialVersionUID = 1L; 22 | /** 23 | * 24 | */ 25 | @TableId(value = "id", type = IdType.AUTO) 26 | private Integer id; 27 | /** 28 | * 29 | */ 30 | @TableField(value = "project_id") 31 | private String projectId; 32 | /** 33 | * 34 | */ 35 | @TableField(value = "chapter_id") 36 | private String chapterId; 37 | /** 38 | * 39 | */ 40 | @TableField(value = "para_index") 41 | private Integer paraIndex; 42 | /** 43 | * 44 | */ 45 | @TableField(value = "sent_index") 46 | private Integer sentIndex; 47 | /** 48 | * 49 | */ 50 | @TableField(value = "text_id") 51 | private String textId; 52 | /** 53 | * 54 | */ 55 | @TableField(value = "text") 56 | private String text; 57 | /** 58 | * 59 | */ 60 | @TableField(value = "text_mood") 61 | private String textMood; 62 | /** 63 | * 64 | */ 65 | @TableField(value = "text_lang") 66 | private String textLang; 67 | /** 68 | * 69 | */ 70 | @TableField(value = "text_sort") 71 | private Integer textSort; 72 | /** 73 | * 74 | */ 75 | @TableField(value = "dialogue_flag") 76 | private Boolean dialogueFlag; 77 | /** 78 | * 79 | */ 80 | @TableField(value = "audio_volume") 81 | private Double audioVolume; 82 | /** 83 | * 84 | */ 85 | @TableField(value = "audio_speed") 86 | private Double audioSpeed; 87 | /** 88 | * 89 | */ 90 | @TableField(value = "audio_interval") 91 | private Integer audioInterval; 92 | /** 93 | * 94 | */ 95 | @TableField(value = "audio_length") 96 | private Long audioLength; 97 | /** 98 | * 99 | */ 100 | @TableField(value = "audio_files") 101 | private String audioFiles; 102 | /** 103 | * 104 | */ 105 | @TableField(value = "audio_task_state") 106 | private Integer audioTaskState; 107 | /** 108 | * 109 | */ 110 | @TableField(value = "text_markup_info_json") 111 | private String textMarkupInfoJson; 112 | 113 | public String getIndex() { 114 | if (Objects.nonNull(paraIndex) && Objects.nonNull(sentIndex)) { 115 | return paraIndex + "-" + sentIndex; 116 | } 117 | return null; 118 | } 119 | 120 | public TextMarkupInfo getTextMarkupInfo() { 121 | if (Objects.nonNull(textMarkupInfoJson)) { 122 | return JSON.parseObject(textMarkupInfoJson, TextMarkupInfo.class); 123 | } 124 | return new TextMarkupInfo(); 125 | } 126 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TextChapterEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName text_chapter 13 | */ 14 | @TableName(value = "text_chapter") 15 | @Data 16 | public class TextChapterEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "chapter_id") 28 | private String chapterId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "project_id") 33 | private String projectId; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "chapter_name") 38 | private String chapterName; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "content") 43 | private String content; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "dialogue_pattern") 48 | private String dialoguePattern; 49 | /** 50 | * 51 | */ 52 | @TableField(value = "sort_order") 53 | private Integer sortOrder; 54 | 55 | 56 | @TableField(exist = false) 57 | private Integer wordNum; 58 | 59 | @TableField(exist = false) 60 | private Integer textNum; 61 | 62 | @TableField(exist = false) 63 | private Integer dialogueNum; 64 | 65 | @TableField(exist = false) 66 | private Integer roleNum; 67 | 68 | @TableField(exist = false) 69 | private Integer audioTaskState; 70 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TextCommonRoleEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName text_common_role 13 | */ 14 | @TableName(value = "text_common_role") 15 | @Data 16 | public class TextCommonRoleEntity extends AudioRoleInfo implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "project_id") 28 | private String projectId; 29 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TextProjectEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName text_project 13 | */ 14 | @TableName(value = "text_project") 15 | @Data 16 | public class TextProjectEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "project_id") 28 | private String projectId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "project_name") 33 | private String projectName; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "project_type") 38 | private String projectType; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "content") 43 | private String content; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "chapter_pattern") 48 | private String chapterPattern; 49 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TextRoleEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName text_role 13 | */ 14 | @TableName(value = "text_role") 15 | @Data 16 | public class TextRoleEntity extends AudioRoleInfo implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "project_id") 28 | private String projectId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "chapter_id") 33 | private String chapterId; 34 | 35 | @TableField(exist = false) 36 | private Long roleCount; 37 | 38 | @TableField(exist = false) 39 | private Boolean coverCommonRole; 40 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TextRoleInferenceEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName text_role_inference 13 | */ 14 | @TableName(value = "text_role_inference") 15 | @Data 16 | public class TextRoleInferenceEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "project_id") 28 | private String projectId; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "chapter_id") 33 | private String chapterId; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "role") 38 | private String role; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "gender") 43 | private String gender; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "age") 48 | private String age; 49 | /** 50 | * 51 | */ 52 | @TableField(value = "mood") 53 | private String mood; 54 | /** 55 | * 56 | */ 57 | @TableField(value = "text_index") 58 | private String textIndex; 59 | 60 | @TableField(exist = false) 61 | private String text; 62 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TmPromptTemplateEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | @TableName(value = "tm_prompt_template") 12 | @Data 13 | public class TmPromptTemplateEntity implements Serializable { 14 | @TableField(exist = false) 15 | private static final long serialVersionUID = 1L; 16 | /** 17 | * 18 | */ 19 | @TableId(value = "id", type = IdType.AUTO) 20 | private Integer id; 21 | /** 22 | * 23 | */ 24 | @TableField(value = "template_group") 25 | private String templateGroup; 26 | /** 27 | * 28 | */ 29 | @TableField(value = "is_default") 30 | private Boolean isDefault; 31 | /** 32 | * 33 | */ 34 | @TableField(value = "template_name") 35 | private String templateName; 36 | /** 37 | * 38 | */ 39 | @TableField(value = "system_prompt") 40 | private String systemPrompt; 41 | /** 42 | * 43 | */ 44 | @TableField(value = "user_prompt") 45 | private String userPrompt; 46 | /** 47 | * 48 | */ 49 | @TableField(value = "is_preset") 50 | private Boolean isPreset; 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/entity/TmServerEntity.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName tm_server 13 | */ 14 | @TableName(value = "tm_server") 15 | @Data 16 | public class TmServerEntity implements Serializable { 17 | @TableField(exist = false) 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 21 | */ 22 | @TableId(value = "id", type = IdType.AUTO) 23 | private Integer id; 24 | /** 25 | * 26 | */ 27 | @TableField(value = "name") 28 | private String name; 29 | /** 30 | * 31 | */ 32 | @TableField(value = "interface_type") 33 | private String interfaceType; 34 | /** 35 | * 36 | */ 37 | @TableField(value = "host") 38 | private String host; 39 | /** 40 | * 41 | */ 42 | @TableField(value = "path") 43 | private String path; 44 | /** 45 | * 46 | */ 47 | @TableField(value = "api_key") 48 | private String apiKey; 49 | /** 50 | * 51 | */ 52 | @TableField(value = "model") 53 | private String model; 54 | /** 55 | * 56 | */ 57 | @TableField(value = "temperature") 58 | private Float temperature; 59 | /** 60 | * 61 | */ 62 | @TableField(value = "max_tokens") 63 | private Integer maxTokens; 64 | /** 65 | * 66 | */ 67 | @TableField(value = "active") 68 | private Boolean active; 69 | /** 70 | * 71 | */ 72 | @TableField(value = "app_id") 73 | private String appId; 74 | /** 75 | * 76 | */ 77 | @TableField(value = "api_secret") 78 | private String apiSecret; 79 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/exception/BizException.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.exception; 2 | 3 | import lombok.Getter; 4 | import space.wenliang.ai.aigcplatformserver.common.ResultEnum; 5 | 6 | @Getter 7 | public class BizException extends RuntimeException { 8 | 9 | public String code; 10 | 11 | public String msg; 12 | 13 | public Object data; 14 | 15 | public BizException(String msg) { 16 | super(msg); 17 | this.code = ResultEnum.FAILURE.getCode(); 18 | this.msg = msg; 19 | } 20 | 21 | public BizException(ResultEnum resultEnum) { 22 | super(resultEnum.getMsg()); 23 | this.code = resultEnum.getCode(); 24 | this.msg = resultEnum.getMsg(); 25 | } 26 | 27 | public BizException(String code, String msg) { 28 | super(msg); 29 | this.code = code; 30 | this.msg = msg; 31 | } 32 | 33 | public BizException(String code, String msg, Object data) { 34 | super(msg); 35 | this.code = code; 36 | this.msg = msg; 37 | this.data = data; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.exception; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.context.support.DefaultMessageSourceResolvable; 5 | import org.springframework.validation.ObjectError; 6 | import org.springframework.web.bind.MethodArgumentNotValidException; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import space.wenliang.ai.aigcplatformserver.common.Result; 11 | import space.wenliang.ai.aigcplatformserver.common.ResultEnum; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | @Slf4j 17 | @ControllerAdvice 18 | public class GlobalExceptionHandler { 19 | 20 | @ExceptionHandler(value = BizException.class) 21 | @ResponseBody 22 | public Result bizExceptionHandler(BizException e) { 23 | log.error("bizExceptionHandler, message: {}", e.getMessage(), e); 24 | return Result.failure(e.getCode(), e.getMsg()); 25 | } 26 | 27 | @ExceptionHandler(value = MethodArgumentNotValidException.class) 28 | @ResponseBody 29 | public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) { 30 | List allErrors = e.getBindingResult().getAllErrors(); 31 | String message = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); 32 | return Result.failure(ResultEnum.PARAMETER_ERROR.getCode(), message); 33 | } 34 | 35 | @ExceptionHandler(value = Exception.class) 36 | @ResponseBody 37 | public Result exceptionHandler(Exception e) { 38 | log.error("exceptionHandler, message: {}", e.getMessage(), e); 39 | return Result.failure(e.getMessage()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/hooks/ShutdownHook.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.hooks; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.event.ContextClosedEvent; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | 12 | @Slf4j 13 | @Component 14 | @RequiredArgsConstructor 15 | public class ShutdownHook implements ApplicationListener { 16 | 17 | private final List shutdownHookListeners; 18 | 19 | @Override 20 | public void onApplicationEvent(@NotNull ContextClosedEvent event) { 21 | for (ShutdownHookListener listener : shutdownHookListeners) { 22 | try { 23 | listener.shutdownHook(); 24 | } catch (Exception e) { 25 | log.error("Shutdown Exception, ClassName: {}", listener.getClass().getName(), e); 26 | } 27 | } 28 | } 29 | 30 | public interface ShutdownHookListener { 31 | void shutdownHook() throws Exception; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/hooks/StartHook.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.hooks; 2 | 3 | 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.boot.ApplicationArguments; 7 | import org.springframework.boot.ApplicationRunner; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | 12 | @Slf4j 13 | @Component 14 | @RequiredArgsConstructor 15 | public class StartHook implements ApplicationRunner { 16 | 17 | private final List startHookListeners; 18 | 19 | @Override 20 | public void run(ApplicationArguments args) throws Exception { 21 | for (StartHookListener listener : startHookListeners) { 22 | try { 23 | listener.startHook(); 24 | } catch (Exception e) { 25 | log.error("Start Exception, ClassName: {}", listener.getClass().getName(), e); 26 | } 27 | } 28 | } 29 | 30 | public interface StartHookListener { 31 | void startHook() throws Exception; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/hooks/start/CacheLoad.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.hooks.start; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.stereotype.Component; 5 | import space.wenliang.ai.aigcplatformserver.common.ModelTypeEnum; 6 | import space.wenliang.ai.aigcplatformserver.hooks.StartHook; 7 | import space.wenliang.ai.aigcplatformserver.service.AmModelFileService; 8 | import space.wenliang.ai.aigcplatformserver.service.AmPromptAudioService; 9 | 10 | @Component 11 | @RequiredArgsConstructor 12 | public class CacheLoad implements StartHook.StartHookListener { 13 | 14 | private final AmModelFileService amModelFileService; 15 | private final AmPromptAudioService amPromptAudioService; 16 | 17 | @Override 18 | public void startHook() { 19 | amModelFileService.refreshCache(ModelTypeEnum.gpt_sovits.getName()); 20 | amPromptAudioService.refreshCache(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/hooks/start/StartupInfoPrinter.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.hooks.start; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.context.annotation.Profile; 5 | import org.springframework.stereotype.Component; 6 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 7 | import space.wenliang.ai.aigcplatformserver.hooks.StartHook; 8 | 9 | @Profile("integrated") 10 | @Component 11 | @RequiredArgsConstructor 12 | public class StartupInfoPrinter implements StartHook.StartHookListener { 13 | 14 | private final EnvConfig envConfig; 15 | 16 | @Override 17 | public void startHook() { 18 | String[] messages = { 19 | "AIGC Platform Server Startup Information", 20 | String.format("Version: %s", envConfig.getApplicationVersion()), 21 | String.format("Console URL: http://127.0.0.1:%s/webui/text", envConfig.getPort()) 22 | }; 23 | 24 | // Calculate the length of the longest message 25 | int maxLength = 0; 26 | for (String message : messages) { 27 | if (message.length() > maxLength) { 28 | maxLength = message.length(); 29 | } 30 | } 31 | 32 | // Create the border 33 | String border = new String(new char[maxLength + 4]).replace("\0", "*"); 34 | 35 | // Print the messages inside the box 36 | System.out.println(border); 37 | for (String message : messages) { 38 | System.out.println("* " + padRight(message, maxLength) + " *"); 39 | } 40 | System.out.println(border); 41 | } 42 | 43 | private String padRight(String s, int n) { 44 | return String.format("%1$-" + n + "s", s); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/AmModelConfigMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmModelConfigEntity; 5 | 6 | public interface AmModelConfigMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/AmModelFileMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmModelFileEntity; 5 | 6 | public interface AmModelFileMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/AmPromptAudioMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmPromptAudioEntity; 5 | 6 | public interface AmPromptAudioMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/AmServerMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 5 | 6 | public interface AmServerMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/ChapterInfoMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Select; 5 | import space.wenliang.ai.aigcplatformserver.bean.ChapterSummary; 6 | import space.wenliang.ai.aigcplatformserver.entity.ChapterInfoEntity; 7 | 8 | import java.util.List; 9 | 10 | public interface ChapterInfoMapper extends BaseMapper { 11 | 12 | @Select(""" 13 | select chapter_id as chapter_id, 14 | sum(char_length(text)) as word_count, 15 | count(*) as text_count, 16 | sum(case when dialogue_flag = 1 then 1 else 0 end) as dialogue_count, 17 | max(audio_task_state) as max_task_state 18 | from chapter_info 19 | group by chapter_id 20 | """) 21 | List chapterSummary4MySQL(); 22 | 23 | @Select(""" 24 | select chapter_id as chapter_id, 25 | sum(length(text)) as word_count, 26 | count(*) as text_count, 27 | sum(case when dialogue_flag = 1 then 1 else 0 end) as dialogue_count, 28 | max(audio_task_state) as max_task_state 29 | from chapter_info 30 | group by chapter_id 31 | """) 32 | List chapterSummary4SQLite(); 33 | } 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TextChapterMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Select; 5 | import space.wenliang.ai.aigcplatformserver.bean.GroupCount; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 7 | 8 | import java.util.List; 9 | 10 | public interface TextChapterMapper extends BaseMapper { 11 | 12 | @Select("select project_id as group1, count(*) as count1 from text_chapter group by project_id") 13 | List projectGroupCount(); 14 | } 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TextCommonRoleMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextCommonRoleEntity; 5 | 6 | public interface TextCommonRoleMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TextProjectMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 5 | 6 | public interface TextProjectMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TextRoleInferenceMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleInferenceEntity; 5 | 6 | public interface TextRoleInferenceMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TextRoleMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import org.apache.ibatis.annotations.Select; 5 | import space.wenliang.ai.aigcplatformserver.bean.GroupCount; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleEntity; 7 | 8 | import java.util.List; 9 | 10 | public interface TextRoleMapper extends BaseMapper { 11 | 12 | @Select(""" 13 | select chapter_id as group1, count(*) as count1 14 | from text_role 15 | group by chapter_id 16 | """) 17 | List chapterRoleGroupCount(); 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TmPromptTemplateMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.TmPromptTemplateEntity; 5 | 6 | public interface TmPromptTemplateMapper extends BaseMapper { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/mapper/TmServerMapper.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 5 | 6 | public interface TmServerMapper extends BaseMapper { 7 | 8 | } 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/AmModelConfigService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmModelConfigEntity; 5 | 6 | import java.io.IOException; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public interface AmModelConfigService extends IService { 11 | 12 | AmModelConfigEntity getByMcId(String mcId); 13 | 14 | List getByModelType(String modelType, Integer showMode); 15 | 16 | void updateConfig(AmModelConfigEntity modelConfig); 17 | 18 | void syncEdgeTtsConfig() throws IOException; 19 | 20 | void updateEdgeTtsShowFlag(Map data); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/AmModelFileService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmModelFileEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface AmModelFileService extends IService { 9 | 10 | AmModelFileEntity getByMfId(String mfId); 11 | 12 | void refreshCache(String modelType); 13 | 14 | List getByModelType(String modelType); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/AmPromptAudioService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.bean.PromptAudio; 5 | import space.wenliang.ai.aigcplatformserver.bean.PromptAudioSort; 6 | import space.wenliang.ai.aigcplatformserver.entity.AmPromptAudioEntity; 7 | 8 | import java.util.List; 9 | 10 | public interface AmPromptAudioService extends IService { 11 | 12 | AmPromptAudioEntity getByPaId(String paId); 13 | 14 | void refreshCache(); 15 | 16 | List queryPromptAudioSorts(); 17 | 18 | List promptAudios(); 19 | 20 | void updatePromptAudio(PromptAudio promptAudio); 21 | 22 | void updatePromptAudioSorts(List promptAudioSorts); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/AmServerService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 5 | 6 | public interface AmServerService extends IService { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/ChapterInfoService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.bean.ChapterSummary; 5 | import space.wenliang.ai.aigcplatformserver.entity.ChapterInfoEntity; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public interface ChapterInfoService extends IService { 12 | 13 | Map chapterSummaryMap(); 14 | 15 | void deleteByChapterId(String chapterId); 16 | 17 | List getByChapterId(String chapterId); 18 | 19 | List buildChapterInfos(TextChapterEntity textChapterEntity); 20 | 21 | void deleteByProjectId(String projectId); 22 | 23 | void audioModelReset(List ids); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TextChapterService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 5 | 6 | import java.util.Map; 7 | 8 | public interface TextChapterService extends IService { 9 | 10 | Map chapterCount(); 11 | 12 | void deleteByChapterId(String chapterId); 13 | 14 | TextChapterEntity getTextChapterAndContent(String projectId, String chapterId); 15 | 16 | TextChapterEntity getByChapterId(String chapterId); 17 | 18 | void deleteByProjectId(String projectId); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TextCommonRoleService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextCommonRoleEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface TextCommonRoleService extends IService { 9 | 10 | List getByProjectId(String projectId); 11 | 12 | void deleteByProjectId(String projectId); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TextProjectService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 5 | 6 | public interface TextProjectService extends IService { 7 | 8 | TextProjectEntity getByProjectId(String projectId); 9 | 10 | TextProjectEntity getByProjectName(String projectName); 11 | 12 | void deleteByProjectId(String projectId); 13 | 14 | TextProjectEntity getAndContentByProjectId(String projectId); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TextRoleInferenceService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleInferenceEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface TextRoleInferenceService extends IService { 9 | 10 | void deleteByChapterId(String chapterId); 11 | 12 | void deleteByProjectId(String projectId); 13 | 14 | List getByChapterId(String chapterId); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TextRoleService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleEntity; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public interface TextRoleService extends IService { 10 | 11 | Map chapterRoleGroupCount(); 12 | 13 | void deleteByChapterId(String chapterId); 14 | 15 | List getByChapterId(String chapterId); 16 | 17 | void deleteByProjectId(String projectId); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TmPromptTemplateService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TmPromptTemplateEntity; 5 | 6 | public interface TmPromptTemplateService extends IService { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/TmServerService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 5 | 6 | public interface TmServerService extends IService { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/business/BChapterInfoService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.business; 2 | 3 | import space.wenliang.ai.aigcplatformserver.bean.ChapterBatchOperator; 4 | import space.wenliang.ai.aigcplatformserver.bean.ControlsUpdate; 5 | import space.wenliang.ai.aigcplatformserver.bean.PolyphonicParams; 6 | import space.wenliang.ai.aigcplatformserver.bean.UpdateModelInfo; 7 | import space.wenliang.ai.aigcplatformserver.entity.ChapterInfoEntity; 8 | 9 | import java.util.List; 10 | 11 | public interface BChapterInfoService { 12 | 13 | List chapterInfos(String projectId, String chapterId); 14 | 15 | void chapterInfoSort(List chapterInfoEntities); 16 | 17 | void audioModelChange(UpdateModelInfo updateModelInfo); 18 | 19 | void updateVolume(ChapterInfoEntity chapterInfoEntity); 20 | 21 | void updateSpeed(ChapterInfoEntity chapterInfoEntity); 22 | 23 | void updateInterval(ChapterInfoEntity chapterInfoEntity); 24 | 25 | void updateControls(ControlsUpdate controlsUpdate); 26 | 27 | void updateChapterText(ChapterInfoEntity chapterInfoEntity); 28 | 29 | void deleteChapterInfo(ChapterInfoEntity chapterInfoEntity); 30 | 31 | void addAudioCreateTask(ChapterInfoEntity chapterInfoEntity); 32 | 33 | void startCreateAudio(String projectId, String chapterId, String actionType, List chapterInfoIds); 34 | 35 | void stopCreateAudio(); 36 | 37 | List chapterCondition(String projectId, String chapterId); 38 | 39 | void addPolyphonicInfo(PolyphonicParams polyphonicParams); 40 | 41 | void removePolyphonicInfo(PolyphonicParams polyphonicParams); 42 | 43 | ChapterInfoEntity addChapterInfo(ChapterInfoEntity chapterInfo); 44 | 45 | void batchOperator(ChapterBatchOperator chapterBatchOperator); 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/business/BTextChapterService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.business; 2 | 3 | import reactor.core.publisher.Flux; 4 | import space.wenliang.ai.aigcplatformserver.bean.*; 5 | import space.wenliang.ai.aigcplatformserver.common.Page; 6 | import space.wenliang.ai.aigcplatformserver.entity.*; 7 | 8 | import java.io.IOException; 9 | import java.util.List; 10 | 11 | public interface BTextChapterService { 12 | 13 | Page pageChapters(ProjectQuery projectQuery); 14 | 15 | List chapters4Sort(String projectId); 16 | 17 | void deleteChapter(TextChapterEntity textChapter) throws IOException; 18 | 19 | List tmpDialogueParse(TextChapterEntity textChapter); 20 | 21 | void chapterEdit(TextChapterEntity textChapter); 22 | 23 | void chapterAdd(ChapterAdd chapterAdd); 24 | 25 | void chapterSort(List sortChapters); 26 | 27 | List roles(String chapterId); 28 | 29 | void updateRole(TextRoleEntity textRoleEntity); 30 | 31 | void updateRoleModel(UpdateModelInfo updateModelInfo); 32 | 33 | void roleCombine(String projectId, String chapterId, String fromRoleName, String toRoleName); 34 | 35 | void textRoleChange(TextRoleChange textRoleChange); 36 | 37 | Boolean saveToCommonRole(TextRoleEntity textRoleEntity); 38 | 39 | List commonRoles(String projectId); 40 | 41 | void createCommonRole(TextCommonRoleEntity textCommonRoleEntity); 42 | 43 | void updateCommonRole(UpdateModelInfo updateModelInfo); 44 | 45 | void deleteCommonRole(TextCommonRoleEntity textCommonRoleEntity); 46 | 47 | RoleInferenceData queryRoleInferenceCache(String projectId, String chapterId); 48 | 49 | void loadRoleInference(String projectId, String chapterId, List textRoleInferences); 50 | 51 | void chapterExpose(ChapterExpose chapterExpose) throws Exception; 52 | 53 | Flux roleInference(RoleInferenceParam roleInferenceParam); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/business/BTextProjectService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.business; 2 | 3 | import space.wenliang.ai.aigcplatformserver.bean.FormatTextProject; 4 | import space.wenliang.ai.aigcplatformserver.bean.TextProject; 5 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 6 | 7 | import java.io.IOException; 8 | import java.util.List; 9 | 10 | public interface BTextProjectService { 11 | 12 | List projectList(); 13 | 14 | TextProjectEntity getByProjectId(String projectId); 15 | 16 | void createProject(String project, String projectType, String content); 17 | 18 | void createFormatTextProject(FormatTextProject project); 19 | 20 | void updateProject(TextProjectEntity textProjectEntity); 21 | 22 | void deleteProject(TextProjectEntity textProjectEntity) throws IOException; 23 | 24 | List tmpChapterSplit(String projectId, String chapterPattern, String dialoguePattern); 25 | 26 | void chapterSplit(String projectId, String chapterPattern, String dialoguePattern); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/cache/DictService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.cache; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.util.CollectionUtils; 9 | import space.wenliang.ai.aigcplatformserver.bean.LangDict; 10 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 11 | import space.wenliang.ai.aigcplatformserver.hooks.ShutdownHook; 12 | import space.wenliang.ai.aigcplatformserver.hooks.StartHook; 13 | import space.wenliang.ai.aigcplatformserver.util.FileUtils; 14 | 15 | import java.io.IOException; 16 | import java.nio.file.Files; 17 | import java.nio.file.Path; 18 | import java.util.ArrayList; 19 | import java.util.Comparator; 20 | import java.util.List; 21 | 22 | @Slf4j 23 | @Service 24 | @RequiredArgsConstructor 25 | public class DictService implements StartHook.StartHookListener, ShutdownHook.ShutdownHookListener { 26 | 27 | private static List LANG_DICT_LIST = new ArrayList<>(List.of( 28 | new LangDict("zh", "中文", "你好啊,今天又是充满希望的一天。"), 29 | new LangDict("en", "英文", "Hello! Today is another day full of hope."), 30 | new LangDict("ja", "日文", "こんにちは!今日も希望に満ちた一日です。"), 31 | new LangDict("ko", "韩文", "안녕하세요! 오늘도 희망으로 가득 찬 하루입니다.") 32 | )); 33 | 34 | private final EnvConfig envConfig; 35 | 36 | @Override 37 | public void startHook() { 38 | Path path = envConfig.buildConfigPath("lang-dict.json"); 39 | if (Files.exists(path)) { 40 | try { 41 | LANG_DICT_LIST = FileUtils.getListFromFile(path, LangDict.class); 42 | } catch (Exception e) { 43 | log.error("读取[lang-dict.json]失败", e); 44 | throw new RuntimeException(e); 45 | } 46 | } 47 | } 48 | 49 | @Override 50 | public void shutdownHook() throws IOException { 51 | if (!CollectionUtils.isEmpty(LANG_DICT_LIST)) { 52 | Path path = envConfig.buildConfigPath("lang-dict.json"); 53 | if (Files.notExists(path.getParent())) { 54 | Files.createDirectories(path.getParent()); 55 | } 56 | Files.write(path, JSON.toJSONBytes(LANG_DICT_LIST)); 57 | } 58 | } 59 | 60 | public List getLangDict() { 61 | return LANG_DICT_LIST; 62 | } 63 | 64 | public LangDict getLangDict(String enName) { 65 | return LANG_DICT_LIST.stream().filter(v -> StringUtils.equals(v.getEnName(), enName)) 66 | .findAny().orElse(null); 67 | } 68 | 69 | public void editLangDict(LangDict langDict) { 70 | for (LangDict dict : LANG_DICT_LIST) { 71 | if (StringUtils.equals(dict.getEnName(), langDict.getEnName())) { 72 | dict.setZhName(langDict.getZhName()); 73 | dict.setText(langDict.getText()); 74 | } 75 | } 76 | } 77 | 78 | public void langDictSort(List langDicts) { 79 | List enNames = langDicts.stream().map(LangDict::getEnName).toList(); 80 | LANG_DICT_LIST = LANG_DICT_LIST.stream() 81 | .sorted(Comparator.comparingInt(v -> enNames.indexOf(v.getEnName()))) 82 | .toList(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/cache/GlobalSettingService.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.cache; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import lombok.Data; 5 | import lombok.RequiredArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.stereotype.Service; 8 | import space.wenliang.ai.aigcplatformserver.bean.GlobalSetting; 9 | import space.wenliang.ai.aigcplatformserver.config.EnvConfig; 10 | import space.wenliang.ai.aigcplatformserver.hooks.ShutdownHook; 11 | import space.wenliang.ai.aigcplatformserver.hooks.StartHook; 12 | import space.wenliang.ai.aigcplatformserver.util.FileUtils; 13 | 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | 17 | @Data 18 | @Slf4j 19 | @Service 20 | @RequiredArgsConstructor 21 | public class GlobalSettingService implements StartHook.StartHookListener, ShutdownHook.ShutdownHookListener { 22 | 23 | private static GlobalSetting globalSetting = new GlobalSetting(); 24 | 25 | private final EnvConfig envConfig; 26 | 27 | @Override 28 | public void startHook() throws Exception { 29 | Path path = envConfig.buildConfigPath("global-setting.json"); 30 | if (Files.exists(path)) { 31 | try { 32 | globalSetting = FileUtils.getObjectFromFile(path, GlobalSetting.class); 33 | } catch (Exception e) { 34 | log.error("读取[global-setting.json]失败", e); 35 | throw new RuntimeException(e); 36 | } 37 | } 38 | } 39 | 40 | @Override 41 | public void shutdownHook() throws Exception { 42 | Path path = envConfig.buildConfigPath("global-setting.json"); 43 | if (Files.notExists(path.getParent())) { 44 | Files.createDirectories(path.getParent()); 45 | } 46 | Files.write(path, JSON.toJSONBytes(globalSetting)); 47 | } 48 | 49 | public GlobalSetting getGlobalSetting() { 50 | return globalSetting; 51 | } 52 | 53 | public void updateGlobalSetting(GlobalSetting globalSetting) { 54 | GlobalSettingService.globalSetting = globalSetting; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/AmServerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import org.springframework.stereotype.Service; 5 | import space.wenliang.ai.aigcplatformserver.entity.AmServerEntity; 6 | import space.wenliang.ai.aigcplatformserver.mapper.AmServerMapper; 7 | import space.wenliang.ai.aigcplatformserver.service.AmServerService; 8 | 9 | @Service 10 | public class AmServerServiceImpl extends ServiceImpl 11 | implements AmServerService { 12 | 13 | } 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TextChapterServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.stereotype.Service; 7 | import space.wenliang.ai.aigcplatformserver.bean.GroupCount; 8 | import space.wenliang.ai.aigcplatformserver.entity.TextChapterEntity; 9 | import space.wenliang.ai.aigcplatformserver.mapper.TextChapterMapper; 10 | import space.wenliang.ai.aigcplatformserver.service.TextChapterService; 11 | 12 | import java.util.Map; 13 | import java.util.stream.Collectors; 14 | 15 | @Service 16 | @RequiredArgsConstructor 17 | public class TextChapterServiceImpl extends ServiceImpl 18 | implements TextChapterService { 19 | 20 | private final TextChapterMapper textChapterMapper; 21 | 22 | @Override 23 | public Map chapterCount() { 24 | return textChapterMapper.projectGroupCount().stream() 25 | .collect(Collectors.toMap(GroupCount::getGroup1, GroupCount::getCount1)); 26 | } 27 | 28 | @Override 29 | public void deleteByChapterId(String chapterId) { 30 | this.remove(new LambdaQueryWrapper() 31 | .eq(TextChapterEntity::getChapterId, chapterId)); 32 | } 33 | 34 | @Override 35 | public TextChapterEntity getTextChapterAndContent(String projectId, String chapterId) { 36 | return this.getOne(new LambdaQueryWrapper() 37 | .eq(TextChapterEntity::getProjectId, projectId) 38 | .eq(TextChapterEntity::getChapterId, chapterId)); 39 | } 40 | 41 | @Override 42 | public TextChapterEntity getByChapterId(String chapterId) { 43 | return this.getOne(new LambdaQueryWrapper() 44 | .eq(TextChapterEntity::getChapterId, chapterId)); 45 | } 46 | 47 | @Override 48 | public void deleteByProjectId(String projectId) { 49 | this.remove(new LambdaQueryWrapper() 50 | .eq(TextChapterEntity::getProjectId, projectId)); 51 | } 52 | } 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TextCommonRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextCommonRoleEntity; 7 | import space.wenliang.ai.aigcplatformserver.mapper.TextCommonRoleMapper; 8 | import space.wenliang.ai.aigcplatformserver.service.TextCommonRoleService; 9 | 10 | import java.util.List; 11 | 12 | @Service 13 | public class TextCommonRoleServiceImpl extends ServiceImpl 14 | implements TextCommonRoleService { 15 | 16 | @Override 17 | public List getByProjectId(String projectId) { 18 | return super.list(new LambdaQueryWrapper() 19 | .eq(TextCommonRoleEntity::getProjectId, projectId)); 20 | } 21 | 22 | @Override 23 | public void deleteByProjectId(String projectId) { 24 | this.remove(new LambdaQueryWrapper() 25 | .eq(TextCommonRoleEntity::getProjectId, projectId)); 26 | } 27 | } 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TextProjectServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextProjectEntity; 7 | import space.wenliang.ai.aigcplatformserver.mapper.TextProjectMapper; 8 | import space.wenliang.ai.aigcplatformserver.service.TextProjectService; 9 | 10 | @Service 11 | public class TextProjectServiceImpl extends ServiceImpl 12 | implements TextProjectService { 13 | 14 | @Override 15 | public TextProjectEntity getByProjectId(String projectId) { 16 | return this.getOne(new LambdaQueryWrapper() 17 | .select(TextProjectEntity.class, entityClass -> !entityClass.getColumn().equals("content")) 18 | .eq(TextProjectEntity::getProjectId, projectId)); 19 | } 20 | 21 | @Override 22 | public TextProjectEntity getByProjectName(String projectName) { 23 | return this.getOne(new LambdaQueryWrapper() 24 | .select(TextProjectEntity.class, entityClass -> !entityClass.getColumn().equals("content")) 25 | .eq(TextProjectEntity::getProjectName, projectName)); 26 | } 27 | 28 | @Override 29 | public void deleteByProjectId(String projectId) { 30 | this.remove(new LambdaQueryWrapper() 31 | .eq(TextProjectEntity::getProjectId, projectId)); 32 | } 33 | 34 | @Override 35 | public TextProjectEntity getAndContentByProjectId(String projectId) { 36 | return this.getOne(new LambdaQueryWrapper() 37 | .eq(TextProjectEntity::getProjectId, projectId)); 38 | } 39 | } 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TextRoleInferenceServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import org.springframework.stereotype.Service; 6 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleInferenceEntity; 7 | import space.wenliang.ai.aigcplatformserver.mapper.TextRoleInferenceMapper; 8 | import space.wenliang.ai.aigcplatformserver.service.TextRoleInferenceService; 9 | 10 | import java.util.List; 11 | 12 | @Service 13 | public class TextRoleInferenceServiceImpl extends ServiceImpl 14 | implements TextRoleInferenceService { 15 | 16 | @Override 17 | public void deleteByChapterId(String chapterId) { 18 | this.remove(new LambdaQueryWrapper() 19 | .eq(TextRoleInferenceEntity::getChapterId, chapterId)); 20 | } 21 | 22 | @Override 23 | public void deleteByProjectId(String projectId) { 24 | this.remove(new LambdaQueryWrapper() 25 | .eq(TextRoleInferenceEntity::getProjectId, projectId)); 26 | } 27 | 28 | @Override 29 | public List getByChapterId(String chapterId) { 30 | return this.list(new LambdaQueryWrapper() 31 | .eq(TextRoleInferenceEntity::getChapterId, chapterId)); 32 | } 33 | } 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TextRoleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.stereotype.Service; 7 | import space.wenliang.ai.aigcplatformserver.bean.GroupCount; 8 | import space.wenliang.ai.aigcplatformserver.entity.TextRoleEntity; 9 | import space.wenliang.ai.aigcplatformserver.mapper.TextRoleMapper; 10 | import space.wenliang.ai.aigcplatformserver.service.TextRoleService; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.stream.Collectors; 15 | 16 | @Service 17 | @RequiredArgsConstructor 18 | public class TextRoleServiceImpl extends ServiceImpl 19 | implements TextRoleService { 20 | 21 | private final TextRoleMapper textRoleMapper; 22 | 23 | @Override 24 | public Map chapterRoleGroupCount() { 25 | return textRoleMapper.chapterRoleGroupCount().stream() 26 | .collect(Collectors.toMap(GroupCount::getGroup1, GroupCount::getCount1)); 27 | } 28 | 29 | @Override 30 | public void deleteByChapterId(String chapterId) { 31 | this.remove(new LambdaQueryWrapper() 32 | .eq(TextRoleEntity::getChapterId, chapterId)); 33 | } 34 | 35 | @Override 36 | public List getByChapterId(String chapterId) { 37 | return this.list(new LambdaQueryWrapper() 38 | .eq(TextRoleEntity::getChapterId, chapterId)); 39 | } 40 | 41 | @Override 42 | public void deleteByProjectId(String projectId) { 43 | this.remove(new LambdaQueryWrapper() 44 | .eq(TextRoleEntity::getProjectId, projectId)); 45 | } 46 | } 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TmPromptTemplateServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import org.springframework.stereotype.Service; 5 | import space.wenliang.ai.aigcplatformserver.entity.TmPromptTemplateEntity; 6 | import space.wenliang.ai.aigcplatformserver.mapper.TmPromptTemplateMapper; 7 | import space.wenliang.ai.aigcplatformserver.service.TmPromptTemplateService; 8 | 9 | @Service 10 | public class TmPromptTemplateServiceImpl extends ServiceImpl 11 | implements TmPromptTemplateService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/service/impl/TmServerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import org.springframework.stereotype.Service; 5 | import space.wenliang.ai.aigcplatformserver.entity.TmServerEntity; 6 | import space.wenliang.ai.aigcplatformserver.mapper.TmServerMapper; 7 | import space.wenliang.ai.aigcplatformserver.service.TmServerService; 8 | 9 | @Service 10 | public class TmServerServiceImpl extends ServiceImpl 11 | implements TmServerService { 12 | 13 | } 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/socket/GlobalWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.socket; 2 | 3 | import com.alibaba.fastjson2.JSONObject; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.socket.CloseStatus; 8 | import org.springframework.web.socket.TextMessage; 9 | import org.springframework.web.socket.WebSocketSession; 10 | import org.springframework.web.socket.handler.TextWebSocketHandler; 11 | 12 | import java.io.IOException; 13 | import java.util.Map; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | 16 | @Slf4j 17 | @Component 18 | public class GlobalWebSocketHandler extends TextWebSocketHandler { 19 | 20 | private static final Map sessions = new ConcurrentHashMap<>(); 21 | 22 | @Override 23 | public void afterConnectionEstablished(@NotNull WebSocketSession session) { 24 | sessions.put(session.getId(), session); 25 | } 26 | 27 | @Override 28 | public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus status) { 29 | sessions.values().remove(session); 30 | log.info("Connection closed with session id: {}", session.getId()); 31 | } 32 | 33 | public void sendErrorMessage(String title, String message) { 34 | JSONObject jsonObject = new JSONObject(); 35 | jsonObject.put("type", "message"); 36 | jsonObject.put("state", "error"); 37 | jsonObject.put("title", title); 38 | jsonObject.put("message", message); 39 | for (WebSocketSession session : sessions.values()) { 40 | try { 41 | session.sendMessage(new TextMessage(jsonObject.toJSONString())); 42 | } catch (IOException e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | } 47 | 48 | public void sendSuccessMessage(String title, String message) { 49 | JSONObject jsonObject = new JSONObject(); 50 | jsonObject.put("type", "message"); 51 | jsonObject.put("state", "success"); 52 | jsonObject.put("title", title); 53 | jsonObject.put("message", message); 54 | for (WebSocketSession session : sessions.values()) { 55 | try { 56 | session.sendMessage(new TextMessage(jsonObject.toJSONString())); 57 | } catch (IOException e) { 58 | throw new RuntimeException(e); 59 | } 60 | } 61 | } 62 | 63 | public void sendEvent(String event) { 64 | JSONObject jsonObject = new JSONObject(); 65 | jsonObject.put("type", "event"); 66 | jsonObject.put("event", event); 67 | for (WebSocketSession session : sessions.values()) { 68 | try { 69 | session.sendMessage(new TextMessage(jsonObject.toJSONString())); 70 | } catch (IOException e) { 71 | throw new RuntimeException(e); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/socket/TextProjectWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.socket; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang3.StringUtils; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.socket.CloseStatus; 8 | import org.springframework.web.socket.TextMessage; 9 | import org.springframework.web.socket.WebSocketSession; 10 | import org.springframework.web.socket.handler.TextWebSocketHandler; 11 | 12 | import java.util.Arrays; 13 | import java.util.Map; 14 | import java.util.Objects; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | import java.util.stream.Collectors; 17 | 18 | @Slf4j 19 | @Component 20 | public class TextProjectWebSocketHandler extends TextWebSocketHandler { 21 | 22 | private static final Map sessions = new ConcurrentHashMap<>(); 23 | 24 | @Override 25 | public void afterConnectionEstablished(WebSocketSession session) { 26 | Map params = getQueryParams(Objects.requireNonNull(session.getUri()).getQuery()); 27 | String projectId = params.get("projectId"); 28 | if (StringUtils.isNotBlank(projectId)) { 29 | sessions.put(projectId, session); 30 | log.info("Connection established with session id: {} for project: {}", session.getId(), projectId); 31 | } 32 | } 33 | 34 | @Override 35 | public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus status) { 36 | sessions.values().remove(session); 37 | log.info("Connection closed with session id: {}", session.getId()); 38 | } 39 | 40 | public void sendMessageToProject(String project, String message) { 41 | try { 42 | WebSocketSession session = sessions.get(project); 43 | if (session != null && session.isOpen()) { 44 | session.sendMessage(new TextMessage(message)); 45 | } else { 46 | log.warn("No open session found for user: {}", project); 47 | } 48 | } catch (Exception e) { 49 | log.error("Exception while sending message to project: {}", project, e); 50 | } 51 | } 52 | 53 | private Map getQueryParams(String query) { 54 | return Arrays.stream(query.split("&")) 55 | .map(param -> param.split("=")) 56 | .collect(Collectors.toMap(parts -> parts[0], parts -> parts[1])); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/spring/annotation/SingleValueParam.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.spring.annotation; 2 | 3 | import org.springframework.web.bind.annotation.ValueConstants; 4 | 5 | import java.lang.annotation.*; 6 | 7 | @Target(ElementType.PARAMETER) 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Documented 10 | public @interface SingleValueParam { 11 | 12 | String value(); 13 | 14 | boolean required() default true; 15 | 16 | String defaultValue() default ValueConstants.DEFAULT_NONE; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/spring/resolver/SingleValueParamHandlerMethodArgumentResolver.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.spring.resolver; 2 | 3 | import com.alibaba.fastjson2.JSONObject; 4 | import jakarta.servlet.http.HttpServletRequest; 5 | import org.springframework.core.MethodParameter; 6 | import org.springframework.web.bind.support.WebDataBinderFactory; 7 | import org.springframework.web.context.request.NativeWebRequest; 8 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 9 | import org.springframework.web.method.support.ModelAndViewContainer; 10 | import space.wenliang.ai.aigcplatformserver.spring.annotation.SingleValueParam; 11 | 12 | import java.io.BufferedReader; 13 | import java.util.Objects; 14 | 15 | public class SingleValueParamHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { 16 | 17 | private static final String REQUEST_BODY_ATTRIBUTE = "REQUEST_BODY_ATTRIBUTE"; 18 | 19 | @Override 20 | public boolean supportsParameter(MethodParameter parameter) { 21 | return parameter.hasParameterAnnotation(SingleValueParam.class); 22 | } 23 | 24 | @Override 25 | public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 26 | NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 27 | SingleValueParam singleValueParam = parameter.getParameterAnnotation(SingleValueParam.class); 28 | HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); 29 | if (Objects.isNull(request) || Objects.isNull(singleValueParam)) { 30 | return null; 31 | } 32 | 33 | JSONObject jsonObject = (JSONObject) request.getAttribute(REQUEST_BODY_ATTRIBUTE); 34 | if (jsonObject == null) { 35 | BufferedReader reader = request.getReader(); 36 | StringBuilder sb = new StringBuilder(); 37 | char[] buf = new char[1024]; 38 | int rd; 39 | while ((rd = reader.read(buf)) != -1) { 40 | sb.append(buf, 0, rd); 41 | } 42 | jsonObject = JSONObject.parseObject(sb.toString()); 43 | request.setAttribute(REQUEST_BODY_ATTRIBUTE, jsonObject); 44 | } 45 | 46 | String value = singleValueParam.value(); 47 | if (Objects.isNull(jsonObject)) { 48 | return null; 49 | } 50 | return jsonObject.get(value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/test/OpenFolder.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.test; 2 | 3 | import java.awt.*; 4 | import java.io.File; 5 | import java.io.IOException; 6 | 7 | public class OpenFolder { 8 | public static void main(String[] args) throws IOException { 9 | Desktop desktop = Desktop.getDesktop(); 10 | File dirToOpen = null; 11 | try { 12 | dirToOpen = new File("C:\\Users\\liuwe\\IdeaProjects\\aigc-platform-server\\project\\text\\斗破苍穹测试\\第1章 陨落的天才"); 13 | desktop.open(dirToOpen); 14 | } catch (IllegalArgumentException iae) { 15 | System.out.println("File Not Found"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/ChapterUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | import io.vavr.Tuple; 4 | import io.vavr.Tuple2; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.springframework.util.CollectionUtils; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.ByteArrayInputStream; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Objects; 15 | import java.util.regex.Matcher; 16 | import java.util.regex.Pattern; 17 | import java.util.stream.Collectors; 18 | 19 | public class ChapterUtils { 20 | 21 | public static List> chapterSplit(byte[] bytes, String chapterTitlePattern) throws IOException { 22 | List> chapters = new ArrayList<>(); 23 | StringBuilder preface = new StringBuilder(); 24 | 25 | try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)))) { 26 | String line; 27 | StringBuilder chapterContent = new StringBuilder(); 28 | 29 | String title = null; 30 | String content; 31 | 32 | while ((line = reader.readLine()) != null) { 33 | 34 | if (isChapterTitle(line, chapterTitlePattern)) { 35 | if (title != null) { 36 | content = chapterContent.toString(); 37 | chapters.add(Tuple.of(title, content)); 38 | chapterContent.setLength(0); // Resetting the content for the next chapterParse 39 | } 40 | 41 | title = FileUtils.fileNameFormat(line.trim()); 42 | } 43 | if (title == null) { 44 | // If content is null, it means this part is before the first chapterParse 45 | preface.append(line.trim()).append("\n"); 46 | } else { 47 | // Append line to chapter content if it's not a title 48 | chapterContent.append(line.trim()).append("\n"); 49 | } 50 | } 51 | 52 | if (title != null) { 53 | content = chapterContent.toString(); 54 | chapters.add(Tuple.of(title, content)); 55 | } 56 | } 57 | 58 | if (StringUtils.isNotBlank(preface.toString())) { 59 | 60 | String title = FileUtils.fileNameFormat(preface.toString().split("\\n")[0].trim()); 61 | String content = preface.toString(); 62 | chapters.addFirst(Tuple.of(title, content)); 63 | } 64 | 65 | return chapters; 66 | } 67 | 68 | public static boolean isChapterTitle(String line, String chapterTitlePattern) { 69 | if (StringUtils.isBlank(chapterTitlePattern)) { 70 | return false; 71 | } 72 | return line.matches(chapterTitlePattern); 73 | } 74 | 75 | public static List> dialogueSplit(String line, List linesModifiers) { 76 | if (StringUtils.isBlank(line)) { 77 | return new ArrayList<>(); 78 | } 79 | 80 | List> sentences = new ArrayList<>(); 81 | 82 | if (CollectionUtils.isEmpty(linesModifiers)) { 83 | return List.of(Tuple.of(false, line)); 84 | } 85 | 86 | Matcher matcher = buildModifiersPatternStr(linesModifiers).matcher(line); 87 | int lastIndex = 0; 88 | while (matcher.find()) { 89 | if (matcher.start() > lastIndex) { 90 | String text = line.substring(lastIndex, matcher.start()).trim().stripLeading(); 91 | if (StringUtils.isNotBlank(text)) { 92 | sentences.add(Tuple.of(false, text)); 93 | } 94 | } 95 | 96 | String text = line.substring(matcher.start(), matcher.end()).trim().stripLeading(); 97 | if (StringUtils.isNotBlank(text)) { 98 | sentences.add(Tuple.of(true, text.substring(1, text.length() - 1))); 99 | } 100 | 101 | lastIndex = matcher.end(); 102 | } 103 | if (lastIndex < line.length()) { 104 | String text = line.substring(lastIndex).trim().stripLeading(); 105 | if (StringUtils.isNotBlank(text)) { 106 | sentences.add(Tuple.of(false, text)); 107 | } 108 | } 109 | return sentences; 110 | } 111 | 112 | public static Pattern buildModifiersPatternStr(List strings) { 113 | String patternStr = strings.stream().map(s -> { 114 | if (s != null && s.length() == 2) { 115 | String var0 = Pattern.quote(s.substring(0, 1)); 116 | String var1 = Pattern.quote(s.substring(1, 2)); 117 | return var0 + ".*?" + var1; 118 | } 119 | return null; 120 | }).filter(Objects::nonNull) 121 | .collect(Collectors.joining("|")); 122 | return Pattern.compile(patternStr); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/FileUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import org.mozilla.universalchardet.UniversalDetector; 5 | 6 | import java.io.BufferedInputStream; 7 | import java.io.ByteArrayInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.nio.charset.Charset; 11 | import java.nio.file.FileVisitResult; 12 | import java.nio.file.Files; 13 | import java.nio.file.Path; 14 | import java.nio.file.SimpleFileVisitor; 15 | import java.nio.file.attribute.BasicFileAttributes; 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | import java.util.Optional; 19 | 20 | public class FileUtils { 21 | 22 | public static void deleteDirectoryAll(Path path) throws IOException { 23 | if (Files.exists(path)) { 24 | // 使用Files.walkFileTree来遍历文件夹中的所有文件和目录 25 | Files.walkFileTree(path, new SimpleFileVisitor<>() { 26 | @Override 27 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 28 | // 删除文件 29 | Files.delete(file); 30 | return FileVisitResult.CONTINUE; 31 | } 32 | 33 | @Override 34 | public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { 35 | // 如果访问文件失败,则抛出异常 36 | throw exc; 37 | } 38 | 39 | @Override 40 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { 41 | // 所有文件已被删除,现在可以删除空目录 42 | if (exc == null) { 43 | Files.delete(dir); 44 | return FileVisitResult.CONTINUE; 45 | } else { 46 | // 访问目录失败,则抛出异常 47 | throw exc; 48 | } 49 | } 50 | }); 51 | } 52 | } 53 | 54 | public static Charset detectCharset(byte[] bytes) throws IOException { 55 | try (InputStream inputStream = new ByteArrayInputStream(bytes); 56 | BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) { 57 | 58 | byte[] buffer = new byte[1024]; 59 | int bytesRead; 60 | UniversalDetector detector = new UniversalDetector(null); 61 | while ((bytesRead = bufferedInputStream.read(buffer)) != -1) { 62 | detector.handleData(buffer, 0, bytesRead); 63 | } 64 | detector.dataEnd(); 65 | String detectedCharset = detector.getDetectedCharset(); 66 | 67 | return detectedCharset == null ? Charset.defaultCharset() : Charset.forName(detectedCharset); 68 | } 69 | } 70 | 71 | public static String fileNameFormat(String fileName) { 72 | return fileName 73 | .replace("\\", "") 74 | .replace("/", "") 75 | .replace(":", ":") 76 | .replace("*", "") 77 | .replace("?", "?") 78 | .replace("\"", "") 79 | .replace("<", "") 80 | .replace(">", "") 81 | .replace("|", "") 82 | .replace("--", "-") 83 | ; 84 | } 85 | 86 | public static T getObjectFromFile(Path path, Class aClass) { 87 | try { 88 | if (Files.exists(path)) { 89 | return JSON.parseObject(Optional.ofNullable(Files.readString(path)).orElse("[]"), aClass); 90 | } 91 | return aClass.getDeclaredConstructor().newInstance(); 92 | } catch (Exception e) { 93 | throw new RuntimeException(e); 94 | } 95 | } 96 | 97 | public static List getListFromFile(Path path, Class aClass) { 98 | try { 99 | if (Files.exists(path)) { 100 | return JSON.parseArray(Optional.ofNullable(Files.readString(path)).orElse("[]"), aClass); 101 | } 102 | return new ArrayList<>(); 103 | } catch (Exception e) { 104 | throw new RuntimeException(e); 105 | } 106 | } 107 | 108 | public static void openFolder(Path path) throws IOException { 109 | String os = System.getProperty("os.name").toLowerCase(); 110 | 111 | if (Files.notExists(path) || !Files.isDirectory(path)) { 112 | throw new IllegalArgumentException("路径无效或不是目录:" + path); 113 | } 114 | 115 | ProcessBuilder processBuilder = null; 116 | 117 | if (os.contains("win")) { 118 | processBuilder = new ProcessBuilder("explorer", path.toAbsolutePath().toString()); 119 | } else if (os.contains("mac")) { 120 | processBuilder = new ProcessBuilder("open", path.toAbsolutePath().toString()); 121 | } else if (os.contains("nix") || os.contains("nux")) { 122 | processBuilder = new ProcessBuilder("xdg-open", path.toAbsolutePath().toString()); 123 | } else { 124 | throw new UnsupportedOperationException("不支持的操作系统:" + os); 125 | } 126 | 127 | processBuilder.start(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/IdUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | import java.util.UUID; 4 | 5 | public class IdUtils { 6 | 7 | public static String uuid() { 8 | return UUID.randomUUID().toString().replaceAll("-", ""); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/KeyUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | public class KeyUtils { 4 | 5 | public static String combineKey(String... keys) { 6 | return String.join("-", keys); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/PathWrapperUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | import java.nio.file.Path; 4 | 5 | public class PathWrapperUtils { 6 | 7 | public static String getAbsolutePath(Path path, String platform) { 8 | // 检查输入路径是否为null 9 | if (path == null) { 10 | throw new IllegalArgumentException("Path cannot be null"); 11 | } 12 | 13 | // 检查平台是否为null 14 | if (platform == null || platform.isEmpty()) { 15 | return path.toAbsolutePath().toString(); 16 | } 17 | 18 | // 转换路径为绝对路径 19 | Path absolutePath = path.toAbsolutePath(); 20 | 21 | // 获取绝对路径字符串 22 | String absolutePathStr = absolutePath.toString(); 23 | 24 | // 处理不同平台的路径格式 25 | if (platform.equalsIgnoreCase("Windows")) { 26 | // Windows平台的路径格式 27 | return absolutePathStr.replace("/", "\\"); 28 | } else if (platform.equalsIgnoreCase("Unix")) { 29 | // 去掉Windows路径中的驱动器号(如 C:) 30 | if (absolutePathStr.length() > 2 && absolutePathStr.charAt(1) == ':') { 31 | absolutePathStr = absolutePathStr.substring(2); 32 | } 33 | // Unix/Linux平台的路径格式 34 | return absolutePathStr.replace("\\", "/"); 35 | } else { 36 | throw new IllegalArgumentException("Unsupported platform: " + platform); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/SubtitleUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | import space.wenliang.ai.aigcplatformserver.bean.AudioSegment; 4 | import space.wenliang.ai.aigcplatformserver.bean.Subtitle; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.FileReader; 8 | import java.io.IOException; 9 | import java.nio.file.Files; 10 | import java.nio.file.Path; 11 | import java.util.ArrayList; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | public class SubtitleUtils { 17 | 18 | private static final int MAX_CHARS_PER_LINE = 15; 19 | private static final List PUNCTUATION = List.of(',', '。', '!', '?', ';', ':', ',', '.', '!', '?', ';', ':'); 20 | private static final Set punctuationSet = new HashSet<>(PUNCTUATION); 21 | 22 | public static void srtFile(List audioSegments, Path outputFilePath) throws IOException { 23 | 24 | long startTime = 0; 25 | StringBuilder builder = new StringBuilder(); 26 | 27 | for (int i = 0; i < audioSegments.size(); i++) { 28 | AudioSegment audioSegment = audioSegments.get(i); 29 | 30 | Long lengthInMs = audioSegment.getAudioLength(); 31 | Integer interval = audioSegment.getAudioInterval(); 32 | 33 | long endTime = startTime + lengthInMs; 34 | 35 | String startTimeStr = formatTime(startTime); 36 | String endTimeStr = formatTime(endTime); 37 | 38 | builder.append((i + 1)).append("\n"); 39 | builder.append(startTimeStr).append(" --> ").append(endTimeStr).append("\n"); 40 | builder.append(replacePunctuations(audioSegment.getText())).append("\n"); 41 | builder.append("\n"); 42 | 43 | startTime = endTime + interval; 44 | } 45 | Files.writeString(outputFilePath, builder.toString()); 46 | } 47 | 48 | private static String formatTime(long timeInMilliseconds) { 49 | int hours = (int) (timeInMilliseconds / 3600000); 50 | int minutes = (int) ((timeInMilliseconds % 3600000) / 60000); 51 | int seconds = (int) ((timeInMilliseconds % 60000) / 1000); 52 | int milliseconds = (int) (timeInMilliseconds % 1000); 53 | 54 | return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds); 55 | } 56 | 57 | public static List subtitleSplit(String text, boolean enable) { 58 | List result = new ArrayList<>(); 59 | if (text == null || text.isEmpty()) { 60 | return result; 61 | } 62 | 63 | if (!enable) { 64 | return List.of(text); 65 | } 66 | 67 | int start = 0; 68 | while (start < text.length()) { 69 | int end = findSplitPoint(text, start, MAX_CHARS_PER_LINE); 70 | String subtitle = text.substring(start, end).trim(); 71 | 72 | result.add(subtitle); 73 | start = end; 74 | } 75 | 76 | return result; 77 | } 78 | 79 | private static int findSplitPoint(String text, int start, int maxLength) { 80 | int end = start + maxLength; 81 | if (end >= text.length()) { 82 | return text.length(); 83 | } 84 | 85 | for (int i = end; i > start; i--) { 86 | if (PUNCTUATION.contains(text.charAt(i))) { 87 | return i + 1; 88 | } 89 | } 90 | 91 | for (int i = end; i < text.length(); i++) { 92 | if (PUNCTUATION.contains(text.charAt(i))) { 93 | return i + 1; 94 | } 95 | } 96 | 97 | return text.length(); 98 | } 99 | 100 | public static String replacePunctuations(String text) { 101 | StringBuilder sb = new StringBuilder(); 102 | for (char c : text.toCharArray()) { 103 | if (punctuationSet.contains(c)) { 104 | sb.append(' '); 105 | } else { 106 | sb.append(c); 107 | } 108 | } 109 | return sb.toString(); 110 | } 111 | 112 | public static List readSrtFile(Path filePath) throws IOException { 113 | List subtitles = new ArrayList<>(); 114 | BufferedReader reader = new BufferedReader(new FileReader(filePath.toAbsolutePath().toString())); 115 | 116 | String line; 117 | while ((line = reader.readLine()) != null) { 118 | // Skip the index line 119 | line = reader.readLine(); 120 | if (line == null) break; 121 | 122 | // Process the time line 123 | String[] timeParts = line.split(" --> "); 124 | if (timeParts.length != 2) break; 125 | 126 | double startTime = parseTimeToSeconds(timeParts[0]); 127 | double endTime = parseTimeToSeconds(timeParts[1]); 128 | 129 | // Collect text lines 130 | StringBuilder textBuilder = new StringBuilder(); 131 | while ((line = reader.readLine()) != null && !line.isEmpty()) { 132 | textBuilder.append(line).append(" "); 133 | } 134 | String text = textBuilder.toString().trim(); 135 | 136 | // Add subtitle to list 137 | subtitles.add(new Subtitle(startTime, endTime, text)); 138 | } 139 | 140 | reader.close(); 141 | return subtitles; 142 | } 143 | 144 | private static double parseTimeToSeconds(String time) { 145 | String[] parts = time.split(":|,"); 146 | int hours = Integer.parseInt(parts[0]); 147 | int minutes = Integer.parseInt(parts[1]); 148 | int seconds = Integer.parseInt(parts[2]); 149 | int milliseconds = Integer.parseInt(parts[3]); 150 | 151 | return hours * 3600 + minutes * 60 + seconds + milliseconds / 1000.0; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/space/wenliang/ai/aigcplatformserver/util/UnicodeUtils.java: -------------------------------------------------------------------------------- 1 | package space.wenliang.ai.aigcplatformserver.util; 2 | 3 | public class UnicodeUtils { 4 | 5 | public static String unicodeToChar(String unicode) { 6 | if (unicode == null) { 7 | return null; 8 | } 9 | if (unicode.startsWith("U+")) { 10 | unicode = unicode.substring(2).toUpperCase(); 11 | } 12 | 13 | try { 14 | int codePoint = Integer.parseInt(unicode, 16); 15 | return new String(Character.toChars(codePoint)); 16 | } catch (NumberFormatException e) { 17 | throw new IllegalArgumentException("输入的Unicode编码格式不正确。"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | domain: https://api.aigc.wenliang.space 4 | tomcat: 5 | connection-timeout: 600000 6 | threads: 7 | max: 200 8 | max-connections: 10000 9 | accept-count: 1000 10 | max-http-form-post-size: 104857600 11 | keep-alive-timeout: 600000 12 | 13 | spring: 14 | application: 15 | name: aigc-platform-server 16 | servlet: 17 | multipart: 18 | max-file-size: 100MB 19 | max-request-size: 101MB 20 | mvc: 21 | async: 22 | request-timeout: 600000 23 | 24 | datasource: 25 | url: jdbc:mysql://mysql/aigc_platform?rewriteBatchedStatements=true&useServerPrepStmts=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 26 | username: ${DB_USERNAME} 27 | password: ${DB_PASSWORD} 28 | driver-class-name: com.mysql.cj.jdbc.Driver 29 | 30 | mybatis-plus: 31 | mapper-locations: classpath:mapper/*.xml 32 | # configuration: 33 | # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 34 | 35 | remote: 36 | enable: false 37 | platform: unix 38 | model-dir: /model -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | domain: http://127.0.0.1:8080 4 | tomcat: 5 | connection-timeout: 600000 6 | threads: 7 | max: 200 8 | max-connections: 10000 9 | accept-count: 1000 10 | max-http-form-post-size: 104857600 11 | keep-alive-timeout: 600000 12 | 13 | spring: 14 | profiles: 15 | active: @platform@,@deployment@,@db.type@ 16 | application: 17 | name: aigc-platform-server 18 | servlet: 19 | multipart: 20 | max-file-size: 100MB 21 | max-request-size: 101MB 22 | mvc: 23 | async: 24 | request-timeout: 600000 25 | 26 | datasource: 27 | url: jdbc:mysql:///aigc_platform?rewriteBatchedStatements=true&useServerPrepStmts=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC 28 | username: root 29 | password: 123456 30 | driver-class-name: com.mysql.cj.jdbc.Driver 31 | 32 | mybatis-plus: 33 | mapper-locations: classpath:mapper/*.xml 34 | # configuration: 35 | # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 36 | 37 | application: 38 | version: @project.version@ 39 | 40 | --- 41 | spring: 42 | config: 43 | activate: 44 | on-profile: sqlite 45 | datasource: 46 | driver-class-name: org.sqlite.JDBC 47 | url: jdbc:sqlite:aigc_platform.db 48 | username: 49 | password: -------------------------------------------------------------------------------- /src/main/resources/liquibase/mysql/changelogs/changelog-1.1.0.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | alter table text_chapter_entity 5 | add sort_order int null; 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/liquibase/mysql/changelogs/changelog-2.6.4.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | create table tm_prompt_template 5 | ( 6 | id int auto_increment 7 | primary key, 8 | template_group varchar(255) null, 9 | is_default bit null, 10 | template_name varchar(255) null, 11 | system_prompt text null, 12 | user_prompt text null, 13 | is_preset bit null 14 | ); 15 | INSERT INTO tm_prompt_template (id, template_group, is_default, template_name, system_prompt, user_prompt, is_preset) VALUES (1, 'novel_role_inference', true, '小说角色推理', '你是一个小说内容台词分析员,你会精确的找到台词在原文中的位置并分析属于哪个角色,以及角色在说这句台词时的上下文环境及情绪等。', '严格按照以下要求工作: 16 | 1. 分析下面原文中有哪些角色,角色中有观众、群众之类的角色时统一使用观众这个角色,他们的性别和年龄段只能在下面范围中选择一个: 17 | 性别:男、女、未知。 18 | 年龄段:少年、青年、中年、老年、未知。 19 | 20 | 2. 请分析下面台词部分的内容是属于原文部分中哪个角色的,然后结合上下文分析当时的情绪,情绪只能在下面范围中选择一个: 21 | 情绪:中立、开心、吃惊、难过、厌恶、生气、恐惧。 22 | 23 | 3. 严格按照台词文本中的顺序在原文文本中查找。每行台词都做一次处理,不能合并台词。 24 | 4. 分析的台词内容如果不是台词,不要加入到返回结果中。 25 | 5. 返回结果只能包含角色分析、台词分析两个部分。 26 | 27 | 输出格式如下: 28 | 角色分析: 29 | 角色名,男,青年 30 | 角色名,女,青年 31 | 32 | 台词分析: 33 | 台词序号,角色名,高兴 34 | 台词序号,角色名,难过 35 | 36 | 原文部分: 37 | @{小说内容} 38 | 39 | 台词部分: 40 | @{对话列表}', true); 41 | -------------------------------------------------------------------------------- /src/main/resources/liquibase/mysql/changelogs/changelog-2.6.5.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | alter table chapter_info 5 | add text_mood varchar(255) null after text; 6 | 7 | update chapter_info 8 | set text_mood = am_pa_mood 9 | where dialogue_flag = 1; 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/liquibase/mysql/master.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/liquibase/sqlite/changelogs/changelog-1.1.0.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | alter table text_chapter_entity 5 | add sort_order int null; -------------------------------------------------------------------------------- /src/main/resources/liquibase/sqlite/changelogs/changelog-2.6.4.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | create table tm_prompt_template 5 | ( 6 | id integer primary key autoincrement, 7 | template_group varchar(255) null, 8 | is_default bit null, 9 | template_name varchar(255) null, 10 | system_prompt text null, 11 | user_prompt text null, 12 | is_preset bit null 13 | ); 14 | INSERT INTO tm_prompt_template (id, template_group, is_default, template_name, system_prompt, user_prompt, is_preset) VALUES (1, 'novel_role_inference', true, '小说角色推理', '你是一个小说内容台词分析员,你会精确的找到台词在原文中的位置并分析属于哪个角色,以及角色在说这句台词时的上下文环境及情绪等。', '严格按照以下要求工作: 15 | 1. 分析下面原文中有哪些角色,角色中有观众、群众之类的角色时统一使用观众这个角色,他们的性别和年龄段只能在下面范围中选择一个: 16 | 性别:男、女、未知。 17 | 年龄段:少年、青年、中年、老年、未知。 18 | 19 | 2. 请分析下面台词部分的内容是属于原文部分中哪个角色的,然后结合上下文分析当时的情绪,情绪只能在下面范围中选择一个: 20 | 情绪:中立、开心、吃惊、难过、厌恶、生气、恐惧。 21 | 22 | 3. 严格按照台词文本中的顺序在原文文本中查找。每行台词都做一次处理,不能合并台词。 23 | 4. 分析的台词内容如果不是台词,不要加入到返回结果中。 24 | 5. 返回结果只能包含角色分析、台词分析两个部分。 25 | 26 | 输出格式如下: 27 | 角色分析: 28 | 角色名,男,青年 29 | 角色名,女,青年 30 | 31 | 台词分析: 32 | 台词序号,角色名,高兴 33 | 台词序号,角色名,难过 34 | 35 | 原文部分: 36 | @{小说内容} 37 | 38 | 台词部分: 39 | @{对话列表}', true); -------------------------------------------------------------------------------- /src/main/resources/liquibase/sqlite/changelogs/changelog-2.6.5.sql: -------------------------------------------------------------------------------- 1 | -- liquibase formatted sql 2 | 3 | -- changeset wenliang:1 4 | alter table chapter_info 5 | add column text_mood text; 6 | 7 | update chapter_info 8 | set text_mood = am_pa_mood 9 | where dialogue_flag = 1; -------------------------------------------------------------------------------- /src/main/resources/liquibase/sqlite/master.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zddgg/aigc-platform-server/ad0d65e0cb4c5f65fa22933e630a8c29d655e6e0/src/main/resources/static/favicon.ico --------------------------------------------------------------------------------