diff --git a/yudao-module-langchat/yudao-module-langchat-api/pom.xml b/yudao-module-langchat/yudao-module-langchat-api/pom.xml new file mode 100644 index 0000000..d2735da --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + + cn.iocoder.cloud + yudao-module-langchat + ${revision} + + + yudao-module-langchat-api + jar + + ${project.artifactId} + + + langchat 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.cloud + yudao-common + + + \ No newline at end of file diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/CacheConst.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/CacheConst.java new file mode 100644 index 0000000..16a9fb2 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/CacheConst.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.enums; + +/** + * @author tycoding + * @since 2024/1/15 + */ +public interface CacheConst { + + /** + * 系统所有Redis缓存Key前缀 prefix + */ + String REDIS_KEY_PREFIX = "langchat:"; + + /** + * Auth缓存前缀 + */ + String AUTH_PREFIX = REDIS_KEY_PREFIX + "auth:"; + + /** + * Auth Session缓存前缀 + */ + String AUTH_SESSION_PREFIX = AUTH_PREFIX + "session:"; + + /** + * Auth Session缓存变量前缀 + */ + String AUTH_USER_INFO_KEY = "USER_INFO"; + + /** + * Auth Token缓存变量前缀 + */ + String AUTH_TOKEN_INFO_KEY = "TOKEN_INFO"; + + /** + * 用户信息缓存 + */ + String USER_DETAIL_KEY = REDIS_KEY_PREFIX + "user_details"; + + /** + * 验证码缓存前缀 + */ + String CAPTCHA_PREFIX = REDIS_KEY_PREFIX + "auth:captcha:"; + +} diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ChatErrorEnum.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ChatErrorEnum.java new file mode 100644 index 0000000..976400c --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ChatErrorEnum.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.langchat.enums; + +import lombok.AllArgsConstructor; + +/** + * @author GB + * @desc + * @since 2024-08-21 + */ +@AllArgsConstructor +public enum ChatErrorEnum { + API_KEY_IS_NULL(1000, "模型 %s %s api key 为空,请检查配置"), + BASE_URL_IS_NULL(1003, "模型 %s %s base url 为空,请检查配置"), + SECRET_KEY_IS_NULL(1005, "模型 %s %s base secret Key 为空,请检查配置"), + ; + + /** + * 错误码 + */ + private int errorCode; + /** + * 错误描述,用于展示给用户 + */ + private String errorDesc; + + public int getErrorCode() { + return this.errorCode; + } + + public String getErrorDesc(String modelName, String type) { + return this.errorDesc.formatted(modelName, type); + } + +} diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedConst.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedConst.java new file mode 100644 index 0000000..d83aac2 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedConst.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.enums; + +/** + * @author tycoding + * @since 2024/6/6 + */ +public interface EmbedConst { + + String ORIGIN_TYPE_INPUT = "INPUT"; + String ORIGIN_TYPE_UPLOAD = "UPLOAD"; + + String KNOWLEDGE = "knowledgeId"; + String FILENAME = "docsName"; + + String CLAZZ_NAME_OPENAI = "OpenAiEmbeddingModel"; + String CLAZZ_NAME_QIANFAN = "QianfanEmbeddingModel"; + String CLAZZ_NAME_QIANWEN = "QwenEmbeddingModel"; + String CLAZZ_NAME_ZHIPU = "ZhipuAiEmbeddingModel"; + String CLAZZ_NAME_OLLAMA = "OllamaEmbeddingModel"; +} diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedStoreEnum.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedStoreEnum.java new file mode 100644 index 0000000..9f14456 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/EmbedStoreEnum.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.enums; + +import lombok.Getter; + +/** + * @author tycoding + * @since 2024/10/28 + */ +@Getter +public enum EmbedStoreEnum { + + REDIS, + PGVECTOR, + MILVUS, + ; +} diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ModelConst.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ModelConst.java new file mode 100644 index 0000000..c7bb4df --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ModelConst.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.enums; + +/** + * @author tycoding + * @since 2024/1/6 + */ +public interface ModelConst { + + String TEXT_SUFFIX = "_text"; + String IMAGE_SUFFIX = "_image"; +} diff --git a/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ProviderEnum.java b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ProviderEnum.java new file mode 100644 index 0000000..e402b30 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-api/src/main/java/cn/iocoder/yudao/module/langchat/enums/ProviderEnum.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.enums; + +import lombok.Getter; + +/** + * @author tycoding + * @since 2024/6/16 + */ +@Getter +public enum ProviderEnum { + + OPENAI, + AZURE_OPENAI, + GEMINI, + OLLAMA, + CLAUDE, + Q_FAN, + Q_WEN, + ZHIPU, + YI, + DOUYIN, + DEEPSEEK, + SILICON, + SPARK, + ; + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/pom.xml b/yudao-module-langchat/yudao-module-langchat-biz/pom.xml index 8462d22..5171210 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/pom.xml +++ b/yudao-module-langchat/yudao-module-langchat-biz/pom.xml @@ -12,11 +12,100 @@ jar ${project.artifactId} + + + 1.0.0-beta1 + + + + + dev.langchain4j + langchain4j + ${langchain4j.version} + + + dev.langchain4j + langchain4j-core + ${langchain4j.version} + + + dev.langchain4j + langchain4j-community-redis + ${langchain4j.version} + + + dev.langchain4j + langchain4j-pgvector + ${langchain4j.version} + + + dev.langchain4j + langchain4j-milvus + ${langchain4j.version} + + + dev.langchain4j + langchain4j-document-parser-apache-tika + ${langchain4j.version} + + + dev.langchain4j + langchain4j-ollama + ${langchain4j.version} + + + dev.langchain4j + langchain4j-open-ai + ${langchain4j.version} + + + dev.langchain4j + langchain4j-community-qianfan + ${langchain4j.version} + + + dev.langchain4j + langchain4j-community-dashscope + ${langchain4j.version} + + + org.slf4j + slf4j-simple + + + + + dev.langchain4j + langchain4j-community-zhipu-ai + ${langchain4j.version} + + + + org.dromara.x-file-storage + x-file-storage-core + 2.2.1 + + + com.qiniu + qiniu-java-sdk + 7.12.1 + + + com.aliyun.oss + aliyun-sdk-oss + 3.16.1 + + + com.qcloud + cos_api + 5.6.137 + + cn.iocoder.cloud @@ -24,13 +113,15 @@ - - - + yudao-common + + + cn.iocoder.cloud + yudao-module-langchat-api + 2.3.0-jdk8-SNAPSHOT + cn.iocoder.cloud diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/LangChatApplication.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/LangChatApplication.java index 617b7bd..4c8d0ed 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/LangChatApplication.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/LangChatApplication.java @@ -16,17 +16,21 @@ package cn.iocoder.yudao.module.langchat; -import org.mybatis.spring.annotation.MapperScan; +import cn.iocoder.yudao.module.langchat.config.EnableFileStorage; +import cn.iocoder.yudao.module.langchat.config.SpringFileStorageProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; /** * @author tycoding * @since 2024/2/4 */ -//@EnableFileStorage +@EnableFileStorage @SpringBootApplication -@MapperScan("cn.iocoder.yudao.module.langchat.server.mapper") +@EnableConfigurationProperties({ + SpringFileStorageProperties.class, +}) public class LangChatApplication { public static void main(String[] args) { diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/annotation/ApiLog.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/annotation/ApiLog.java similarity index 94% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/annotation/ApiLog.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/annotation/ApiLog.java index 2aa7858..3c1ba34 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/annotation/ApiLog.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/annotation/ApiLog.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.annotation; +package cn.iocoder.yudao.module.langchat.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/EmbeddingRefreshEvent.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/EmbeddingRefreshEvent.java similarity index 94% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/EmbeddingRefreshEvent.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/EmbeddingRefreshEvent.java index a4ff9f4..3b039ed 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/EmbeddingRefreshEvent.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/EmbeddingRefreshEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.component; +package cn.iocoder.yudao.module.langchat.component; import org.springframework.context.ApplicationEvent; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ModelTypeEnum.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ModelTypeEnum.java similarity index 93% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ModelTypeEnum.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ModelTypeEnum.java index bb52ffa..10d5097 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ModelTypeEnum.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ModelTypeEnum.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.component; +package cn.iocoder.yudao.module.langchat.component; import lombok.Getter; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ProviderRefreshEvent.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ProviderRefreshEvent.java similarity index 94% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ProviderRefreshEvent.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ProviderRefreshEvent.java index c46c164..0e1a56c 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/ProviderRefreshEvent.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/ProviderRefreshEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.component; +package cn.iocoder.yudao.module.langchat.component; import org.springframework.context.ApplicationEvent; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/SpringContextHolder.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/SpringContextHolder.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/SpringContextHolder.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/SpringContextHolder.java index f53c3c4..f8e0b87 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/component/SpringContextHolder.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/component/SpringContextHolder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.component; +package cn.iocoder.yudao.module.langchat.component; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanDefinition; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/EnableFileStorage.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/EnableFileStorage.java new file mode 100644 index 0000000..4f17374 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/EnableFileStorage.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.config; + +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * 启用文件存储,会自动根据配置文件进行加载 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +@Documented +@Import({FileStorageAutoConfiguration.class, SpringFileStorageProperties.class}) +public @interface EnableFileStorage {} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/FileStorageAutoConfiguration.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/FileStorageAutoConfiguration.java new file mode 100644 index 0000000..46f8857 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/FileStorageAutoConfiguration.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.config; + +import cn.iocoder.yudao.module.langchat.wrapper.MultipartFileWrapperAdapter; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.dromara.x.file.storage.core.FileStorageService; +import org.dromara.x.file.storage.core.FileStorageServiceBuilder; +import org.dromara.x.file.storage.core.aspect.FileStorageAspect; +import org.dromara.x.file.storage.core.file.FileWrapperAdapter; +import org.dromara.x.file.storage.core.platform.FileStorage; +import org.dromara.x.file.storage.core.platform.FileStorageClientFactory; +import org.dromara.x.file.storage.core.recorder.DefaultFileRecorder; +import org.dromara.x.file.storage.core.recorder.FileRecorder; +import org.dromara.x.file.storage.core.tika.ContentTypeDetect; +import org.dromara.x.file.storage.core.tika.DefaultTikaFactory; +import org.dromara.x.file.storage.core.tika.TikaContentTypeDetect; +import org.dromara.x.file.storage.core.tika.TikaFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Configuration +@ConditionalOnMissingBean(FileStorageService.class) +public class FileStorageAutoConfiguration { + + @Autowired + private SpringFileStorageProperties properties; + + @Autowired + private ApplicationContext applicationContext; + + /** + * 当没有找到 FileRecorder 时使用默认的 FileRecorder + */ + @Bean + @ConditionalOnMissingBean(FileRecorder.class) + public FileRecorder fileRecorder() { + log.warn("没有找到 FileRecorder 的实现类,文件上传之外的部分功能无法正常使用,必须实现该接口才能使用完整功能!"); + return new DefaultFileRecorder(); + } + + /** + * Tika 工厂类型,用于识别上传的文件的 MINE + */ + @Bean + @ConditionalOnMissingBean(TikaFactory.class) + public TikaFactory tikaFactory() { + return new DefaultTikaFactory(); + } + + /** + * 识别文件的 MIME 类型 + */ + @Bean + @ConditionalOnMissingBean(ContentTypeDetect.class) + public ContentTypeDetect contentTypeDetect(TikaFactory tikaFactory) { + return new TikaContentTypeDetect(tikaFactory); + } + + /** + * 文件存储服务 + */ + @Bean(destroyMethod = "destroy") + public FileStorageService fileStorageService( + FileRecorder fileRecorder, + @Autowired(required = false) List> fileStorageLists, + @Autowired(required = false) List aspectList, + @Autowired(required = false) List fileWrapperAdapterList, + ContentTypeDetect contentTypeDetect, + @Autowired(required = false) List>> clientFactoryList) { + + if (fileStorageLists == null) fileStorageLists = new ArrayList<>(); + if (aspectList == null) aspectList = new ArrayList<>(); + if (fileWrapperAdapterList == null) fileWrapperAdapterList = new ArrayList<>(); + if (clientFactoryList == null) clientFactoryList = new ArrayList<>(); + + FileStorageServiceBuilder builder = FileStorageServiceBuilder.create(properties.toFileStorageProperties()) + .setFileRecorder(fileRecorder) + .setAspectList(aspectList) + .setContentTypeDetect(contentTypeDetect) + .setFileWrapperAdapterList(fileWrapperAdapterList) + .setClientFactoryList(clientFactoryList); + + fileStorageLists.forEach(builder::addFileStorage); + + if (properties.getEnableByteFileWrapper()) { + builder.addByteFileWrapperAdapter(); + } + if (properties.getEnableUriFileWrapper()) { + builder.addUriFileWrapperAdapter(); + } + if (properties.getEnableInputStreamFileWrapper()) { + builder.addInputStreamFileWrapperAdapter(); + } + if (properties.getEnableLocalFileWrapper()) { + builder.addLocalFileWrapperAdapter(); + } + if (properties.getEnableHttpServletRequestFileWrapper()) { + if (FileStorageServiceBuilder.doesNotExistClass("javax.servlet.http.HttpServletRequest") + && FileStorageServiceBuilder.doesNotExistClass("jakarta.servlet.http.HttpServletRequest")) { + log.warn( + "当前未检测到 Servlet 环境,无法加载 HttpServletRequest 的文件包装适配器,请将参数【dromara.x-file-storage.enable-http-servlet-request-file-wrapper】设置为 【false】来消除此警告"); + } else { + builder.addHttpServletRequestFileWrapperAdapter(); + } + } + if (properties.getEnableMultipartFileWrapper()) { + if (FileStorageServiceBuilder.doesNotExistClass("org.springframework.web.multipart.MultipartFile")) { + log.warn( + "当前未检测到 SpringWeb 环境,无法加载 MultipartFile 的文件包装适配器,请将参数【dromara.x-file-storage.enable-multipart-file-wrapper】设置为 【false】来消除此警告"); + } else { + builder.addFileWrapperAdapter(new MultipartFileWrapperAdapter()); + } + } + + if (FileStorageServiceBuilder.doesNotExistClass("org.springframework.web.servlet.config.annotation.WebMvcConfigurer")) { + long localAccessNum = properties.getLocal().stream() + .filter(SpringFileStorageProperties.SpringLocalConfig::getEnableStorage) + .filter(SpringFileStorageProperties.SpringLocalConfig::getEnableAccess) + .count(); + long localPlusAccessNum = properties.getLocalPlus().stream() + .filter(SpringFileStorageProperties.SpringLocalPlusConfig::getEnableStorage) + .filter(SpringFileStorageProperties.SpringLocalPlusConfig::getEnableAccess) + .count(); + + if (localAccessNum + localPlusAccessNum > 0) { + log.warn("当前未检测到 SpringWeb 环境,无法开启本地存储平台的本地访问功能,请将关闭本地访问来消除此警告"); + } + } + + return builder.build(); + } + + /** + * 对 FileStorageService 注入自己的代理对象,不然会导致针对 FileStorageService 的代理方法不生效 + */ + @EventListener(ContextRefreshedEvent.class) + public void onContextRefreshedEvent() { + FileStorageService service = applicationContext.getBean(FileStorageService.class); + service.setSelf(service); + } + + /** + * 本地存储文件访问自动配置类 + */ + @Configuration + @ConditionalOnClass(name = "org.springframework.web.servlet.config.annotation.WebMvcConfigurer") + public static class FileStorageLocalFileAccessAutoConfiguration { + @Autowired + private SpringFileStorageProperties properties; + + /** + * 配置本地存储的访问地址 + */ + @Bean + public WebMvcConfigurer fileStorageWebMvcConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addResourceHandlers(@NonNull ResourceHandlerRegistry registry) { + for (SpringFileStorageProperties.SpringLocalConfig local : properties.getLocal()) { + if (local.getEnableStorage() && local.getEnableAccess()) { + registry.addResourceHandler(local.getPathPatterns()) + .addResourceLocations("file:" + local.getBasePath()); + } + } + for (SpringFileStorageProperties.SpringLocalPlusConfig local : properties.getLocalPlus()) { + if (local.getEnableStorage() && local.getEnableAccess()) { + registry.addResourceHandler(local.getPathPatterns()) + .addResourceLocations("file:" + local.getStoragePath()); + } + } + } + }; + } + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/SpringFileStorageProperties.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/SpringFileStorageProperties.java new file mode 100644 index 0000000..0f31e0d --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/config/SpringFileStorageProperties.java @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.config; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.dromara.x.file.storage.core.FileStorageProperties; +import org.dromara.x.file.storage.core.FileStorageProperties.*; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Data +@Accessors(chain = true) +@Component +@ConditionalOnMissingBean(SpringFileStorageProperties.class) +@ConfigurationProperties(prefix = "langchat.oss") +public class SpringFileStorageProperties { + + /** + * 默认存储平台 + */ + private String defaultPlatform = "local"; + /** + * 缩略图后缀,例如【.min.jpg】【.png】 + */ + private String thumbnailSuffix = ".min.jpg"; + /** + * 上传时不支持元数据时抛出异常 + */ + private Boolean uploadNotSupportMetadataThrowException = true; + /** + * 上传时不支持 ACL 时抛出异常 + */ + private Boolean uploadNotSupportAclThrowException = true; + /** + * 复制时不支持元数据时抛出异常 + */ + private Boolean copyNotSupportMetadataThrowException = true; + /** + * 复制时不支持 ACL 时抛出异常 + */ + private Boolean copyNotSupportAclThrowException = true; + /** + * 移动时不支持元数据时抛出异常 + */ + private Boolean moveNotSupportMetadataThrowException = true; + /** + * 移动时不支持 ACL 时抛出异常 + */ + private Boolean moveNotSupportAclThrowException = true; + /** + * 启用 byte[] 文件包装适配器 + */ + private Boolean enableByteFileWrapper = true; + /** + * 启用 URI 文件包装适配器,包含 URL 和 String + */ + private Boolean enableUriFileWrapper = true; + /** + * 启用 InputStream 文件包装适配器 + */ + private Boolean enableInputStreamFileWrapper = true; + /** + * 启用本地文件包装适配器 + */ + private Boolean enableLocalFileWrapper = true; + /** + * 启用 HttpServletRequest 文件包装适配器 + */ + private Boolean enableHttpServletRequestFileWrapper = true; + /** + * 启用 MultipartFile 文件包装适配器 + */ + private Boolean enableMultipartFileWrapper = true; + /** + * 本地存储 + */ + @Deprecated + private List local = new ArrayList<>(); + /** + * 本地存储 + */ + private List localPlus = new ArrayList<>(); + /** + * 华为云 OBS + */ + private List huaweiObs = new ArrayList<>(); + /** + * 阿里云 OSS + */ + private List aliyunOss = new ArrayList<>(); + /** + * 七牛云 Kodo + */ + private List qiniuKodo = new ArrayList<>(); + /** + * 腾讯云 COS + */ + private List tencentCos = new ArrayList<>(); + /** + * 百度云 BOS + */ + private List baiduBos = new ArrayList<>(); + /** + * 又拍云 USS + */ + private List upyunUss = new ArrayList<>(); + /** + * MinIO USS + */ + private List minio = new ArrayList<>(); + + /** + * Amazon S3 + */ + private List amazonS3 = new ArrayList<>(); + + /** + * FTP + */ + private List ftp = new ArrayList<>(); + + /** + * FTP + */ + private List sftp = new ArrayList<>(); + + /** + * WebDAV + */ + private List webdav = new ArrayList<>(); + + /** + * GoogleCloud Storage + */ + private List googleCloudStorage = new ArrayList<>(); + + /** + * FastDFS + */ + private List fastdfs = new ArrayList<>(); + + /** + * Azure Blob Storage + */ + private List azureBlob = new ArrayList<>(); + + /** + * 转换成 FileStorageProperties ,并过滤掉没有启用的存储平台 + */ + public FileStorageProperties toFileStorageProperties() { + FileStorageProperties properties = new FileStorageProperties(); + properties.setDefaultPlatform(defaultPlatform); + properties.setThumbnailSuffix(thumbnailSuffix); + properties.setUploadNotSupportMetadataThrowException(uploadNotSupportMetadataThrowException); + properties.setUploadNotSupportAclThrowException(uploadNotSupportAclThrowException); + properties.setCopyNotSupportMetadataThrowException(copyNotSupportMetadataThrowException); + properties.setCopyNotSupportAclThrowException(copyNotSupportAclThrowException); + properties.setMoveNotSupportMetadataThrowException(moveNotSupportMetadataThrowException); + properties.setMoveNotSupportAclThrowException(moveNotSupportAclThrowException); + properties.setLocal( + local.stream().filter(SpringLocalConfig::getEnableStorage).collect(Collectors.toList())); + properties.setLocalPlus(localPlus.stream() + .filter(SpringLocalPlusConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setHuaweiObs(huaweiObs.stream() + .filter(SpringHuaweiObsConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setAliyunOss(aliyunOss.stream() + .filter(SpringAliyunOssConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setQiniuKodo(qiniuKodo.stream() + .filter(SpringQiniuKodoConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setTencentCos(tencentCos.stream() + .filter(SpringTencentCosConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setBaiduBos( + baiduBos.stream().filter(SpringBaiduBosConfig::getEnableStorage).collect(Collectors.toList())); + properties.setUpyunUss( + upyunUss.stream().filter(SpringUpyunUssConfig::getEnableStorage).collect(Collectors.toList())); + properties.setMinio( + minio.stream().filter(SpringMinioConfig::getEnableStorage).collect(Collectors.toList())); + properties.setAmazonS3( + amazonS3.stream().filter(SpringAmazonS3Config::getEnableStorage).collect(Collectors.toList())); + properties.setFtp(ftp.stream().filter(SpringFtpConfig::getEnableStorage).collect(Collectors.toList())); + properties.setSftp( + sftp.stream().filter(SpringSftpConfig::getEnableStorage).collect(Collectors.toList())); + properties.setWebdav( + webdav.stream().filter(SpringWebDavConfig::getEnableStorage).collect(Collectors.toList())); + properties.setGoogleCloudStorage(googleCloudStorage.stream() + .filter(SpringGoogleCloudStorageConfig::getEnableStorage) + .collect(Collectors.toList())); + properties.setFastdfs( + fastdfs.stream().filter(SpringFastDfsConfig::getEnableStorage).collect(Collectors.toList())); + properties.setAzureBlob(azureBlob.stream() + .filter(SpringAzureBlobStorageConfig::getEnableStorage) + .collect(Collectors.toList())); + + return properties; + } + + /** + * 本地存储 + */ + @Deprecated + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringLocalConfig extends LocalConfig { + /** + * 本地存储访问路径 + */ + private String[] pathPatterns = new String[0]; + /** + * 启用本地存储 + */ + private Boolean enableStorage = false; + /** + * 启用本地访问 + */ + private Boolean enableAccess = false; + } + + /** + * 本地存储升级版 + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringLocalPlusConfig extends LocalPlusConfig { + /** + * 本地存储访问路径 + */ + private String[] pathPatterns = new String[0]; + /** + * 启用本地存储 + */ + private Boolean enableStorage = false; + /** + * 启用本地访问 + */ + private Boolean enableAccess = false; + } + + /** + * 华为云 OBS + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringHuaweiObsConfig extends HuaweiObsConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * 阿里云 OSS + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringAliyunOssConfig extends AliyunOssConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * 七牛云 Kodo + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringQiniuKodoConfig extends QiniuKodoConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * 腾讯云 COS + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringTencentCosConfig extends TencentCosConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * 百度云 BOS + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringBaiduBosConfig extends BaiduBosConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * 又拍云 USS + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringUpyunUssConfig extends UpyunUssConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * MinIO + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringMinioConfig extends MinioConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * Amazon S3 + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringAmazonS3Config extends AmazonS3Config { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * FTP + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringFtpConfig extends FtpConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * SFTP + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringSftpConfig extends SftpConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * WebDAV + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringWebDavConfig extends WebDavConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * GoogleCloud Storage + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringGoogleCloudStorageConfig extends GoogleCloudStorageConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * FastDFS Storage + * @author XS + * @date 2023/10/23 + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringFastDfsConfig extends FastDfsConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } + + /** + * AzureBlob Storage + */ + @Data + @Accessors(chain = true) + @EqualsAndHashCode(callSuper = true) + public static class SpringAzureBlobStorageConfig extends AzureBlobStorageConfig { + /** + * 启用存储 + */ + private Boolean enableStorage = false; + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsController.java new file mode 100644 index 0000000..cd78165 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsController.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsMapper; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; +import cn.iocoder.yudao.module.langchat.service.core.EmbeddingService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author tycoding + * @since 2024/4/15 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/chat/aigc/docs") +public class AigcDocsController { + + private final AigcDocsMapper docsMapper; + private final EmbeddingService embeddingService; + + @GetMapping("/list") + @TenantIgnore + public CommonResult> list(AigcDocs data) { + return CommonResult.success(docsMapper.selectList(Wrappers.lambdaQuery().orderByDesc(AigcDocs::getCreateTime))); + } + + @GetMapping("/page") + @TenantIgnore + public CommonResult list(AigcDocs data, QueryPage queryPage) { + Page page = new Page<>(queryPage.getPageNo(), queryPage.getPageSize()); + return CommonResult.success(MybatisUtil.getData(docsMapper.selectPage(page, Wrappers.lambdaQuery() + .eq(data.getKnowledgeId() != null, AigcDocs::getKnowledgeId, data.getKnowledgeId()) + .eq(data.getSliceStatus() != null, AigcDocs::getSliceStatus, data.getSliceStatus()) + .orderByDesc(AigcDocs::getCreateTime) + ))); + } + + @GetMapping("/{id}") + @TenantIgnore + public CommonResult findById(@PathVariable String id) { + return CommonResult.success(docsMapper.selectById(id)); + } + + @PostMapping + @ApiLog("新增文档") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:add')") + public CommonResult add(@RequestBody AigcDocs data) { + docsMapper.insert(data); + return CommonResult.success("success"); + } + + @PutMapping + @ApiLog("修改文档") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:update')") + public CommonResult update(@RequestBody AigcDocs data) { + docsMapper.updateById(data); + return CommonResult.success("success"); + } + + @DeleteMapping("/{id}") + @ApiLog("删除文档") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:delete')") + @Transactional + public CommonResult delete(@PathVariable String id) { + // 删除切面数据 + embeddingService.clearDocSlices(id); + + // 删除文档 + docsMapper.deleteById(id); + return CommonResult.success("success"); + } +} + diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsSliceController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsSliceController.java new file mode 100644 index 0000000..b83026b --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcDocsSliceController.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsSliceMapper; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; + +/** + * @author tycoding + * @since 2024/4/15 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/chat/aigc/docs/slice") +public class AigcDocsSliceController { + + private final AigcDocsSliceMapper docsSliceMapper; + + @GetMapping("/list") + @TenantIgnore + public CommonResult> list(AigcDocsSlice data) { + return CommonResult.success(docsSliceMapper.selectList(Wrappers.lambdaQuery().orderByDesc(AigcDocsSlice::getCreateTime))); + } + + @GetMapping("/page") + @TenantIgnore + public CommonResult list(AigcDocsSlice data, QueryPage queryPage) { + Page page = new Page<>(queryPage.getPageNo(), queryPage.getPageSize()); + return CommonResult.success(MybatisUtil.getData(docsSliceMapper.selectPage(page, Wrappers.lambdaQuery() + .eq(data.getKnowledgeId() != null, AigcDocsSlice::getKnowledgeId, data.getKnowledgeId()) + .eq(data.getDocsId() != null, AigcDocsSlice::getDocsId, data.getDocsId()) + .orderByDesc(AigcDocsSlice::getCreateTime) + ))); + } + + @GetMapping("/{id}") + @TenantIgnore + public CommonResult findById(@PathVariable String id) { + return CommonResult.success(docsSliceMapper.selectById(id)); + } + + @PostMapping + @ApiLog("新增切片数据") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:slice:add')") + public CommonResult add(@RequestBody AigcDocsSlice data) { + data.setCreateTime(new Date()); + docsSliceMapper.insert(data); + return CommonResult.success("success"); + } + + @PutMapping + @ApiLog("修改切片数据") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:slice:update')") + public CommonResult update(@RequestBody AigcDocsSlice data) { + docsSliceMapper.updateById(data); + return CommonResult.success("success"); + } + + @DeleteMapping("/{id}") + @ApiLog("删除切片数据") + @TenantIgnore + @PreAuthorize("@ss.hasPermission('aigc:docs:slice:delete')") + public CommonResult delete(@PathVariable String id) { + docsSliceMapper.deleteById(id); + return CommonResult.success("success"); + } +} + diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcEmbedStoreController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcEmbedStoreController.java similarity index 66% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcEmbedStoreController.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcEmbedStoreController.java index f254e37..e976708 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcEmbedStoreController.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcEmbedStoreController.java @@ -14,20 +14,21 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.controller; +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.component.EmbeddingRefreshEvent; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; -import cn.iocoder.yudao.module.langchat.server.service.AigcEmbedStoreService; -import cn.iocoder.yudao.module.langchat.server.annotation.ApiLog; -import cn.iocoder.yudao.module.langchat.server.component.SpringContextHolder; -import cn.iocoder.yudao.module.langchat.server.utils.MybatisUtil; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.component.EmbeddingRefreshEvent; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcEmbedStoreService; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.component.SpringContextHolder; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; -import cn.iocoder.yudao.module.langchat.server.utils.R; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; @@ -42,68 +43,74 @@ import java.util.List; */ @RestController @RequiredArgsConstructor -@RequestMapping("/aigc/embed-store") +@RequestMapping("/chat/aigc/embed-store") public class AigcEmbedStoreController { private final AigcEmbedStoreService embedStoreService; private final SpringContextHolder contextHolder; @GetMapping("/list") - public R> list(AigcEmbedStore data) { + @TenantIgnore + public CommonResult> list(AigcEmbedStore data) { List list = embedStoreService.list(Wrappers.lambdaQuery()); list.forEach(this::hide); - return R.ok(list); + return CommonResult.success(list); } @GetMapping("/page") - public R page(AigcEmbedStore embedStore, QueryPage queryPage) { + @TenantIgnore + public CommonResult page(AigcEmbedStore embedStore, QueryPage queryPage) { IPage page = embedStoreService.page(MybatisUtil.wrap(embedStore, queryPage), Wrappers.lambdaQuery()); page.getRecords().forEach(this::hide); - return R.ok(MybatisUtil.getData(page)); + return CommonResult.success(MybatisUtil.getData(page)); } @GetMapping("/{id}") - public R findById(@PathVariable String id) { + @TenantIgnore + public CommonResult findById(@PathVariable String id) { AigcEmbedStore store = embedStoreService.getById(id); hide(store); - return R.ok(store); + return CommonResult.success(store); } @PostMapping @ApiLog("新增向量库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:embed-store:add')") - public R add(@RequestBody AigcEmbedStore data) { + public CommonResult add(@RequestBody AigcEmbedStore data) { if (StrUtil.isNotBlank(data.getPassword()) && data.getPassword().contains("*")) { data.setPassword(null); } embedStoreService.save(data); SpringContextHolder.publishEvent(new EmbeddingRefreshEvent(data)); - return R.ok(); + return CommonResult.success(data); } @PutMapping @ApiLog("修改向量库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:embed-store:update')") - public R update(@RequestBody AigcEmbedStore data) { + public CommonResult update(@RequestBody AigcEmbedStore data) { if (StrUtil.isNotBlank(data.getPassword()) && data.getPassword().contains("*")) { data.setPassword(null); } embedStoreService.updateById(data); SpringContextHolder.publishEvent(new EmbeddingRefreshEvent(data)); - return R.ok(); + return CommonResult.success("success"); } @DeleteMapping("/{id}") @ApiLog("删除向量库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:embed-store:delete')") - public R delete(@PathVariable String id) { + public CommonResult delete(@PathVariable String id) { AigcEmbedStore store = embedStoreService.getById(id); if (store != null) { embedStoreService.removeById(id); contextHolder.unregisterBean(id); } - return R.ok(); + return CommonResult.success("success"); } private void hide(AigcEmbedStore data) { diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcKnowledgeController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcKnowledgeController.java similarity index 69% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcKnowledgeController.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcKnowledgeController.java index f5f5a9c..8f28617 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcKnowledgeController.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcKnowledgeController.java @@ -14,24 +14,25 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.controller; +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocs; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; -import cn.iocoder.yudao.module.langchat.server.entity.AigcKnowledge; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcDocsMapper; -import cn.iocoder.yudao.module.langchat.server.provider.KnowledgeStoreFactory; -import cn.iocoder.yudao.module.langchat.server.service.AigcEmbedStoreService; -import cn.iocoder.yudao.module.langchat.server.service.AigcKnowledgeService; -import cn.iocoder.yudao.module.langchat.server.service.AigcModelService; -import cn.iocoder.yudao.module.langchat.server.annotation.ApiLog; -import cn.iocoder.yudao.module.langchat.server.utils.MybatisUtil; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsMapper; +import cn.iocoder.yudao.module.langchat.provider.KnowledgeStoreFactory; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcEmbedStoreService; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcKnowledgeService; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcModelService; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; -import cn.iocoder.yudao.module.langchat.server.utils.R; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -49,7 +50,7 @@ import java.util.stream.Collectors; */ @RestController @RequiredArgsConstructor -@RequestMapping("/aigc/knowledge") +@RequestMapping("/chat/aigc/knowledge") public class AigcKnowledgeController { private final AigcKnowledgeService kbService; @@ -59,10 +60,11 @@ public class AigcKnowledgeController { private final KnowledgeStoreFactory knowledgeStore; @GetMapping("/list") - public R> list(AigcKnowledge data) { + @TenantIgnore + public CommonResult> list(AigcKnowledge data) { List list = kbService.list(Wrappers.lambdaQuery().orderByDesc(AigcKnowledge::getCreateTime)); build(list); - return R.ok(list); + return CommonResult.success(list); } private void build(List records) { @@ -87,8 +89,9 @@ public class AigcKnowledgeController { } @GetMapping("/page") - public R list(AigcKnowledge data, QueryPage queryPage) { - Page page = new Page<>(queryPage.getPage(), queryPage.getLimit()); + @TenantIgnore + public CommonResult list(AigcKnowledge data, QueryPage queryPage) { + Page page = new Page<>(queryPage.getPageNo(), queryPage.getPageSize()); LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .like(!StrUtil.isBlank(data.getName()), AigcKnowledge::getName, data.getName()) .orderByDesc(AigcKnowledge::getCreateTime); @@ -96,11 +99,12 @@ public class AigcKnowledgeController { build(iPage.getRecords()); - return R.ok(MybatisUtil.getData(iPage)); + return CommonResult.success(MybatisUtil.getData(iPage)); } @GetMapping("/{id}") - public R findById(@PathVariable String id) { + @TenantIgnore + public CommonResult findById(@PathVariable String id) { AigcKnowledge knowledge = kbService.getById(id); if (knowledge.getEmbedStoreId() != null) { knowledge.setEmbedStore(embedStoreService.getById(knowledge.getEmbedStoreId())); @@ -108,35 +112,38 @@ public class AigcKnowledgeController { if (knowledge.getEmbedModelId() != null) { knowledge.setEmbedModel(modelService.getById(knowledge.getEmbedModelId())); } - return R.ok(knowledge); + return CommonResult.success(knowledge); } @PostMapping @ApiLog("新增知识库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:knowledge:add')") - public R add(@RequestBody AigcKnowledge data) { + public CommonResult add(@RequestBody AigcKnowledge data) { data.setCreateTime(String.valueOf(System.currentTimeMillis())); kbService.save(data); knowledgeStore.init(); - return R.ok(); + return CommonResult.success("success"); } @PutMapping @ApiLog("更新知识库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:knowledge:update')") - public R update(@RequestBody AigcKnowledge data) { + public CommonResult update(@RequestBody AigcKnowledge data) { kbService.updateById(data); knowledgeStore.init(); - return R.ok(); + return CommonResult.success("success"); } @DeleteMapping("/{id}") @ApiLog("删除知识库") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:knowledge:delete')") - public R delete(@PathVariable String id) { + public CommonResult delete(@PathVariable String id) { kbService.removeKnowledge(id); knowledgeStore.init(); - return R.ok(); + return CommonResult.success("success"); } } diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcMessageController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcMessageController.java similarity index 66% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcMessageController.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcMessageController.java index 1584d52..3407a87 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcMessageController.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcMessageController.java @@ -14,17 +14,18 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.controller; +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.entity.AigcMessage; -import cn.iocoder.yudao.module.langchat.server.service.AigcMessageService; -import cn.iocoder.yudao.module.langchat.server.annotation.ApiLog; -import cn.iocoder.yudao.module.langchat.server.utils.MybatisUtil; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.entity.AigcMessage; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcMessageService; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; -import cn.iocoder.yudao.module.langchat.server.utils.R; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -36,7 +37,7 @@ import org.springframework.web.bind.annotation.*; * @author tycoding * @since 2024/1/19 */ -@RequestMapping("/aigc/message") +@RequestMapping("/chat/aigc/message") @RestController @AllArgsConstructor public class AigcMessageController { @@ -44,26 +45,29 @@ public class AigcMessageController { private final AigcMessageService aigcMessageService; @GetMapping("/page") - public R list(AigcMessage data, QueryPage queryPage) { + @TenantIgnore + public CommonResult list(AigcMessage data, QueryPage queryPage) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .like(!StrUtil.isBlank(data.getMessage()), AigcMessage::getMessage, data.getMessage()) .like(!StrUtil.isBlank(data.getUsername()), AigcMessage::getUsername, data.getUsername()) .eq(!StrUtil.isBlank(data.getRole()), AigcMessage::getRole, data.getRole()) .orderByDesc(AigcMessage::getCreateTime); IPage iPage = aigcMessageService.page(MybatisUtil.wrap(data, queryPage), queryWrapper); - return R.ok(MybatisUtil.getData(iPage)); + return CommonResult.success(MybatisUtil.getData(iPage)); } @GetMapping("/{id}") - public R getById(@PathVariable String id) { - return R.ok(aigcMessageService.getById(id)); + @TenantIgnore + public CommonResult getById(@PathVariable String id) { + return CommonResult.success(aigcMessageService.getById(id)); } @DeleteMapping("/{id}") @ApiLog("删除会话消息") + @TenantIgnore @PreAuthorize("@ss.hasPermission('aigc:message:delete')") - public R del(@PathVariable String id) { - return R.ok(aigcMessageService.removeById(id)); + public CommonResult del(@PathVariable String id) { + return CommonResult.success(aigcMessageService.removeById(id)); } } diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcModelController.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcModelController.java similarity index 63% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcModelController.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcModelController.java index 8e1f0dc..352321a 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/controller/AigcModelController.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/aigc/AigcModelController.java @@ -14,19 +14,20 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.controller; +package cn.iocoder.yudao.module.langchat.controller.admin.aigc; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.component.ProviderRefreshEvent; -import cn.iocoder.yudao.module.langchat.server.component.SpringContextHolder; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; -import cn.iocoder.yudao.module.langchat.server.service.AigcModelService; -import cn.iocoder.yudao.module.langchat.server.annotation.ApiLog; -import cn.iocoder.yudao.module.langchat.server.utils.MybatisUtil; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.component.ProviderRefreshEvent; +import cn.iocoder.yudao.module.langchat.component.SpringContextHolder; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcModelService; +import cn.iocoder.yudao.module.langchat.annotation.ApiLog; +import cn.iocoder.yudao.module.langchat.utils.MybatisUtil; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; -import cn.iocoder.yudao.module.langchat.server.utils.R; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; @@ -40,32 +41,36 @@ import java.util.List; */ @RestController @RequiredArgsConstructor -@RequestMapping("/aigc/model") +@RequestMapping("/chat/aigc/model") public class AigcModelController { private final AigcModelService modelService; private final SpringContextHolder contextHolder; @GetMapping("/list") - public R> list(AigcModel data) { - return R.ok(modelService.list(data)); + @TenantIgnore + public CommonResult> list(AigcModel data) { + return CommonResult.success(modelService.list(data)); } @GetMapping("/page") - public R list(AigcModel data, QueryPage queryPage) { + @TenantIgnore + public CommonResult list(AigcModel data, QueryPage queryPage) { Page iPage = modelService.page(data, queryPage); - return R.ok(MybatisUtil.getData(iPage)); + return CommonResult.success(MybatisUtil.getData(iPage)); } @GetMapping("/{id}") - public R findById(@PathVariable String id) { - return R.ok(modelService.selectById(id)); + @TenantIgnore + public CommonResult findById(@PathVariable String id) { + return CommonResult.success(modelService.selectById(id)); } @PostMapping @ApiLog("添加模型") @PreAuthorize("@ss.hasPermission('aigc:model:add')") - public R add(@RequestBody AigcModel data) { + @TenantIgnore + public CommonResult add(@RequestBody AigcModel data) { if (StrUtil.isNotBlank(data.getApiKey()) && data.getApiKey().contains("*")) { data.setApiKey(null); } @@ -74,13 +79,14 @@ public class AigcModelController { } modelService.save(data); SpringContextHolder.publishEvent(new ProviderRefreshEvent(data)); - return R.ok(); + return CommonResult.success("success"); } @PutMapping @ApiLog("修改模型") @PreAuthorize("@ss.hasPermission('aigc:model:update')") - public R update(@RequestBody AigcModel data) { + @TenantIgnore + public CommonResult update(@RequestBody AigcModel data) { if (StrUtil.isNotBlank(data.getApiKey()) && data.getApiKey().contains("*")) { data.setApiKey(null); } @@ -89,18 +95,19 @@ public class AigcModelController { } modelService.updateById(data); SpringContextHolder.publishEvent(new ProviderRefreshEvent(data)); - return R.ok(); + return CommonResult.success("success"); } @DeleteMapping("/{id}") @ApiLog("删除模型") @PreAuthorize("@ss.hasPermission('aigc:model:delete')") - public R delete(@PathVariable String id) { + @TenantIgnore + public CommonResult delete(@PathVariable String id) { modelService.removeById(id); // Delete dynamically registered beans, according to ID contextHolder.unregisterBean(id); - return R.ok(); + return CommonResult.success("success"); } } diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/endpoint/EmbeddingEndpoint.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/endpoint/EmbeddingEndpoint.java new file mode 100644 index 0000000..5930f2b --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/controller/admin/endpoint/EmbeddingEndpoint.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.controller.admin.endpoint; + +import ch.qos.logback.core.net.LoginAuthenticator; +import cn.hutool.core.util.StrUtil; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.langchat.dal.dto.ChatReq; +import cn.iocoder.yudao.module.langchat.dal.dto.EmbeddingR; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.entity.AigcOss; +import cn.iocoder.yudao.module.langchat.enums.EmbedConst; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcKnowledgeService; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcOssService; +import cn.iocoder.yudao.module.langchat.service.core.EmbeddingService; +import cn.iocoder.yudao.module.langchat.service.core.LangEmbeddingService; +import cn.iocoder.yudao.module.langchat.task.TaskManager; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.concurrent.Executors; + +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +/** + * @author tycoding + * @since 2024/4/25 + */ +@Slf4j +@RestController +@AllArgsConstructor +@RequestMapping("/chat/aigc/embedding") +public class EmbeddingEndpoint { + + private final LangEmbeddingService langEmbeddingService; + private final AigcKnowledgeService aigcKnowledgeService; + private final AigcDocsMapper aigcDocsMapper; + private final AigcOssService aigcOssService; + private final EmbeddingService embeddingService; + + @PostMapping("/text") + @PreAuthorize("@ss.hasPermission('aigc:embedding:text')") + @TenantIgnore + public CommonResult text(@RequestBody AigcDocs data) { + if (StrUtil.isBlankIfStr(data.getContent())) { + throw new ServiceException(-1003,"文档内容不能为空"); + } + if (StrUtil.isBlank(data.getId())) { + aigcKnowledgeService.addDocs(data); + } + data.setType(EmbedConst.ORIGIN_TYPE_INPUT).setSliceStatus(false); + + try { + EmbeddingR embeddingR = langEmbeddingService.embeddingText( + new ChatReq().setMessage(data.getContent()) + .setDocsName(data.getType()) + .setDocsId(data.getId()) + .setKnowledgeId(data.getKnowledgeId())); + + aigcKnowledgeService.addDocsSlice(new AigcDocsSlice() + .setKnowledgeId(data.getKnowledgeId()) + .setDocsId(data.getId()) + .setVectorId(embeddingR.getVectorId()) + .setName(data.getName()) + .setContent(embeddingR.getText()) + ); + + aigcKnowledgeService.updateDocs(new AigcDocs().setId(data.getId()).setSliceStatus(true).setSliceNum(1)); + } catch (Exception e) { + e.printStackTrace(); + + // del data + aigcKnowledgeService.removeSlicesOfDoc(data.getId()); + } + return CommonResult.success("success"); + } + + @PostMapping("/docs/{knowledgeId}") + @PreAuthorize("@ss.hasPermission('aigc:embedding:docs')") + @TenantIgnore + public CommonResult docs(MultipartFile file, @PathVariable String knowledgeId) { + // 1.1 获得用户信息 + String userId = getLoginUserId().toString(); + AigcOss oss = aigcOssService.upload(file, userId); + AigcDocs data = new AigcDocs() + .setName(oss.getOriginalFilename()) + .setSliceStatus(false) + .setUrl(oss.getUrl()) + .setSize(file.getSize()) + .setType(EmbedConst.ORIGIN_TYPE_UPLOAD) + .setKnowledgeId(knowledgeId); + aigcKnowledgeService.addDocs(data); + TaskManager.submitTask(userId, Executors.callable(() -> { + embeddingService.embedDocsSlice(data, oss.getUrl()); + })); + return CommonResult.success("success"); + } + + @GetMapping("/re-embed/{docsId}") + @TenantIgnore + public CommonResult reEmbed(@PathVariable String docsId) { + String userId = getLoginUserId().toString(); + AigcDocs docs = aigcDocsMapper.selectById(docsId); + if (docs == null) { + throw new ServiceException(-1003,"没有查询到文档数据"); + } + if (EmbedConst.ORIGIN_TYPE_INPUT.equals(docs.getType())) { + text(docs); + } + if (EmbedConst.ORIGIN_TYPE_UPLOAD.equals(docs.getType())) { + // clear before re-embed + embeddingService.clearDocSlices(docsId); + TaskManager.submitTask(userId, Executors.callable(() -> { + embeddingService.embedDocsSlice(docs, docs.getUrl()); + })); + } + return CommonResult.success("success"); + } + + @PostMapping("/search") + @TenantIgnore + public CommonResult search(@RequestBody AigcDocs data) { + return CommonResult.success(embeddingService.search(data)); + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/ChatReq.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/ChatReq.java new file mode 100644 index 0000000..3006e34 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/ChatReq.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.dal.dto; + + +import cn.iocoder.yudao.module.langchat.utils.StreamEmitter; +import dev.langchain4j.model.input.Prompt; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * @author tycoding + * @since 2024/1/30 + */ +@Data +@Accessors(chain = true) +public class ChatReq { + + private String appId; + private String modelId; + private String modelName; + private String modelProvider; + + private String message; + + private String conversationId; + + private String userId; + + private String username; + + private String chatId; + + private String promptText; + + private String docsName; + + private String knowledgeId; + private List knowledgeIds = new ArrayList<>(); + + private String docsId; + + private String url; + + private String role; + + private Prompt prompt; + + private StreamEmitter emitter; + private Executor executor; +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/EmbeddingR.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/EmbeddingR.java new file mode 100644 index 0000000..afff8c3 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/dal/dto/EmbeddingR.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.dal.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author tycoding + * @since 2024/4/26 + */ +@Data +@Accessors(chain = true) +public class EmbeddingR { + + /** + * 写入到vector store的ID + */ + private String vectorId; + + /** + * 文档ID + */ + private String docsId; + + /** + * 知识库ID + */ + private String knowledgeId; + + /** + * Embedding后切片的文本 + */ + private String text; +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcApp.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcApp.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcApp.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcApp.java index fa6f674..59b3943 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcApp.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcApp.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcAppApi.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcAppApi.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcAppApi.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcAppApi.java index cdda786..2911629 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcAppApi.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcAppApi.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcConversation.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcConversation.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcConversation.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcConversation.java index abb270c..7f3d945 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcConversation.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcConversation.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocs.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocs.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocs.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocs.java index 4a8b9f5..15d107f 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocs.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocs.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocsSlice.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocsSlice.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocsSlice.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocsSlice.java index 237a3ac..ef72ec4 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcDocsSlice.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcDocsSlice.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcEmbedStore.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcEmbedStore.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcEmbedStore.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcEmbedStore.java index 4570ba3..3e54664 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcEmbedStore.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcEmbedStore.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcKnowledge.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcKnowledge.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcKnowledge.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcKnowledge.java index dced548..f745969 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcKnowledge.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcKnowledge.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcMessage.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcMessage.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcMessage.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcMessage.java index 3e1b2d7..0ba2510 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcMessage.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcModel.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcModel.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcModel.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcModel.java index c25b675..de79361 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/AigcModel.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcModel.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcOss.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcOss.java new file mode 100644 index 0000000..66551db --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/AigcOss.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @author tycoding + * @since 2024/1/6 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +public class AigcOss extends OssR { + private static final long serialVersionUID = -250127374910520163L; + + /** + * 主键 + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 用户ID + */ + private String userId; +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/OssR.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/OssR.java new file mode 100644 index 0000000..1ac1c64 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/OssR.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.entity; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * OSS 文件对象 + * + * @author tycoding + * @since 2024/1/30 + */ +@Data +@Accessors(chain = true) +public class OssR implements Serializable { + private static final long serialVersionUID = 5117927170776709434L; + + private String ossId; + private String url; + private Long size; + private String filename; + private String originalFilename; + private String basePath; + private String path; + private String ext; + private String contentType; + private String platform; + private Date createTime; +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysDept.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysDept.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysDept.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysDept.java index a1c1f69..5b8740a 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysDept.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysDept.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysRole.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysRole.java similarity index 95% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysRole.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysRole.java index 49a2b33..d136161 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysRole.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysRole.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysUser.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysUser.java similarity index 97% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysUser.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysUser.java index c358087..065e23b 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/SysUser.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/SysUser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/UserInfo.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/UserInfo.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/UserInfo.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/UserInfo.java index 1147538..5acf0c1 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/entity/UserInfo.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/entity/UserInfo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.entity; +package cn.iocoder.yudao.module.langchat.entity; import lombok.Data; import lombok.experimental.Accessors; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/package-info.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/package-info.java similarity index 57% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/package-info.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/package-info.java index a4c6968..182ad4d 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/package-info.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/package-info.java @@ -3,4 +3,4 @@ * * @author 芋道源码 */ -package cn.iocoder.yudao.module.langchat.server.framework; +package cn.iocoder.yudao.module.langchat.framework; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/ApiConstants.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/ApiConstants.java similarity index 86% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/ApiConstants.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/ApiConstants.java index 5b0d442..c33df65 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/ApiConstants.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/ApiConstants.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.langchat.server.framework.security; +package cn.iocoder.yudao.module.langchat.framework.security; import cn.iocoder.yudao.framework.common.enums.RpcConstants; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/config/SecurityConfiguration.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/config/SecurityConfiguration.java similarity index 91% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/config/SecurityConfiguration.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/config/SecurityConfiguration.java index 58445b8..d4ecb65 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/config/SecurityConfiguration.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.module.langchat.server.framework.security.config; +package cn.iocoder.yudao.module.langchat.framework.security.config; import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; -import cn.iocoder.yudao.module.langchat.server.framework.security.ApiConstants; +import cn.iocoder.yudao.module.langchat.framework.security.ApiConstants; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/core/package-info.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/core/package-info.java new file mode 100644 index 0000000..efe5cd9 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/framework/security/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.langchat.framework.security.core; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcConversationMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcConversationMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcConversationMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcConversationMapper.java index 2cc13be..516393a 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcConversationMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcConversationMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcConversation; +import cn.iocoder.yudao.module.langchat.entity.AigcConversation; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsMapper.java index beee89b..e7d0ad0 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsSliceMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsSliceMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsSliceMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsSliceMapper.java index 21550ad..9be517b 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcDocsSliceMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcDocsSliceMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcEmbedStoreMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcEmbedStoreMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcEmbedStoreMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcEmbedStoreMapper.java index 8ded639..d7e913c 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcEmbedStoreMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcEmbedStoreMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcKnowledgeMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcKnowledgeMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcKnowledgeMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcKnowledgeMapper.java index 8ef0ca7..ba8bfc4 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcKnowledgeMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcKnowledgeMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcKnowledge; +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcMessageMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcMessageMapper.java similarity index 96% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcMessageMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcMessageMapper.java index 0f851d6..1b3bb49 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcMessageMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcMessageMapper.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; import cn.hutool.core.lang.Dict; -import cn.iocoder.yudao.module.langchat.server.entity.AigcMessage; +import cn.iocoder.yudao.module.langchat.entity.AigcMessage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcModelMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcModelMapper.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcModelMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcModelMapper.java index c73e688..bbb6305 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/AigcModelMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcModelMapper.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcOssMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcOssMapper.java new file mode 100644 index 0000000..e21a1c9 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/AigcOssMapper.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.mapper; + +import cn.iocoder.yudao.module.langchat.entity.AigcOss; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author tycoding + * @since 2024/1/19 + */ +@Mapper +public interface AigcOssMapper extends BaseMapper { + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/SysUserMapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/SysUserMapper.java similarity index 88% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/SysUserMapper.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/SysUserMapper.java index 1dfa9e4..4bf4ee2 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/mapper/SysUserMapper.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/mapper/SysUserMapper.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.mapper; +package cn.iocoder.yudao.module.langchat.mapper; import cn.hutool.core.lang.Dict; -import cn.iocoder.yudao.module.langchat.server.entity.SysUser; -import cn.iocoder.yudao.module.langchat.server.entity.UserInfo; +import cn.iocoder.yudao.module.langchat.entity.SysUser; +import cn.iocoder.yudao.module.langchat.entity.UserInfo; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/properties/LangChatProps.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/properties/LangChatProps.java new file mode 100644 index 0000000..82d96c7 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/properties/LangChatProps.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author tycoding + * @since 2024/4/15 + */ +@Data +@Component +@ConfigurationProperties(prefix = "langchat") +public class LangChatProps { +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingProvider.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingProvider.java new file mode 100644 index 0000000..7c03110 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingProvider.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider; + +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; +import dev.langchain4j.data.document.DocumentSplitter; +import dev.langchain4j.data.document.splitter.DocumentSplitters; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.store.embedding.EmbeddingStore; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +/** + * @author tycoding + * @since 2024/3/8 + */ +@Slf4j +@Component +@AllArgsConstructor +public class EmbeddingProvider { + + private final EmbeddingStoreFactory embeddingStoreFactory; + private final KnowledgeStoreFactory knowledgeStoreFactory; + private final ModelStoreFactory modelStoreFactory; + + public static DocumentSplitter splitter() { + return DocumentSplitters.recursive(300, 20); + } + + public EmbeddingModel getEmbeddingModel(List knowledgeIds) { + List storeIds = new ArrayList<>(); + knowledgeIds.forEach(id -> { + if (knowledgeStoreFactory.containsKnowledge(id)) { + AigcKnowledge data = knowledgeStoreFactory.getKnowledge(id); + if (data.getEmbedModelId() != null) { + storeIds.add(data.getEmbedModelId()); + } + } + }); + if (storeIds.isEmpty()) { + throw new UnsupportedOperationException("知识库缺少Embedding Model配置,请先检查配置"); + } + + HashSet filterIds = new HashSet<>(storeIds); + if (filterIds.size() > 1) { + throw new UnsupportedOperationException("存在多个不同Embedding Model的知识库,请先检查配置"); + } + + return modelStoreFactory.getEmbeddingModel(storeIds.get(0)); + } + + public EmbeddingModel getEmbeddingModel(String knowledgeId) { + if (knowledgeStoreFactory.containsKnowledge(knowledgeId)) { + AigcKnowledge data = knowledgeStoreFactory.getKnowledge(knowledgeId); + if (modelStoreFactory.containsEmbeddingModel(data.getEmbedModelId())) { + return modelStoreFactory.getEmbeddingModel(data.getEmbedModelId()); + } + } + throw new UnsupportedOperationException("没有找到匹配的Embedding向量数据库"); + } + + public EmbeddingStore getEmbeddingStore(String knowledgeId) { + if (knowledgeStoreFactory.containsKnowledge(knowledgeId)) { + AigcKnowledge data = knowledgeStoreFactory.getKnowledge(knowledgeId); + if (embeddingStoreFactory.containsEmbeddingStore(data.getEmbedStoreId())) { + return embeddingStoreFactory.getEmbeddingStore(data.getEmbedStoreId()); + } + } + throw new UnsupportedOperationException("没有找到匹配的Embedding向量数据库"); + } + + public EmbeddingStore getEmbeddingStore(List knowledgeIds) { + List storeIds = new ArrayList<>(); + knowledgeIds.forEach(id -> { + if (knowledgeStoreFactory.containsKnowledge(id)) { + AigcKnowledge data = knowledgeStoreFactory.getKnowledge(id); + if (data.getEmbedStoreId() != null) { + storeIds.add(data.getEmbedStoreId()); + } + } + }); + if (storeIds.isEmpty()) { + throw new UnsupportedOperationException("知识库缺少Embedding Store配置,请先检查配置"); + } + + HashSet filterIds = new HashSet<>(storeIds); + if (filterIds.size() > 1) { + throw new UnsupportedOperationException("存在多个不同Embedding Store数据源的知识库,请先检查配置"); + } + + return embeddingStoreFactory.getEmbeddingStore(storeIds.get(0)); + } + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingStoreFactory.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingStoreFactory.java new file mode 100644 index 0000000..a8798ff --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/EmbeddingStoreFactory.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.langchat.enums.EmbedStoreEnum; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcEmbedStoreService; +import dev.langchain4j.community.store.embedding.redis.RedisEmbeddingStore; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.milvus.MilvusEmbeddingStore; +import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author tycoding + * @since 2024/10/28 + */ +@Slf4j +@Component +public class EmbeddingStoreFactory { + + @Autowired + private AigcEmbedStoreService aigcEmbedStoreService; + + private final List modelStore = new ArrayList<>(); + private final Map> embedStoreMap = new ConcurrentHashMap<>(); + + @Async + @PostConstruct + public void init() { + modelStore.clear(); + List list = aigcEmbedStoreService.list(); + list.forEach(embed -> { + try { + if (EmbedStoreEnum.REDIS.name().equalsIgnoreCase(embed.getProvider())) { + RedisEmbeddingStore.Builder builder = RedisEmbeddingStore.builder() + .host(embed.getHost()) + .port(embed.getPort()) + .indexName(embed.getDatabaseName()) + .dimension(embed.getDimension()); + if (StrUtil.isNotBlank(embed.getUsername()) && StrUtil.isNotBlank(embed.getPassword())) { + builder.user(embed.getUsername()).password(embed.getPassword()); + } + EmbeddingStore store = builder.build(); + embedStoreMap.put(embed.getId(), store); + } + if (EmbedStoreEnum.PGVECTOR.name().equalsIgnoreCase(embed.getProvider())) { + EmbeddingStore store = PgVectorEmbeddingStore.builder() + .host(embed.getHost()) + .port(embed.getPort()) + .database(embed.getDatabaseName()) + .dimension(embed.getDimension()) + .user(embed.getUsername()) + .password(embed.getPassword()) + .table(embed.getTableName()) + .indexListSize(1) + .useIndex(true) + .createTable(true) + .dropTableFirst(false) + .build(); + embedStoreMap.put(embed.getId(), store); + } + if (EmbedStoreEnum.MILVUS.name().equalsIgnoreCase(embed.getProvider())) { + EmbeddingStore store = MilvusEmbeddingStore.builder() + .host(embed.getHost()) + .port(embed.getPort()) + .databaseName(embed.getDatabaseName()) + .dimension(embed.getDimension()) + .username(embed.getUsername()) + .password(embed.getPassword()) + .collectionName(embed.getTableName()) + .build(); + embedStoreMap.put(embed.getId(), store); + } + modelStore.add(embed); + } catch (Exception e) { + e.printStackTrace(); + log.error("向量数据库初始化失败:[{}] --- [{}],数据库配置信息:[{}]", embed.getName(), embed.getProvider(), embed); + } + }); + + modelStore.forEach(i -> log.info("已成功注册Embedding Store:{}, 配置信息:{}", i.getProvider(), i)); + } + + public EmbeddingStore getEmbeddingStore(String embeddingId) { + return embedStoreMap.get(embeddingId); + } + + public boolean containsEmbeddingStore(String embeddingId) { + return embedStoreMap.containsKey(embeddingId); + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/provider/KnowledgeStoreFactory.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/KnowledgeStoreFactory.java similarity index 84% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/provider/KnowledgeStoreFactory.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/KnowledgeStoreFactory.java index 1ffd4b7..84ad893 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/provider/KnowledgeStoreFactory.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/KnowledgeStoreFactory.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.provider; +package cn.iocoder.yudao.module.langchat.provider; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; -import cn.iocoder.yudao.module.langchat.server.entity.AigcKnowledge; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; -import cn.iocoder.yudao.module.langchat.server.service.AigcEmbedStoreService; -import cn.iocoder.yudao.module.langchat.server.service.AigcKnowledgeService; -import cn.iocoder.yudao.module.langchat.server.service.AigcModelService; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcEmbedStoreService; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcKnowledgeService; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcModelService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/ModelStoreFactory.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/ModelStoreFactory.java new file mode 100644 index 0000000..07eeb60 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/ModelStoreFactory.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.langchat.enums.ModelConst; +import cn.iocoder.yudao.module.langchat.component.ModelTypeEnum; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.provider.build.ModelBuildHandler; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcModelService; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Async; + +import javax.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author tycoding + * @since 2024/6/16 + */ +@Configuration +@Slf4j +public class ModelStoreFactory { + + @Autowired + private AigcModelService aigcModelService; + @Autowired + private List modelBuildHandlers; + + private final List modelStore = new ArrayList<>(); + private final Map streamingChatMap = new ConcurrentHashMap<>(); + private final Map chatLanguageMap = new ConcurrentHashMap<>(); + private final Map embeddingModelMap = new ConcurrentHashMap<>(); + private final Map imageModelMap = new ConcurrentHashMap<>(); + + @Async + @PostConstruct + public void init() { + modelStore.clear(); + streamingChatMap.clear(); + chatLanguageMap.clear(); + embeddingModelMap.clear(); + imageModelMap.clear(); + + List list = aigcModelService.list(); + list.forEach(model -> { + if (Objects.equals(model.getBaseUrl(), "")) { + model.setBaseUrl(null); + } + + chatHandler(model); + embeddingHandler(model); + imageHandler(model); + }); + + modelStore.forEach(i -> log.info("已成功注册模型:{} -- {}, 模型配置:{}", i.getProvider(), i.getType(), i)); + } + + private void chatHandler(AigcModel model) { + try { + String type = model.getType(); + if (!ModelTypeEnum.CHAT.name().equals(type)) { + return; + } + modelBuildHandlers.forEach(x -> { + StreamingChatLanguageModel streamingChatLanguageModel = x.buildStreamingChat(model); + if (ObjectUtil.isNotEmpty(streamingChatLanguageModel)) { + streamingChatMap.put(model.getId(), streamingChatLanguageModel); + modelStore.add(model); + } + + ChatLanguageModel languageModel = x.buildChatLanguageModel(model); + if (ObjectUtil.isNotEmpty(languageModel)) { + chatLanguageMap.put(model.getId() + ModelConst.TEXT_SUFFIX, languageModel); + } + }); + } catch (Exception e) { + log.error("model 【 id: {} name: {}】streaming chat 配置报错", model.getId(), model.getName()); + } + } + + private void embeddingHandler(AigcModel model) { + try { + String type = model.getType(); + if (!ModelTypeEnum.EMBEDDING.name().equals(type)) { + return; + } + modelBuildHandlers.forEach(x -> { + EmbeddingModel embeddingModel = x.buildEmbedding(model); + if (ObjectUtil.isNotEmpty(embeddingModel)) { + embeddingModelMap.put(model.getId(), embeddingModel); + modelStore.add(model); + } + }); + + } catch (Exception e) { + log.error("model 【id{} name{}】 embedding 配置报错", model.getId(), model.getName()); + } + } + + private void imageHandler(AigcModel model) { + try { + String type = model.getType(); + if (!ModelTypeEnum.TEXT_IMAGE.name().equals(type)) { + return; + } + modelBuildHandlers.forEach(x -> { + ImageModel imageModel = x.buildImage(model); + if (ObjectUtil.isNotEmpty(imageModel)) { + imageModelMap.put(model.getId(), imageModel); + modelStore.add(model); + } + }); + } catch (Exception e) { + log.error("model 【id{} name{}】 image 配置报错", model.getId(), model.getName()); + } + } + + public StreamingChatLanguageModel getStreamingChatModel(String modelId) { + return streamingChatMap.get(modelId); + } + + public boolean containsStreamingChatModel(String modelId) { + return streamingChatMap.containsKey(modelId); + } + + public ChatLanguageModel getChatLanguageModel(String modelId) { + return chatLanguageMap.get(modelId + ModelConst.TEXT_SUFFIX); + } + + public boolean containsChatLanguageModel(String modelId) { + return chatLanguageMap.containsKey(modelId + ModelConst.TEXT_SUFFIX); + } + + public EmbeddingModel getEmbeddingModel(String modelId) { + return embeddingModelMap.get(modelId); + } + + public boolean containsEmbeddingModel(String modelId) { + return embeddingModelMap.containsKey(modelId); + } + + public ImageModel getImageModel(String modelId) { + return imageModelMap.get(modelId); + } + + public boolean containsImageModel(String modelId) { + return imageModelMap.containsKey(modelId); + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ModelBuildHandler.java new file mode 100644 index 0000000..6501015 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ModelBuildHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import org.springframework.stereotype.Component; + +/** + * @author GB + * @since 2024-08-18 09:57 + */ +public interface ModelBuildHandler { + + /** + * 判断是不是当前模型 + */ + boolean whetherCurrentModel(AigcModel model); + + /** + * basic check + */ + boolean basicCheck(AigcModel model); + + /** + * streaming chat build + */ + StreamingChatLanguageModel buildStreamingChat(AigcModel model); + + /** + * chat build + */ + ChatLanguageModel buildChatLanguageModel(AigcModel model); + + /** + * embedding config + */ + EmbeddingModel buildEmbedding(AigcModel model); + + /** + * image config + */ + ImageModel buildImage(AigcModel model); + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OllamaModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OllamaModelBuildHandler.java new file mode 100644 index 0000000..cd17a7c --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OllamaModelBuildHandler.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.enums.ChatErrorEnum; +import cn.iocoder.yudao.module.langchat.enums.ProviderEnum; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import dev.langchain4j.model.ollama.OllamaChatModel; +import dev.langchain4j.model.ollama.OllamaEmbeddingModel; +import dev.langchain4j.model.ollama.OllamaStreamingChatModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +/** + * @author GB + * @since 2024-08-19 10:08 + */ +@Slf4j +@Component +public class OllamaModelBuildHandler implements ModelBuildHandler { + + @Override + public boolean whetherCurrentModel(AigcModel model) { + return ProviderEnum.OLLAMA.name().equals(model.getProvider()); + } + + @Override + public boolean basicCheck(AigcModel model) { + if (StringUtils.isBlank(model.getBaseUrl())) { + throw new ServiceException(ChatErrorEnum.BASE_URL_IS_NULL.getErrorCode(), + ChatErrorEnum.BASE_URL_IS_NULL.getErrorDesc(ProviderEnum.OLLAMA.name(), model.getType())); + } + return true; + } + + @Override + public StreamingChatLanguageModel buildStreamingChat(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OllamaStreamingChatModel + .builder() + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Ollama streaming chat 配置报错", e); + return null; + } + } + + @Override + public ChatLanguageModel buildChatLanguageModel(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OllamaChatModel + .builder() + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Ollama chat 配置报错", e); + return null; + } + } + + @Override + public EmbeddingModel buildEmbedding(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OllamaEmbeddingModel + .builder() + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .logRequests(true) + .logResponses(true) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Ollama embedding 配置报错", e); + return null; + } + } + + @Override + public ImageModel buildImage(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return null; + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Ollama image 配置报错", e); + return null; + } + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OpenAIModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OpenAIModelBuildHandler.java new file mode 100644 index 0000000..3a293ec --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/OpenAIModelBuildHandler.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.enums.ChatErrorEnum; +import cn.iocoder.yudao.module.langchat.enums.ProviderEnum; +import cn.iocoder.yudao.module.langchat.properties.LangChatProps; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import dev.langchain4j.model.openai.OpenAiChatModel; +import dev.langchain4j.model.openai.OpenAiEmbeddingModel; +import dev.langchain4j.model.openai.OpenAiImageModel; +import dev.langchain4j.model.openai.OpenAiStreamingChatModel; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +/** + * @author tycoding + * @since 2024-08-19 10:08 + */ +@Slf4j +@Component +@AllArgsConstructor +public class OpenAIModelBuildHandler implements ModelBuildHandler { + + private final LangChatProps props; + + /** + * 合并处理支持OpenAI接口的模型 + */ + @Override + public boolean whetherCurrentModel(AigcModel model) { + String provider = model.getProvider(); + return ProviderEnum.OPENAI.name().equals(provider) || + ProviderEnum.GEMINI.name().equals(provider) || + ProviderEnum.CLAUDE.name().equals(provider) || + ProviderEnum.AZURE_OPENAI.name().equals(provider) || + ProviderEnum.DOUYIN.name().equals(provider) || + ProviderEnum.YI.name().equals(provider) || + ProviderEnum.SILICON.name().equals(provider) || + ProviderEnum.DEEPSEEK.name().equals(provider) || + ProviderEnum.SPARK.name().equals(provider) + ; + } + + @Override + public boolean basicCheck(AigcModel model) { + String apiKey = model.getApiKey(); + if (StrUtil.isBlank(apiKey)) { + throw new ServiceException(ChatErrorEnum.API_KEY_IS_NULL.getErrorCode(), + ChatErrorEnum.API_KEY_IS_NULL.getErrorDesc(model.getProvider().toUpperCase(), model.getType())); + } + return true; + } + + @Override + public StreamingChatLanguageModel buildStreamingChat(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OpenAiStreamingChatModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .maxTokens(model.getResponseLimit()) + .temperature(model.getTemperature()) + .logRequests(true) + .logResponses(true) + .topP(model.getTopP()) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error(model.getProvider() + " Streaming Chat 模型配置报错", e); + return null; + } + } + + @Override + public ChatLanguageModel buildChatLanguageModel(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OpenAiChatModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .maxTokens(model.getResponseLimit()) + .temperature(model.getTemperature()) + .logRequests(true) + .logResponses(true) + .topP(model.getTopP()) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error(model.getProvider() + " Chat 模型配置报错", e); + return null; + } + } + + @Override + public EmbeddingModel buildEmbedding(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + OpenAiEmbeddingModel openAiEmbeddingModel = OpenAiEmbeddingModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .dimensions(model.getDimension()) + .logRequests(true) + .logResponses(true) + .dimensions(1024) + .timeout(Duration.ofMinutes(10)) + .build(); + return openAiEmbeddingModel; + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error(model.getProvider() + " Embedding 模型配置报错", e); + return null; + } + } + + @Override + public ImageModel buildImage(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return OpenAiImageModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .modelName(model.getModel()) + .size(model.getImageSize()) + .quality(model.getImageQuality()) + .style(model.getImageStyle()) + .logRequests(true) + .logResponses(true) + .timeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error(model.getProvider() + " Image 模型配置报错", e); + return null; + } + + + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QFanModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QFanModelBuildHandler.java new file mode 100644 index 0000000..81cbade --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QFanModelBuildHandler.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.enums.ChatErrorEnum; +import cn.iocoder.yudao.module.langchat.enums.ProviderEnum; +import dev.langchain4j.community.model.qianfan.QianfanChatModel; +import dev.langchain4j.community.model.qianfan.QianfanEmbeddingModel; +import dev.langchain4j.community.model.qianfan.QianfanStreamingChatModel; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +/** + * @author GB + * @since 2024-08-19 10:08 + */ +@Slf4j +@Component +public class QFanModelBuildHandler implements ModelBuildHandler { + + @Override + public boolean whetherCurrentModel(AigcModel model) { + return ProviderEnum.Q_FAN.name().equals(model.getProvider()); + } + + @Override + public boolean basicCheck(AigcModel model) { + if (StringUtils.isBlank(model.getApiKey())) { + throw new ServiceException(ChatErrorEnum.API_KEY_IS_NULL.getErrorCode(), + ChatErrorEnum.API_KEY_IS_NULL.getErrorDesc(ProviderEnum.Q_FAN.name(), model.getType())); + } + if (StringUtils.isBlank(model.getSecretKey())) { + throw new ServiceException(ChatErrorEnum.SECRET_KEY_IS_NULL.getErrorCode(), + ChatErrorEnum.SECRET_KEY_IS_NULL.getErrorDesc(ProviderEnum.Q_FAN.name(), model.getType())); + } + return true; + } + + @Override + public StreamingChatLanguageModel buildStreamingChat(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return QianfanStreamingChatModel + .builder() + .apiKey(model.getApiKey()) + .secretKey(model.getSecretKey()) + .modelName(model.getModel()) + .baseUrl(model.getBaseUrl()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Qianfan streaming chat 配置报错", e); + return null; + } + } + + @Override + public ChatLanguageModel buildChatLanguageModel(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return QianfanChatModel + .builder() + .apiKey(model.getApiKey()) + .secretKey(model.getSecretKey()) + .modelName(model.getModel()) + .baseUrl(model.getBaseUrl()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Qianfan chat 配置报错", e); + return null; + } + + + } + + @Override + public EmbeddingModel buildEmbedding(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return QianfanEmbeddingModel + .builder() + .apiKey(model.getApiKey()) + .modelName(model.getModel()) + .secretKey(model.getSecretKey()) + .logRequests(true) + .logResponses(true) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Qianfan embedding 配置报错", e); + return null; + } + } + + @Override + public ImageModel buildImage(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return null; + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("Qianfan image 配置报错", e); + return null; + } + + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QWenModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QWenModelBuildHandler.java new file mode 100644 index 0000000..038720e --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/QWenModelBuildHandler.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.enums.ChatErrorEnum; +import cn.iocoder.yudao.module.langchat.enums.ProviderEnum; +import dev.langchain4j.community.model.dashscope.QwenChatModel; +import dev.langchain4j.community.model.dashscope.QwenEmbeddingModel; +import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +/** + * @author GB + * @since 2024-08-19 10:08 + */ +@Slf4j +@Component +public class QWenModelBuildHandler implements ModelBuildHandler { + + @Override + public boolean whetherCurrentModel(AigcModel model) { + return ProviderEnum.Q_WEN.name().equals(model.getProvider()); + } + + @Override + public boolean basicCheck(AigcModel model) { + if (StringUtils.isBlank(model.getApiKey())) { + throw new ServiceException(ChatErrorEnum.API_KEY_IS_NULL.getErrorCode(), + ChatErrorEnum.API_KEY_IS_NULL.getErrorDesc(ProviderEnum.Q_WEN.name(), model.getType())); + } + return true; + } + + @Override + public StreamingChatLanguageModel buildStreamingChat(AigcModel model) { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + try { + return QwenStreamingChatModel + .builder() + .apiKey(model.getApiKey()) + .modelName(model.getModel()) + .baseUrl(model.getBaseUrl()) + .maxTokens(model.getResponseLimit()) + .temperature(Float.parseFloat(model.getTemperature().toString())) + .topP(model.getTopP()) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("qian wen streaming chat 配置报错", e); + return null; + } + } + + @Override + public ChatLanguageModel buildChatLanguageModel(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return QwenChatModel + .builder() + .apiKey(model.getApiKey()) + .modelName(model.getModel()) + .baseUrl(model.getBaseUrl()) + .enableSearch(true) + .maxTokens(model.getResponseLimit()) + .temperature(Float.parseFloat(model.getTemperature().toString())) + .topP(model.getTopP()) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("qian wen chat 配置报错", e); + return null; + } + } + + @Override + public EmbeddingModel buildEmbedding(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return QwenEmbeddingModel + .builder() + .apiKey(model.getApiKey()) + .modelName(model.getModel()) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("qian wen embedding 配置报错", e); + return null; + } + } + + @Override + public ImageModel buildImage(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return null; + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("qian wen image 配置报错", e); + return null; + } + + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ZhipuModelBuildHandler.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ZhipuModelBuildHandler.java new file mode 100644 index 0000000..e98b8ab --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/provider/build/ZhipuModelBuildHandler.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.provider.build; + +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.enums.ChatErrorEnum; +import cn.iocoder.yudao.module.langchat.enums.ProviderEnum; +import cn.iocoder.yudao.module.langchat.properties.LangChatProps; +import dev.langchain4j.community.model.zhipu.ZhipuAiChatModel; +import dev.langchain4j.community.model.zhipu.ZhipuAiEmbeddingModel; +import dev.langchain4j.community.model.zhipu.ZhipuAiImageModel; +import dev.langchain4j.community.model.zhipu.ZhipuAiStreamingChatModel; +import dev.langchain4j.model.chat.ChatLanguageModel; +import dev.langchain4j.model.chat.StreamingChatLanguageModel; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.model.image.ImageModel; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +/** + * @author GB + * @since 2024-08-19 + */ +@Slf4j +@Component +@AllArgsConstructor +public class ZhipuModelBuildHandler implements ModelBuildHandler { + + private final LangChatProps props; + + @Override + public boolean whetherCurrentModel(AigcModel model) { + return ProviderEnum.ZHIPU.name().equals(model.getProvider()); + } + + @Override + public boolean basicCheck(AigcModel model) { + if (StringUtils.isBlank(model.getApiKey())) { + throw new ServiceException(ChatErrorEnum.API_KEY_IS_NULL.getErrorCode(), + ChatErrorEnum.API_KEY_IS_NULL.getErrorDesc(ProviderEnum.ZHIPU.name(), model.getType())); + } + return true; + } + + @Override + public StreamingChatLanguageModel buildStreamingChat(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return ZhipuAiStreamingChatModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .model(model.getModel()) + .maxToken(model.getResponseLimit()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .callTimeout(Duration.ofMinutes(10)) + .connectTimeout(Duration.ofMinutes(10)) + .writeTimeout(Duration.ofMinutes(10)) + .readTimeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("zhipu streaming chat 配置报错", e); + return null; + } + + } + + @Override + public ChatLanguageModel buildChatLanguageModel(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return ZhipuAiChatModel + .builder() + .apiKey(model.getApiKey()) + .baseUrl(model.getBaseUrl()) + .model(model.getModel()) + .maxToken(model.getResponseLimit()) + .temperature(model.getTemperature()) + .topP(model.getTopP()) + .logRequests(true) + .logResponses(true) + .callTimeout(Duration.ofMinutes(10)) + .connectTimeout(Duration.ofMinutes(10)) + .writeTimeout(Duration.ofMinutes(10)) + .readTimeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("zhipu chat 配置报错", e); + return null; + } + + } + + @Override + public EmbeddingModel buildEmbedding(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return ZhipuAiEmbeddingModel + .builder() + .apiKey(model.getApiKey()) + .model(model.getModel()) + .baseUrl(model.getBaseUrl()) + .logRequests(true) + .logResponses(true) + .callTimeout(Duration.ofMinutes(10)) + .connectTimeout(Duration.ofMinutes(10)) + .writeTimeout(Duration.ofMinutes(10)) + .readTimeout(Duration.ofMinutes(10)) + .dimensions(1024) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("zhipu embedding 配置报错", e); + return null; + } + } + + @Override + public ImageModel buildImage(AigcModel model) { + try { + if (!whetherCurrentModel(model)) { + return null; + } + if (!basicCheck(model)) { + return null; + } + return ZhipuAiImageModel + .builder() + .apiKey(model.getApiKey()) + .model(model.getModel()) + .baseUrl(model.getBaseUrl()) + .logRequests(true) + .logResponses(true) + .callTimeout(Duration.ofMinutes(10)) + .connectTimeout(Duration.ofMinutes(10)) + .writeTimeout(Duration.ofMinutes(10)) + .readTimeout(Duration.ofMinutes(10)) + .build(); + } catch (ServiceException e) { + log.error(e.getMessage()); + throw e; + } catch (Exception e) { + log.error("zhipu image 配置报错", e); + return null; + } + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/core/package-info.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/core/package-info.java deleted file mode 100644 index fc863b8..0000000 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/framework/security/core/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.module.langchat.server.framework.security.core; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/R.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/R.java deleted file mode 100644 index 6bcaf7d..0000000 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/R.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. - * - * Licensed under the GNU Affero General Public License, Version 3 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.gnu.org/licenses/agpl-3.0.html - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package cn.iocoder.yudao.module.langchat.server.utils; - -import lombok.Data; -import org.springframework.http.HttpStatus; - -import java.io.Serializable; - -/** - * @author tycoding - * @since 2024/1/2 - */ -@Data -public class R implements Serializable { - - private static final long serialVersionUID = 1L; - - private int code = HttpStatus.OK.value(); - - private String message = HttpStatus.OK.getReasonPhrase(); - - private T result; - - public R() { - super(); - } - - public R(int code, String message) { - this.code = code; - this.message = message; - } - - protected R(T result) { - this.result = result; - } - - protected R(HttpStatus httpStatus) { - this.code = httpStatus.value(); - this.message = httpStatus.getReasonPhrase(); - } - - protected R(T result, HttpStatus httpStatus) { - this.result = result; - this.code = httpStatus.value(); - this.message = httpStatus.getReasonPhrase(); - } - - protected R(Throwable e) { - super(); - this.code = HttpStatus.INTERNAL_SERVER_ERROR.value(); - this.message = e.getMessage(); - } - - public static R ok(T result) { - return new R(result); - } - - public static R ok(T result, HttpStatus httpStatus) { - return new R(result, httpStatus); - } - - public static R ok() { - return new R<>(); - } - - public static R ok(String message) { - return new R<>(HttpStatus.OK.value(), message); - } - - public static R ok(HttpStatus httpStatus) { - return new R<>(httpStatus); - } - - public static R fail(String message) { - return new R<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), message); - } - - public static R fail(int code, String message) { - return new R<>(code, message); - } - - public static R fail(HttpStatus status) { - return new R<>(status.value(), status.getReasonPhrase()); - } - - public static R fail(Throwable e) { - return new R<>(e); - } -} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcEmbedStoreService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcEmbedStoreService.java similarity index 86% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcEmbedStoreService.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcEmbedStoreService.java index 2ded47a..d946413 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcEmbedStoreService.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcEmbedStoreService.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service; +package cn.iocoder.yudao.module.langchat.service.aigc; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; import com.baomidou.mybatisplus.extension.service.IService; /** diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcKnowledgeService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcKnowledgeService.java similarity index 82% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcKnowledgeService.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcKnowledgeService.java index 30147b5..40a6647 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcKnowledgeService.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcKnowledgeService.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service; +package cn.iocoder.yudao.module.langchat.service.aigc; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocs; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocsSlice; -import cn.iocoder.yudao.module.langchat.server.entity.AigcKnowledge; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcMessageService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcMessageService.java similarity index 86% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcMessageService.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcMessageService.java index e42251f..e9a37f3 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcMessageService.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcMessageService.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service; +package cn.iocoder.yudao.module.langchat.service.aigc; -import cn.iocoder.yudao.module.langchat.server.entity.AigcConversation; -import cn.iocoder.yudao.module.langchat.server.entity.AigcMessage; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.module.langchat.entity.AigcConversation; +import cn.iocoder.yudao.module.langchat.entity.AigcMessage; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcModelService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcModelService.java similarity index 86% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcModelService.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcModelService.java index e21480e..1bd4100 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/AigcModelService.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcModelService.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service; +package cn.iocoder.yudao.module.langchat.service.aigc; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcOssService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcOssService.java new file mode 100644 index 0000000..a323015 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/AigcOssService.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.aigc; + +import cn.iocoder.yudao.module.langchat.entity.AigcOss; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author tycoding + * @since 2024/1/4 + */ +public interface AigcOssService extends IService { + + AigcOss upload(MultipartFile file, String userId); +} + diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcEmbedStoreServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcEmbedStoreServiceImpl.java similarity index 76% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcEmbedStoreServiceImpl.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcEmbedStoreServiceImpl.java index 4ff3c32..0b910f5 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcEmbedStoreServiceImpl.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcEmbedStoreServiceImpl.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service.impl; +package cn.iocoder.yudao.module.langchat.service.aigc.impl; -import cn.iocoder.yudao.module.langchat.server.entity.AigcEmbedStore; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcEmbedStoreMapper; -import cn.iocoder.yudao.module.langchat.server.service.AigcEmbedStoreService; +import cn.iocoder.yudao.module.langchat.entity.AigcEmbedStore; +import cn.iocoder.yudao.module.langchat.mapper.AigcEmbedStoreMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcEmbedStoreService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcKnowledgeServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcKnowledgeServiceImpl.java similarity index 86% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcKnowledgeServiceImpl.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcKnowledgeServiceImpl.java index c2d4484..af6ddef 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcKnowledgeServiceImpl.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcKnowledgeServiceImpl.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service.impl; +package cn.iocoder.yudao.module.langchat.service.aigc.impl; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocs; -import cn.iocoder.yudao.module.langchat.server.entity.AigcDocsSlice; -import cn.iocoder.yudao.module.langchat.server.entity.AigcKnowledge; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcDocsMapper; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcDocsSliceMapper; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcKnowledgeMapper; -import cn.iocoder.yudao.module.langchat.server.service.AigcKnowledgeService; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.entity.AigcKnowledge; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsMapper; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsSliceMapper; +import cn.iocoder.yudao.module.langchat.mapper.AigcKnowledgeMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcKnowledgeService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcMessageServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcMessageServiceImpl.java similarity index 89% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcMessageServiceImpl.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcMessageServiceImpl.java index 337e427..c27b829 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcMessageServiceImpl.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcMessageServiceImpl.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service.impl; +package cn.iocoder.yudao.module.langchat.service.aigc.impl; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.entity.AigcConversation; -import cn.iocoder.yudao.module.langchat.server.entity.AigcMessage; -import cn.iocoder.yudao.module.langchat.server.entity.SysUser; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcConversationMapper; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcMessageMapper; -import cn.iocoder.yudao.module.langchat.server.mapper.SysUserMapper; -import cn.iocoder.yudao.module.langchat.server.service.AigcMessageService; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.module.langchat.entity.AigcConversation; +import cn.iocoder.yudao.module.langchat.entity.AigcMessage; +import cn.iocoder.yudao.module.langchat.entity.SysUser; +import cn.iocoder.yudao.module.langchat.mapper.AigcConversationMapper; +import cn.iocoder.yudao.module.langchat.mapper.AigcMessageMapper; +import cn.iocoder.yudao.module.langchat.mapper.SysUserMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcMessageService; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -60,7 +60,7 @@ public class AigcMessageServiceImpl extends ServiceImpl conversationPages(AigcConversation data, QueryPage queryPage) { - Page page = new Page<>(queryPage.getPage(), queryPage.getLimit()); + Page page = new Page<>(queryPage.getPageNo(), queryPage.getPageSize()); Page iPage = aigcConversationMapper.selectPage(page, Wrappers.lambdaQuery() .like(!StrUtil.isBlank(data.getTitle()), AigcConversation::getTitle, data.getTitle()) .orderByDesc(AigcConversation::getCreateTime)); diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcModelServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcModelServiceImpl.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcModelServiceImpl.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcModelServiceImpl.java index 41cfe11..4278f3f 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/service/impl/AigcModelServiceImpl.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcModelServiceImpl.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.service.impl; +package cn.iocoder.yudao.module.langchat.service.aigc.impl; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.langchat.server.component.ModelTypeEnum; -import cn.iocoder.yudao.module.langchat.server.entity.AigcModel; -import cn.iocoder.yudao.module.langchat.server.mapper.AigcModelMapper; -import cn.iocoder.yudao.module.langchat.server.service.AigcModelService; -import cn.iocoder.yudao.module.langchat.server.utils.QueryPage; +import cn.iocoder.yudao.module.langchat.component.ModelTypeEnum; +import cn.iocoder.yudao.module.langchat.entity.AigcModel; +import cn.iocoder.yudao.module.langchat.mapper.AigcModelMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcModelService; +import cn.iocoder.yudao.module.langchat.utils.QueryPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -73,7 +73,7 @@ public class AigcModelServiceImpl extends ServiceImpl page(AigcModel data, QueryPage queryPage) { - Page page = new Page<>(queryPage.getPage(), queryPage.getLimit()); + Page page = new Page<>(queryPage.getPageNo(), queryPage.getPageSize()); Page iPage = this.page(page, Wrappers.lambdaQuery().eq(AigcModel::getProvider, data.getProvider())); iPage.getRecords().forEach(this::hide); return iPage; diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcOssServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcOssServiceImpl.java new file mode 100644 index 0000000..49ae40b --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/aigc/impl/AigcOssServiceImpl.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.oss.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.langchat.entity.AigcOss; +import cn.iocoder.yudao.module.langchat.mapper.AigcOssMapper; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcOssService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.x.file.storage.core.FileInfo; +import org.dromara.x.file.storage.core.FileStorageService; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Date; + +/** + * @author tycoding + * @since 2024/1/4 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class AigcOssServiceImpl extends ServiceImpl implements AigcOssService { + + private final FileStorageService fileStorageService; + + @Override + public AigcOss upload(MultipartFile file, String userId) { + log.info(">>>>>>>>>>>>>> OSS文件上传开始: {}", file.getOriginalFilename()); + FileInfo info = fileStorageService.of(file) + .setPath(DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN)) + .upload(); + log.info(">>>>>>>>>>>>>> OSS文件上传结束: {} - {}", info.getFilename(), info.getUrl()); + AigcOss oss = BeanUtil.copyProperties(info, AigcOss.class); + oss.setOssId(info.getId()); + oss.setUserId(userId); + this.save(oss); + return oss; + } +} + diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/EmbeddingService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/EmbeddingService.java new file mode 100644 index 0000000..092be3d --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/EmbeddingService.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.core; + + +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; + +import java.util.List; +import java.util.Map; + +/** + * @author tycoding + * @since 2024/6/6 + */ +public interface EmbeddingService { + + void clearDocSlices(String docsId); + + void embedDocsSlice(AigcDocs data, String url); + + List> search(AigcDocs data); +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/LangEmbeddingService.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/LangEmbeddingService.java new file mode 100644 index 0000000..865fb48 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/LangEmbeddingService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.core; + + +import cn.iocoder.yudao.module.langchat.dal.dto.ChatReq; +import cn.iocoder.yudao.module.langchat.dal.dto.EmbeddingR; + +import java.util.List; + +/** + * @author tycoding + * @since 2024/4/4 + */ +public interface LangEmbeddingService { + + EmbeddingR embeddingText(ChatReq req); + + List embeddingDocs(ChatReq req); +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/EmbeddingServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/EmbeddingServiceImpl.java new file mode 100644 index 0000000..485a3df --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/EmbeddingServiceImpl.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.core.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.langchat.dal.dto.ChatReq; +import cn.iocoder.yudao.module.langchat.dal.dto.EmbeddingR; +import cn.iocoder.yudao.module.langchat.enums.EmbedConst; +import cn.iocoder.yudao.module.langchat.entity.AigcDocs; +import cn.iocoder.yudao.module.langchat.entity.AigcDocsSlice; +import cn.iocoder.yudao.module.langchat.mapper.AigcDocsMapper; +import cn.iocoder.yudao.module.langchat.provider.EmbeddingProvider; +import cn.iocoder.yudao.module.langchat.service.aigc.AigcKnowledgeService; +import cn.iocoder.yudao.module.langchat.service.core.EmbeddingService; +import cn.iocoder.yudao.module.langchat.service.core.LangEmbeddingService; +import dev.langchain4j.data.embedding.Embedding; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.store.embedding.EmbeddingSearchRequest; +import dev.langchain4j.store.embedding.EmbeddingSearchResult; +import dev.langchain4j.store.embedding.EmbeddingStore; +import dev.langchain4j.store.embedding.filter.Filter; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey; + + +/** + * @author tycoding + * @since 2024/6/6 + */ +@Slf4j +@Service +@AllArgsConstructor +public class EmbeddingServiceImpl implements EmbeddingService { + + private final EmbeddingProvider embeddingProvider; + private final LangEmbeddingService langEmbeddingService; + private final AigcKnowledgeService aigcKnowledgeService; + private final AigcDocsMapper aigcDocsMapper; + + @Override + @Transactional + public void clearDocSlices(String docsId) { + if (StrUtil.isBlank(docsId)) { + return; + } + // remove from embedding store + List vectorIds = aigcKnowledgeService.listSliceVectorIdsOfDoc(docsId); + if (vectorIds.isEmpty()) { + return; + } + AigcDocs docs = aigcDocsMapper.selectById(docsId); + EmbeddingStore embeddingStore = embeddingProvider.getEmbeddingStore(docs.getKnowledgeId()); + embeddingStore.removeAll(vectorIds); + // remove from docSlice + aigcKnowledgeService.removeSlicesOfDoc(docsId); + } + + @Override + public void embedDocsSlice(AigcDocs data, String url) { + List list = langEmbeddingService.embeddingDocs( + new ChatReq() + .setDocsName(data.getName()) + .setKnowledgeId(data.getKnowledgeId()) + .setUrl(url)); + list.forEach(i -> { + aigcKnowledgeService.addDocsSlice(new AigcDocsSlice() + .setKnowledgeId(data.getKnowledgeId()) + .setDocsId(data.getId()) + .setVectorId(i.getVectorId()) + .setName(data.getName()) + .setContent(i.getText()) + ); + }); + + aigcKnowledgeService.updateDocs(new AigcDocs().setId(data.getId()).setSliceStatus(true).setSliceNum(list.size())); + } + + @Override + public List> search(AigcDocs data) { + if (StrUtil.isBlank(data.getKnowledgeId()) || StrUtil.isBlank(data.getContent())) { + return List.of(); + } + + EmbeddingModel embeddingModel = embeddingProvider.getEmbeddingModel(data.getKnowledgeId()); + EmbeddingStore embeddingStore = embeddingProvider.getEmbeddingStore(data.getKnowledgeId()); + Embedding queryEmbedding = embeddingModel.embed(data.getContent()).content(); + Filter filter = metadataKey(EmbedConst.KNOWLEDGE).isEqualTo(data.getKnowledgeId()); + EmbeddingSearchResult list = embeddingStore.search(EmbeddingSearchRequest + .builder() + .queryEmbedding(queryEmbedding) + .filter(filter) + .build()); + + List> result = new ArrayList<>(); + list.matches().forEach(i -> { + TextSegment embedded = i.embedded(); + Map map = embedded.metadata().toMap(); + map.put("text", embedded.text()); + result.add(map); + }); + return result; + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/LangEmbeddingServiceImpl.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/LangEmbeddingServiceImpl.java new file mode 100644 index 0000000..af38eb8 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/service/core/impl/LangEmbeddingServiceImpl.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.service.core.impl; + +import cn.iocoder.yudao.module.langchat.dal.dto.ChatReq; +import cn.iocoder.yudao.module.langchat.dal.dto.EmbeddingR; +import cn.iocoder.yudao.module.langchat.enums.EmbedConst; +import cn.iocoder.yudao.module.langchat.provider.EmbeddingProvider; +import cn.iocoder.yudao.module.langchat.service.core.LangEmbeddingService; +import dev.langchain4j.data.document.Document; +import dev.langchain4j.data.document.DocumentSplitter; +import dev.langchain4j.data.document.Metadata; +import dev.langchain4j.data.document.loader.UrlDocumentLoader; + +import dev.langchain4j.data.document.parser.apache.tika.ApacheTikaDocumentParser; +import dev.langchain4j.data.embedding.Embedding; +import dev.langchain4j.data.segment.TextSegment; +import dev.langchain4j.model.embedding.EmbeddingModel; +import dev.langchain4j.store.embedding.EmbeddingStore; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author tycoding + * @since 2024/4/4 + */ +@Slf4j +@Service +@AllArgsConstructor +public class LangEmbeddingServiceImpl implements LangEmbeddingService { + + private final EmbeddingProvider embeddingProvider; + + @Override + public EmbeddingR embeddingText(ChatReq req) { + log.info(">>>>>>>>>>>>>> Text文本向量解析开始,KnowledgeId={}, DocsName={}", req.getKnowledgeId(), req.getDocsName()); + TextSegment segment = TextSegment.from(req.getMessage(), + Metadata.metadata(EmbedConst.KNOWLEDGE, req.getKnowledgeId()).put(EmbedConst.FILENAME, req.getDocsName())); + + EmbeddingModel embeddingModel = embeddingProvider.getEmbeddingModel(req.getKnowledgeId()); + EmbeddingStore embeddingStore = embeddingProvider.getEmbeddingStore(req.getKnowledgeId()); + Embedding embedding = embeddingModel.embed(segment).content(); + String id = embeddingStore.add(embedding, segment); + + log.info(">>>>>>>>>>>>>> Text文本向量解析结束,KnowledgeId={}, DocsName={}", req.getKnowledgeId(), req.getDocsName()); + return new EmbeddingR().setVectorId(id).setText(segment.text()); + } + + @Override + public List embeddingDocs(ChatReq req) { + log.info(">>>>>>>>>>>>>> Docs文档向量解析开始,KnowledgeId={}, DocsName={}", req.getKnowledgeId(), req.getDocsName()); + Document document = UrlDocumentLoader.load(req.getUrl(), new ApacheTikaDocumentParser()); + document.metadata().put(EmbedConst.KNOWLEDGE, req.getKnowledgeId()).put(EmbedConst.FILENAME, req.getDocsName()); + + List list = new ArrayList<>(); + try { + DocumentSplitter splitter = EmbeddingProvider.splitter(); + List segments = splitter.split(document); + + EmbeddingModel embeddingModel = embeddingProvider.getEmbeddingModel(req.getKnowledgeId()); + EmbeddingStore embeddingStore = embeddingProvider.getEmbeddingStore(req.getKnowledgeId()); + List embeddings = embeddingModel.embedAll(segments).content(); + List ids = embeddingStore.addAll(embeddings, segments); + + for (int i = 0; i < ids.size(); i++) { + list.add(new EmbeddingR().setVectorId(ids.get(i)).setText(segments.get(i).text())); + } + } catch (Exception e) { + e.printStackTrace(); + } + + log.info(">>>>>>>>>>>>>> Docs文档向量解析结束,KnowledgeId={}, DocsName={}", req.getKnowledgeId(), req.getDocsName()); + return list; + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/AnalysisThreadPool.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/AnalysisThreadPool.java new file mode 100644 index 0000000..bac8074 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/AnalysisThreadPool.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.task; + +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author GB + * @since 2024-08-22 + */ +public class AnalysisThreadPool { + /** + * 根据cpu 数量动态配置核心线程数和最大线程数 + */ + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); + /** + * 核心线程数 + */ + private static final int CORE_PO0L_SIZE = CPU_COUNT + 1; + /** + * 最大线程数 + */ + private static final int MAX_POOL_SIZE = 2 * CPU_COUNT + 1; + /** + * 线程队列 + */ + private static final int MAX_LIMIT_JOB_SIZE = 1000; + /** + * 非核心线程存活时间1s + */ + private static final int KEEP_ALIVE = 1; + volatile private static ThreadPoolExecutor EXECUTOR = null; + + public static ThreadPoolExecutor getThreadPool() { + if (null == EXECUTOR) { + synchronized (AnalysisThreadPool.class) { + if (null == EXECUTOR) { + EXECUTOR = new ThreadPoolExecutor( + CORE_PO0L_SIZE, + MAX_POOL_SIZE, + KEEP_ALIVE, + TimeUnit.MICROSECONDS, + new LinkedBlockingDeque<>(MAX_LIMIT_JOB_SIZE), + Executors.defaultThreadFactory(), + new ThreadPoolExecutor.AbortPolicy() { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { + super.rejectedExecution(r, e); + } + } + ); + } + } + } + return EXECUTOR; + } + + public static void execute(Runnable runable) { + getThreadPool().execute(runable); + + } + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/TaskManager.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/TaskManager.java new file mode 100644 index 0000000..767e9f3 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/task/TaskManager.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.task; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; + + +/** + * @author GB + * @since 2024-08-22 + */ +public class TaskManager { + private static final ConcurrentHashMap>> TASK_MAP = new ConcurrentHashMap<>(); + + /** + * 提交任务 + */ + public static void submitTask(String id, Callable function) { + Future future = AnalysisThreadPool.getThreadPool().submit(function); + List> orDefault = TASK_MAP.getOrDefault(id, new ArrayList<>()); + orDefault.add(future); + TASK_MAP.put(id, orDefault); + } + + /** + * 弹出任务 + */ + public void popTaskResult(String id) { + TASK_MAP.remove(id); + } + + public int getCount(String id) { + if (TASK_MAP.containsKey(id)) { + Collection collection = TASK_MAP.get(id); + return collection != null ? collection.size() : 0; + } + return 0; + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/MybatisUtil.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/MybatisUtil.java similarity index 87% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/MybatisUtil.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/MybatisUtil.java index 5290181..215fc2a 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/MybatisUtil.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/MybatisUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.utils; +package cn.iocoder.yudao.module.langchat.utils; import cn.hutool.core.lang.Dict; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -33,13 +33,13 @@ public class MybatisUtil { * @return 格式化后的Map对象 */ public static Dict getData(IPage page) { - return Dict.create().set("rows", page.getRecords()).set("total", (int) page.getTotal()); + return Dict.create().set("list", page.getRecords()).set("total", (int) page.getTotal()); } /** * QueryPage对象转换为Page对象 */ public static IPage wrap(T t, QueryPage query) { - return new Page(query.getPage(), query.getLimit()); + return new Page(query.getPageNo(), query.getPageSize()); } } diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/QueryPage.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/QueryPage.java similarity index 90% rename from yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/QueryPage.java rename to yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/QueryPage.java index a51f061..2e5e3b1 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/server/utils/QueryPage.java +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/QueryPage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package cn.iocoder.yudao.module.langchat.server.utils; +package cn.iocoder.yudao.module.langchat.utils; import lombok.AllArgsConstructor; import lombok.Data; @@ -33,10 +33,10 @@ public class QueryPage implements Serializable { /** * 当前页 */ - private int page = 1; + private int pageNo = 1; /** * 每页的记录数 */ - private int limit = 10; + private int pageSize = 10; } diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/StreamEmitter.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/StreamEmitter.java new file mode 100644 index 0000000..4da7e5d --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/utils/StreamEmitter.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.utils; + +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; + +/** + * @author tycoding + * @since 2024/1/30 + */ +public class StreamEmitter { + + private final SseEmitter emitter; + + public StreamEmitter() { + emitter = new SseEmitter(5 * 60 * 1000L); + } + + public SseEmitter get() { + return emitter; + } + + public SseEmitter streaming(final ExecutorService executor, Runnable func) { +// ExecutorService executor = Executors.newSingleThreadExecutor(); + + emitter.onCompletion(() -> { + System.out.println("SseEmitter 完成"); + executor.shutdownNow(); + }); + + emitter.onError((e) -> { + System.out.println("SseEmitter 出现错误: " + e.getMessage()); + executor.shutdownNow(); + }); + + emitter.onTimeout(() -> { + System.out.println("SseEmitter 超时"); + emitter.complete(); + executor.shutdownNow(); + }); + executor.execute(() -> { + try { + func.run(); + } catch (Exception e) { + System.out.println("捕获到异常: " + e.getMessage()); + emitter.completeWithError(e); + Thread.currentThread().interrupt(); + } finally { + if (!executor.isShutdown()) { + executor.shutdownNow(); + } + } + }); + return emitter; + } + + public void send(Object obj) { + try { + emitter.send(obj); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public void complete() { + emitter.complete(); + } + + public void error(String message) { + try { + emitter.send("Error: " + message); + emitter.complete(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapper.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapper.java new file mode 100644 index 0000000..6474a00 --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapper.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.wrapper; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.dromara.x.file.storage.core.exception.FileStorageRuntimeException; +import org.dromara.x.file.storage.core.file.FileWrapper; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * MultipartFile 文件包装类 + */ +@Getter +@Setter +@NoArgsConstructor +public class MultipartFileWrapper implements FileWrapper { + private MultipartFile file; + private String name; + private String contentType; + private InputStream inputStream; + private Long size; + + public MultipartFileWrapper(MultipartFile file, String name, String contentType, Long size) { + this.file = file; + this.name = name; + this.contentType = contentType; + this.size = size; + } + + @Override + public InputStream getInputStream() throws IOException { + if (inputStream == null) { + inputStream = new BufferedInputStream(file.getInputStream()); + } + return inputStream; + } + + @Override + public void transferTo(File dest) { + // 在某些 SpringBoot 版本中,例如 2.4.6,此方法会调用失败, + // 此时尝试手动将 InputStream 写入指定文件, + // 根据文档来看 MultipartFile 最终都会由框架从临时目录中删除 + try { + file.transferTo(dest); + IoUtil.close(inputStream); + } catch (Exception ignored) { + try { + FileUtil.writeFromStream(getInputStream(), dest); + } catch (Exception e) { + throw new FileStorageRuntimeException("文件移动失败", e); + } + } + } + + @Override + public boolean supportTransfer() { + return true; + } + + public void setSize(Long size) { + this.size = size; + } + + public void setName(String name) { + this.name = name; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapperAdapter.java b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapperAdapter.java new file mode 100644 index 0000000..d08b70c --- /dev/null +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/java/cn/iocoder/yudao/module/langchat/wrapper/MultipartFileWrapperAdapter.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 LangChat. TyCoding All Rights Reserved. + * + * Licensed under the GNU Affero General Public License, Version 3 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.gnu.org/licenses/agpl-3.0.html + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.iocoder.yudao.module.langchat.wrapper; + +import lombok.Getter; +import lombok.Setter; +import org.dromara.x.file.storage.core.file.FileWrapper; +import org.dromara.x.file.storage.core.file.FileWrapperAdapter; +import org.springframework.web.multipart.MultipartFile; + +/** + * MultipartFile 文件包装适配器 + */ +@Getter +@Setter +public class MultipartFileWrapperAdapter implements FileWrapperAdapter { + + @Override + public boolean isSupport(Object source) { + return source instanceof MultipartFile || source instanceof MultipartFileWrapper; + } + + @Override + public FileWrapper getFileWrapper(Object source, String name, String contentType, Long size) { + if (source instanceof MultipartFileWrapper) { + return updateFileWrapper((MultipartFileWrapper) source, name, contentType, size); + } else { + MultipartFile file = (MultipartFile) source; + if (name == null) name = file.getOriginalFilename(); + if (contentType == null) contentType = file.getContentType(); + if (size == null) size = file.getSize(); + return new MultipartFileWrapper(file, name, contentType, size); + } + } +} diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-dev.yaml b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-dev.yaml index f065e93..b55cc1e 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-dev.yaml +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-dev.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 192.168.0.17:8848 # Nacos 服务器地址 + server-addr: 192.168.0.15:8848 # Nacos 服务器地址 username: nacos # Nacos 账号 password: nacos # Nacos 密码 discovery: # 【配置中心】配置项 diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-local.yaml b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-local.yaml index 363357c..f541324 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-local.yaml +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-local.yaml @@ -3,16 +3,16 @@ spring: cloud: nacos: - server-addr: 192.168.0.17:8848 # Nacos 服务器地址 + server-addr: 192.168.0.15:8848 # Nacos 服务器地址 username: nacos # Nacos 账号 password: nacos # Nacos 密码 discovery: # 【配置中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 + namespace: yudao # 命名空间。这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP metadata: version: 1.0.0 # 服务实例的版本号,可用于灰度发布 config: # 【注册中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 + namespace: yudao # 命名空间。这里使用 dev 开发环境 group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP --- #################### 数据库相关配置 #################### @@ -77,7 +77,7 @@ spring: # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 192.168.0.21 # 地址 + host: 127.0.0.1 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 password: 123456 # 密码,建议生产环境开启 @@ -211,3 +211,23 @@ justauth: type: REDIS prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 +langchat: + oss: + default-platform: local + qiniu-kodo: + - platform: qiniu # 存储平台标识,七牛:qiniu、阿里OSS:aliyun-oss、腾讯OSS:tencent-cos + enable-storage: true # 启用存储 + access-key: + secret-key: + bucket-name: + domain: / # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/ + base-path: langchat/ # 基础路径 + local-plus: + - platform: local # 存储平台标识 + enable-storage: true #启用存储 + enable-access: true #启用访问(线上请使用 Nginx 配置,效率更高) + domain: http://127.0.0.1:8100/ # 访问域名,例如:“http://127.0.0.1:8030/file/”,注意后面要和 path-patterns 保持一致,“/”结尾,本地存储建议使用相对路径,方便后期更换域名 + base-path: langchat/ # 基础路径 + path-patterns: /static/** # 访问路径(默认本地target目录),注意:如果使用本地nginx容器,此路径要修改为nginx存储路径 + storage-path: ./static/ # 存储路径(默认本地target目录),注意:如果使用本地nginx容器,此路径要修改为nginx存储路径 + diff --git a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-prd.yaml b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-prd.yaml index f065e93..b55cc1e 100644 --- a/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-prd.yaml +++ b/yudao-module-langchat/yudao-module-langchat-biz/src/main/resources/application-prd.yaml @@ -3,7 +3,7 @@ spring: cloud: nacos: - server-addr: 192.168.0.17:8848 # Nacos 服务器地址 + server-addr: 192.168.0.15:8848 # Nacos 服务器地址 username: nacos # Nacos 账号 password: nacos # Nacos 密码 discovery: # 【配置中心】配置项