From 7bee2e3c45b6a459a09490b15481417acfbd6249 Mon Sep 17 00:00:00 2001 From: Jiang Yulong Date: Wed, 3 Dec 2025 17:40:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20AI=E6=B6=88=E6=81=AF=E7=82=B9=E8=B5=9E/?= =?UTF-8?q?=E8=B8=A9/=E5=8F=96=E6=B6=88=E7=82=B9=E8=B5=9E/=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E8=B8=A9/=E9=97=AE=E9=A2=98=E5=8F=8D=E9=A6=88?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/boecase/api/CaseAiChatApi.java | 40 +++++++++++++++++++ .../module/boecase/dto/CaseAiMsgLikeDto.java | 24 +++++++++++ .../entity/AiChatConversationData.java | 14 +++++++ .../boecase/service/ICaseAiChatService.java | 10 +++++ .../service/IElasticSearchIndexService.java | 8 ++++ .../service/impl/CaseAiChatServiceImpl.java | 17 ++++++++ .../impl/ElasticSearchIndexServiceImpl.java | 36 +++++++++++++++++ 7 files changed, 149 insertions(+) create mode 100644 servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java index 5cde7b0c..9544f950 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseAiChatApi.java @@ -3,6 +3,7 @@ package com.xboe.module.boecase.api; import com.xboe.core.api.ApiBaseController; import com.xboe.core.JsonResponse; import com.xboe.module.boecase.dto.CaseAiChatDto; +import com.xboe.module.boecase.dto.CaseAiMsgLikeDto; import com.xboe.module.boecase.entity.AiChatConversationData; import com.xboe.module.boecase.service.ICaseAiChatService; import com.xboe.module.boecase.service.ICaseAiPermissionService; @@ -79,6 +80,45 @@ public class CaseAiChatApi extends ApiBaseController { return error("停止输出失败", e.getMessage()); } } + + /** + * 赞消息 + * @param caseAiMsgLikeDto + * @return + */ + @PostMapping("/likeMsg") + public JsonResponse likeMsg(@RequestBody CaseAiMsgLikeDto caseAiMsgLikeDto) { + try { + if (caseAiChatService.msgFeedback(caseAiMsgLikeDto)) { + return success(true, "保存成功"); + } else { + return success(false, "保存失败"); + } + } catch (Exception e) { + log.error("消息赞/踩操作保存异常", e); + return error("保存失败", e.getMessage()); + } + } + + + /** + * 消息问题反馈保存 + * @param caseAiMsgLikeDto + * @return + */ + @PostMapping("/msgFeedback") + public JsonResponse msgFeedback(@RequestBody CaseAiMsgLikeDto caseAiMsgLikeDto) { + try { + if (caseAiChatService.msgFeedback(caseAiMsgLikeDto)) { + return success(true, "保存成功"); + } else { + return success(false, "保存失败"); + } + } catch (Exception e) { + log.error("消息问题反馈保存异常", e); + return error("保存失败", e.getMessage()); + } + } /** * 根据conversationId查看会话内消息记录 diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java new file mode 100644 index 00000000..2f533b70 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dto/CaseAiMsgLikeDto.java @@ -0,0 +1,24 @@ +package com.xboe.module.boecase.dto; + +import lombok.Data; + +@Data +public class CaseAiMsgLikeDto { + /** + * 文档id + */ + private String docId; + + /** + * 点赞状态: + * -1 踩 + * 1 赞 + * 0/null 无操作 + */ + private String likeStatus; + + /** + * 反馈 + */ + private String feedback; +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/AiChatConversationData.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/AiChatConversationData.java index d62b056b..9f1dfcb3 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/AiChatConversationData.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/AiChatConversationData.java @@ -44,6 +44,20 @@ public class AiChatConversationData { */ private List suggestions = new ArrayList<>(); + /** + * 用户点赞状态 + * -1: 踩 + * 1:赞 + * 0/null 无操作 + */ + private String likeStatus; + + /** + * 用户踩的时候, 可以填写反馈意见 + * 反馈意见 + */ + private String feedback; + /** * 用户ID */ diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICaseAiChatService.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICaseAiChatService.java index 87e401e5..d424400b 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICaseAiChatService.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICaseAiChatService.java @@ -2,6 +2,7 @@ package com.xboe.module.boecase.service; import com.xboe.core.CurrentUser; import com.xboe.module.boecase.dto.CaseAiChatDto; +import com.xboe.module.boecase.dto.CaseAiMsgLikeDto; import com.xboe.module.boecase.entity.CaseAiConversations; import com.xboe.module.boecase.vo.CaseAiMessageVo; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @@ -64,4 +65,13 @@ public interface ICaseAiChatService { * @return 是否成功停止 */ boolean stopChatOutput(String conversationId); + + /** + * 消息反馈保存 + * likeStatus: 踩/赞 + * feedBack: 反馈消息内容 + * + * @param caseAiMsgLikeDto + */ + boolean msgFeedback(CaseAiMsgLikeDto caseAiMsgLikeDto); } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/IElasticSearchIndexService.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/IElasticSearchIndexService.java index ea1d4207..a7f13cf9 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/IElasticSearchIndexService.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/IElasticSearchIndexService.java @@ -40,4 +40,12 @@ public interface IElasticSearchIndexService { * @return */ List queryData(String conversationId); + + /** + * 更新数据 + * @param docId + * @param data + * @return + */ + boolean updateData(String docId, AiChatConversationData data); } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java index 76b69314..db29dc7a 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseAiChatServiceImpl.java @@ -10,6 +10,7 @@ import com.xboe.module.boecase.dao.CaseAiConversationsDao; import com.xboe.module.boecase.dao.CaseDocumentLogDao; import com.xboe.module.boecase.dao.CasesDao; import com.xboe.module.boecase.dto.CaseAiChatDto; +import com.xboe.module.boecase.dto.CaseAiMsgLikeDto; import com.xboe.module.boecase.entity.CaseAiConversations; import com.xboe.module.boecase.entity.CaseDocumentLog; import com.xboe.module.boecase.entity.Cases; @@ -779,6 +780,22 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService { } } + @Override + public boolean msgFeedback(CaseAiMsgLikeDto caseAiMsgLikeDto) { + AiChatConversationData aiChatConversationData = new AiChatConversationData(); + if (StringUtils.isBlank(caseAiMsgLikeDto.getDocId())) { + log.error("操作失败,docId为空"); + return false; + } + if ((StringUtils.equalsAny(caseAiMsgLikeDto.getLikeStatus(), "0", "1", "-1")) || StringUtils.isBlank(caseAiMsgLikeDto.getFeedback())) { + log.error("操作失败,参数错误"); + return false; + } + aiChatConversationData.setLikeStatus(caseAiMsgLikeDto.getLikeStatus()); + aiChatConversationData.setFeedback(caseAiMsgLikeDto.getFeedback()); + return elasticSearchIndexService.updateData(caseAiMsgLikeDto.getDocId() ,aiChatConversationData); + } + /** * 判断Throwable是否为超时类异常 * @param e diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/ElasticSearchIndexServiceImpl.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/ElasticSearchIndexServiceImpl.java index ae2769cc..0442c1e3 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/ElasticSearchIndexServiceImpl.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/ElasticSearchIndexServiceImpl.java @@ -8,12 +8,15 @@ import com.xboe.module.boecase.service.IElasticSearchIndexService; import com.xboe.module.boecase.vo.CaseAiMessageVo; import com.xboe.module.boecase.vo.CaseReferVo; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.CreateIndexRequest; @@ -22,6 +25,7 @@ import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; @@ -260,6 +264,38 @@ public class ElasticSearchIndexServiceImpl implements IElasticSearchIndexService } } + @Override + public boolean updateData(String docId, AiChatConversationData data) { + if (elasticsearchClient == null) { + log.error("未配置Elasticsearch客户端,无法更新对话记录"); + return false; + } + try{ + UpdateRequest updateRequest = new UpdateRequest(CaseAiConstants.CASE_AI_INDEX_NAME, docId); + JSONObject esData = new JSONObject(); + // 目前只支持更新点赞状态和反馈信息 + if (StringUtils.isNotBlank(data.getLikeStatus())) { + // 进行点赞/踩或取消操作是, 将feedback字段置空 + esData.put("likeStatus", data.getLikeStatus()); + esData.put("feedback", ""); + } + if (StringUtils.isNotBlank(data.getFeedback())) { + esData.put("feedback", data.getFeedback()); + } + updateRequest.doc(esData.toJSONString(), XContentType.JSON); + elasticsearchClient.update(updateRequest, RequestOptions.DEFAULT); + return true; + } catch (ElasticsearchException e) { + if (e.status() == RestStatus.NOT_FOUND) { + log.error("文档不存在", e); + } + return false; + } catch (Exception e) { + log.error("更新对话记录异常", e); + return false; + } + } + /** * 获取ai_chat_messages索引的字段映射配置 * 根据项目中的会话消息数据结构规范定义映射