feat(ai): 优化 AI 对话功能
- 在 AiPromptJsonReq 中添加 question 字段
- 更新 AiTalkOutputEnum 的描述
- 新增 ApiMemberTalkMemberAnswerSavaDto 类用于保存用户回答- 在 ApiMemberTalkStreamController 中添加保存用户回答的接口
- 在 ApiMemberTalkStreamService 中添加保存用户回答的方法
- 优化 ApiMemberTalkStreamServiceImpl 中的保存用户回答逻辑
- 调整 buildPrompt 方法以支持问题和回答
5 files modified
1 files added
| | |
| | | package cc.mrbird.febs.ai.controller.memberTalk; |
| | | |
| | | import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.AiTalkAnswerStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkAnswerSavaDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkReloadStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.*; |
| | | import cc.mrbird.febs.ai.req.talk.AiTalkAnswerStream; |
| | | import cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkItemVo; |
| | | import cc.mrbird.febs.ai.res.memberTalkStream.ApiMemberTalkReloadStreamVo; |
| | |
| | | return apiMemberTalkStreamService.historyPage(dto); |
| | | } |
| | | |
| | | @ApiOperation(value = "保存用户回答", notes = "保存答案") |
| | | @PostMapping(value = "/saveMemberAnswer") |
| | | public FebsResponse saveMemberAnswer(@RequestBody @Validated ApiMemberTalkMemberAnswerSavaDto dto) { |
| | | |
| | | return apiMemberTalkStreamService.saveMemberAnswer(dto); |
| | | } |
| | | |
| | | @ApiOperation("回答(流式)") |
| | | @ApiResponses({ |
| | | @ApiResponse(code = 200, message = "流式响应", response = cc.mrbird.febs.ai.res.memberTalk.ApiMemberTalkStreamVo.class), |
| | |
| | | return apiMemberTalkStreamService.answer(dto); |
| | | } |
| | | |
| | | @ApiOperation(value = "保存答案", notes = "保存答案") |
| | | @ApiOperation(value = "保存AI回答", notes = "保存AI回答") |
| | | @PostMapping(value = "/saveAnswer") |
| | | public FebsResponse saveAnswer(@RequestBody @Validated ApiMemberTalkAnswerSavaDto dto) { |
| | | |
| | |
| | | @Getter |
| | | public enum AiTalkOutputEnum { |
| | | |
| | | KEY_KNOWLEDGE(4,"只输出知识点总结","KEY_KNOWLEDGE"), |
| | | KEY_KNOWLEDGE(4,"根据问题和用户输入的内容,进行知识点总结。","KEY_KNOWLEDGE"), |
| | | |
| | | REFERENCE_ANSWER(3,"只输出参考答案","REFERENCE_ANSWER"), |
| | | REFERENCE_ANSWER(3,"根据问题和用户输入的内容,输出参考答案。","REFERENCE_ANSWER"), |
| | | |
| | | SUGGESTION(2,"只输出建议","SUGGESTION"), |
| | | SUGGESTION(2,"根据问题和用户输入的内容,给出建议并文字输出。","SUGGESTION"), |
| | | |
| | | HIGH_LIGHT(1,"只输出亮点","HIGH_LIGHT"); |
| | | HIGH_LIGHT(1,"根据问题和用户输入的内容,分析答案的亮点并文字输出。","HIGH_LIGHT"); |
| | | |
| | | private final int type; |
| | | private final String content; |
| | |
| | | |
| | | private String task; |
| | | |
| | | private String question; |
| | | |
| | | private String rule; |
| | | |
| | | private String outputFormat; |
New file |
| | |
| | | package cc.mrbird.febs.ai.req.memberTalkStream; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | /** |
| | | * @author Administrator |
| | | */ |
| | | @Data |
| | | @ApiModel(value = "ApiMemberTalkMemberAnswerSavaDto", description = "参数") |
| | | public class ApiMemberTalkMemberAnswerSavaDto { |
| | | |
| | | |
| | | /** |
| | | * 用户对话ID (UUID) |
| | | */ |
| | | @NotBlank(message = "会话ID不能为空") |
| | | @ApiModelProperty(value = "会话ID", example = "10") |
| | | private String memberTalkId; |
| | | |
| | | @NotBlank(message = "回复内容不能为空") |
| | | @ApiModelProperty(value = "回复内容", example = "10") |
| | | private String content; |
| | | |
| | | } |
| | |
| | | |
| | | import cc.mrbird.febs.ai.entity.AiMemberTalk; |
| | | import cc.mrbird.febs.ai.req.memberTalk.ApiMemberTalkItemPageDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.AiTalkAnswerStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkAnswerSavaDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkReloadStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.ApiMemberTalkStreamDto; |
| | | import cc.mrbird.febs.ai.req.memberTalkStream.*; |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import reactor.core.publisher.Flux; |
| | |
| | | |
| | | FebsResponse historyPage(ApiMemberTalkItemPageDto dto); |
| | | |
| | | FebsResponse saveMemberAnswer(ApiMemberTalkMemberAnswerSavaDto dto); |
| | | |
| | | Flux<FebsResponse> answer(AiTalkAnswerStreamDto dto); |
| | | |
| | | FebsResponse saveAnswer(ApiMemberTalkAnswerSavaDto dto); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public FebsResponse saveMemberAnswer(ApiMemberTalkMemberAnswerSavaDto dto) { |
| | | String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); |
| | | String memberTalkId = dto.getMemberTalkId(); |
| | | String content = dto.getContent(); |
| | | |
| | | AiMemberTalk aiMemberTalk = this.getById(memberTalkId); |
| | | if (ObjectUtil.isNull(aiMemberTalk)){ |
| | | throw new FebsException("对话不存在"); |
| | | } |
| | | aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),2,content,new Date()); |
| | | return new FebsResponse().success(); |
| | | } |
| | | |
| | | @Override |
| | | public Flux<FebsResponse> answer(AiTalkAnswerStreamDto dto) { |
| | | |
| | | String memberUuid = LoginUserUtil.getLoginUser().getMemberUuid(); |
| | |
| | | memberTalkItemQuery.orderByDesc(AiMemberTalkItem::getCreatedTime); |
| | | memberTalkItemQuery.last("limit 1"); |
| | | AiMemberTalkItem aiMemberTalkItem = aiMemberTalkItemService.getByQuery(memberTalkItemQuery); |
| | | aiMemberTalkItemService.add(memberUuid,aiMemberTalk.getId(),2,reqContext,new Date()); |
| | | |
| | | String prompt = this.buildPrompt(aiProductRole.getPromptHead(), aiProductRole.getPromptTemplate(), type); |
| | | String prompt = this.buildPrompt(aiMemberTalkItem.getContext(),reqContext,aiProductRole.getPromptHead(), aiProductRole.getPromptTemplate(), type); |
| | | |
| | | |
| | | List<LlmStrategyDto> llmStrategyDtoList = new ArrayList<>(); |
| | |
| | | return llmStrategyFactory.getCalculationStrategyMap().get(modelName).llmInvokeStreamingNoThink(llmStrategyDtoList); |
| | | } |
| | | |
| | | private String buildPrompt(String promptHead, String promptTemplate,Integer type){ |
| | | private String buildPrompt(String question,String answer,String promptHead, String promptTemplate,Integer type){ |
| | | AiPromptJsonReq aiPromptJsonReq = new AiPromptJsonReq(); |
| | | aiPromptJsonReq.setTask(promptHead); |
| | | aiPromptJsonReq.setRule(promptTemplate); |
| | | aiPromptJsonReq.setQuestion( question); |
| | | aiPromptJsonReq.setTask( promptHead); |
| | | aiPromptJsonReq.setRule( promptTemplate); |
| | | String contentByCode = AiTalkOutputEnum.HIGH_LIGHT.getContentByType(type); |
| | | aiPromptJsonReq.setOutputFormat(contentByCode); |
| | | |