src/main/java/cc/mrbird/febs/ai/controller/talk/ApiAiTalkController.java
New file @@ -0,0 +1,68 @@ package cc.mrbird.febs.ai.controller.talk; import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkAnswerDto; import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkDto; import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto; import cc.mrbird.febs.ai.req.talk.ApiTalkDto; import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto; import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo; import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVo; import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkVo; import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo; import cc.mrbird.febs.ai.res.talk.ApiTalkVo; import cc.mrbird.febs.ai.service.AiMemberTalkService; import cc.mrbird.febs.ai.service.AiTalkService; import cc.mrbird.febs.common.entity.FebsResponse; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import reactor.core.publisher.Flux; import java.io.IOException; /** * @author Administrator */ @Slf4j @Validated @RestController @RequiredArgsConstructor @RequestMapping(value = "/api/ai/talk") @Api(value = "ApiAiTalkController", tags = "AI-灵通") public class ApiAiTalkController { private final AiTalkService aiTalkService; @ApiOperation(value = "用户AI问答", notes = "用户AI问答") @ApiResponses({ @ApiResponse(code = 200, message = "success", response = ApiTalkVo.class) }) @PostMapping(value = "/talkOpen") public FebsResponse talkOpen(@RequestBody @Validated ApiTalkDto dto) { return aiTalkService.talkOpen(dto); } @ApiOperation(value = "用户AI问答记录分页查询", notes = "用户AI问答记录分页查询") @ApiResponses({ @ApiResponse(code = 200, message = "success", response = ApiTalkPageVo.class) }) @PostMapping(value = "/talkList") public FebsResponse talkList(@RequestBody @Validated ApiTalkPageDto dto) { return aiTalkService.talkList(dto); } @ApiOperation("提问AI(流式)") @ApiResponses({ @ApiResponse(code = 200, message = "流式响应", response = ApiMemberTalkStreamVo.class), }) @GetMapping("/answer-stream") public Flux<FebsResponse> answerStream(@RequestParam String question) { return aiTalkService.answerStream(question); } } src/main/java/cc/mrbird/febs/ai/entity/AiTalk.java
@@ -19,6 +19,11 @@ private String companyId; /** * 主要问题 */ private String question; /** * 用户ID (UUID) */ private String memberId; src/main/java/cc/mrbird/febs/ai/entity/AiTalkItem.java
@@ -25,7 +25,7 @@ /** * 用户对话ID (UUID) */ private String memberTalkId; private String talkId; /** * 类型 1-用户提问 2-AI回答 src/main/java/cc/mrbird/febs/ai/enumerates/AiTypeEnum.java
@@ -10,6 +10,13 @@ public enum AiTypeEnum { /** * 1:用户提问 * 2:AI回答 */ MEMBER_QUESTION(1,"用户提问"), AI_ANSWER(2,"AI回答"), /** * 1:AI提问 * 2:用户回答 * 3:生成答案解析 src/main/java/cc/mrbird/febs/ai/mapper/AiTalkMapper.java
@@ -1,7 +1,14 @@ package cc.mrbird.febs.ai.mapper; import cc.mrbird.febs.ai.entity.AiTalk; import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto; import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; public interface AiTalkMapper extends BaseMapper<AiTalk> { Page<ApiTalkPageVo> getPageTalkListByQuery(Page<ApiTalkPageVo> page, @Param("record")ApiTalkPageDto dto); } src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkDto.java
New file @@ -0,0 +1,27 @@ package cc.mrbird.febs.ai.req.talk; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author Administrator */ @Data @ApiModel(value = "ApiTalkDto", description = "参数") public class ApiTalkDto { @NotBlank(message = "内容不能为空") @ApiModelProperty(value = "内容", example = "10") private String context; @NotNull(message = "类型不能为空") @ApiModelProperty(value = "类型 1-用户提问 2-AI回答", example = "10") private Integer type; @ApiModelProperty(value = "会话ID", example = "10") private String talkId; } src/main/java/cc/mrbird/febs/ai/req/talk/ApiTalkPageDto.java
New file @@ -0,0 +1,26 @@ package cc.mrbird.febs.ai.req.talk; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; /** * @author Administrator */ @Data @ApiModel(value = "ApiTalkPageDto", description = "参数") public class ApiTalkPageDto { @NotNull(message = "页码不能为空") @ApiModelProperty(value = "页码", example = "1") private Integer pageNow; @NotNull(message = "每页数量不能为空") @ApiModelProperty(value = "每页数量", example = "10") private Integer pageSize; @ApiModelProperty(hidden = true) private String memberUuid; } src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkPageVo.java
New file @@ -0,0 +1,26 @@ package cc.mrbird.febs.ai.res.talk; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; /** * @author Administrator */ @Data @ApiModel(value = "ApiTalkPageVo", description = "参数") public class ApiTalkPageVo { @ApiModelProperty(value = "会话ID") private String talkId; @ApiModelProperty(value = "题目") private String question; @ApiModelProperty(value = "时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createdTime; } src/main/java/cc/mrbird/febs/ai/res/talk/ApiTalkVo.java
New file @@ -0,0 +1,19 @@ package cc.mrbird.febs.ai.res.talk; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author Administrator */ @Data @ApiModel(value = "ApiTalkVo", description = "参数") public class ApiTalkVo { /** * 视频号 id,以"sph"开头的id,可在视频号助手获取 */ @ApiModelProperty(value = "会话ID") private String talkId; } src/main/java/cc/mrbird/febs/ai/service/AiTalkItemService.java
New file @@ -0,0 +1,11 @@ package cc.mrbird.febs.ai.service; import cc.mrbird.febs.ai.entity.AiTalkItem; import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.extension.service.IService; public interface AiTalkItemService extends IService<AiTalkItem> { void add(String id, int code, String context, String memberUuid, DateTime date); } src/main/java/cc/mrbird/febs/ai/service/AiTalkService.java
New file @@ -0,0 +1,21 @@ package cc.mrbird.febs.ai.service; import cc.mrbird.febs.ai.entity.AiTalk; import cc.mrbird.febs.ai.req.talk.ApiTalkDto; import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto; import cc.mrbird.febs.common.entity.FebsResponse; import com.baomidou.mybatisplus.extension.service.IService; import reactor.core.publisher.Flux; import java.util.Date; public interface AiTalkService extends IService<AiTalk> { FebsResponse talkOpen(ApiTalkDto dto); AiTalk add(String memberUuid, String question, Date date); Flux<FebsResponse> answerStream(String question); FebsResponse talkList(ApiTalkPageDto dto); } src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkItemServiceImpl.java
New file @@ -0,0 +1,28 @@ package cc.mrbird.febs.ai.service.impl; import cc.mrbird.febs.ai.entity.AiTalkItem; import cc.mrbird.febs.ai.mapper.AiTalkItemMapper; import cc.mrbird.febs.ai.service.AiTalkItemService; import cc.mrbird.febs.ai.utils.UUID; import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Slf4j @Service @RequiredArgsConstructor public class AiTalkItemServiceImpl extends ServiceImpl<AiTalkItemMapper, AiTalkItem> implements AiTalkItemService { @Override public void add(String id, int code, String context, String memberUuid, DateTime date) { AiTalkItem aiTalkItem = new AiTalkItem(); aiTalkItem.setId(UUID.getSimpleUUIDString()); aiTalkItem.setMemberId(memberUuid); aiTalkItem.setType(code); aiTalkItem.setTalkId(id); aiTalkItem.setCreatedTime(date); aiTalkItem.setContext(context); this.baseMapper.insert(aiTalkItem); } } src/main/java/cc/mrbird/febs/ai/service/impl/AiTalkServiceImpl.java
New file @@ -0,0 +1,83 @@ package cc.mrbird.febs.ai.service.impl; import cc.mrbird.febs.ai.entity.AiTalk; import cc.mrbird.febs.ai.mapper.AiTalkMapper; import cc.mrbird.febs.ai.req.talk.ApiTalkDto; import cc.mrbird.febs.ai.req.talk.ApiTalkPageDto; import cc.mrbird.febs.ai.res.memberAnswer.ApiMemberProductWorkVo; import cc.mrbird.febs.ai.res.talk.ApiTalkPageVo; import cc.mrbird.febs.ai.res.talk.ApiTalkVo; import cc.mrbird.febs.ai.service.AiService; import cc.mrbird.febs.ai.service.AiTalkItemService; import cc.mrbird.febs.ai.service.AiTalkService; import cc.mrbird.febs.ai.utils.UUID; import cc.mrbird.febs.common.entity.FebsResponse; import cc.mrbird.febs.common.utils.LoginUserUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.util.Date; @Slf4j @Service @RequiredArgsConstructor public class AiTalkServiceImpl extends ServiceImpl<AiTalkMapper, AiTalk> implements AiTalkService { private final AiTalkItemService aiTalkItemService; private final AiService aiService; @Override public FebsResponse talkOpen(ApiTalkDto dto) { String talkId = dto.getTalkId(); String context = dto.getContext(); Integer type = dto.getType(); String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); AiTalk aiTalk = this.getById(talkId); DateTime date = DateUtil.date(); if (StrUtil.isEmpty(talkId)){ aiTalk = this.add(memberUuid,context, date); } aiTalkItemService.add(aiTalk.getId(), type, context, memberUuid, date); ApiTalkVo apiTalkVo = new ApiTalkVo(); apiTalkVo.setTalkId(aiTalk.getId()); return new FebsResponse().success().data(apiTalkVo); } @Override public AiTalk add(String memberUuid, String question, Date date) { AiTalk aiTalk = new AiTalk(); aiTalk.setId(UUID.getSimpleUUIDString()); aiTalk.setQuestion(question); aiTalk.setCreatedTime(date); aiTalk.setMemberId(memberUuid); this.baseMapper.insert(aiTalk); return aiTalk; } @Override public Flux<FebsResponse> answerStream(String question) { return aiService.answerStream(question); } @Override public FebsResponse talkList(ApiTalkPageDto dto) { String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); dto.setMemberUuid(memberUuid); // 创建分页对象,传入当前页和每页大小 Page<ApiTalkPageVo> page = new Page<>(dto.getPageNow(), dto.getPageSize()); Page<ApiTalkPageVo> pageListByQuery = this.getBaseMapper().getPageTalkListByQuery(page, dto); return new FebsResponse().success().data(pageListByQuery); } } src/main/resources/mapper/modules/AiTalkMapper.xml
@@ -1,4 +1,16 @@ <?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="cc.mrbird.febs.ai.mapper.AiTalkMapper"> <select id="getPageTalkListByQuery" resultType="cc.mrbird.febs.ai.res.talk.ApiTalkPageVo"> select a.id as talkId, a.question as question, a.CREATED_TIME as createdTime from ai_talk a where a.member_id = #{record.memberUuid} order by a.CREATED_TIME desc </select> </mapper>