Browse Source

feat: ai

master
wangxiang 2 years ago
parent
commit
7fadc41297
No known key found for this signature in database
GPG Key ID: 1BA7946AB6B232E4
  1. 4
      kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImContent.java
  2. 42
      kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImSession.java
  3. 2
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ChatGptController.java
  4. 98
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ImSessionController.java
  5. 16
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/mapper/ImSessionMapper.java
  6. 16
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/IImSessionService.java
  7. 18
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImContentServiceImpl.java
  8. 20
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImSessionServiceImpl.java
  9. 5
      kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper/ImSessionMapper.xml

4
kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImContent.java

@ -31,6 +31,10 @@ public class ImContent extends CommonEntity {
@ApiModelProperty("主键") @ApiModelProperty("主键")
private String id; private String id;
@ApiModelProperty("会话ID")
@NotBlank(message = "发送会话ID不能为空")
private String sessionId;
@ApiModelProperty("发送者") @ApiModelProperty("发送者")
@NotBlank(message = "发送者ID不能为空") @NotBlank(message = "发送者ID不能为空")
private String sendUserId; private String sendUserId;

42
kicc-platform/kicc-platform-api/kicc-system-api/src/main/java/com/cloud/kicc/system/api/entity/ImSession.java

@ -0,0 +1,42 @@
package com.cloud.kicc.system.api.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cloud.kicc.common.data.entity.CommonEntity;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* <p>
* 聊天会话
* </p>
*
* @author wangxiang4
* @since 2023-12-12
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName(value = "sys_im_session", excludeProperty = { "createById", "createByName", "createTime", "updateById", "updateByName", "updateTime", "remarks" })
@ApiModel(value = "ImSession对象", description = "聊天会话")
public class ImSession extends CommonEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键")
private String id;
@ApiModelProperty("用户主键")
private String userId;
@ApiModelProperty("接收用户")
private String receiveUserId;
@ApiModelProperty("接收时间")
private LocalDateTime receiveTime;
}

2
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ChatGptController.java

@ -37,7 +37,7 @@ public class ChatGptController {
public R list(Page page, ImContent imContent) { public R list(Page page, ImContent imContent) {
if (StrUtil.isBlank(imContent.getSendUserId()) || StrUtil.isBlank(imContent.getReceiveUserId())) if (StrUtil.isBlank(imContent.getSendUserId()) || StrUtil.isBlank(imContent.getReceiveUserId()))
throw new CheckedException("当前发送者ID与接收者ID必填!"); throw new CheckedException("当前发送者ID与接收者ID必填!");
// 查询一个会话内的聊天记录 // 查询当前用户的所有会话内的聊天记录
SecurityUtils.openInterfaceTemporaryLoginSession(imContent.getSendUserId()); SecurityUtils.openInterfaceTemporaryLoginSession(imContent.getSendUserId());
IPage<Map<String, Object>> result = iImContentService.listHistoryMessage(page, imContent); IPage<Map<String, Object>> result = iImContentService.listHistoryMessage(page, imContent);
return R.ok(result.getRecords(), result.getTotal()); return R.ok(result.getRecords(), result.getTotal());

98
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/ImSessionController.java

@ -0,0 +1,98 @@
package com.cloud.kicc.system.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.api.entity.ImSession;
import com.cloud.kicc.system.service.IImSessionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Optional;
/**
* <p>
* 聊天会话 前端控制器
* </p>
*
* @author wangxiang4
* @since 2023-12-12
*/
@Controller
@RequiredArgsConstructor
@RequestMapping(AppConstants.APP_SYSTEM + "/imSession")
public class ImSessionController {
private final IImSessionService iImSessionService;
private LambdaQueryWrapper<ImSession> getQueryWrapper(ImSession imSession) {
return new LambdaQueryWrapper<ImSession>()
.eq(StrUtil.isNotBlank(imSession.getUserId()), ImSession::getUserId, imSession.getUserId())
.eq(StrUtil.isNotBlank(imSession.getReceiveUserId()), ImSession::getReceiveUserId, imSession.getReceiveUserId())
.orderByDesc(ImSession::getReceiveTime);
}
@GetMapping("/list")
public R list(Page page, ImSession imSession) {
IPage<ImSession> result = iImSessionService.page(page, getQueryWrapper(imSession));
return R.ok(result.getRecords(), result.getTotal());
}
@GetMapping("/{id:\\w+}")
public R getById(@PathVariable("id") String id) {
return R.ok(iImSessionService.getById(id));
}
@PostMapping("/save")
public R save(@Validated @RequestBody ImSession imSession) {
iImSessionService.save(imSession);
return R.ok();
}
@Inner(false)
@PostMapping("/sessionSave")
public R sessionSave(@Validated @RequestBody ImSession imSession) {
SecurityUtils.openInterfaceTemporaryLoginSession(imSession.getUserId());
imSession.setReceiveTime(LocalDateTime.now());
iImSessionService.save(imSession);
return R.ok(imSession);
}
@Inner(false)
@GetMapping("/lastSession")
public R lastSession(String userId) {
Optional.ofNullable(userId).orElseThrow(() -> new CheckedException("发送用户ID必传!"));
ImSession session = iImSessionService.getOne(Wrappers.<ImSession>lambdaQuery()
.eq(ImSession::getUserId, userId)
.orderByDesc(ImSession::getReceiveTime)
.last("LIMIT 1"));
return R.ok(session);
}
@PutMapping("/update")
public R update(@Validated @RequestBody ImSession imSession) {
iImSessionService.updateById(imSession);
return R.ok();
}
@DeleteMapping("/remove/{id:[\\w,]+}")
public R remove(@PathVariable String[] id) {
iImSessionService.removeByIds(Arrays.asList(id));
return R.ok();
}
}

16
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/mapper/ImSessionMapper.java

@ -0,0 +1,16 @@
package com.cloud.kicc.system.mapper;
import com.cloud.kicc.system.api.entity.ImSession;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 聊天会话 Mapper 接口
* </p>
*
* @author wangxiang4
* @since 2023-12-12
*/
public interface ImSessionMapper extends BaseMapper<ImSession> {
}

16
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/IImSessionService.java

@ -0,0 +1,16 @@
package com.cloud.kicc.system.service;
import com.cloud.kicc.system.api.entity.ImSession;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 聊天会话 服务类
* </p>
*
* @author wangxiang4
* @since 2023-12-12
*/
public interface IImSessionService extends IService<ImSession> {
}

18
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImContentServiceImpl.java

@ -75,18 +75,9 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public ImContent chatCompletions(ImContent imContent) { public ImContent chatCompletions(ImContent imContent) {
if (StrUtil.isBlank(imContent.getContent())) { // 根据当前会话查询当前历史消息,进行AI上下文消息合并
throw new CheckedException("提问内容不能为空请检查!"); List<ImContent> imContents = super.list(Wrappers.<ImContent>lambdaQuery().eq(ImContent::getSessionId, imContent.getSessionId())
} .last(String.format("LIMIT %s", openAiConfigProperties.getContextMessageMaxCount()))
// 查询当前历史消息,进行AI上下文消息合并
List<ImContent> imContents = super.list(Wrappers.<ImContent>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())
).last(String.format("LIMIT %s", openAiConfigProperties.getContextMessageMaxCount()))
.orderByDesc(ImContent::getSendTime)); .orderByDesc(ImContent::getSendTime));
// 历史上下文消息 // 历史上下文消息
@ -98,6 +89,7 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
}).collect(Collectors.toList()); }).collect(Collectors.toList());
CollUtil.reverse(historyMessages); CollUtil.reverse(historyMessages);
if (StrUtil.isNotBlank(imContent.getContent())) {
// 保存用户发送聊天记录 // 保存用户发送聊天记录
imContent.setSendUserId(SecurityUtils.getCasUser().getId()); imContent.setSendUserId(SecurityUtils.getCasUser().getId());
imContent.setSendTime(LocalDateTime.now()); imContent.setSendTime(LocalDateTime.now());
@ -108,6 +100,7 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
// Completion消息 // Completion消息
ChatMessage completionMessage = new ChatMessage(ChatMessageRole.USER.value(), imContent.getContent()); ChatMessage completionMessage = new ChatMessage(ChatMessageRole.USER.value(), imContent.getContent());
historyMessages.add(completionMessage); historyMessages.add(completionMessage);
}
ChatCompletionResult chatCompletionResult = AiUtil.getChatCompletion(historyMessages); ChatCompletionResult chatCompletionResult = AiUtil.getChatCompletion(historyMessages);
List<ChatCompletionChoice> choiceList = chatCompletionResult.getChoices(); List<ChatCompletionChoice> choiceList = chatCompletionResult.getChoices();
@ -118,6 +111,7 @@ public class ImContentServiceImpl extends ServiceImpl<ImContentMapper, ImContent
// ai chat message build // ai chat message build
ImContent receiveContent = new ImContent() ImContent receiveContent = new ImContent()
.setSessionId(imContent.getSessionId())
.setSendUserId(imContent.getReceiveUserId()) .setSendUserId(imContent.getReceiveUserId())
.setSendTime(LocalDateTime.now()) .setSendTime(LocalDateTime.now())
.setReceiveUserId(SecurityUtils.getCasUser().getId()) .setReceiveUserId(SecurityUtils.getCasUser().getId())

20
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/ImSessionServiceImpl.java

@ -0,0 +1,20 @@
package com.cloud.kicc.system.service.impl;
import com.cloud.kicc.system.api.entity.ImSession;
import com.cloud.kicc.system.mapper.ImSessionMapper;
import com.cloud.kicc.system.service.IImSessionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 聊天会话 服务实现类
* </p>
*
* @author wangxiang4
* @since 2023-12-12
*/
@Service
public class ImSessionServiceImpl extends ServiceImpl<ImSessionMapper, ImSession> implements IImSessionService {
}

5
kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/resources/mapper/ImSessionMapper.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cloud.kicc.system.mapper.ImSessionMapper">
</mapper>
Loading…
Cancel
Save