diff --git a/kicc-common/kicc-common-bom/pom.xml b/kicc-common/kicc-common-bom/pom.xml index ef519022..5a49f827 100644 --- a/kicc-common/kicc-common-bom/pom.xml +++ b/kicc-common/kicc-common-bom/pom.xml @@ -32,6 +32,7 @@ 6.4.2 4.22.0 2.2.9 + 0.17.0 @@ -253,6 +254,21 @@ ureport2-console ${ureport2.version} + + com.theokanning.openai-gpt3-java + api + ${openai-gpt-java.api.version} + + + com.theokanning.openai-gpt3-java + client + ${openai-gpt-java.api.version} + + + com.theokanning.openai-gpt3-java + service + ${openai-gpt-java.api.version} + diff --git a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/util/SecurityUtils.java b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/util/SecurityUtils.java index 537d402d..53a6ca15 100644 --- a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/util/SecurityUtils.java +++ b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/util/SecurityUtils.java @@ -122,10 +122,18 @@ public class SecurityUtils { * @param userId 用户id * @return User 用户对象 */ - @SneakyThrows public T openInterfaceTemporaryLoginSession(String userId) { UserProviderTemplate userProviderTemplate = SpringContextHolderUtil.getBean(UserProviderTemplate.class); - Object user = userProviderTemplate.selectByUserId(userId); + return setSessionUser(userProviderTemplate.selectByUserId(userId)); + } + + + /** + * 设置当前上下文用户信息 + * @param user cas用户 + */ + @SneakyThrows + public T setSessionUser(Object user) { if (ObjectUtil.isEmpty(user)) { throw new UnConfiguredUserDataException("System user not found Contact your system administrator for configuration!", null); } @@ -166,9 +174,9 @@ public class SecurityUtils { BeanUtils.copyProperties(user, exUser); // 设置扩展用户数据 casUser.getExPrincipals().put(casProperties.getIdentity(), new ObjectMapper() - .registerModule(new KiccJavaTimeModule()) - .setSerializationInclusion(JsonInclude.Include.NON_NULL) - .writeValueAsString(exUser)); + .registerModule(new KiccJavaTimeModule()) + .setSerializationInclusion(JsonInclude.Include.NON_NULL) + .writeValueAsString(exUser)); Authentication authentication = new UsernamePasswordAuthenticationToken(casUser, "N/A", casUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); return (T) user; diff --git a/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImContent.java b/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImContent.java new file mode 100644 index 00000000..306b6555 --- /dev/null +++ b/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImContent.java @@ -0,0 +1,64 @@ +package com.cloud.kicc.system.api.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.cloud.kicc.common.data.entity.CommonEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +/** + *

+ * IM聊天内容 + *

+ * + * @author wangxiang4 + * @since 2023-11-15 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName(value = "sys_im_content", excludeProperty = { "createById", "createByName", "createTime", "updateById", "updateByName", "updateTime", "remarks" }) +@ApiModel(value = "ImContent对象", description = "IM聊天内容") +public class ImContent extends CommonEntity { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("主键") + private String id; + + @ApiModelProperty("发送者") + @NotBlank(message = "发送者ID不能为空") + private String sendUserId; + + @ApiModelProperty("发送时间") + private LocalDateTime sendTime; + + @ApiModelProperty("接收者") + @NotBlank(message = "接收者ID不能为空") + private String receiveUserId; + + @ApiModelProperty("接收时间") + private LocalDateTime receiveTime; + + @ApiModelProperty("内容") + private String content; + + @ApiModelProperty("内容类型") + @NotBlank(message = "发送内容类型不能为空") + private String contentType; + + @ApiModelProperty("状态") + private String status; + + @ApiModelProperty("附件") + private String files; + + @ApiModelProperty("撤销标记") + private String revert; + +} diff --git a/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/enums/ImMessageTypeEnum.java b/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/enums/ImMessageTypeEnum.java new file mode 100644 index 00000000..cfae02a4 --- /dev/null +++ b/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/enums/ImMessageTypeEnum.java @@ -0,0 +1,29 @@ +package com.cloud.kicc.system.api.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + *

+ * IM消息类型 + *

+ * + * @Author: wangxiang4 + * @Since: 2023/11/15 + */ +@Getter +@RequiredArgsConstructor +public enum ImMessageTypeEnum { + + + TEXT("0", "文本"), + + AUDIO("1", "音频"); + + + private final String value; + + + private final String description; + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-common-biz/src/main/test/SimpleCrudGeneratorTest.java b/kicc-platform/kicc-platform-biz/kicc-common-biz/src/main/test/SimpleCrudGeneratorTest.java index 26bb8fc2..1b520b40 100644 --- a/kicc-platform/kicc-platform-biz/kicc-common-biz/src/main/test/SimpleCrudGeneratorTest.java +++ b/kicc-platform/kicc-platform-biz/kicc-common-biz/src/main/test/SimpleCrudGeneratorTest.java @@ -18,11 +18,11 @@ public class SimpleCrudGeneratorTest { /** 代码生成全局配置 */ interface Config { - String url = "jdbc:mysql://192.168.3.10:8052/kicc?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true"; + String url = "jdbc:mysql://139.9.72.189:8052/db_kicc?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true"; - String username = "root"; + String username = "u_kanglai_account"; - String password = "kanglai@2022"; + String password = "$kanglai.<2021>#"; String author = "wangxiang4"; diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/pom.xml b/kicc-platform/kicc-platform-biz/kicc-system-biz/pom.xml index 5c826afc..e6203370 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/pom.xml +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/pom.xml @@ -74,6 +74,24 @@ com.cloud kicc-common-datasource + + + com.theokanning.openai-gpt3-java + api + + + com.squareup.retrofit2 + converter-jackson + ${retrofit2.converter-jackson.version} + + + com.theokanning.openai-gpt3-java + client + + + com.theokanning.openai-gpt3-java + service + diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/config/OpenAiConfigProperties.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/config/OpenAiConfigProperties.java new file mode 100644 index 00000000..2ed3b199 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/config/OpenAiConfigProperties.java @@ -0,0 +1,38 @@ +package com.cloud.kicc.system.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + + +/** + *

+ * ai 配置 + *

+ * + * @Author: wangxiang4 + * @Since: 2023/11/15 + */ +@Data +@RefreshScope +@Configuration +@ConfigurationProperties("openai.api") +public class OpenAiConfigProperties { + + /** + * change this to an `accessToken` extracted from the ChatGPT site's + * `...` response + */ + private String token; + + /** OpenAI API Base URL - ... */ + private String baseUrl; + + /** OpenAI API Model - ... */ + private String model; + + /** timeout time unit seconds */ + private int timeout = 10; + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ChatGptController.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ChatGptController.java new file mode 100644 index 00000000..dfd3cca4 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ChatGptController.java @@ -0,0 +1,53 @@ +package com.cloud.kicc.system.controller; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cloud.kicc.common.core.api.R; +import com.cloud.kicc.common.core.constant.AppConstants; +import com.cloud.kicc.common.core.exception.CheckedException; +import com.cloud.kicc.common.security.annotation.Inner; +import com.cloud.kicc.common.security.util.SecurityUtils; +import com.cloud.kicc.system.api.entity.ImContent; +import com.cloud.kicc.system.service.IImContentService; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.validation.Valid; +import java.util.Map; + +/** + *

+ * ChatGpt APi Support + *

+ * + * @Author: wangxiang4 + * @Since: 2023/11/15 + */ +@RestController +@AllArgsConstructor +@RequestMapping(AppConstants.APP_SYSTEM + "/ai") +public class ChatGptController { + + private final IImContentService iImContentService; + + @Inner(false) + @GetMapping("/chat/message") + public R list(Page page, ImContent imContent) { + if (StrUtil.isBlank(imContent.getSendUserId()) || StrUtil.isBlank(imContent.getReceiveUserId())) + throw new CheckedException("当前发送者ID与接收者ID必填!"); + // 查询一个会话内的聊天记录 + SecurityUtils.openInterfaceTemporaryLoginSession(imContent.getSendUserId()); + IPage> result = iImContentService.listHistoryMessage(page, imContent); + return R.ok(result.getRecords(), result.getTotal()); + } + + + @Inner(false) + @PostMapping("/chat/completions") + public R completions(@Valid @ModelAttribute ImContent imContent, @RequestPart(value = "file", required = false) MultipartFile file) { + return R.ok(iImContentService.completions(imContent, file)); + } + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java index 815b0c6d..a83afb9a 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java @@ -123,6 +123,14 @@ public class UserController { return R.ok(userService.getUserAuthority(user)); } + @Inner(false) + @GetMapping("/transformationUserByCasUserId/{casUserId:\\w+}") + public R transformationUserByCasUserId(@PathVariable String casUserId) { + KiccUser user = userService.getUserByCasUserId(casUserId); + if (user == null) return R.error("该用户不存在,请先注册!"); + return R.ok(userService.getUserAuthority(user)); + } + @SysLog("用户新增") @PostMapping("/save") @PreAuthorize("@pms.hasPermission('user_add')") diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/mapper/ImContentMapper.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/mapper/ImContentMapper.java new file mode 100644 index 00000000..60b34c45 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/mapper/ImContentMapper.java @@ -0,0 +1,24 @@ +package com.cloud.kicc.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cloud.kicc.system.api.entity.ImContent; +import org.apache.ibatis.annotations.Param; + +import java.util.Map; + +/** + *

+ * IM聊天内容 Mapper 接口 + *

+ * + * @author wangxiang4 + * @since 2023-11-15 + */ +public interface ImContentMapper extends BaseMapper { + + IPage> listHistoryMessage(Page page, @Param("ew") ImContent imContent); + + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/IImContentService.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/IImContentService.java new file mode 100644 index 00000000..34e3c3da --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/IImContentService.java @@ -0,0 +1,25 @@ +package com.cloud.kicc.system.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.cloud.kicc.system.api.entity.ImContent; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Map; + +/** + *

+ * IM聊天内容 服务类 + *

+ * + * @author wangxiang4 + * @since 2023-11-15 + */ +public interface IImContentService extends IService { + + IPage> listHistoryMessage(Page page, ImContent imContent); + + ImContent completions(ImContent imContent, MultipartFile file); + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImContentServiceImpl.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImContentServiceImpl.java new file mode 100644 index 00000000..640baec8 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImContentServiceImpl.java @@ -0,0 +1,195 @@ +package com.cloud.kicc.system.service.impl; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.cloud.kicc.common.core.exception.CheckedException; +import com.cloud.kicc.common.security.util.SecurityUtils; +import com.cloud.kicc.system.api.entity.ImContent; +import com.cloud.kicc.system.api.enums.ImMessageTypeEnum; +import com.cloud.kicc.system.mapper.ImContentMapper; +import com.cloud.kicc.system.service.FileService; +import com.cloud.kicc.system.service.IImContentService; +import com.cloud.kicc.system.util.AiUtil; +import com.pig4cloud.plugin.oss.OssProperties; +import com.pig4cloud.plugin.oss.service.OssTemplate; +import com.theokanning.openai.audio.CreateSpeechRequest; +import com.theokanning.openai.audio.CreateTranscriptionRequest; +import com.theokanning.openai.audio.TranscriptionResult; +import com.theokanning.openai.completion.chat.ChatCompletionChoice; +import com.theokanning.openai.completion.chat.ChatCompletionResult; +import com.theokanning.openai.completion.chat.ChatMessage; +import com.theokanning.openai.completion.chat.ChatMessageRole; +import com.theokanning.openai.service.OpenAiService; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import okhttp3.ResponseBody; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + *

+ * IM聊天内容 服务实现类 + *

+ * + * @author wangxiang4 + * @since 2023-11-15 + */ +@Service +@RequiredArgsConstructor +public class ImContentServiceImpl extends ServiceImpl implements IImContentService { + + private final FileService fileService; + + private final OssProperties ossProperties; + + private final OssTemplate ossTemplate; + + @Override + public IPage> listHistoryMessage(Page page, ImContent imContent) { + return baseMapper.listHistoryMessage(page, imContent); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @SneakyThrows + public ImContent completions(ImContent imContent, MultipartFile file) { + SecurityUtils.openInterfaceTemporaryLoginSession(imContent.getSendUserId()); + if (imContent.getContentType().equals(ImMessageTypeEnum.AUDIO.getValue())) { + Optional.ofNullable(file).orElseThrow(() -> new CheckedException("当前语音文件为空,请检查后重试!")); + OpenAiService openAiService = AiUtil.getOpenAiService(); + String speechName = "speech.mp3"; + String sendFileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename()); + String receiveFileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(speechName); + + // 构建发送文件信息进行OSS存储 + com.cloud.kicc.system.api.entity.File sendOssFile = new com.cloud.kicc.system.api.entity.File() + .setFileName(sendFileName) + .setBucketName(ossProperties.getBucketName()) + .setOriginal(file.getOriginalFilename()) + .setType(FileUtil.extName(file.getOriginalFilename())) + .setFileSize(file.getSize()) + .setMimeType(file.getContentType()); + ossTemplate.putObject(ossProperties.getBucketName(), sendFileName, file.getContentType(), file.getInputStream()); + String sendVoiceUrl = ossTemplate.getObjectURL(ossProperties.getBucketName(), sendFileName); + sendOssFile.setAvailablePath(sendVoiceUrl); + fileService.save(sendOssFile); + imContent.setFiles(sendOssFile.getId()); + + // 语音转文字 + File voiceFile = File.createTempFile(sendFileName, null); + CreateTranscriptionRequest request = CreateTranscriptionRequest.builder() + .model("whisper-1") + .language("zh") + .build(); + FileUtil.writeBytes(file.getBytes(), voiceFile); + TranscriptionResult transcriptionResult = openAiService.createTranscription(request, voiceFile); + if (voiceFile.delete()) { + System.out.println("已成功删除临时文件!"); + } + if (StrUtil.isBlank(transcriptionResult.getText())) { + throw new CheckedException("Ai语音转文字为空解析失败!"); + } + + imContent.setContent(transcriptionResult.getText()); + ImContent content = askChatCompletion(imContent); + content.setContentType(ImMessageTypeEnum.AUDIO.getValue()); + + // 文字转语音 + CreateSpeechRequest createSpeechRequest = CreateSpeechRequest.builder() + .model("tts-1") + .input(content.getContent()) + .voice("nova") + .responseFormat(FileUtil.extName(speechName)) + .speed(1.0) + .build(); + ResponseBody responseBody = openAiService.createSpeech(createSpeechRequest); + + // 构建发送文件信息进行OSS存储 + com.cloud.kicc.system.api.entity.File receiveOssFile = new com.cloud.kicc.system.api.entity.File() + .setFileName(receiveFileName) + .setBucketName(ossProperties.getBucketName()) + .setOriginal(speechName) + .setType(FileUtil.extName(speechName)) + .setFileSize(responseBody.contentLength()) + .setMimeType(Objects.requireNonNull(responseBody.contentType()).toString()); + ossTemplate.putObject(ossProperties.getBucketName(), receiveFileName, Objects.requireNonNull(responseBody.contentType()).toString(), responseBody.byteStream()); + String receiveVoiceUrl = ossTemplate.getObjectURL(ossProperties.getBucketName(), receiveFileName); + receiveOssFile.setAvailablePath(receiveVoiceUrl); + fileService.save(receiveOssFile); + + // 保存AI回复聊天记录 + imContent.setFiles(receiveOssFile.getId()); + super.save(content); + return content; + } else { + // 保存AI回复聊天记录 + ImContent content = askChatCompletion(imContent); + super.save(content); + return content; + } + } + + private ImContent askChatCompletion(ImContent imContent) { + if (StrUtil.isBlank(imContent.getContent())) { + throw new CheckedException("提问内容不能为空请检查!"); + } + // 保存用户发送聊天记录 + imContent.setSendUserId(SecurityUtils.getCasUser().getId()); + imContent.setSendTime(LocalDateTime.now()); + imContent.setReceiveUserId(imContent.getReceiveUserId()); + imContent.setReceiveTime(LocalDateTime.now()); + super.save(imContent); + + // 查询当前历史消息,进行AI上下文消息合并 + List imContents = super.list(Wrappers.lambdaQuery().and(i -> + i.eq(ImContent::getSendUserId, imContent.getSendUserId()) + .eq(ImContent::getReceiveUserId, imContent.getReceiveUserId()) + ).or(i -> + i.eq(ImContent::getSendUserId, imContent.getReceiveUserId()) + .eq(ImContent::getReceiveUserId, imContent.getSendUserId()) + ) .orderByAsc(ImContent::getSendTime)); + + // 历史上下文消息 + List historyMessages = imContents.stream().map(item -> { + ChatMessage chatMessage = new ChatMessage(); + chatMessage.setRole(StrUtil.equals(item.getSendUserId(), imContent.getSendUserId()) ? ChatMessageRole.USER.value() : ChatMessageRole.ASSISTANT.value()); + chatMessage.setContent(item.getContent()); + return chatMessage; + }).collect(Collectors.toList()); + + // 提问消息 + ChatMessage askMessage = new ChatMessage(ChatMessageRole.USER.value(), imContent.getContent()); + historyMessages.add(askMessage); + + ChatCompletionResult chatCompletionResult = AiUtil.getChatCompletion(historyMessages); + List choiceList = chatCompletionResult.getChoices(); + + if (choiceList.isEmpty()) { + throw new CheckedException("Ai生成解析失败!"); + } + + // 构建AI生成消息 + return new ImContent() + .setSendUserId(imContent.getReceiveUserId()) + .setSendTime(LocalDateTime.now()) + .setReceiveUserId(SecurityUtils.getCasUser().getId()) + .setReceiveTime(LocalDateTime.now()) + .setContent(choiceList.get(0).getMessage().getContent()) + .setContentType(ImMessageTypeEnum.TEXT.getValue()); + } + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserProviderTemplateImpl.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserProviderTemplateImpl.java index 5af0ba9e..bd94af97 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserProviderTemplateImpl.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserProviderTemplateImpl.java @@ -6,6 +6,7 @@ import com.cloud.kicc.common.data.entity.KiccUser; import com.cloud.kicc.common.security.exception.SecurityCheckedException; import com.cloud.kicc.common.security.template.UserProviderTemplate; import com.cloud.kicc.system.api.feign.RemoteUserService; +import com.cloud.kicc.system.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -15,6 +16,8 @@ public class UserProviderTemplateImpl implements UserProviderTemplate private final RemoteUserService remoteUserService; + private final UserService userService; + @Override public KiccUser selectByCasUserId(String casUserId) { R result = remoteUserService.selectByCasUserId(casUserId); @@ -30,7 +33,7 @@ public class UserProviderTemplateImpl implements UserProviderTemplate if (result.getCode() != R.SUCCESS) { throw new SecurityCheckedException(ObjectUtil.defaultIfBlank(result.getMsg(), "SecurityProviderTemplateImpl invoke failed!")); } - return result.getData(); + return userService.getUserAuthority(result.getData()); } } diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java index aa4434ac..46997077 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java @@ -64,6 +64,7 @@ public class UserServiceImpl extends ServiceImpl implements Us // 新增用户信息 int rows = baseMapper.insert(user); // 新增用户与角色管理 + kiccUser.setId(user.getId()); addUserRole(kiccUser); return rows; } else { diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/util/AiUtil.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/util/AiUtil.java new file mode 100644 index 00000000..63ff3d46 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/util/AiUtil.java @@ -0,0 +1,72 @@ +package com.cloud.kicc.system.util; + +import cn.hutool.core.map.MapUtil; +import com.cloud.kicc.common.core.util.SpringContextHolderUtil; +import com.cloud.kicc.common.security.util.SecurityUtils; +import com.cloud.kicc.system.config.OpenAiConfigProperties; +import com.theokanning.openai.client.OpenAiApi; +import com.theokanning.openai.completion.chat.*; +import com.theokanning.openai.service.OpenAiService; +import lombok.experimental.UtilityClass; +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + *

+ * Ai 调用工具 + *

+ * + * @Author: wangxiang4 + * @Since: 2023/11/16 + */ +@UtilityClass +public class AiUtil { + + OpenAiConfigProperties openAiConfigProperties = SpringContextHolderUtil.getBean(OpenAiConfigProperties.class); + + /** + * 获取OpenAiService + */ + public OpenAiService getOpenAiService() { + OkHttpClient client = OpenAiService.defaultClient(openAiConfigProperties.getToken(), Duration.ofSeconds(openAiConfigProperties.getTimeout())); + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(openAiConfigProperties.getBaseUrl()) + .client(client) + .addConverterFactory(JacksonConverterFactory.create(OpenAiService.defaultObjectMapper())) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + OpenAiApi api = retrofit.create(OpenAiApi.class); + return new OpenAiService(api); + } + + + /** + * ... + */ + public ChatCompletionResult getChatCompletion(List historyMessages) { + String rule = "是与AI助手的对话。助手乐于助人,富有创造力,聪明每次回答限制在300字以内不得超过300字。"; + List messages = new ArrayList<>(); + ChatMessage systemMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), rule); + messages.add(systemMessage); + messages.addAll(historyMessages); + ChatCompletionRequest request = ChatCompletionRequest.builder() + .model(openAiConfigProperties.getModel()) + .messages(messages) + .n(1) + .frequencyPenalty(1.0) + .presencePenalty(1.0) + .maxTokens(160) + .topP(0.8) + .user(SecurityUtils.getCasUser().getId()) + .build(); + return getOpenAiService().createChatCompletion(request); + } + +} diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper/ImContentMapper.xml b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper/ImContentMapper.xml new file mode 100644 index 00000000..9034d09d --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper/ImContentMapper.xml @@ -0,0 +1,36 @@ + + + + + + + diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/test/SimpleCrudGeneratorTest.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/test/SimpleCrudGeneratorTest.java new file mode 100644 index 00000000..13e73c22 --- /dev/null +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/test/SimpleCrudGeneratorTest.java @@ -0,0 +1,102 @@ +import com.baomidou.mybatisplus.generator.AutoGenerator; +import com.baomidou.mybatisplus.generator.config.*; +import com.cloud.kicc.common.data.entity.CommonEntity; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + *

+ * mysql crud代码自动生成 + *

+ * + * @Author: wangxiang4 + * @Date: 2022/7/22 + */ +public class SimpleCrudGeneratorTest { + + /** 代码生成全局配置 */ + interface Config { + + String url = "jdbc:mysql://139.9.72.189:8052/db_kicc?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true"; + + String username = "u_kanglai_account"; + + String password = "$kanglai.<2021>#"; + + String author = "wangxiang4"; + + String rootOutputDir = "/Users/wangxiang/IdeaProjects/org/kicc/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java"; + + String entityOutputDir = "/Users/wangxiang/IdeaProjects/org/kicc/kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity"; + + String mapperXmlOutputDir = "/Users/wangxiang/IdeaProjects/org/kicc/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper"; + + String packageParent = "com.cloud.kicc.system"; + + String packageService = "service"; + + String packageEntity = "api.entity"; + + String packageServiceImpl = "service.impl"; + + String packageMapper = "mapper"; + + String packageController = "controller"; + + String[] includeTable = { "sys_im_content" }; + + String[] filterEntityTablePrefix = { "sys_" }; + + String[] superEntityColumns = { "createById", "createByName", "createTime", "updateById","updateByName", "updateTime", "remarks", "delFlag" }; + + String[] ignoreColumns = { "tenant_id" }; + + } + + @Test + /** 运行代码生成 */ + public void CrudSimpleGenerator() { + + AutoGenerator generator = new AutoGenerator(new DataSourceConfig.Builder(Config.url, Config.username, Config.password).build()); + // 全局配置 参考:https://github.com/baomidou/generator#%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AEglobalconfig + generator.global(new GlobalConfig.Builder() + .author(Config.author) + .enableSwagger() + .fileOverride() + .outputDir(Config.rootOutputDir) + .build() + ); + // 包路径配置 参考:https://github.com/baomidou/generator#%E5%8C%85%E9%85%8D%E7%BD%AEpackageconfig + Map pathInfos = new ConcurrentHashMap(); + pathInfos.put(OutputFile.entity, Config.entityOutputDir); + pathInfos.put(OutputFile.mapperXml, Config.mapperXmlOutputDir); + generator.packageInfo(new PackageConfig.Builder() + .parent(Config.packageParent) + .service(Config.packageService) + .entity(Config.packageEntity) + .serviceImpl(Config.packageServiceImpl) + .mapper(Config.packageMapper) + .controller(Config.packageController) + .pathInfo(pathInfos) + .build() + ); + // 策略配置 参考:https://github.com/baomidou/generator#%E7%AD%96%E7%95%A5%E9%85%8D%E7%BD%AEstrategyconfig + generator.strategy(new StrategyConfig.Builder() + .addInclude(Config.includeTable) + .addTablePrefix(Config.filterEntityTablePrefix) + .entityBuilder() + .enableChainModel() + .enableLombok() + .enableRemoveIsPrefix() + .superClass(CommonEntity.class) + .addSuperEntityColumns(Config.superEntityColumns) + .addIgnoreColumns(Config.ignoreColumns) + .build() + ); + generator.execute(); + } + + +} diff --git a/pom.xml b/pom.xml index 9e01671c..c7124368 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ 3.0.0 2.0.9 2.3.0 + 2.9.0 4.4 12.2.0.1 4.9.9